diff --git a/local/config/vufind/FincILS.ini b/local/config/vufind/FincILS.ini index 93e8a4feddd6d36b3b6ae14e90a73a792bc06631..f7bc8fa461580f94c5b2d7657e53f79b6c07b590 100644 --- a/local/config/vufind/FincILS.ini +++ b/local/config/vufind/FincILS.ini @@ -1,5 +1,8 @@ ; General configuration [General] +; Set the time to live (ttl) for cached data (default is 30 seconds). +;cacheLifetime = 90 + ; This setting defines the connection timeout for testing the availability of the ILS ; in seconds (default is 1 second). ilsTestTimeout = 30 @@ -13,6 +16,12 @@ queryIls[] = 'getFacetAvail:Local' ;[DAIA] ; The base URL for the DAIA webservice. ;baseUrl = "http://localhost/daiawachtl/daia/" + +; Set a DAIA specific timeout in seconds to be used for DAIA http requests (defaults +; to Zend defaults or as defined in +; vendor/vufind-org/vufindhttp/src/VuFindHttp/HttpService.php) +;timeout = 30 + ; The prefix prepended to the VuFind record Id resulting in the document URI ; used for the DAIA request (default = ppn:) (the prefix usually defines the ; field which the DAIA server uses for the loookup - e.g. ppn: or isbn:). @@ -22,7 +31,7 @@ queryIls[] = 'getFacetAvail:Local' ;daiaResponseFormat = json ; Set multiQuery to true if your DAIA webservice supports queries with multiple -; ids (cf. http://gbv.github.io/daiaspec/daia.html#query-api). +; ids (cf. https://gbv.github.io/daia/daia.html#query-parameters). ; Default is false. ;multiQuery = false @@ -31,7 +40,7 @@ queryIls[] = 'getFacetAvail:Local' ; daiaContentTypes is not set, Content-Type HTTP header is NOT checked. ; ; expected Content-Types for DAIA XML format: -; (seperate multiple values by commata, for example: +; (separate multiple values by commas, for example: ; daiaContentTypes['xml'] = "application/xml, text/xml" ;daiaContentTypes['xml'] = "application/xml" @@ -43,8 +52,17 @@ queryIls[] = 'getFacetAvail:Local' ; Enable caching for DAIA items (default is false). ;daiaCache = false -; Set the time to live (ttl) for cached DAIA data (default is 30 seconds). -;daiaCacheLifetime = 90 +; DAIA does not support placing holds (this functionality is covered by PAIA) but is +; able to provide a link to the OPAC to perform such an action. Regarding placing +; holds/recalls such link is usually given as href for an unavailable service. +; Uncomment the below section Holds with the setting 'function' to show a link to +; the OPAC (if it was provided in the DAIA response) instead of a VuFind +; Holds-Button. +; If PAIA is used in combination with the DAIA driver, handling holds etc. should be +; left to the logic in the PAIA driver - thus keep this section commented out if you +; are using PAIA as well. +; [Holds] +; function = getHoldLink ;FincILS configuration ; refer to ticket #4499 for further info on configuring it @@ -60,7 +78,8 @@ queryIls[] = 'getFacetAvail:Local' ; vendor/vufind-org/vufindhttp/src/VuFindHttp/HttpService.php) ;timeout = 30 -; Enable caching for PAIA items (default is false). +; Enable caching for PAIA items (default is false). TTL for cached data will be the +; same as for DAIA cache (see cacheLifetime setting in DAIA.ini). ;paiaCache = false ; A PAIA auth server acts as OAuth authorization server (RFC 6749) with @@ -84,6 +103,66 @@ queryIls[] = 'getFacetAvail:Local' ;root_username = 'root' ;root_password = '' +; Driver configuration, usually you can leave it untouched + +; Without customization the PAIA driver will offer to place a recall for items with +; unavailable service loan but set href for loan. The recall will be performed via +; PAIA request. +; The pre-defined HMACKeys (id:item_id:doc_id) should suffice to place a recall. No +; extra fields are allowed (if you need those you might be able to cover this +; functionality in a custom driver by using PAIA confirm/conditions). +[Holds] +; HMACKeys - A list of form element names that will be analyzed for consistency +; during form processing. Most users should not need to change this setting. +HMACKeys = "id:item_id:doc_id" + +; PAIA status which should be mapped to Holds +; status are: 1 = reserved (not available yet but later) +; 2 = ordered (and not yet ready to be picked up) +; 3 = held by patron +; 4 = provided (and ready to be picked up) +status = "1:4" + +; Without customization the PAIA driver will offer to place a storageretrievalrequest +; for items with available service loan and set href for loan. The +; storageretrievalrequest will be performed via PAIA request (technically the same as +; for recall, but with different frontend templates etc.). +; The pre-defined HMACKeys (id:item_id:doc_id) should suffice to request an item. No +; extra fields are allowed (if you need those you might be able to cover this +; functionality in a custom driver by using PAIA confirm/conditions). +[StorageRetrievalRequests] +; HMACKeys - A list of form element names that will be analyzed for consistency +; during form processing. Most users should not need to change this setting. +HMACKeys = id:item_id:doc_id + +; PAIA status which should be mapped to StorageRetrievalRequests +; status are: 1 = reserved (not available yet but later) +; 2 = ordered (and not yet ready to be picked up) +; 3 = held by patron +; 4 = provided (and ready to be picked up) +status = "2" + +; All kinds of transactions by a specific patron. Transactions are eg checked out +; items +[Transactions] +; PAIA status which should be mapped to Transactions +; status are: 1 = reserved (not available yet but later) +; 2 = ordered (and not yet ready to be picked up) +; 3 = held by patron +; 4 = provided (and ready to be picked up) +status = "3" + +; The PAIA driver supports renewals in MyResearch views. The renewal will be +; performed via PAIA renew. +; The pre-defined HMACKeys (id:item_id:doc_id) should suffice to renew an item. No +; extra fields are allowed (if you need those you might be able to cover this +; functionality in a custom driver by using PAIA confirm/conditions). +[Renewals] +; HMACKeys - A list of form element names that will be analyzed for consistency +; during form processing. Most users should not need to change this setting. +HMACKeys = "id:item_id:doc_id" + +; FincILS specific ; Enable EmailHold to allow placing orders via Email instead of direct ILS ; interaction. ;[EmailHold] diff --git a/local/config/vufind/facets.ini b/local/config/vufind/facets.ini index f13fa9bd50dc06e39dcdb7cded6c5405aa3994c2..bd6a48cea17b71d7dcb6bd7a75c3171580ee8b64 100644 --- a/local/config/vufind/facets.ini +++ b/local/config/vufind/facets.ini @@ -236,6 +236,7 @@ special_facets = "daterange" translated_facets[] = format translated_facets[] = language translated_facets[] = mega_collection +translated_facets[] = finc_class_facet ; Any facets named here will be treated as a delimited facet. ; Delimited facets can be used to display a text value for otherwise incomprehensible @@ -309,6 +310,12 @@ hide_facets = "genre_facet,era_facet,geographic_facet" [SortedByIndex] ;index[] = format +[Results_Settings] +; By default, how many values should we show for each facet? (-1 for no limit) +;facet_limit = 30 +; Override facet_limit on a per-field basis using this array: +facet_limit_by_field[publishDateSort] = -1 + ; Special terms (key), which can't / shouldn't be translated but marked as other language (value) for BARF reasons [LanguageTags] en[] = "American Museum of Natural History" diff --git a/local/languages/de.ini b/local/languages/de.ini index c0d4b806d03fb7b45848a9c0ca6d142764a1f556..7980b367eac6fd631c9e651c394ed37fdf924281 100644 --- a/local/languages/de.ini +++ b/local/languages/de.ini @@ -199,6 +199,7 @@ Ask a Librarian = "Frage an die Bibliothek" Audience = Zielpublikum Author = "Person / Institution" Available = Verfügbar +Available_Via = Verfügbar über Available Stock = Verfügbarer Bestand Awards = Auszeichnungen Back = Zurück @@ -359,6 +360,7 @@ Library = Bibliothek Library Regulations = Benutzungsordnung Limit To = "Begrenze auf" Link to = "Zur Webseite" +Link-to = "Link zum" List of new items = "Neuerwerbungsliste" Local Holdings = "Lokale Bestände" Local Subjects = "Lokale Schlagwörter" diff --git a/local/languages/en.ini b/local/languages/en.ini index e478706d99d221ea711ea4b766014e6c03389357..ee7ffca62fa7102466cbe0188d26d3b006558ec4 100644 --- a/local/languages/en.ini +++ b/local/languages/en.ini @@ -337,6 +337,7 @@ Audience = Audience # Author = Creator Author = "Author / Corporation" Available = Available +Available_Via = available via Awards = Awards Back = Back Backtrace = Backtrace @@ -460,6 +461,7 @@ Library = Library Library Catalog Username = "Library Catalog User Name" Limit To = "Limit to" Link to = "To Website" +Link-to = "Link to" List = List Loading = Loading Located = Located diff --git a/module/finc/src/finc/AjaxHandler/GetRecordCover.php b/module/finc/src/finc/AjaxHandler/GetRecordCover.php index 8c6333421a14867637c08a4ce3308124bf026029..5555926d6e7b9e235edacc918c4df16b42c444c3 100644 --- a/module/finc/src/finc/AjaxHandler/GetRecordCover.php +++ b/module/finc/src/finc/AjaxHandler/GetRecordCover.php @@ -139,13 +139,6 @@ class GetRecordCover extends AbstractBase implements AjaxHandlerInterface return ($url || !$this->renderer || !$this->useCoverFallbacksOnFail) ? $this->formatResponse(compact('url', 'size')) - : $this->formatResponse( - [ - 'html' => $this->renderer->render( - 'record/coverReplacement', - ['driver' => $record] - ) - ] - ); + : [""]; } } diff --git a/module/finc/src/finc/Controller/HoldsTrait.php b/module/finc/src/finc/Controller/HoldsTrait.php index 6190199a96e3400917abea11cabb5cb7fefde9b0..0f410598ee9246474a84f711a82d0a4ec4cb41eb 100644 --- a/module/finc/src/finc/Controller/HoldsTrait.php +++ b/module/finc/src/finc/Controller/HoldsTrait.php @@ -2,7 +2,7 @@ /** * Holds trait (for subclasses of AbstractRecord) * - * PHP version 5 + * PHP version 7 * * Copyright (C) Villanova University 2010. * @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * @category VuFind * @package Controller @@ -38,17 +38,6 @@ namespace finc\Controller; */ trait HoldsTrait { - /** - * Action for dealing with blocked holds. - * - * @return mixed - */ - public function blockedholdAction() - { - $this->flashMessenger()->addMessage('hold_error_blocked', 'error'); - return $this->redirectToRecord('#top'); - } - /** * Action for dealing with holds. * @@ -84,23 +73,31 @@ trait HoldsTrait } // Block invalid requests: - if (!$catalog->checkRequestIsValid( + $validRequest = $catalog->checkRequestIsValid( $driver->getUniqueID(), $gatheredDetails, $patron - )) { - return $this->blockedholdAction(); + ); + if ((is_array($validRequest) && !$validRequest['valid']) || !$validRequest) { + $this->flashMessenger()->addErrorMessage( + is_array($validRequest) + ? $validRequest['status'] : 'hold_error_blocked' + ); + return $this->redirectToRecord('#top'); } // Send various values to the view so we can build the form: $requestGroups = $catalog->checkCapability( - 'getRequestGroups', [$driver->getUniqueID(), $patron] - ) ? $catalog->getRequestGroups($driver->getUniqueID(), $patron) : []; + 'getRequestGroups', [$driver->getUniqueID(), $patron, $gatheredDetails] + ) ? $catalog->getRequestGroups( + $driver->getUniqueID(), $patron, $gatheredDetails + ) : []; $extraHoldFields = isset($checkHolds['extraHoldFields']) ? explode(":", $checkHolds['extraHoldFields']) : []; $requestGroupNeeded = in_array('requestGroup', $extraHoldFields) && !empty($requestGroups) && (empty($gatheredDetails['level']) - || $gatheredDetails['level'] != 'copy'); + || ($gatheredDetails['level'] != 'copy' + || count($requestGroups) > 1)); $pickupDetails = $gatheredDetails; if (!$requestGroupNeeded && !empty($requestGroups) @@ -113,18 +110,20 @@ trait HoldsTrait $pickup = $catalog->getPickUpLocations($patron, $pickupDetails); // Process form submissions if necessary: - if (!is_null($this->params()->fromPost('placeHold'))) { + if (null !== $this->params()->fromPost('placeHold')) { // If the form contained a pickup location or request group, make sure // they are valid: - $valid = $this->holds()->validateRequestGroupInput( + $validGroup = $this->holds()->validateRequestGroupInput( $gatheredDetails, $extraHoldFields, $requestGroups ); - if (!$valid) { + $validPickup = $validGroup && $this->holds()->validatePickUpInput( + $gatheredDetails['pickUpLocation'] ?? null, + $extraHoldFields, $pickup + ); + if (!$validGroup) { $this->flashMessenger() ->addMessage('hold_invalid_request_group', 'error'); - } elseif (!$this->holds()->validatePickUpInput( - $gatheredDetails['pickUpLocation'], $extraHoldFields, $pickup - )) { + } elseif (!$validPickup) { $this->flashMessenger()->addMessage('hold_invalid_pickup', 'error'); } else { // If we made it this far, we're ready to place the hold; @@ -146,7 +145,7 @@ trait HoldsTrait '%%url%%' => $this->url()->fromRoute('myresearch-holds') ], ]; - $this->flashMessenger()->addMessage(isset($results['sysMessage']) ? $results['sysMessage'] : $msg, 'success'); + $this->flashMessenger()->addMessage($results['sysMessage'] ?? $msg, 'success'); return $this->redirectToRecord('#top'); } else { // Failure: use flash messenger to display messages, stay on @@ -167,7 +166,7 @@ trait HoldsTrait $defaultRequired = $this->holds()->getDefaultRequiredDate( $checkHolds, $catalog, $patron, $gatheredDetails ); - $defaultRequired = $this->serviceLocator->get('VuFind\DateConverter') + $defaultRequired = $this->serviceLocator->get(\VuFind\Date\Converter::class) ->convertToDisplayDate("U", $defaultRequired); try { $defaultPickup @@ -183,19 +182,21 @@ trait HoldsTrait $defaultRequestGroup = false; } + $config = $this->getConfig(); + $allowHomeLibrary = $config->Account->set_home_library ?? true; $view = $this->createViewModel( [ 'gatheredDetails' => $gatheredDetails, 'pickup' => $pickup, 'defaultPickup' => $defaultPickup, - 'homeLibrary' => $this->getUser()->home_library, + 'homeLibrary' => $allowHomeLibrary + ? $this->getUser()->home_library : '', 'extraHoldFields' => $extraHoldFields, 'defaultRequiredDate' => $defaultRequired, 'requestGroups' => $requestGroups, 'defaultRequestGroup' => $defaultRequestGroup, 'requestGroupNeeded' => $requestGroupNeeded, - 'helpText' => isset($checkHolds['helpText']) - ? $checkHolds['helpText'] : null + 'helpText' => $checkHolds['helpText'] ?? null ] ); $view->setTemplate('record/hold'); diff --git a/module/finc/src/finc/ILS/Connection.php b/module/finc/src/finc/ILS/Connection.php index a7f05faf35fdc579c430ccbc362c746858fe0187..2fe8401af447bc639eac7cdc7f73c73ae5ddb913 100644 --- a/module/finc/src/finc/ILS/Connection.php +++ b/module/finc/src/finc/ILS/Connection.php @@ -33,8 +33,6 @@ */ namespace finc\ILS; -use VuFind\Exception\ILS as ILSException; -use VuFind\ILS\Driver\DriverInterface; use VuFind\I18n\Translator\TranslatorAwareInterface; /** diff --git a/module/finc/src/finc/ILS/Driver/FincILS.php b/module/finc/src/finc/ILS/Driver/FincILS.php index fb1e390e34fed1d3ad28441098dbaef53e371994..6eab90c6eea0d407403fddcaa95df5435fe46db3 100644 --- a/module/finc/src/finc/ILS/Driver/FincILS.php +++ b/module/finc/src/finc/ILS/Driver/FincILS.php @@ -37,6 +37,7 @@ use VuFind\Exception\ILS as ILSException; use VuFindSearch\Service as SearchService; use Zend\Log\LoggerAwareInterface as LoggerAwareInterface; + /** * Finc specific ILS Driver for VuFind, using PAIA and DAIA services. * @@ -162,6 +163,13 @@ class FincILS extends PAIA implements LoggerAwareInterface */ protected $auth; + /** + * Array of records + * + * @var array + */ + protected $recordCache = []; + /** * Constructor * @@ -1130,6 +1138,11 @@ class FincILS extends PAIA implements LoggerAwareInterface */ protected function paiaGetItems($patron, $filter = []) { + // check if user has appropriate scope + if (!$this->paiaCheckScope(self::SCOPE_READ_ITEMS)) { + throw new ILSException('You are not entitled to read items.'); + } + // check for existing data in cache if ($this->paiaCacheEnabled) { $itemsResponse = $this->getCachedData($patron['cat_username']); @@ -1515,7 +1528,7 @@ class FincILS extends PAIA implements LoggerAwareInterface */ protected function getRecord($id) { - return $this->recordLoader->load($id); + return $this->recordCache[$id] ?? $this->recordCache[$id] = $this->recordLoader->load($id); } /** diff --git a/module/finc/src/finc/ILS/Driver/PAIA.php b/module/finc/src/finc/ILS/Driver/PAIA.php index 7e38e65ccbbd09bd86e9b271e3d8b4aea613b11c..39aca6e9c61dd4d78d83216be122c2f8efefc04d 100644 --- a/module/finc/src/finc/ILS/Driver/PAIA.php +++ b/module/finc/src/finc/ILS/Driver/PAIA.php @@ -304,13 +304,23 @@ class PAIA extends \VuFind\ILS\Driver\PAIA throw new ILSException('You are not entitled to read fees.'); } - try { - $fees = $this->paiaGetAsArray( - 'core/' . $patron['cat_username'] . '/fees' - ); - } catch (\Exception $e) { - // all error handling is done in paiaHandleErrors so pass on the excpetion - throw $e; + if ($this->paiaCacheEnabled) { + $fees = $this->getCachedData($this->_feesCacheKey($patron)); + } + + if (!isset($fees) || $fees == null) { + try { + $fees = $this->paiaGetAsArray( + 'core/' . $patron['cat_username'] . '/fees' + ); + } catch (\Exception $e) { + // all error handling is done in paiaHandleErrors so pass on the excpetion + throw $e; + } + + if ($this->paiaCacheEnabled) { + $this->putCachedData($this->_feesCacheKey($patron), $fees); + } } // PAIA simple data type money: a monetary value with currency (format @@ -576,6 +586,10 @@ class PAIA extends \VuFind\ILS\Driver\PAIA if ($this->daiaCacheEnabled) { $this->removeCachedData($holdDetails['doc_id']); } + + if ($this->paiaCacheEnabled) { + $this->removeCachedData($patron['cat_username']); + } } } } @@ -755,18 +769,34 @@ class PAIA extends \VuFind\ILS\Driver\PAIA } /** - * Helper function to generate cache key - * @param array $patron + * Helper function to generate cache key for fees. + * + * @param array $patron Array with patron information + * * @return string */ - private function notificationsCacheKey($patron) + private function _feesCacheKey($patron) + { + return $patron['cat_username'] . '_fees'; + } + + /** + * Helper function to generate cache key for notifications. + * + * @param array $patron Array with patron information + * + * @return string + */ + private function _notificationsCacheKey($patron) { return $patron['cat_username'] . '_notifications'; } /** * Helper function to retrieve notification ID + * * @param string $messageId + * * @return string */ protected function getPaiaNotificationsId($messageId) @@ -797,8 +827,8 @@ class PAIA extends \VuFind\ILS\Driver\PAIA } if ($this->paiaCacheEnabled) { - $response = $this->getCachedData($this->notificationsCacheKey($patron)); - if (!empty($response)) { + $response = $this->getCachedData($this->_notificationsCacheKey($patron)); + if ($response !== null) { return $response; } } @@ -833,7 +863,7 @@ class PAIA extends \VuFind\ILS\Driver\PAIA } if ($this->paiaCacheEnabled) { - $this->putCachedData($this->notificationsCacheKey($patron), $response); + $this->putCachedData($this->_notificationsCacheKey($patron), $response); } return $response; @@ -866,7 +896,7 @@ class PAIA extends \VuFind\ILS\Driver\PAIA } if (!$keepCache && $this->paiaCacheEnabled) { - $this->removeCachedData($this->notificationsCacheKey($patron)); + $this->removeCachedData($this->_notificationsCacheKey($patron)); } return $response; @@ -887,7 +917,7 @@ class PAIA extends \VuFind\ILS\Driver\PAIA } if ($this->paiaCacheEnabled) { - $this->removeCachedData($this->notificationsCacheKey($patron)); + $this->removeCachedData($this->_notificationsCacheKey($patron)); } return true; @@ -1384,19 +1414,26 @@ class PAIA extends \VuFind\ILS\Driver\PAIA throw new ILSException('You are not entitled to read patron.'); } - $responseJson = $this->paiaGetRequest( - 'core/' . $patron, - $this->getSession()->access_token - ); + $cacheKey = function ($patron) { + return $patron . '_user_details'; + }; - try { - $responseArray = $this->paiaParseJsonAsArray($responseJson); - } catch (ILSException $e) { - // all error handling is done in paiaHandleErrors so pass on the - // excpetion - throw $e; + $response = null; + + if ($this->paiaCacheEnabled) { + $response = $this->getCachedData($cacheKey($patron)); } - return $this->paiaParseUserDetails($patron, $responseArray); + + if ($response === null) { + // all error handling is done in paiaHandleErrors so pass on the excpetion + $response = $this->paiaGetAsArray('core/' . $patron); + + if ($this->paiaCacheEnabled) { + $this->putCachedData($cacheKey($patron), $response); + } + } + + return $this->paiaParseUserDetails($patron, $response); } /** diff --git a/module/finc/src/finc/ILS/Logic/Holds.php b/module/finc/src/finc/ILS/Logic/Holds.php index 0b7d745c965d079c3d3fff0fcbfe45e036bc4cce..4687058931355da31dc434201d1ecf8c4a2769fe 100644 --- a/module/finc/src/finc/ILS/Logic/Holds.php +++ b/module/finc/src/finc/ILS/Logic/Holds.php @@ -28,7 +28,6 @@ * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License * @link https://vufind.org/wiki/development Wiki */ - namespace finc\ILS\Logic; use VuFind\Exception\ILS as ILSException; diff --git a/module/finc/src/finc/View/Helper/Root/EnhancedRenderArray.php b/module/finc/src/finc/View/Helper/Root/EnhancedRenderArray.php index f2cd204de7f9d8c76795c8741306d01eb3e49836..3979230f556eca19752e6616b9fe6b9299ca6bad 100644 --- a/module/finc/src/finc/View/Helper/Root/EnhancedRenderArray.php +++ b/module/finc/src/finc/View/Helper/Root/EnhancedRenderArray.php @@ -27,6 +27,7 @@ * @link https://vufind.org/wiki/development Wiki */ namespace finc\View\Helper\Root; + use Zend\View\Helper\AbstractHelper; /** diff --git a/module/finc/src/finc/View/Helper/Root/Record.php b/module/finc/src/finc/View/Helper/Root/Record.php index 76d54ff47774e4edb3c8f5c8f82ab59a5658c935..c7117e000c20d159e2d93575dfd7706d58610e12 100644 --- a/module/finc/src/finc/View/Helper/Root/Record.php +++ b/module/finc/src/finc/View/Helper/Root/Record.php @@ -160,22 +160,24 @@ class Record extends \VuFind\View\Helper\Root\Record /** * Render a (list of) record icons. * - * @param string $tpl Template for record icon, default: record-icon.phtml - * @param bool $addText Return additional access / format. Default: true + * @param string $tpl phtml for record icon, default: record-icon.phtml + * @param bool $setIconText Return additional access / format. Default: true * * @return string */ public function getRecordIcon( string $tpl = 'record-icon', - bool $addText = true + bool $setIconText = true ): string { $iconType = $this->getRecordIconType(); $iconClass = $this->getRecordIconClass($iconType); return $this->renderTemplate( $tpl . '.phtml', - ['iconClass' => $this->baseIconClass . ' ' . $iconClass] - ) - . ($addText ? $this->getRecordIconText($iconType, $iconClass) : ''); + [ + 'iconClass' => $this->baseIconClass . ' ' . $iconClass, + 'setIconText' => $setIconText + ] + ); } /** diff --git a/themes/finc-accessibility/templates/Recommend/SideFacets/facet.phtml b/themes/finc-accessibility/templates/Recommend/SideFacets/facet.phtml index 6bbd232147abb52157005b00c1c5930a8596c48d..5a57cbf7ac67ad07553b19c8e9e63d93253b8b32 100644 --- a/themes/finc-accessibility/templates/Recommend/SideFacets/facet.phtml +++ b/themes/finc-accessibility/templates/Recommend/SideFacets/facet.phtml @@ -10,9 +10,10 @@ $facet = $this->facet; ?> <?php if (isset($rangeFacets[$facet])): // special display for ranges ?> + <?php /* finc: usability date range slider #22511: add cluster for extracting possible year ranges */ ?> <?=$this->context($this)->renderInContext( 'Recommend/SideFacets/range-slider.phtml', - ['title' => $facet, 'facet' => $rangeFacets[$facet]] + ['title' => $facet, 'facet' => $rangeFacets[$facet], 'cluster' => $cluster] ); ?> <?php else: ?> <?php diff --git a/themes/finc/js/covers.js b/themes/finc/js/covers.js index 3eb309ef70b9765951f99e163e3185e1084aca2d..7c0771977116dbf3aa7fd9648c982760b2accbbf 100644 --- a/themes/finc/js/covers.js +++ b/themes/finc/js/covers.js @@ -33,8 +33,18 @@ function loadCoverByElement(data, element) { container.children().not('img').hide(); anchor.show(); anchor.attr('href', response.data.url); - anchor.removeClass('hidden'); // finc specific - registerCoverForModal(anchor, response.data.url); // finc specific + // finc specific + registerCoverForModal(anchor, response.data.url); + if (data.ariaLabel) { + anchor.attr('aria-label', data.ariaLabel); + } + if (data.alt) { + img.attr('alt', data.alt); + } + anchor.attr('tabindex', 0); + anchor.removeClass('hidden'); + anchor.removeAttr('aria-hidden'); + // finc specific - END } else { img.remove(); if (typeof response.data.html !== 'undefined') { diff --git a/themes/finc/scss/_customVariables.scss b/themes/finc/scss/_customVariables.scss index 3addf93540077be42f536c633128efc4b9317269..6115953cf9801ff4547e71da9f23b23f44f47eab 100644 --- a/themes/finc/scss/_customVariables.scss +++ b/themes/finc/scss/_customVariables.scss @@ -93,6 +93,7 @@ $mainbody-sidebar-top-padding-xs: 0 !default; // Sidebar item padding $sidebar-item-padding: .75em 1em !default; +$sidebar-item-padding-sm: .75em .5em !default; // Table cell padding - adjust in themes to avoid content jumps when switching tabs // $table-cell-padding: 5px !default; @@ -1078,6 +1079,7 @@ $sidebar-facet-active-background-color: $brand-warning !default; $sidebar-facet-active-color: $black !default; $sidebar-facet-active-hover-color: $btn-primary-color !default; $sidebar-facet-active-text-inside-padding-left: 1.25em !default; +$sidebar-facet-active-text-inside-padding-left-sm: 1.0em !default; $sidebar-or-facet-text-indent: -3px !default; $sidebar-facet-my-account-padding: 0 !default; $sidebar-facet-my-account-link-width: 100% !default; diff --git a/themes/finc/scss/activate-on-demand/_sidebar-filter-hide-checkbox.scss b/themes/finc/scss/activate-on-demand/_sidebar-filter-hide-checkbox.scss new file mode 100644 index 0000000000000000000000000000000000000000..c2638f7b745a62c8fb3997a0b9b9a20599615aca --- /dev/null +++ b/themes/finc/scss/activate-on-demand/_sidebar-filter-hide-checkbox.scss @@ -0,0 +1,45 @@ +// improve sidebar for tablet devices + +// ***************************************************************** +// ************ General ******************************************** +// ***************************************************************** + +.sidebar { + .facet { + &.active { + .text { + // reduce padding for active filters on tablet devices #22377 + @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + padding-left: $sidebar-facet-active-text-inside-padding-left-sm; + } + } + } + + @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + // cut text in sidebar for tablet devices #22377 + .text { + overflow: hidden; + text-overflow: ellipsis; + + // hide checkboxes in sidebar for tablet devices #22377 + .fa-square-o { + display: none; + } + } + } + } +} + +.facet-group { + a, + .text, + .badge, + .title, + .help-link, + .facet a:not(.exclude):not(:last-of-type) { + // reduce padding for small devices #22377 + @media (min-width: $screen-sm-min) and (max-width: $screen-sm-max) { + padding: $sidebar-item-padding-sm; + } + } +} diff --git a/themes/finc/scss/components/_sidebar.scss b/themes/finc/scss/components/_sidebar.scss index 784e9013abeaabafb26cd739e774470409eba17f..8a481519ecaa8698c7042e2d4edd82b77151dc5a 100644 --- a/themes/finc/scss/components/_sidebar.scss +++ b/themes/finc/scss/components/_sidebar.scss @@ -86,7 +86,6 @@ padding-left: $sidebar-facet-active-text-inside-padding-left; } } - } } diff --git a/themes/finc/scss/finc.scss b/themes/finc/scss/finc.scss index 4b04d5ac2638217f130a2d49c5542f4fac3918cc..25582576e7c68b525f70b1e924dbe24401d2ffd1 100644 --- a/themes/finc/scss/finc.scss +++ b/themes/finc/scss/finc.scss @@ -48,7 +48,9 @@ // 1. To make bulk action buttons visible on small devices (Accessibility) // @import 'activate-on-demand/bulkaction-visible-xs'; // 2. To make visited links use a different color, use the import in anchors.scss -// 3. .............. +// 3. If you want to hide the checkboxes for the filters on SM devices, import the following file +@import 'activate-on-demand/sidebar-filter-hide-checkbox'; +// 4. ............. // ***************************************************************** // ********** HTML basics ****************************************** diff --git a/themes/finc/templates/Recommend/SideFacets/range-slider.phtml b/themes/finc/templates/Recommend/SideFacets/range-slider.phtml index af5d03e35da24a86da112f39442210d1ba1634e5..f535319ed665b002361a9763fa4bd79d4c2275b7 100644 --- a/themes/finc/templates/Recommend/SideFacets/range-slider.phtml +++ b/themes/finc/templates/Recommend/SideFacets/range-slider.phtml @@ -4,6 +4,22 @@ * slider-container element */ ?> +<?php + /** finc: usability date range slider #22511: + * set boundary values for daterange input and slider + * min & max values of handles and inputs are defined by search results + * if date range filter is applied additionaly: lowest and highest record years can be within filter values + */ + foreach ($cluster['list'] as $facet) { + $years[] = $facet['value']; + } + $facetmin = min($years); + $facetmax = max($years); + $low = $facetmin; + $min = !empty($this->facet['values'][0]) ? $this->facet['values'][0] : $facetmin; + $high = $facetmax; + $max = !empty($this->facet['values'][1]) ? $this->facet['values'][1] : $facetmax; +?> <?php /* finc changes div into li for compatibility with facet list structure */ ?> <li class="facet"> <?php /* finc adds landmarks for active facets */ ?> @@ -17,22 +33,24 @@ <?=$results->getUrlQuery()->asHiddenFields(['page' => "/./", 'filter' => "/^{$this->title}:.*/"])?> <input type="hidden" name="<?=$this->escapeHtmlAttr($this->facet['type'])?>range[]" value="<?=$this->escapeHtmlAttr($this->title)?>"/> <div class="date-fields"> - <?php /* finc adds 'max="'.(date('Y')+1).' to prevent dates beyond the year + 1 to be entered; maxlength was causing w3c issues */ ?> - <?php $extraInputAttribs = ($this->facet['type'] == 'date') ? 'max="'.(date('Y')+1).'" ' : ''; ?> + <?php /* finc: usability date range slider #22511: + prefill min & max attributes by possible date range (given by search results or chosen date range filter) + */ ?> + <?php $extraInputAttribs = ($this->facet['type'] == 'date') ? " min=\"{$min}\" max=\"{$max}\" " : ''; ?> <div class="date-from"> <?php /* finc adds label ids */ ?> <label id="from-label" for="<?=$this->escapeHtmlAttr($this->title)?>from"> <?=$this->transEsc('date_from')?>: </label> - <?php /* finc changes this to number for consistency with adv search */ ?> - <input type="number" class="form-control" name="<?=$this->escapeHtmlAttr($this->title)?>from" id="<?=$this->escapeHtmlAttr($this->title)?>from" value="<?=isset($this->facet['values'][0]) ? $this->escapeHtmlAttr($this->facet['values'][0]) : ''?>" <?=$extraInputAttribs?>/> + <?php /* finc: usability date range slider #22135, #22511: change input type and value */ ?> + <input type="number" class="form-control" name="<?=$this->escapeHtmlAttr($this->title)?>from" id="<?=$this->escapeHtmlAttr($this->title)?>from" value="<?=!empty($this->facet['values'][0]) ? $this->escapeHtmlAttr($low) : ''?>" <?=$extraInputAttribs?>/> </div> <div class="date-to"> <label id="to-label" for="<?=$this->escapeHtmlAttr($this->title)?>to"> <?=$this->transEsc('date_to')?>: </label> - <?php /* finc changes this to number for consistency with adv search */ ?> - <input type="number" class="form-control" name="<?=$this->escapeHtmlAttr($this->title)?>to" id="<?=$this->escapeHtmlAttr($this->title)?>to" value="<?=isset($this->facet['values'][1]) ? $this->escapeHtmlAttr($this->facet['values'][1]) : ''?>" <?=$extraInputAttribs?>/> + <?php /* finc: usability date range slider #22135, #22511: change input type and value input */ ?> + <input type="number" class="form-control" name="<?=$this->escapeHtmlAttr($this->title)?>to" id="<?=$this->escapeHtmlAttr($this->title)?>to" value="<?=!empty($this->facet['values'][1]) ? $this->escapeHtmlAttr($high) : ''?>" <?=$extraInputAttribs?>/> </div> </div> <?php if ($this->facet['type'] == 'date'): ?> @@ -49,11 +67,7 @@ <?php $this->headScript()->appendFile('vendor/bootstrap-slider.min.js'); ?> <?php $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css'); ?> <?php - $min = !empty($this->facet['values'][0]) ? min($this->facet['values'][0], 1400) : 1400; - $future = date('Y', time() + 31536000); // next year - $max = !empty($this->facet['values'][1]) ? max($future, $this->facet['values'][1]) : $future; - $low = !empty($this->facet['values'][0]) ? $this->facet['values'][0] : $min; - $high = !empty($this->facet['values'][1]) ? $this->facet['values'][1] : $max; + /* finc: usability date range slider #22511: variables moved to top */ $script = <<<JS $(document).ready(function() { var fillTexts = function() { diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-text.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-text.phtml index 997f06c9234e5b470499e6b3e5a94b43f87a4786..ea9258f886e259c331a5fd198867d10f8c105873 100644 --- a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-text.phtml +++ b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon-text.phtml @@ -2,7 +2,7 @@ <?php if ($iconClass): ?> <div class="access-icon hidden-print"> <span> - <?=$this->translate("($iconClass)")?> + <span class="sr-only"><?=$this->translate("Available_Via")?></span> <?=$this->translate("($iconClass)")?> </span> </div> <?php endif; ?> diff --git a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon.phtml b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon.phtml index 6cd2fbe8890f1db9ea1319f2a1045ebbf1a6a977..c79e96867483e6a986f4cfab5ecbb40955963b42 100644 --- a/themes/finc/templates/RecordDriver/DefaultRecord/record-icon.phtml +++ b/themes/finc/templates/RecordDriver/DefaultRecord/record-icon.phtml @@ -4,5 +4,8 @@ <i aria-hidden="true" class="<?=$iconClass?>"></i> <?php /* separate access text from icon - moved to cover.phtml */ ?> </span> + <?php if ($this->setIconText ?? true): ?> + <?=$this->record($this->driver)->getRecordIconText()?> + <?php endif; ?> <?php endif; ?> <!-- finc: recordDriver - DefaultRecord - record-icon - END --> \ No newline at end of file diff --git a/themes/finc/templates/myresearch/profile.phtml b/themes/finc/templates/myresearch/profile.phtml index a8787ed1ecc200bdaa38df3bcb71dcaeb5996d45..1ed8eeb96ae529398fb453501c95d8a259bb055a 100644 --- a/themes/finc/templates/myresearch/profile.phtml +++ b/themes/finc/templates/myresearch/profile.phtml @@ -18,69 +18,22 @@ <h1><?=$this->transEsc('Your Profile')?></h1> <?=$this->flashmessages();?> - <?php /* This table works well without inserting responsive data titles - CK */ ?> - <table class="table table-striped"> - <?=$this->renderArray( - $arrTemplate, $this->user, - [ - $this->transEsc('First Name') => 'firstname', - $this->transEsc('Last Name') => 'lastname', - // finc: uses show e-mail in table below - // $this->transEsc('Email') => 'email', - ] - )?> - <?php /* this section renders under two distinct circumstances; see if/else below: */ ?> - <?php if (count($this->pickup ?? []) > 1 || !empty($this->preferredLibraryDisplay)): ?> - <tr> - <th><?=$this->transEsc('Preferred Library')?>:</th> - <td> - <?php if (count($this->pickup ?? []) > 1): // case 1: set home library allowed ?> - <?php - $selected = (strlen($this->profile['home_library'] ?? '') > 0) - ? $this->profile['home_library'] : $this->defaultPickupLocation - ?> - <form id="profile_form" class="form-inline" method="post"> - <select id="home_library" name="home_library" class="form-control"> - <?php foreach ($this->pickup as $lib): ?> - <option value="<?=$this->escapeHtmlAttr($lib['locationID'])?>"<?=($selected == $lib['locationID'])?' selected="selected"':''?>><?=$this->transEscWithPrefix('location_', $lib['locationDisplay'])?></option> - <?php endforeach; ?> - </select> - <input class="btn btn-default" type="submit" value="<?=$this->transEsc('Save')?>" /> - </form> - <?php else: // case 2: set home library disallowed, but default provided by ILS ?> - <?=$this->transEscWithPrefix('location_', $this->preferredLibraryDisplay)?> - <?php endif; ?> - </td> - </tr> - <?php endif; ?> - </table> - - <div id="account-actions"> - <?php if ($this->auth()->getManager()->supportsEmailChange()): ?> - <a class="btn btn-default" href="<?=$this->url('myresearch-changeemail') ?>"> - <i class="fa fa-fw fa-envelope" aria-hidden="true"></i> <?=$this->transEsc('Change Email Address') ?> - </a> - <?php endif; ?> - - <?php if ($this->auth()->getManager()->supportsPasswordChange()): ?> - <a class="btn btn-default" href="<?=$this->url('myresearch-changepassword') ?>"> - <i class="fa fa-fw fa-lock" aria-hidden="true"></i> <?=$this->transEsc('Change Password') ?> - </a> - <?php endif; ?> - - <?php if ($this->accountDeletion): ?> - <a class="btn btn-default" href="<?=$this->url('myresearch-deleteaccount') ?>" data-lightbox> - <i class="fa fa-times"></i> <?=$this->transEsc('delete_account_title') ?> - </a> - <?php endif; ?> - </div> + <?php + /* finc-specific: + * Removed part of template responsible for rendering user data from VuFind + * database as in finc we only store name/surname/email in database which is + * identical to profile data from the ILS shown below. Also gone are action + * buttons for password/emal change and account deletion as this is all handled + * by the ILS as well. */ + ?> <?php if (is_array($this->profile)): ?> - <?php /* finc: change h3 to h2 */ ?> - <h2><?=$this->transEsc('Library Catalog Profile')?></h2> - <p> - <?=$this->context($this)->renderInContext('librarycards/selectcard.phtml', ['user' => $this->user]); ?> - </p> + + <?php + /* finc-specific: + * Removed sub-heading and library card selector (should never be used in finc). + */ + ?> <?php /* Table works without further responsiveness code inserted - CK */ ?> <table class="table table-striped"> <?=$this->renderArray( diff --git a/themes/finc/templates/record/cover.phtml b/themes/finc/templates/record/cover.phtml index 63b6241951f925b51482ac0eee112e7bade88bd4..ff34f1c1bd441e8f3c0a9abcc6390b4ffb0dc517 100644 --- a/themes/finc/templates/record/cover.phtml +++ b/themes/finc/templates/record/cover.phtml @@ -5,13 +5,16 @@ the class '.nocover' prevents nocover images from loading in lightbox or can be used to hide the images */ ?> <?php $alt = $alt ?? $this->transEsc('Cover Image')?> <?php $id = $driver->getUniqueID() ?> +<?php $title = $this->transEsc($driver->getTitle()); ?> + <?php if ($id) { - $coverId = "cover-$id-" . time(); + $coverId = "cover-$id-" . time(); } else { - $cover = false; + $cover = false; } ?> <?php if ($cover): ?> + <?php /* load cover directly... */ ?> <?php if ($this->link): ?><a id="<?=$coverId?>" href="<?=$this->escapeHtmlAttr($this->link)?>" tabindex="-1" aria-hidden="true"><?php endif; ?> <img alt="<?=$alt?>" <?php if ($linkPreview): ?>data-linkpreview="true" <?php endif; ?>class="recordcover" src="<?=$this->escapeHtmlAttr($cover); ?>" /> <?php if ($this->link): ?> @@ -23,16 +26,27 @@ <?php elseif ($cover === false): ?> <img src="<?=$this->url('cover-unavailable')?>" <?php if ($linkPreview): ?>data-linkpreview="true" <?php endif; ?>class="nocover" alt="<?=$this->transEsc('No Cover Image')?>" aria-hidden="true" tabindex="-1" /> <?php else: ?> + <?php /* load cover by ajax */ ?> <div id="<?=$coverId?>" class="ajaxcover"> <div class="spinner"><i class="fa fa-spinner fa-spin"></i></div> <div class="cover-container"> + <?=$this->setIconText = false;?> <?=$this->render('record/coverReplacement')?> <a class="coverlink hidden" href="javascript:" aria-hidden="true" tabindex="-1"> <img <?php if ($linkPreview): ?>data-linkpreview="true" <?php endif; ?> class="recordcover ajax" src="<?=$this->imageLink('noCover2.gif')?>" alt="<?=$this->escapeHtmlAttr($alt); ?>" /> + <script> + loadCoverByElement( + { + recordId:'<?=$this->escapeHtmlAttr($driver->getUniqueID())?>', + alt:'<?=$this->transEsc('Cover Image')?> <?=$this->transEsc("of")?> <?=$title?>', + ariaLabel:'<?=$this->transEsc("Link-to")?> <?=$this->transEsc('Cover Image')?> <?=$this->transEsc("of")?> <?=$title?>', + size:'<?=$this->escapeHtmlAttr($size)?>', + source:'<?=$this->escapeHtmlAttr($driver->getSourceIdentifier())?>' + }, + $('#<?=$coverId?>') + ); + </script> </a> - <script> - loadCoverByElement({source:'<?=$this->escapeHtmlAttr($driver->getSourceIdentifier())?>', recordId:'<?=$this->escapeHtmlAttr($driver->getUniqueID())?>', size:'<?=$this->escapeHtmlAttr($size)?>'}, $('#<?=$coverId?>')); - </script> </div> </div> <?php endif; ?> diff --git a/themes/finc/templates/record/coverReplacement.phtml b/themes/finc/templates/record/coverReplacement.phtml index d26b8d7bcb980e7a9d10d36e7f64b1cf126c1a32..4662e1b083a775660904a3f50b12e5df084023bd 100644 --- a/themes/finc/templates/record/coverReplacement.phtml +++ b/themes/finc/templates/record/coverReplacement.phtml @@ -1 +1 @@ -<?= $this->record($this->driver)->getRecordIcon('record-icon', false) ?> \ No newline at end of file +<?= $this->record($this->driver)->getRecordIcon('record-icon', $this->setIconText ?? true) ?> \ No newline at end of file diff --git a/themes/finc/templates/search/advanced/ranges.phtml b/themes/finc/templates/search/advanced/ranges.phtml index d6ec0dbd519608ed33e171a4e22e9caf61f8cbc2..c9f85c898776a075659c06bf173dcb3629a9962c 100644 --- a/themes/finc/templates/search/advanced/ranges.phtml +++ b/themes/finc/templates/search/advanced/ranges.phtml @@ -2,8 +2,15 @@ <?php if (isset($this->ranges) && !empty($this->ranges)): ?> <?php $params = $this->searchParams($this->searchClassId); ?> <?php foreach ($this->ranges as $current): $escField = $this->escapeHtmlAttr($current['field']); ?> - <?php /* finc adds 'max="'.(date('Y')+1).' to prevent dates beyond the year + 1 to be entered; maxlength was causing w3c issues */ ?> - <?php $extraInputAttribs = ($current['type'] == 'date') ? 'max="'.(date('Y')+1).'" ' : ''; ?> + <?php /* finc: usability date range slider #22511:: calculate variables at the beginning */ + $min = !empty($current['values'][0]) ? min($current['values'][0], 1400) : 1400; + $future = date('Y', time() + 31536000); + $max = !empty($current['values'][1]) ? max($future, $current['values'][1]) : $future; + $low = !empty($current['values'][0]) ? $current['values'][0] : $min; + $high = !empty($current['values'][1]) ? $current['values'][1] : $max; + ?> + <?php /* finc: usability date range slider #22511: use previously calculated min-/max-values to limit inputs */ ?> + <?php $extraInputAttribs = ($current['type'] == 'date') ? " min=\"{$min}\" max=\"{$max}\" " : ''; ?> <fieldset class="range"> <legend><?=$this->transEsc($params->getFacetLabel($current['field']))?></legend> <input type="hidden" name="<?=$this->escapeHtmlAttr($current['type'])?>range[]" value="<?=$escField?>"/> @@ -27,11 +34,7 @@ <?php $this->headScript()->appendFile('vendor/bootstrap-slider.min.js'); $this->headLink()->appendStylesheet('vendor/bootstrap-slider.min.css'); - $min = !empty($current['values'][0]) ? min($current['values'][0], 1400) : 1400; - $future = date('Y', time() + 31536000); - $max = !empty($current['values'][1]) ? max($future, $current['values'][1]) : $future; - $low = !empty($current['values'][0]) ? $current['values'][0] : $min; - $high = !empty($current['values'][1]) ? $current['values'][1] : $max; + /* finc: usability date range slider #22511: moving variables to the beginning */ $min = intval($min); $max = intval($max); $low = intval($low);