Bugzilla – Attachment 118476 Details for
Bug 8628
Add digital signs to the OPAC
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 8628: Digital signs - opac interface
Bug-8628-Digital-signs---opac-interface.patch (text/plain), 37.50 KB, created by
Aleisha Amohia
on 2021-03-19 01:08:44 UTC
(
hide
)
Description:
Bug 8628: Digital signs - opac interface
Filename:
MIME Type:
Creator:
Aleisha Amohia
Created:
2021-03-19 01:08:44 UTC
Size:
37.50 KB
patch
obsolete
>From 30069eb73ff60cabdf0cc1df25144db8a74fd845 Mon Sep 17 00:00:00 2001 >From: Aleisha Amohia <aleishaamohia@hotmail.com> >Date: Fri, 26 Apr 2019 01:47:13 +0000 >Subject: [PATCH] Bug 8628: Digital signs - opac interface > >To test: >1. Apply this patch and the database updates patch >2. Run updatedatabase.pl >3. In staff client, go to Tools/Additional Tools/Digital signs >4. You should be warned about OPACDigitalSigns not being enabled, you can ignore > this for now. >5. Add a new sign by clicking the "+ New sign" button >6. Enter a name and optionally numbers for automatic page turing >7. Your new sign should appear in the Signs list >8. Add a new stream by clicking the "+ New stream" button >9. Unless you already have reports in the report group with code SIGN, you should > be warned that there are no reports in the group with code SIGN and given a > link for creating a new report. Follow the link and create a new report with > report group code SIGN. En example SQL command for the report could be: > > SELECT * FROM biblio WHERE timestamp > DATE_SUB(NOW(), INTERVAL 7 DAY) > > or if you are testing the parameters feature of the digital signs, an example report could be: > > SELECT * FROM biblio WHERE biblionumber < placeholder. >10. Go back to the "new stream" page, and reload. You should no longer see a > warning message, and your newly created report should appear in the list of > reports. >11. Select the report and click Submit. Your newly created stream should now > appear in the list of streams. >12. In the list of signs, press "edit streams" for the sign you previously > created. >13. Choose a stream to attach and click Submit. > If you have attached a report with a parameter placeholder, edit the parameters so that the placeholder gets substituted with a value. For example, in the edit parameters box, you can have: > > placeholder = 10000 > > When you submit, you'll see the SQL replaces the placeholder with your value and completes the query. > Your sign is now ready for OPAC. >14. In OPAC, visit /cgi-bin/koha/opac-signs.pl >15. You should be told that Digital signs are not enabled. Enable with new > system preference OPACDigitalSigns and reload the page. >15. You should see a list of available signs, click on a sign that you wish to > display. >16. You should now see a list of all books matching the SQL query in the report > that you attached to your stream. >17. If you have OPACLocalCoverImages enabled, all books with local covers > attached should be presented using this cover. > If no local cover is available and the book has a ISBN with a cover in > openlibrary.org, the cover image from openlibrary.org should be shown. > If all of the above fails, a cover matching the theme of the page should be > seen, showing the book title and author. >18. Clicking a book should bring you to a detailed view of the book where you > can see the books availability. You should also see the two next books and > the two previous books in the stream (unless you're at the beginning or end > of the stream) >19. Swiping (if no touch screen, click and hold left mouse button and drag) > left/right should bring you to next/previous book. Clicking on the > next/previous books (right/left of the active one) should bring you to the > detailed view of the clicked book. >20. Leaving the page idle (i.e no user interaction) for the amount of time > specified in step 6. should result in the page automatically switching to > the next book in the stream. > >Sponsored-by: Regionbibliotek Halland / County library of Halland > >Signed-off-by: Lisette Scheer <lisetteslatah@gmail.com> >--- > koha-tmpl/opac-tmpl/bootstrap/css/signs.css | 100 ++++ > .../opac-tmpl/bootstrap/en/modules/opac-signs.tt | 564 +++++++++++++++++++++ > opac/opac-signs.pl | 113 +++++ > tools/signs.pl | 1 + > 4 files changed, 778 insertions(+) > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/css/signs.css > create mode 100644 koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-signs.tt > create mode 100755 opac/opac-signs.pl > >diff --git a/koha-tmpl/opac-tmpl/bootstrap/css/signs.css b/koha-tmpl/opac-tmpl/bootstrap/css/signs.css >new file mode 100644 >index 0000000000..f481d47cd3 >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/bootstrap/css/signs.css >@@ -0,0 +1,100 @@ >+.carousel-container { >+ height: 225px; >+ position: relative; >+ margin: 0 auto 40px; >+ -webkit-perspective: 1100px; >+ -moz-perspective: 1100px; >+ -o-perspective: 1100px; >+ -ms-perspective: 1100px; >+ perspective: 1100px; >+} >+ >+.carousel { >+ width: 100%; >+ height: 100%; >+ -webkit-transform-style: preserve-3d; >+ -moz-transform-style: preserve-3d; >+ -o-transform-style: preserve-3d; >+ -ms-transform-style: preserve-3d; >+ transform-style: preserve-3d; >+} >+ >+.unicorn { >+ display: inline; >+ position: relative; >+ width: 150px; >+ height: 225px; >+ left: 10px; >+ top: 10px; >+ -webkit-box-reflect: below 0 -webkit-gradient(linear, left bottom, left top, color-stop(0.05, rgba(255, 255, 255, 0.12)), color-stop(0.2, transparent)); >+} >+ >+.ui-li { >+ padding-top: 0px !important; >+ padding-bottom: 0px !important; >+ margin-bottom: -7px !important; >+} >+ >+.ui-li h4 { >+ margin-top: 2px !important; >+ margin-bottom: 2px !important; >+} >+ >+.ui-li-icon { >+ top: 15% !important; >+} >+ >+.vspace { >+ margin-top: 2em; >+} >+ >+.content { >+ text-align: center; >+} >+ >+.btn-record { >+ margin: 10px; >+} >+ >+.cover { >+ border: none; >+ display: inline-block; >+ height: 225px; >+ width: 150px; >+ background-size: 100%; >+ background-repeat: round; >+} >+ >+.cover.cover-blank { >+} >+ >+.cover.placeholder { >+} >+ >+.cover .cover-inner { >+ display: table-cell; >+ vertical-align: middle; >+ padding: 25px; >+ border: 2px solid #fff; >+ height: 171px; >+ max-height: 171px; >+ width: inherit; >+} >+ >+.cover-text { >+ text-align: center; >+ position: relative; >+ font-family: Georgia, "Palatino Linotype", "Book Antiqua", Palatino, "Times New Roman", serif; >+ font-size: 1em; >+ max-height: inherit; >+ overflow: hidden; >+} >+ >+.cover-text .title { >+ font-weight: bold; >+} >+ >+.cover-text .author { >+ font-style: italic; >+ margin-top: 1em; >+} >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-signs.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-signs.tt >new file mode 100644 >index 0000000000..6990d3bad4 >--- /dev/null >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-signs.tt >@@ -0,0 +1,564 @@ >+[% USE Koha %] >+[% USE KohaDates %] >+[% USE Branches %] >+[% USE JSON.Escape %] >+ >+[%- BLOCK item_status -%] >+ [%- SET itemavailable = 1 -%] >+ [%- IF ( item.itemlost ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%-%]Item lost >+ [%- END -%] >+ [%- IF ( item.datedue || issue.date_due ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%- IF item.onsite_checkout -%] >+ [%-%]Currently in local use >+ [%- ELSE -%] >+ [%-%]Checked out >+ [%- END -%] >+ [%- END -%] >+ [%- IF ( item.transfertwhen ) %] >+ [%- SET itemavailable = 0 -%] >+ [%-%]In transit from [%- item.transfertfrom %] to [%- item.transfertto %] since [%- item.transfertwhen | $KohaDates %] >+ [%- END %] >+ [%- IF ( item.waiting ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%-%]On hold >+ [%- END -%] >+ [%- IF ( item.withdrawn ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%-%]Item withdrawn >+ [%- END -%] >+ [%- IF ( item.itemnotforloan ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%- IF ( item.notforloanvalueopac ) -%] >+ [%- item.notforloanvalueopac -%] [%- IF ( item.restrictedopac ) -%] ([%- item.restrictedopac -%])[%- END -%] >+ [%- ELSE -%] >+ [%-%]Not for loan [%- IF ( item.restrictedopac ) -%] ([%- item.restrictedopac -%])[%- END -%] >+ [%- END -%] >+ [%- ELSIF ( item.notforloan_per_itemtype ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%-%]Not for loan [%- IF ( item.restrictedopac ) -%] ([%- item.restrictedopac -%])[%- END -%] >+ [%- END -%] >+ [%- IF ( item.damaged ) -%] >+ [%- SET itemavailable = 0 -%] >+ [%-%]Item damaged >+ [%- END -%] >+ [%- IF item.on_order -%] >+ [%- SET itemavailable = 0 -%] >+ [%-%]On order >+ [%- END -%] >+ [%- IF ( itemavailable ) -%] >+ [%-%]Available [%- IF ( item.restrictedopac ) -%] ([%- item.restrictedopac -%])[%- END -%] >+ [%- END -%] >+[%- END -%] >+ >+[% INCLUDE 'doc-head-open.inc' %] >+<title>[% IF ( sign ) %][% sign.name %] - Koha[% ELSE %]Koha digital signs[% END %]</title> >+[%- IF ( sign.webapp ) %] >+ <meta name="apple-mobile-web-app-capable" content="yes" /> >+ <meta name="viewport" content="width=device-width, initial-scale=1"> >+[% END -%] >+[% BLOCK cssinclude %] >+ [%- IF Koha.Preference( 'OPACDigitalSignsCSS' ) != '' -%] >+ <style type="text/css"> >+ [% Koha.Preference( 'OPACDigitalSignsCSS' ) %] >+ </style> >+ <link rel="stylesheet" href="[% interface %]/lib/jquery/mobile/jquery.mobile.structure.min.css" /> >+ [%- ELSE -%] >+ <link rel="stylesheet" href="[% interface %]/bootstrap/css/signs.css" /> >+ <link rel="stylesheet" href="[% interface %]/lib/jquery/mobile/jquery.mobile.min.css" /> >+ [%- END -%] >+[% END # BLOCK cssinclude %] >+[% INCLUDE 'doc-head-close.inc' %] >+</head> >+[% INCLUDE 'bodytag.inc' bodyid='opac-signs' %] >+ >+[%- UNLESS Koha.Preference( 'OPACDigitalSigns' ) -%] >+ <p>Digital signs are not enabled!</p> >+[%- ELSE -%] >+ [%# Display a sign, all its streams and all records %] >+ [%- IF ( sign ) -%] >+ [%- IF ( streams.0 ) -%] >+ [%# Iterate through the streams, creating one front page for each %] >+ [%- FOREACH s IN streams -%] >+ <div data-role="page" class="page-stream" data-stream-id="[% s.sign_stream_id %]" data-theme="[% sign.swatch %]" id="stream_[% s.sign_stream_id %]"> >+ <div data-role="header" data-theme="[% sign.swatch %]" data-position="fixed"> >+ <div style="text-align: center;"> >+ [%# The header has a list of buttons for all the streams %] >+ [%- SET localstreams = streams -%] >+ [%- FOREACH stream IN localstreams -%] >+ [% IF s.sign_stream_id == stream.sign_stream_id %] >+ <a href="#stream_[% stream.sign_stream_id %]" data-stream-id="[% stream.sign_stream_id %]" class="btn-stream stream-active" data-inline="true" data-icon="star" data-role="button">[% stream.name %]</a> >+ [% ELSE %] >+ <a href="#stream_[% stream.sign_stream_id %]" data-stream-id="[% stream.sign_stream_id %]" class="btn-stream" data-inline="true" data-role="button">[% stream.name %]</a> >+ [% END %] >+ [% END -%] >+ </div> >+ </div> <!-- /header --> >+ <div data-role="content" class="content"> >+ <h1>[% s.name %]</h1> >+ </div> <!-- /content --> >+ </div> <!-- /page --> >+ >+ [% END # FOREACH s IN streams %] >+ [% ELSE %] >+ <p>No streams attached to this sign.</p> >+ [% END # IF ( streams.0 ) %] >+ [% END # IF ( sign ) %] >+ >+ [%# Display a list of all signs, as a default. Links use data-ajax="false" so signs will replace the first page, not be AJAXed in. %] >+ [%# This page is not meant to be viewed by non-librarians, so it can not be themed. %] >+ [% IF ( signs ) %] >+ <div data-role="page" id="allsigns"> >+ <div data-role="header" data-position="fixed"> >+ <h1>All signs</h1> >+ </div> >+ <div data-role="content"> >+ <ul data-role="listview"> >+ [% FOREACH SIGN IN signs %] >+ <li><a href="?sign=[% SIGN.sign_id %]" data-ajax="false">[% SIGN.name %]</a></li> >+ [% END %] >+ </ul> >+ </div> >+ </div> >+ [% END # IF ( signs ) %] >+[% END # UNLESS Koha.Preference( 'OPACDigitalSigns' ) %] >+ >+[% INCLUDE 'opac-bottom.inc' is_popup=1 %] >+[% BLOCK jsinclude %] >+ [% IF sign && Koha.Preference( 'OPACDigitalSigns') %] >+ <script type="text/javascript"> >+ //<![CDATA[ >+ $(function (){ >+ var active_stream = '#' + $('.page-stream').first().attr('id'); >+ var active_record; >+ >+ /***************************************************************** >+ * Page idle handling >+ */ >+ var doIdle = false; >+ var idleTimePage = 0; >+ var idleTime = 0; >+ var idleInterval = setInterval(idleIncrementer, 1000); >+ >+ function resetIdle() { >+ idleTimePage = 0; >+ idleTime = 0; >+ doIdle = false; >+ } >+ >+ function idleIncrementer() { >+ idleTimePage++; >+ idleTime++; >+ >+ [% IF ( sign.idleafter ) -%] >+ if (idleTime >= [% sign.idleafter %]) { >+ doIdle = true; >+ } >+ [%- END -%] >+ >+ [%- IF ( sign.pagedelay ) -%] >+ if (doIdle && idleTimePage >= [% sign.pagedelay %]) { >+ idleTimePage = 0; >+ swipe('next', true, true); >+ } >+ [%- END -%] >+ >+ [%- IF ( sign.reloadafter ) -%] >+ if (doIdle && idleTime >= [% sign.reloadafter %]) { >+ resetIdle(); >+ window.location.reload(true); >+ } >+ [%- END -%] >+ } >+ >+ /***************************************************************** >+ * User interaction methods >+ */ >+ $('.btn-stream').click(function(){ >+ active_stream = $(this).attr('href'); >+ active_record = $(active_stream).find('.content a').first().attr('href'); >+ }); >+ >+ /* swipe to next/previous record/stream */ >+ function swipe(direction, forceRecordView, warp) { >+ var delta = direction == 'prev' ? -1 : 1; >+ var isInRecordView = forceRecordView || window.location.hash.indexOf('#record') >= 0; >+ >+ if(isInRecordView) { >+ active_record = do_swipe( >+ $(active_stream).find('.content a'), >+ function($elm){ >+ return $elm.attr('href'); >+ }, >+ active_record >+ ); >+ } >+ else { // in stream view >+ active_stream = do_swipe( >+ $('.page-stream'), >+ function($elm) { >+ return '#'+$elm.attr('id'); >+ }, >+ active_stream >+ ); >+ } >+ >+ /* jump to next/prev page in pages returned from <selector> >+ * filtered through <filter> in references to <active>. >+ * >+ * Return new active page. >+ */ >+ function do_swipe(selector, filter, active) { >+ var list = []; >+ selector.each(function(){ >+ list.push(filter($(this))); >+ }); >+ >+ var i = list.indexOf(active); >+ i = i == -1 ? 0 : i; // default to first if no active found >+ >+ if(i >= 0) { >+ if(i >= list.length-1 && delta > 0) { >+ if(warp) >+ i = 0; // warp to start >+ else >+ return list[i]; >+ } else if(i == 0 && delta < 0) { >+ if(warp) >+ i = list.length-1; // warp to end >+ else >+ return list[i]; >+ } else { >+ i += delta; >+ } >+ >+ $.mobile.changePage(list[i]); >+ return list[i]; >+ } >+ >+ return active; >+ } >+ } >+ >+ /***************************************************************** >+ * Global events >+ */ >+ $(window).on( 'swiperight', function() { resetIdle(); swipe('prev'); }); >+ $(window).on( 'swipeleft', function() { resetIdle(); swipe('next'); }); >+ $(window).on( 'mousemove', function() { resetIdle(); }); >+ $(window).on( 'keypress', function() { resetIdle(); }); >+ $(window).on( 'tap', function() { resetIdle(); }); >+ >+ /***************************************************************** >+ * Carousel >+ */ >+ var Carousel = function ($elm) { >+ var self = this; >+ this.$elm = $elm; >+ this.unicornCount = $elm.children().length; >+ this.rotateFn = 'rotateY'; >+ this.$unicorns = this.$elm.children(); >+ this.i_active = this.$unicorns.index(this.$elm.children('.active')); >+ this.unicornSize = this.$unicorns.first().outerWidth(); >+ >+ this.modify = function() { >+ var offsetScale = $(window).width() / (this.unicornSize*this.unicornCount); >+ offsetScale = offsetScale > 1 ? 1 : offsetScale; >+ >+ for ( i = 0; i < this.unicornCount ; i++ ) { >+ var $unicorn = this.$unicorns.eq(i); >+ var angle = 50*(i < this.i_active ? 1 : -1); >+ var scale = 0.75/Math.abs(i-this.i_active); >+ if(i == this.i_active) { >+ scale=1; >+ angle=0; >+ } >+ >+ var transform = this.rotateFn + '(' + angle + 'deg) scale('+scale+')'; >+ $unicorn.css({ >+ '-webkit-transform': transform, >+ '-moz-transform': transform, >+ '-o-transform': transform, >+ '-ms-transform': transform, >+ 'transform': transform >+ }); >+ $unicorn.css('left', offsetScale*this.unicornSize*(i-this.i_active)+'px'); >+ $unicorn.css('z-index', -1*Math.abs(i-this.i_active)); >+ } >+ }; >+ }; >+ >+ >+ /***************************************************************** >+ * ImageCache >+ */ >+ var ImageCache = function() { >+ var self = this; >+ self.cached = {}; >+ self.nocover = {}; >+ >+ /* get cover image from local cover or fallbacks */ >+ self.get = function(record, finished_cb) { >+ if( record.biblionumber in self.cached ) { >+ finished_cb(self.cached[record.biblionumber]); >+ } else { >+ // first try local cover >+ var $img = $('<img/>') >+ .attr('src','opac-image.pl?biblionumber='+record.biblionumber) >+ .css('display','none') >+ .appendTo('body'); >+ >+ $img.on('load', function() { >+ self.cached[record.biblionumber] = $(this); >+ // have a 1x1 pixel image, fallback to openlibrary ... >+ if($(this).height() <= 1) { >+ // ... if we can >+ if(record.isbn) { >+ var ol_url = 'http://covers.openlibrary.org/b/isbn/'; >+ ol_url += record.isbn + '-M.jpg?default=false'; >+ >+ var $ol_img = $('<img/>') >+ .attr('src',ol_url) >+ .css('display','none') >+ .appendTo('body') >+ .on('load', function() { >+ $img.remove(); // remove old 1x1 pixel image >+ self.cached[record.biblionumber] = $ol_img; >+ finished_cb($(this)); >+ }) >+ .on('error', function() { >+ // fallback to no cover image >+ self.nocover[record.biblionumber] = true; >+ finished_cb($(this)); >+ }); >+ } else { >+ // fallback to no cover image >+ self.nocover[record.biblionumber] = true; >+ finished_cb($(this)); >+ } >+ } else { >+ finished_cb($(this)); >+ } >+ }); >+ } >+ } >+ >+ self.have_cover = function(record) { return !(record.biblionumber in self.nocover) } >+ }; >+ var img_cache = new ImageCache(); >+ >+ /***************************************************************** >+ * Cover >+ */ >+ var coverCounter = 0; >+ var Cover = function(record) { >+ var self = this; >+ self.record = record; >+ self.id = coverCounter++; >+ >+ /* generate cover div */ >+ self.render = function(finished_cb) { >+ img_cache.get(record, function($img) { >+ self.$cover = $('<div class="cover cover_'+self.id+'" data-id="'+self.id+'"/>'); >+ self.$cover.css('background-image', 'url("'+$img.attr('src')+'")'); >+ self.$cover.css('background-size', '100%'); >+ self.$cover.css('background-position', 'center center'); >+ self.$cover.css('background-repeat', 'no-repeat'); >+ self.$cover.addClass('ui-bar-[% sign.swatch %]'); >+ >+ if( !img_cache.have_cover(record) ) { >+ self.$vcontainer = $('<div class="cover-inner"/>'); >+ self.$vcontainer.addClass('ui-bar-[% sign.swatch %]'); >+ self.$cover.append(self.$vcontainer); >+ >+ self.$cover.addClass('cover-blank'); >+ self.$cover.css('border-color', $('.ui-bar-[% sign.swatch %]').first().css('background-color')); >+ >+ var $covertext = $('<div class="cover-text"></div>'); >+ $covertext.append($('<div class="title">'+record.title+'</div>')); >+ $covertext.append($('<div class="author">'+record.author+'</div>')); >+ >+ self.$vcontainer.append($covertext); >+ } >+ >+ finished_cb(self); >+ }); >+ } >+ }; >+ >+ /* create page for a cover */ >+ function create_CoverPage(cover, sid) { >+ var $cover = cover.$cover.clone(); >+ var $stream = $('#stream_'+sid); >+ >+ var $page = $('<div data-role="page" data-close-btn="none" data-theme="[% sign.swatch %]" id="record_'+sid+'_'+cover.record.biblionumber+'"/>'); >+ var $head = $('<div data-role="header" data-theme="[% sign.swatch %]"/>'); >+ var $content = $('<div data-role="content" class="content"/>') >+ var $foot = $('<div data-role="foot" data-position="fixed" class="foot"/>') >+ >+ /*************** >+ * header >+ *******/ >+ $head.append($('<h1 aria-level="1" role="heading" class="ui-title">'+cover.record.title+'</h1>')); >+ >+ /*************** >+ * content >+ ********/ >+ /* carousel */ >+ var $carousel_container = $('<div class="carousel-container"/>'); >+ $content.append($carousel_container); >+ >+ var $carousel = $('<ul class="carousel"/>'); >+ var neighbours= 2; // on each side >+ var unicorns = []; >+ >+ /* grab <neighbours> covers around the active */ >+ $stream.find('.cover').each(function() { >+ unicorns.push($(this).data('id')); >+ }); >+ var this_unicorn = unicorns.indexOf(cover.id); >+ unicorns = unicorns.slice( >+ Math.max(this_unicorn-neighbours, 0), >+ 1+Math.min(this_unicorn+neighbours, unicorns.length-1) >+ ); >+ >+ /* create unicorns and add to carousel */ >+ for(var i=0; i < unicorns.length; i++) { >+ var $unicorn_cover = $('#stream_'+sid).find('.cover_'+unicorns[i]); >+ $unicorn_cover = $unicorn_cover.parent('a').clone(); >+ var $unicorn = $('<li class="unicorn"/>').append($unicorn_cover); >+ if(unicorns[i] == cover.id) { >+ $unicorn.addClass('active'); >+ } >+ $carousel.append($unicorn); >+ } >+ $carousel_container.append($carousel); >+ >+ /* initilize carousel on pagecreate */ >+ $page.on("pagecreate", function(){ >+ var carousel = new Carousel($carousel); >+ $page.data('carousel', carousel); >+ carousel.modify(); >+ }); >+ >+ /* item info */ >+ var $info = $('<div/>') >+ $info.append($('<span><strong>'+_("Author")+':</strong> ' + cover.record.author+'</span>')); >+ if(cover.record.publisher) { >+ $info.append($('<br/><span><strong>'+_("Publisher")+':</strong> ' + cover.record.publisher + '</span>')); >+ } >+ >+ if(cover.record.items.length > 0) { >+ $info.append('<div class="vspace"/>'); >+ } >+ var $items = $('<ul data-role="listview"/>'); >+ for(var i=0; i < cover.record.items.length; i++) { >+ var $li = $('<li/>'); >+ var item = cover.record.items[i]; >+ >+ if(item.type) { >+ $li.append($('<img src="/opac-tmpl/lib/famfamfam/'+item.type+'.png" class="ui-li-icon"/>')); >+ } >+ var location = item.location_description ? item.location_description + _(" in ") + item.home_branch: item.home_branch; >+ var item_info = item.status + _(" at ") + location; >+ $li.append($('<h4>'+item_info+'</h4>')); >+ if(item.datedue) { >+ $li.append('<p>'+_("Date due") + ': ' + item.datedue+'</p>'); >+ } >+ $items.append($li); >+ } >+ $info.append($items); >+ $content.append($info); >+ >+ /*************** >+ * footer >+ *******/ >+ $foot.append($('<a href="#stream_'+sid+'" data-role="button" data-theme="[% sign.swatch %]" data-transition="[% sign.transition %]">'+_("Back")+'</a>')); >+ >+ /*************** >+ * page >+ *****/ >+ $page.append($head); >+ $page.append($content); >+ $page.append($foot); >+ $page.appendTo('body'); >+ >+ return $page; >+ }; >+ >+ /***************************************************************** >+ * Page generation >+ */ >+ var streams = { >+ [%- FOREACH stream IN streams %] >+ '[% stream.sign_stream_id %]': { >+ 'name': [% stream.name.json || '""' %], >+ 'records': [ >+ [%- FOREACH record IN stream.records %] >+ {'author': [% record.author.json || '""' %], >+ 'title': [% record.title.json || '""' %], >+ 'publisher': [% record.publishercode.json || '""' %], >+ 'biblionumber': [% record.biblionumber.json || '""' %], >+ 'isbn': [% record.isbn.json || '""' %], >+ 'items': [ >+ [%- FOREACH item IN record.items %] >+ { >+ 'type': [% item.itemtype.json || '""' %], >+ 'datedue': "[% item.datedue | $KohaDates as_due_date => 1 %]", >+ 'location': [% item.location.json || '""' %], >+ 'location_description': [% item.location_description.json || '""' %], >+ 'home_branch': "[% Branches.GetName(item.homebranch) | json %]", >+ 'status': "[% INCLUDE item_status item = item %]" >+ >+ } >+ [%- UNLESS loop.last -%],[%- END -%] >+ [%- END %] >+ ] >+ } >+ [%- UNLESS loop.last -%],[%- END -%] >+ [%- END %] >+ ] >+ } >+ [%- UNLESS loop.last -%],[%- END -%] >+ [%- END %] >+ }; >+ >+ /* fill up streams with records */ >+ var firstLoadedRecord = true; >+ $('.page-stream').each(function() { >+ var sid = $(this).data('stream-id'); >+ var $content = $(this).children('.content').first(); >+ >+ for(var i in streams[sid].records) { >+ var cover = new Cover(streams[sid].records[i]); >+ var $link = $('<a href="#record_'+sid+'_'+cover.record.biblionumber+'" class="btn-record" data-transition="[% sign.transition %]"/>') >+ $link.click(function(){ active_record = $(this).attr('href'); }); >+ $content.append($link.append($('<div class="cover placeholder ui-bar-[% sign.swatch %] cover_'+cover.id+'" data-id="'+cover.id+'"/>'))); >+ >+ cover.render(function(cover_rendered) { >+ var $coverPage = create_CoverPage(cover_rendered, sid); >+ /* initialize active_record with first loaded record from active stream */ >+ if(firstLoadedRecord && sid == $(active_stream).data('stream-id') ){ >+ active_record = cover_rendered.$cover.attr('href'); >+ firstLoadedRecord = false; >+ } >+ >+ /* replace all placeholders for this cover with rendered version*/ >+ $('.placeholder.cover_'+cover_rendered.id).each(function() { >+ $(this).replaceWith(cover_rendered.$cover.clone()); >+ }); >+ }); >+ } >+ >+ }); >+ }); >+ //]]> >+ </script> >+ [% END # IF ( sign ) %] >+ <script src="/opac-tmpl/lib/jquery/mobile/jquery.mobile.min.js"></script> >+[% END # BLOCK jsinclude %] >+ >+</body> >+</html> >diff --git a/opac/opac-signs.pl b/opac/opac-signs.pl >new file mode 100755 >index 0000000000..48904689b3 >--- /dev/null >+++ b/opac/opac-signs.pl >@@ -0,0 +1,113 @@ >+#!/usr/bin/perl >+ >+# Copyright 2012 Magnus Enger Libriotech >+# >+# 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, write to the Free Software Foundation, Inc., >+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. >+ >+use CGI; >+use C4::Auth; >+use C4::Output; >+use C4::Biblio; >+use C4::Reports::Guided; >+use C4::Context; >+use C4::Koha; >+use C4::Items; >+use Koha::AuthorisedValues; >+use Koha::Signs; >+use Koha::SignStreams; >+use Koha::SignsToStreams; >+use Koha::Reports; >+use Modern::Perl; >+ >+binmode STDOUT, ':encoding(UTF-8)'; # FIXME Non-ASCII is broken without this >+ >+my $query = CGI->new; >+my $sign_id = $query->param('sign') || ''; >+ >+my ( $template, $borrowernumber, $cookie ) = get_template_and_user({ >+ 'template_name' => 'opac-signs.tt', >+ 'query' => $query, >+ 'type' => 'opac', >+ 'authnotrequired' => ( C4::Context->preference('OpacPublic') ? 1 : 0 ), >+ 'flagsrequired' => { borrowers => 1 }, >+}); >+ >+if ( C4::Context->preference('OPACDigitalSigns') ) { >+ if ( $sign_id ne '' ) { # Display a sign with streams >+ $template->{VARS}->{'sign'} = Koha::Signs->find( $sign_id ); >+ >+ # Getting sign streams attached to sign with records >+ my $schema = Koha::Database->new()->schema(); >+ my @signstostreams = $schema->resultset('SignsToStream')->search({ 'me.sign_id' => $sign_id }, { prefetch => 'sign_stream' }); >+ my @changedstreams; >+ my %record_cache = (); >+ foreach my $s ( @signstostreams ) { >+ my $stream = Koha::SignStreams->find( $s->sign_stream_id ); >+ my $sql = Koha::Reports->find($stream->saved_sql_id); >+ my $params = Koha::SignsToStreams->find({ sign_to_stream_id => $s->sign_to_stream_id }); >+ >+ # Generate SQL with added params >+ my $newsql = $sql->savedsql; >+ foreach my $param ( split /&/, $params->params ) { >+ $param =~ tr/ //ds; # replace any whitespace with nothing, strip the spaces out so the query works >+ my ( $key, $value ) = split /=|<|>/, $param; # The < and > in the split are just to prevent software errors, the sign in the query must be changed in the report itself >+ $newsql =~ s/$key/$value/g; >+ } >+ >+ # Run query with new sql >+ my ( $records, $error ) = execute_query( $newsql, 0, 999999 ); >+ if ( ! $error ) { >+ $records = $records->fetchall_arrayref({}); >+ } >+ # Include marc >+ my @processed_records; >+ foreach my $rec ( @{$records} ) { >+ unless (defined $record_cache{$rec->{'biblionumber'}}) { >+ my $marc = GetMarcBiblio({ biblionumber => $rec->{'biblionumber'} }); >+ if ( ! $marc ) { >+ next; >+ } >+ >+ my $isbn = GetNormalizedISBN( undef, $marc, C4::Context->preference("marcflavor") ) || ''; >+ $rec->{'isbn'} = $isbn; >+ >+ my $dat = GetBiblioData($rec->{'biblionumber'}); >+ my @items = GetItemsInfo($rec->{'biblionumber'}); >+ foreach my $item ( @items ) { >+ my $shelflocations = { map { $_->authorised_value => $_->opac_description } Koha::AuthorisedValues->search_by_koha_field( { frameworkcode => $dat->{frameworkcode}, kohafield => 'items.location' } ) }; >+ if ( defined $item->{'location'} ) { >+ $item->{'location_description'} = $shelflocations->{ $item->{'location'} }; >+ } >+ } >+ $rec->{'items'} = \@items; >+ foreach ( keys %{$dat} ) { >+ $rec->{"$_"} = defined $dat->{$_} ? $dat->{$_} : ''; >+ } >+ $rec->{'marc'} = $marc; >+ $record_cache{$rec->{'biblionumber'}} = $rec; >+ } >+ push @processed_records, $record_cache{$rec->{'biblionumber'}}; >+ } >+ $s->{'records'} = \@processed_records; >+ push @changedstreams, $s; >+ } >+ $template->{VARS}->{'streams'} = \@changedstreams; >+ } else { # Display a list of all available signs >+ $template->{VARS}->{'signs'} = Koha::Signs->search({}); >+ } >+} >+ >+output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/tools/signs.pl b/tools/signs.pl >index 01c70bc4de..eff2784a35 100755 >--- a/tools/signs.pl >+++ b/tools/signs.pl >@@ -188,6 +188,7 @@ if ( $op eq 'add_stream' ) { > # Generate SQL with added params > my $newsql = $sql->savedsql; > foreach my $param ( split /&/, $params->params ) { >+ $param =~ tr/ //ds; # replace any whitespace with nothing, strip the spaces out so the query works > my ( $key, $value ) = split /=|<|>/, $param; # The < and > in the split are just to prevent software errors, the sign in the query must be changed in the report itself > $newsql =~ s/$key/$value/g; > } >-- >2.11.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 8628
:
42703
|
42704
|
45968
|
45969
|
58602
|
58603
|
58604
|
58605
|
62338
|
64249
|
66246
|
66247
|
66248
|
66249
|
66250
|
77025
|
77026
|
77027
|
77028
|
77141
|
77142
|
77143
|
77144
|
77145
|
78709
|
80248
|
80249
|
80250
|
80252
|
82896
|
82897
|
82898
|
82899
|
82900
|
82901
|
83312
|
88821
|
88822
|
88823
|
88824
|
88825
|
88826
|
93054
|
93055
|
93056
|
93057
|
93058
|
93059
|
93066
|
93067
|
93068
|
93069
|
93070
|
93071
|
99608
|
99609
|
99610
|
99611
|
99612
|
99613
|
99614
|
99615
|
99616
|
99617
|
99618
|
99619
|
99620
|
99621
|
99622
|
99623
|
99624
|
99717
|
99718
|
99801
|
118472
|
118473
|
118474
|
118475
|
118476
|
118477
|
118478
|
118479
|
118480
|
119455
|
131223
|
131224
|
145645
|
145646
|
145647
|
145648
|
145649
|
145650
|
145651
|
145652
|
145653
|
145654
|
147000
|
147001
|
147002
|
147003
|
147004
|
147005
|
147006
|
147007
|
147008
|
147009
|
147010