diff --git a/FEATURES/164204 b/FEATURES/164204 new file mode 100644 index 0000000000000000000000000000000000000000..a944a59ea0b7e7031ab6b15f49f07d7d81543a94 --- /dev/null +++ b/FEATURES/164204 @@ -0,0 +1,10 @@ + '164204' => + ['Label' => $this->_('Badge de disponibilité'), + 'Desc' => $this->_('Le badge de disponibilité permet d\'afficher la disponibilité d\'au moins un exemplaire au niveau des badges d\'une notice.'), + 'Image' => '', + 'Video' => '', + 'Category' => $this->_('Affichage'), + 'Right' => function($feature_description, $user) {return true;}, + 'Wiki' => 'https://wiki.bokeh-library-portal.org/index.php/Disponibilit%C3%A9_des_exemplaires', + 'Test' => '', + 'Date' => '2022-10-07'], \ No newline at end of file diff --git a/VERSIONS_WIP/164204 b/VERSIONS_WIP/164204 new file mode 100644 index 0000000000000000000000000000000000000000..cdc3dbd6cde2ea3166ea58b10a0a2e8a1380208e --- /dev/null +++ b/VERSIONS_WIP/164204 @@ -0,0 +1 @@ + - fonctionnalité #164204 : Magasin de thèmes : Nouveau badge de disponibilité. Il est rajouté après le badge du type de document d'une notice. \ No newline at end of file diff --git a/application/modules/opac/controllers/NoticeajaxController.php b/application/modules/opac/controllers/NoticeajaxController.php index e24696b5b47a76c55f56b6c19803b7805d24279c..9dff9e6ccc3639155b9e25159123b6754774448f 100644 --- a/application/modules/opac/controllers/NoticeajaxController.php +++ b/application/modules/opac/controllers/NoticeajaxController.php @@ -623,6 +623,12 @@ class NoticeAjaxController extends ZendAfi_Controller_Action { } + public function availabilityAction() { + session_write_close(); + $this->_helper->getHelper('HTMLAjaxResponse')->direct($this->view->availabilityBadge($this->notice)); + } + + protected function _ajaxResponseWithScript($content) { $this->_helper->getHelper('HTMLAjaxResponse') ->htmlAjaxResponseWithScript($content); diff --git a/library/Class/Exemplaire.php b/library/Class/Exemplaire.php index fd93116a0c259582eba2d9ee9db2e5c368bee721..c1a38c1d211bf032ba7231b15855639c7155ed68 100644 --- a/library/Class/Exemplaire.php +++ b/library/Class/Exemplaire.php @@ -397,7 +397,13 @@ class Class_Exemplaire extends Storm_Model_Abstract { public function updateAvailabilityAndLocationFromSIGBAndSaveIfNeeded() : self { - if ( ! $sigb_exemplaire = $this->_withILSWsItemDo(fn($ils_ws_item) => $ils_ws_item)) + if ( (! $sigb_exemplaire = $this->_withILSWsItemDo(fn($ils_ws_item) => $ils_ws_item)) + && $this->getIsAvailable()) { + $this->setIsAvailable(false)->save(); + return $this; + } + + if ( ! $sigb_exemplaire) return $this; $this->setUrlForCurrentUser($sigb_exemplaire->getUrlForCurrentUser()); diff --git a/library/Class/ScriptLoader.php b/library/Class/ScriptLoader.php index a767949d88b1b22aecb43ab4b6831a0652ba3d63..70f79616e58db73f4704610d5e50dd1611ece855 100644 --- a/library/Class/ScriptLoader.php +++ b/library/Class/ScriptLoader.php @@ -941,4 +941,11 @@ class Class_ScriptLoader { return $this ->addInlineScript('window.activateOpacBlocksSorting = window.deactiveOpacBlocksSorting = function() {};'); } + + + public function ajaxAvailability(Intonation_Library_AjaxAvailabilityBadge $badge) : self { + return $this + ->addOPACScript('ajaxAvailability/ajax_availability.js') + ->addJQueryReady(sprintf('$(".%s").ajax_availability();', $badge->getClassAsSelector())); + } } diff --git a/library/Class/User/Settings.php b/library/Class/User/Settings.php index 7e4ef16eaec3343c4e66cc23c1d09c8db0c5e71b..41d351e73f84f41c58863e7dab42236e1c9ca9e7 100644 --- a/library/Class/User/Settings.php +++ b/library/Class/User/Settings.php @@ -488,4 +488,31 @@ class Class_User_Settings { return $settings; } + + + public function sortItemsByBookmarkedLibraries(array $items) : array { + if ( 1 == count($items)) + return $items; + + if ( ! $this->_user) + return $items; + + if ( ! $libraries = $this->getBookmarkedLibraries()) + return $items; + + $libraries_ids = array_map(fn($library) => $library->getId(), $libraries); + + usort($items, function($item_1, $item_2) use ($libraries_ids) + { + if (($in_array1 = in_array($item_1->getIdBib(), $libraries_ids)) + && in_array($item_2->getIdBib(), $libraries_ids)) + return 0; + + return $in_array1 + ? -1 + : 1; + }); + + return $items; + } } diff --git a/library/ZendAfi/View/Helper/Template/AvailabilityBadge.php b/library/ZendAfi/View/Helper/Template/AvailabilityBadge.php new file mode 100644 index 0000000000000000000000000000000000000000..4e85ca997aa248953d1c4decd96ea802a368187d --- /dev/null +++ b/library/ZendAfi/View/Helper/Template/AvailabilityBadge.php @@ -0,0 +1,59 @@ +<?php +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_View_Helper_Template_AvailabilityBadge extends ZendAfi_View_Helper_BaseHelper { + public function availabilityBadge(Class_Notice $record) : string { + $item = (new Intonation_Library_Record($record))->getFirstAvailableItemByRelevance(); + $is_available = $item->isNew() + ? false + : true; + + $badge = (new Intonation_Library_AvailabilityBadge(new Intonation_Library_View_Wrapper_Record($record, + $this->view))) + ->addClass($is_available + ? 'record_available' + : 'record_not_available') + ->setImage($this->_templateIco('available', 'library')) + ->setText($this->_getDisponibilityText($is_available, $item)); + + if ( ! $is_available) + $badge->setImage($this->_templateIco('not-available', 'library')); + + return $this->view->badge($badge); + } + + + protected function _getDisponibilityText(bool $available, Class_Exemplaire $item) : string { + if ( ! $available) + return $this->_('Non disponible'); + + $available = $this->_('Disponible'); + + if ( (! $user = Class_Users::getIdentity()) + || (! $libraries = $user->getBookmarkedLibraries())) + return $available; + + return in_array($item->getIdBib(), array_map(fn($library) => $library->getId(), $libraries)) + ? $this->_('Disponible à %s', $item->getBib()->getLibelle()) + : $available; + } +} diff --git a/library/ZendAfi/View/Helper/Template/Badge.php b/library/ZendAfi/View/Helper/Template/Badge.php new file mode 100644 index 0000000000000000000000000000000000000000..7dfe42ffb1757675b15a444bfcd2b935a908b611 --- /dev/null +++ b/library/ZendAfi/View/Helper/Template/Badge.php @@ -0,0 +1,54 @@ +<?php +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class ZendAfi_View_Helper_Template_Badge extends ZendAfi_View_Helper_BaseHelper { + public function badge(Intonation_Library_Badge $badge) : string { + if (!$text = $badge->getText()) + return ''; + + if ($title = $badge->getTitle()) + $text = $this->view->screenReaderOnly(str_replace($text, '', $title)).$text; + + $attribs = ['title' => $badge->getTitle(), + 'class' => 'badge_tag ' . $badge->getClass()]; + + foreach ( $badge->getData() as $key => $value) + $attribs['data-' . $key] = $value; + + if ($url = $badge->getUrl()) + $attribs['href'] = $url; + + if ($on_click = $badge->getOnClick()) + $attribs['onclick'] = $on_click; + + $img = ($img = $badge->getImage()) + ? $img + : ''; + + return $this->_tag($badge->getTag(), + $img + . $this->view->tag('span', + $text, + ['class' => 'badge_text']), + array_filter($attribs)); + } +} diff --git a/library/ZendAfi/View/Helper/Template/BadgeGroup.php b/library/ZendAfi/View/Helper/Template/BadgeGroup.php index c5912a798bb8870f0641ee95c23a390efacd4e7f..5d6a76c6555c5abeb187cda54a3afd48e132e21a 100644 --- a/library/ZendAfi/View/Helper/Template/BadgeGroup.php +++ b/library/ZendAfi/View/Helper/Template/BadgeGroup.php @@ -23,36 +23,7 @@ class ZendAfi_View_Helper_Template_BadgeGroup extends ZendAfi_View_Helper_BaseHelper { public function badgeGroup($badges, $instance) { - $badges = - array_map(function($badge) - { - if (!$text = $badge->getText()) - return; - - if ($title = $badge->getTitle()) - $text = $this->view->screenReaderOnly(str_replace($text, '', $title)).$text; - - $attribs = ['title' => $badge->getTitle(), - 'class' => 'badge_tag ' . $badge->getClass()]; - - if ($url = $badge->getUrl()) - $attribs['href'] = $url; - - if ($on_click = $badge->getOnClick()) - $attribs['onclick'] = $on_click; - - $img = ($img = $badge->getImage()) - ? $img - : ''; - - return $this->_tag($badge->getTag(), - $img - . $this->view->tag('span', - $text, - ['class' => 'badge_text']), - array_filter($attribs)); - }, - $badges); + $badges = array_map(fn($badge) => $this->view->badge($badge), $badges); if ( $all_badges = implode(array_filter($badges))) return $this->_tag('div', diff --git a/library/templates/Intonation/Library/AjaxAvailabilityBadge.php b/library/templates/Intonation/Library/AjaxAvailabilityBadge.php new file mode 100644 index 0000000000000000000000000000000000000000..9201c61e798d5acedccc993ea3adc084376f5d55 --- /dev/null +++ b/library/templates/Intonation/Library/AjaxAvailabilityBadge.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Intonation_Library_AjaxAvailabilityBadge extends Intonation_Library_AvailabilityBadge { + + protected Intonation_Library_View_Wrapper_Record $_wrapper; + + public function __construct(Intonation_Library_View_Wrapper_Record $wrapper) { + parent::__construct($wrapper); + $this->_wrapper = $wrapper; + $this + ->addClass('availability_no_answers') + ->addClass('waiting_for_response'); + Class_ScriptLoader::getInstance()->ajaxAvailability($this); + } + + + public function getClassAsSelector() : string { + return implode('.', explode(' ', $this->getClass())); + } +} diff --git a/library/templates/Intonation/Library/AvailabilityBadge.php b/library/templates/Intonation/Library/AvailabilityBadge.php new file mode 100644 index 0000000000000000000000000000000000000000..9a66d14226b7ae10a7ccee64aa3b49c4f972103a --- /dev/null +++ b/library/templates/Intonation/Library/AvailabilityBadge.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class Intonation_Library_AvailabilityBadge extends Intonation_Library_Badge { + + use Trait_Translator; + + + public function __construct(Intonation_Library_View_Wrapper_Record $wrapper) { + $this + ->setClass('badge_record_availability record_id_' . $wrapper->getId()) + ->setData('record-id', $wrapper->getId()) + ->setText(' '); + } + + + public function addClass(string $class) : self { + return $this->setClass($this->getClass() . ' ' . $class); + } +} diff --git a/library/templates/Intonation/Library/Badge.php b/library/templates/Intonation/Library/Badge.php index 9af935cd199002a767ff30fc9cea2ee4f95b207b..ad501109301455bf9500af8d678626e379df5059 100644 --- a/library/templates/Intonation/Library/Badge.php +++ b/library/templates/Intonation/Library/Badge.php @@ -31,6 +31,8 @@ class Intonation_Library_Badge { $_url, $_on_click; + protected array $_data = []; + public function setText($text) { $this->_text = $text; @@ -107,4 +109,15 @@ class Intonation_Library_Badge { public function getOnClick() : string { return $this->_on_click ?? ''; } + + + public function setData(string $key, string $value) : self { + $this->_data[$key] = $value; + return $this; + } + + + public function getData() : array { + return $this->_data; + } } diff --git a/library/templates/Intonation/Library/Record.php b/library/templates/Intonation/Library/Record.php index 471cc5fad1feb0d7d2be7a53edaa6d33bbd6b3c3..a4ac4d1321669116a993ab69f3f624c9c713d27a 100644 --- a/library/templates/Intonation/Library/Record.php +++ b/library/templates/Intonation/Library/Record.php @@ -114,4 +114,17 @@ class Intonation_Library_Record { return $item->getHoldLink(); } ); } + + + public function getFirstAvailableItemByRelevance() : Class_Exemplaire { + $items = Class_User_Settings::newWith(Class_Users::getIdentity()) + ->sortItemsByBookmarkedLibraries($this->getItemsFromSIGB()); + return $this->_getFirstAvailable($items); + } + + + protected function _getFirstAvailable(array $items) : Class_Exemplaire { + return (new Storm_Model_Collection($items))->detect(fn($item) => $item->isDisponible()) + ?? new Class_Exemplaire; + } } diff --git a/library/templates/Intonation/Library/Settings.php b/library/templates/Intonation/Library/Settings.php index 976fee5e735e603f354ffe59486aa2b23d030458..6b71546c97818c7533e7ddc0e0efe864788766a6 100644 --- a/library/templates/Intonation/Library/Settings.php +++ b/library/templates/Intonation/Library/Settings.php @@ -349,7 +349,10 @@ class Intonation_Library_Settings extends Intonation_System_Abstract { 'div class items_shelf' => 'col-12', 'div class title_sibling_picto' => 'd-inline-block', 'h3 class tracks_source' => 'd-none', - 'div class ina_interviews' => 'card bg-dark text-white shadow' + 'div class ina_interviews' => 'card bg-dark text-white shadow', + 'span class record_not_available' => 'badge-danger', + 'span class record_available' => 'badge-success', + 'span class availability_no_answers' => 'badge-info' ], 'icons_map_doc_types' => [], diff --git a/library/templates/Intonation/Library/View/Wrapper/Record.php b/library/templates/Intonation/Library/View/Wrapper/Record.php index f8f6ae034d23f585aff263686a7c59f0cd205d44..b7e694d89ff6388149bb80121da1f13043508f6a 100644 --- a/library/templates/Intonation/Library/View/Wrapper/Record.php +++ b/library/templates/Intonation/Library/View/Wrapper/Record.php @@ -200,6 +200,8 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra ->setTitle($this->_('Affiner le résultat de recherche avec le type de document %s', $this->_model->getTypeDocLabel())))]; + $badges = $this->_addAvailableBadgeTo($badges); + $badges = $this->_addBookmarkedLibraries($badges); $badges = $this->_addUnimarcBadges($badges); @@ -230,7 +232,13 @@ class Intonation_Library_View_Wrapper_Record extends Intonation_Library_View_Wra $badges = $this->_addSearchByWorkBadges($badges); - return $this->_badges = $this->_view->badgeGroup($badges,$this); + return $this->_badges = $this->_view->badgeGroup($badges, $this); + } + + + protected function _addAvailableBadgeTo(array $badges) : array { + $badges[] = new Intonation_Library_AjaxAvailabilityBadge($this); + return $badges; } diff --git a/library/templates/Intonation/View/RenderRecord/RenderItems.php b/library/templates/Intonation/View/RenderRecord/RenderItems.php index c29dc0ce82ef3de7023fce8a70082c1a5b71fb23..b02e7d28357edb3abee797d4f1e7c2296ead0aa1 100644 --- a/library/templates/Intonation/View/RenderRecord/RenderItems.php +++ b/library/templates/Intonation/View/RenderRecord/RenderItems.php @@ -36,9 +36,8 @@ class Intonation_View_RenderRecord_RenderItems extends ZendAfi_View_Helper_BaseH $first_item = reset($items); $record = new Intonation_Library_Record($first_item->getNotice()); - if ($first_item->isTypeSerialArticle()){ + if ($first_item->isTypeSerialArticle()) $items = $first_item->getLinkedSerialItems(); - } return $record->isExternalResource() ? $this->view->RenderRecord_ExternalUrl($record->getUrl()) @@ -309,8 +308,8 @@ abstract class Intonation_View_RenderRecord_RenderItemsStrategy { -class Intonation_View_RenderRecord_RenderItemsStrategyMap extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyMap + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -334,8 +333,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyMap extends -class Intonation_View_RenderRecord_RenderItemsStrategyPagination extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyPagination + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -363,8 +362,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyPagination extends -class Intonation_View_RenderRecord_RenderItemsStrategyILS extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyILS + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -392,8 +391,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyILS extends -class Intonation_View_RenderRecord_RenderItemsStrategyILSAndPagination extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyILSAndPagination + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -426,8 +425,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyILSAndPagination extends -class Intonation_View_RenderRecord_RenderItemsStrategyMapAndILSAndPagination extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyMapAndILSAndPagination + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -448,8 +447,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyMapAndILSAndPagination ext -class Intonation_View_RenderRecord_RenderItemsStrategyMapAndPagination extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyMapAndPagination + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -470,8 +469,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyMapAndPagination extends -class Intonation_View_RenderRecord_RenderItemsStrategyNoMapNoILSNoPagination extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyNoMapNoILSNoPagination + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { @@ -492,8 +491,8 @@ class Intonation_View_RenderRecord_RenderItemsStrategyNoMapNoILSNoPagination ext -class Intonation_View_RenderRecord_RenderItemsStrategyMapAndILS extends - Intonation_View_RenderRecord_RenderItemsStrategy { +class Intonation_View_RenderRecord_RenderItemsStrategyMapAndILS + extends Intonation_View_RenderRecord_RenderItemsStrategy { public function renderItems(array $items, array $same_work, array $html) : array { diff --git a/public/opac/css/core.css b/public/opac/css/core.css index d8d51645386a4daa35ea3ebbb86046d4ad494ef0..4e89400a57fc46daced5ec04b6ebc2eae4bdedf4 100644 --- a/public/opac/css/core.css +++ b/public/opac/css/core.css @@ -229,3 +229,12 @@ body[data-admin_level=""] [data-level="expert"] { .whitespace_after:not(:last-child):after { content: ' '; } + +.badge_record_availability.waiting_for_response { + padding: 0; + margin: 0; +} + +.badge_record_availability.waiting_for_response > .badge_text { + height: 0; + width: 0; diff --git a/public/opac/js/ajaxAvailability/ajax_availability.js b/public/opac/js/ajaxAvailability/ajax_availability.js new file mode 100644 index 0000000000000000000000000000000000000000..0803400d0b5f58f8444e36a2cdd2f6d0929d8e02 --- /dev/null +++ b/public/opac/js/ajaxAvailability/ajax_availability.js @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +(function ( $ ) { + $.fn.ajax_availability = function () { + var badge = $(this); + var replaceBadge = function() { + if ( ! badge.hasClass('availability_no_answers')) + return; + + if (! (($(window).height() + $(window).scrollTop()) > badge.offset().top)) + return; + + if (badge.is("hidden")) + return; + + if ('none' === badge.css('display')) + return; + + badge.removeClass("availability_no_answers"); + + $.ajax({url: "/noticeajax/availability/id/" + badge.attr('data-record-id'), + success: function(html) { + badge.replaceWith($(html)); + }}); + }; + + $(window).scroll(function() { return replaceBadge(); }); + replaceBadge(); + } +} (jQuery)); diff --git a/public/opac/js/ajaxAvailability/ajax_availability_tests.html b/public/opac/js/ajaxAvailability/ajax_availability_tests.html new file mode 100644 index 0000000000000000000000000000000000000000..c04a651aa406c85287b8836f343d4d63bbb1598e --- /dev/null +++ b/public/opac/js/ajaxAvailability/ajax_availability_tests.html @@ -0,0 +1,65 @@ +<!DOCTYPE html> +<!-- + /** + * Copyright (c) 2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + --> +<html> + <head> + <meta charset="utf-8"> + <title>Ajax availability QUnit tests</title> + <link rel="stylesheet" href="../../../qunit-git.css"> + + <script src="../subModal.js"></script> + <script src="../../../admin/js/onload_utils.js"></script> + <script src="../../../tarteaucitron/tarteaucitron.js"></script> + <script src="../../../qunit-1.13.0.js"></script> + <script src="../../../admin/js/jquery-3.6.0.min.js"></script> + + <script src="ajax_availability.js"></script> + <script src="ajax_availability_tests.js"></script> + <style>.record_id_3 { display: none;} </style> + </head> + <body> + <div id="qunit"></div> + <div id="test"> + <div class="badge-group badge_group badge_group_Intonation_Library_View_Wrapper_Record"> + <span title="Disponibilité du document : Lanfeust Odyssey n° 10 Un destin Karaxastin" class="badge_tag badge_record_availability record_id_1 availability_no_answers text-left badge" data-record-id="1"> + <i class="far fa-check-circle library" aria-hidden="true"></i> + <span class="badge_text align-middle d-inline-block text-left"> + + </span> + </span> + <span title="Disponibilité du document : Lanfeust Odyssey n° 7 La méphitique armada" class="badge_tag badge_record_availability record_id_2 availability_no_answers text-left badge" data-record-id="2"> + <i class="far fa-check-circle library" aria-hidden="true"></i> + <span class="badge_text align-middle d-inline-block text-left"> + + </span> + </span> + <span title="Disponibilité du document : Lanfeust Odyssey n° 6 Cixi impératrice" class="badge_tag badge_record_availability record_id_3 availability_no_answers text-left badge " data-record-id="3"> + <i class="far fa-check-circle library" aria-hidden="true"></i> + <span class="badge_text align-middle d-inline-block text-left"> + + </span> + </span> + </div> + </div> + </body> +</head> +</html> diff --git a/public/opac/js/ajaxAvailability/ajax_availability_tests.js b/public/opac/js/ajaxAvailability/ajax_availability_tests.js new file mode 100644 index 0000000000000000000000000000000000000000..0a5c4d258af562fd9895f2d662fe71fa7c9baaed --- /dev/null +++ b/public/opac/js/ajaxAvailability/ajax_availability_tests.js @@ -0,0 +1,52 @@ +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +QUnit.module('ajaxAvailability'); + +var html_fixture; +var availability_badge; + +moduleStart( function() { + html_fixture = $("#test")[0].outerHTML; +}); + + +testStart( function() { + $('#test').replaceWith(html_fixture); + availability_badge = $('.badge_record_availability'); +}); + + +test('availabitity badges should have availability_no_answers class', function() { + deepEqual($('.badge_record_availability').hasClass('availability_no_answers'), true); +}); + + +test('availabitity badges should not have availability_no_answers class', function() { + availability_badge.ajax_availability(); + deepEqual($('.badge_record_availability.record_id_1, .badge_record_availability.record_id_2').hasClass('availability_no_answers'), false); +}); + + +test('cixi l\'impératrice availabitity badges should have availability_no_answers class', function() { + $('.badge_record_availability.record_id_3').ajax_availability(); + deepEqual($('.badge_record_availability.record_id_3').hasClass('availability_no_answers'), true); +}); diff --git a/tests/js/AjaxAvailability.php b/tests/js/AjaxAvailability.php new file mode 100644 index 0000000000000000000000000000000000000000..4ba79717b19b14ac265bbb60ec053127d5bafd9e --- /dev/null +++ b/tests/js/AjaxAvailability.php @@ -0,0 +1,25 @@ +<?php +/** + * Copyright (c) 2012-2022, Agence Française Informatique (AFI). All rights reserved. + * + * BOKEH is free software; you can redistribute it and/or modify + * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by + * the Free Software Foundation. + * + * There are special exceptions to the terms and conditions of the AGPL as it + * is applied to this software (see README file). + * + * BOKEH 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 AFFERO GENERAL PUBLIC LICENSE for more details. + * + * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE + * along with BOKEH; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +class AjaxAvailability extends BrowserTest { + protected $_test_path = 'public/opac/js/ajaxAvailability/ajax_availability_tests.html'; +} diff --git a/tests/scenarios/Templates/TemplatesRecordsTest.php b/tests/scenarios/Templates/TemplatesRecordsTest.php index f8c01e55c1c7ef82f2ab8b21e18d08b320dd6a22..5871bbaa2473d194af447e36d8c952f6ca9fd453 100644 --- a/tests/scenarios/Templates/TemplatesRecordsTest.php +++ b/tests/scenarios/Templates/TemplatesRecordsTest.php @@ -1726,4 +1726,144 @@ class TemplatesRecordsUpdateDispatchViewnoticeTest extends TemplatesRecordsInteg public function publicationDateBadgeShouldBe2019() { $this->assertXPathContentContains('//main//div//a[@class="badge_tag record_edition_year text-left badge badge-dark"]', '2019'); } +} + + + + +abstract class TemplatesRecordsNoticeajaxAvailabilityTestCase extends AbstractControllerTestCase { + + public function setUp() { + parent::setUp(); + $this->_buildTemplateProfil(['id' => 3]); + + $this->fixture(Class_Notice::class, + ['id' => 1]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 1, + 'id_notice' => 1]); + + $this->fixture(Class_Notice::class, + ['id' => 2, + 'type_doc' => 101]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 2, + 'id_notice' => 2]); + } +} + + + +class TemplatesRecordsNoticeajaxAvailabilityTest extends TemplatesRecordsNoticeajaxAvailabilityTestCase { + + /** @test */ + public function withRecordIdOneShouldRenderNotAvailableBadge() { + $this->dispatch('noticeajax/availability/id/1'); + $this->assertXPathContentContains('//span[@class="badge_tag badge_record_availability record_id_1 record_not_available text-left badge badge-danger"][@data-record-id="1"]', 'Non disponible'); + } + + + /** @test */ + public function withRecordIdTwoShouldRenderAvailableBadge() { + $this->dispatch('noticeajax/availability/id/2'); + $this->assertXPath('//span[@class="badge_tag badge_record_availability record_id_2 record_available text-left badge badge-success"][@data-record-id="2"]'); + } + + + /** @test */ + public function dispatchViewNoticeShouldRenderBadgeAvailability() { + $this->dispatch('recherche/viewnotice/id/1'); + $this->assertXPath('//span[@class="badge_tag badge_record_availability record_id_1 availability_no_answers waiting_for_response text-left badge badge-info"][@data-record-id="1"]'); + } + + + /** @test */ + public function dispatchViewNoticeShouldAddScriptFileAjaxAvailibitity() { + $this->dispatch('recherche/viewnotice/id/1'); + $this->assertXPath('//script[contains(@src, "public/opac/js/ajaxAvailability/ajax_availability.js")]'); + } + + + /** @test */ + public function dispatchViewNoticeShouldAddScriptAjaxAvailibitityOnRecordOne() { + $this->dispatch('recherche/viewnotice/id/1'); + $this->assertXPathContentContains('//script', '$(function(){$(".badge_record_availability.record_id_1.availability_no_answers.waiting_for_response").ajax_availability();});'); + } +} + + + + +class TemplatesRecordsNoticeajaxAvailabilityByRelevanceTest extends TemplatesRecordsNoticeajaxAvailabilityTestCase { + + public function setUp() { + parent::setUp(); + + $this->fixture(Class_Bib::class, + ['id' => 7, + 'libelle' => 'Nyon']); + + $this->fixture(Class_IntBib::class, + ['id' => 7, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'https://nanook-ws.fr']]); + + $this->fixture(Class_Bib::class, + ['id' => 8, + 'libelle' => 'Gland']); + + $this->fixture(Class_IntBib::class, + ['id' => 8, + 'comm_sigb' => Class_IntBib::COM_NANOOK, + 'comm_params' => ['url_serveur' => 'https://nanook-ws.fr']]); + + $abonne = + $this->fixture(Class_Users::class, + ['id' => 5, + 'login' => 'abonné', + 'password' => 'avec une bib favorie', + 'id_site' => 8, + 'idabon' => '125', + 'role_level' => ZendAfi_Acl_AdminControllerRoles::ABONNE_SIGB]) + ->setBookmarkedLibraries([8]); + + $abonne->save(); + + ZendAfi_Auth::getInstance()->logUser($abonne); + + $this->fixture(Class_Notice::class, + ['id' => 10]); + + $this->fixture(Class_Exemplaire::class, + ['id' => 9, + 'id_notice' => 10, + 'id_bib' => 7, + 'id_int_bib' => 7]) + ->setSigbExemplaire((new Class_WebService_SIGB_Exemplaire(9))->setDisponibiliteLibre()); + + $this->fixture(Class_Exemplaire::class, + ['id' => 10, + 'id_notice' => 10, + 'id_bib' => 8, + 'id_int_bib' => 8]) + ->setSigbExemplaire((new Class_WebService_SIGB_Exemplaire(10))->setDisponibiliteLibre()); + } + + + /** @test */ + public function withRecordIdThreeShouldRenderAvailableBadge() { + Class_AdminVar::set('ENABLE_BOOKMARKABLE_LIBRARIES', 0); + $this->dispatch('noticeajax/availability/id/10'); + $this->assertXPathContentContains('//span[@class="badge_tag badge_record_availability record_id_10 record_available text-left badge badge-success"][@data-record-id="10"]', 'Disponible'); + } + + + /** @test */ + public function withRecordIdTenAndBookmarkedLibrariesReadyShouldRenderAvailableInMyLibraryBadge() { + Class_AdminVar::set('ENABLE_BOOKMARKABLE_LIBRARIES', 1); + $this->dispatch('noticeajax/availability/id/10'); + $this->assertXPathContentContains('//span[@class="badge_tag badge_record_availability record_id_10 record_available text-left badge badge-success"]', utf8_encode('Disponible à Gland')); + } } \ No newline at end of file