Skip to content
Snippets Groups Projects
Commit 24100d66 authored by Mathias Maaß's avatar Mathias Maaß Committed by André Lahmann
Browse files

refs #23260 [finc]

* add ajax handler to retrieve count of ill requests
* move menu.phtml from finc-accessibitily to finc and and update menu.phtml to contain all possible menu items.
* add sub menu "prefences" to menu.phtml
* add translation strings for use in browser
* override vufinds account_ajax.js to meet fincs account menu needs
* guard menu against missing route exception
* hide ill count if number of ill requests is zero
* add doc header and comments to account_ajax.js
* remove duplicated item in menu.phtml
parent 86d8e60a
Branches
Tags
No related merge requests found
...@@ -92,6 +92,8 @@ $config = [ ...@@ -92,6 +92,8 @@ $config = [
'finc\AjaxHandler\GetResolverLinksFactory', 'finc\AjaxHandler\GetResolverLinksFactory',
'finc\AjaxHandler\GetRecordCover' => 'finc\AjaxHandler\GetRecordCover' =>
'finc\AjaxHandler\GetRecordCoverFactory', 'finc\AjaxHandler\GetRecordCoverFactory',
'finc\AjaxHandler\GetUserILLRequestsStats' =>
'VuFind\AjaxHandler\AbstractIlsAndUserActionFactory',
'finc\AjaxHandler\GetUserMediaReadyToPickup' => 'finc\AjaxHandler\GetUserMediaReadyToPickup' =>
'VuFind\AjaxHandler\AbstractIlsAndUserActionFactory', 'VuFind\AjaxHandler\AbstractIlsAndUserActionFactory',
'finc\AjaxHandler\GetUserPermanentLoans' => 'finc\AjaxHandler\GetUserPermanentLoans' =>
...@@ -108,6 +110,8 @@ $config = [ ...@@ -108,6 +110,8 @@ $config = [
'finc\AjaxHandler\GetResolverLinks', 'finc\AjaxHandler\GetResolverLinks',
'getRecordCover' => 'getRecordCover' =>
'finc\AjaxHandler\GetRecordCover', 'finc\AjaxHandler\GetRecordCover',
'getUserILLRequestsStats' =>
'finc\AjaxHandler\GetUserILLRequestsStats',
'getUserMediaReadyToPickup' => 'getUserMediaReadyToPickup' =>
'finc\AjaxHandler\GetUserMediaReadyToPickup', 'finc\AjaxHandler\GetUserMediaReadyToPickup',
'getUserPermanentLoans' => 'getUserPermanentLoans' =>
......
<?php
/**
* PHP version 7
*
* Copyright (C) Villanova University 2018.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2,
* as published by the Free Software Foundation.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* @category VuFind
* @package AJAX
* @author Demian Katz <demian.katz@villanova.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
namespace finc\AjaxHandler;
use Zend\Mvc\Controller\Plugin\Params;
/**
* AJAX handler to get statistics (e.g. counts) of users interlibrary loans.
*
* @category VuFind
* @package AJAX
* @author Demian Katz <demian.katz@villanova.edu>
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License
* @link https://vufind.org/wiki/development Wiki
*/
class GetUserILLRequestsStats extends \VuFind\AjaxHandler\AbstractUserRequestAction
{
/**
* Handle a request.
*
* @param Params $params Parameter helper from controller
*
* @return array [response data, internal status code, HTTP status code]
*/
public function handleRequest(Params $params)
{
$this->disableSessionWrites(); // avoid session write timing bug
$patron = $this->ilsAuthenticator->storedCatalogLogin();
if (!$patron) {
return $this->formatResponse('', self::STATUS_HTTP_NEED_AUTH, 401);
}
if (!$this->ils->checkCapability('getMyTransactions')) {
return $this->formatResponse('', self::STATUS_HTTP_ERROR, 405);
}
$items = $this->ils->getMyILLRequests($patron);
$stats = [
'total' => count($items)
];
return $this->formatResponse($stats);
}
}
/**
* origin: {vufind}
* called by view helper/controller:
* usage: {}
* modified for finc:
* - Add handler for menu items "permanent loan" and "ready to pickup"
* - Change handler for "ill requests" to show total items count
*configured in: {}
*/
/*global userIsLoggedIn, VuFind */
VuFind.register('account', function Account() {
// Retrieved statuses
var LOADING = -1 * Math.PI; // waiting for request
var MISSING = -2 * Math.PI; // no data available
var INACTIVE = -3 * Math.PI; // status element missing
var _statuses = {};
// Account Icons
var ICON_LEVELS = {
"NONE": 0,
"GOOD": 1,
"WARNING": 2,
"DANGER": 3
};
var _accountIcons = {};
_accountIcons[ICON_LEVELS.NONE] = "fa fa-user-circle";
_accountIcons[ICON_LEVELS.GOOD] = "fa fa-bell text-success";
_accountIcons[ICON_LEVELS.WARNING] = "fa fa-bell text-warning";
_accountIcons[ICON_LEVELS.DANGER] = "fa fa-exclamation-triangle text-danger";
var _submodules = [];
var _sessionDataPrefix = "vf-account-status-";
var _save = function _save(module) {
sessionStorage.setItem(
_sessionDataPrefix + module,
JSON.stringify(_statuses[module])
);
};
// Clearing save forces AJAX update next page load
var clearCache = function clearCache(name) {
if (typeof name === "undefined") {
for (var sub in _submodules) {
if (Object.prototype.hasOwnProperty.call(_submodules, sub)) {
clearCache(sub);
}
}
} else {
sessionStorage.removeItem(_sessionDataPrefix + name);
}
};
var _getStatus = function _getStatus(module) {
return (typeof _statuses[module] === "undefined") ? LOADING : _statuses[module];
};
var _render = function _render() {
var accountStatus = ICON_LEVELS.NONE;
for (var sub in _submodules) {
if (Object.prototype.hasOwnProperty.call(_submodules, sub)) {
var $element = $(_submodules[sub].selector);
if (!$element) {
_statuses[sub] = INACTIVE;
continue;
}
var status = _getStatus(sub);
if (status === MISSING) {
$element.addClass('hidden');
} else {
$element.removeClass('hidden');
if (status === LOADING) {
$element.html('<i class="fa fa-spin fa-spinner"></i>');
} else {
var moduleStatus = _submodules[sub].render($element, _statuses[sub], ICON_LEVELS);
if (moduleStatus > accountStatus) {
accountStatus = moduleStatus;
}
}
}
}
}
$("#account-icon").attr("class", _accountIcons[accountStatus]);
if (accountStatus > ICON_LEVELS.NONE) {
$("#account-icon")
.attr("data-toggle", "tooltip")
.attr("data-placement", "bottom")
.attr("title", VuFind.translate("account_has_alerts"))
.tooltip();
} else {
$("#account-icon").tooltip("destroy");
}
};
var _ajaxLookup = function _ajaxLookup(module) {
$.ajax({
url: VuFind.path + '/AJAX/JSON?method=' + _submodules[module].ajaxMethod,
dataType: 'json'
})
.done(function ajaxLookupDone(response) {
_statuses[module] = response.data;
})
.fail(function ajaxLookupFail() {
_statuses[module] = MISSING;
})
.always(function ajaxLookupAlways() {
_save(module);
_render();
});
};
var _load = function _load(module) {
var $element = $(_submodules[module].selector);
if (!$element) {
_statuses[module] = INACTIVE;
} else {
var json = sessionStorage.getItem(_sessionDataPrefix + module);
var session = typeof json === "undefined" ? null : JSON.parse(json);
if (
session === null ||
session === LOADING ||
session === MISSING
) {
_statuses[module] = LOADING;
_ajaxLookup(module);
} else {
_statuses[module] = session;
}
_render();
}
};
var init = function init() {
// Update information when certain actions are performed
$("[data-clear-account-cache]").submit(function dataClearCache() {
clearCache($(this).attr("data-clear-account-cache"));
});
$("#library_card").change(function clearChangeLibraryCard() {
clearCache(/* all */);
});
};
var register = function register(name, module) {
if (typeof _submodules[name] === "undefined") {
_submodules[name] = typeof module == 'function' ? module() : module;
}
var $el = $(_submodules[name].selector);
if ($el.length > 0) {
$el.removeClass("hidden");
_statuses[name] = LOADING;
_load(name);
} else {
_statuses[name] = INACTIVE;
}
};
return {
init: init,
clearCache: clearCache,
// if user is logged out, clear cache instead of register
register: userIsLoggedIn ? register : clearCache
};
});
$(document).ready(function registerAccountAjax() {
VuFind.account.register("fines", {
selector: ".fines-status",
ajaxMethod: "getUserFines",
render: function render($element, status, ICON_LEVELS) {
if (status.value === 0) {
$element.addClass("hidden");
return ICON_LEVELS.NONE;
}
$element.html('<span class="badge overdue">' + status.display + '</span>');
return ICON_LEVELS.DANGER;
}
});
VuFind.account.register("checkedOut", {
selector: ".checkedout-status",
ajaxMethod: "getUserTransactions",
render: function render($element, status, ICON_LEVELS) {
var html = '';
var level = ICON_LEVELS.NONE;
if (status.ok > 0) {
html += '<span class="badge ok" data-toggle="tooltip" title="' + VuFind.translate('Checked Out Items') + '">' + status.ok + '</span>';
}
if (status.warn > 0) {
html += '<span class="badge warn" data-toggle="tooltip" title="' + VuFind.translate('renew_item_due_tooltip') + '">' + status.warn + '</span>';
level = ICON_LEVELS.WARNING;
}
if (status.overdue > 0) {
html += '<span class="badge overdue" data-toggle="tooltip" title="' + VuFind.translate('renew_item_overdue_tooltip') + '">' + status.overdue + '</span>';
level = ICON_LEVELS.DANGER;
}
$element.html(html);
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
}
});
// finc: add handler for "media ready to pickup" #23285
VuFind.account.register("mediareadytopickup", {
selector: ".mediareadytopickup-status",
ajaxMethod: "getUserMediaReadyToPickup",
render: function render($element, status, ICON_LEVELS) {
var level = ICON_LEVELS.NONE;
if (status.available > 0) {
$element.html('<i class="fa fa-bell text-success" data-toggle="tooltip" title="' + VuFind.translate('hold_available') + '"></i>');
level = ICON_LEVELS.GOOD;
} else if (status.in_transit > 0) {
$element.html('<i class="fa fa-clock-o text-warning" data-toggle="tooltip" title="' + VuFind.translate('request_in_transit') + '"></i>');
} else {
$element.addClass("holds-status hidden");
}
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
}
});
// finc: add handler for permanent loans #23285
VuFind.account.register("permanentLoans", {
selector: ".permanentloans-status",
ajaxMethod: "getUserPermanentLoans",
render: function render($element, status, ICON_LEVELS) {
var html = '';
var level = ICON_LEVELS.NONE;
if (status.ok > 0) {
html += '<span class="badge ok" data-toggle="tooltip" title="' + VuFind.translate('Permanent Checked Out Items') + '">' + status.ok + '</span>';
}
if (status.warn > 0) {
html += '<span class="badge warn" data-toggle="tooltip" title="' + VuFind.translate('renew_item_due_tooltip') + '">' + status.warn + '</span>';
level = ICON_LEVELS.WARNING;
}
if (status.overdue > 0) {
html += '<span class="badge overdue" data-toggle="tooltip" title="' + VuFind.translate('renew_item_overdue_tooltip') + '">' + status.overdue + '</span>';
level = ICON_LEVELS.DANGER;
}
$element.html(html);
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
}
});
VuFind.account.register("holds", {
selector: ".holds-status",
ajaxMethod: "getUserHolds",
render: function render($element, status, ICON_LEVELS) {
var level = ICON_LEVELS.NONE;
if (status.available > 0) {
$element.html('<i class="fa fa-bell text-success" data-toggle="tooltip" title="' + VuFind.translate('hold_available') + '"></i>');
level = ICON_LEVELS.GOOD;
} else if (status.in_transit > 0) {
$element.html('<i class="fa fa-clock-o text-warning" data-toggle="tooltip" title="' + VuFind.translate('request_in_transit') + '"></i>');
} else {
$element.addClass("holds-status hidden");
}
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
}
});
VuFind.account.register("storageRetrievalRequests", {
selector: ".storageretrievalrequests-status",
ajaxMethod: "getUserStorageRetrievalRequests",
render: function render($element, status, ICON_LEVELS) {
var level = ICON_LEVELS.NONE;
if (status.available > 0) {
$element.html('<i class="fa fa-bell text-success" data-toggle="tooltip" title="' + VuFind.translate('hold_available') + '"></i>');
level = ICON_LEVELS.GOOD;
} else if (status.in_transit > 0) {
$element.html('<i class="fa fa-clock-o text-warning" data-toggle="tooltip" title="' + VuFind.translate('request_in_transit') + '"></i>');
} else {
$element.addClass("holds-status hidden");
}
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
}
});
// finc: show total count of ill request items #23285
VuFind.account.register("illRequests", {
selector: ".illrequests-status",
ajaxMethod: "getUserILLRequestsStats",
render: function render($element, stats, ICON_LEVELS) {
var html = stats.total > 0
? '<span class="badge ok" data-toggle="tooltip" title="' + VuFind.translate('Interlibrary Loan Requests') + '">' + stats.total + '</span>'
: ''
$element.html(html)
return ICON_LEVELS.GOOD;
}
});
});
...@@ -149,7 +149,9 @@ ...@@ -149,7 +149,9 @@
'renew_item_due_tooltip' => 'renew_item_due_tooltip', 'renew_item_due_tooltip' => 'renew_item_due_tooltip',
'renew_item_overdue_tooltip' => 'renew_item_overdue_tooltip', 'renew_item_overdue_tooltip' => 'renew_item_overdue_tooltip',
'request_in_transit' => 'request_in_transit', 'request_in_transit' => 'request_in_transit',
'storage_retrieval_request_available' => 'storage_retrieval_request_available' 'storage_retrieval_request_available' => 'storage_retrieval_request_available',
'Interlibrary Loan Requests' => 'Interlibrary Loan Requests',
'Permanent Checked Out Items' => 'Permanent Checked Out Items'
] ]
); );
} }
......
...@@ -17,6 +17,15 @@ ...@@ -17,6 +17,15 @@
$patron = $user ? $this->auth()->getILSPatron() : false; $patron = $user ? $this->auth()->getILSPatron() : false;
$capabilityParams = $patron ? ['patron' => $patron] : []; $capabilityParams = $patron ? ['patron' => $patron] : [];
$ilsOnline = ('ils-none' !== $this->ils()->getOfflineMode()); $ilsOnline = ('ils-none' !== $this->ils()->getOfflineMode());
$routeExists = function($route) {
try {
$this->url($route);
return true;
} catch (Exception $e) {
return false;
}
};
?> ?>
<?php /* finc change btn-link to btn-default */ ?> <?php /* finc change btn-link to btn-default */ ?>
<button class="close-offcanvas btn btn-default" data-toggle="offcanvas"><?=$this->transEsc('navigate_back') ?></button> <button class="close-offcanvas btn btn-default" data-toggle="offcanvas"><?=$this->transEsc('navigate_back') ?></button>
...@@ -28,13 +37,6 @@ ...@@ -28,13 +37,6 @@
<?php /* finc: myreasearch menu as list #19734 */ ?> <?php /* finc: myreasearch menu as list #19734 */ ?>
<?php /* finc: specify current page menu entry in following elements #19941 */ ?> <?php /* finc: specify current page menu entry in following elements #19941 */ ?>
<ul class="myresearch-menu account-menu facet-group"> <ul class="myresearch-menu account-menu facet-group">
<?php if ($this->userlist()->getMode() !== 'disabled'): ?>
<li class="facet">
<a href="<?=$this->url('myresearch-favorites')?>"<?=$this->active == 'favorites' ? ' class="active" aria-current="page"' : ''?>>
<i class="fa fa-fw fa-star" aria-hidden="true"></i> <?=$this->transEsc('Favorites')?>
</a>
</li>
<?php endif; ?>
<?php if ($ilsOnline && $this->ils()->checkCapability('getMyTransactions', $capabilityParams)): ?> <?php if ($ilsOnline && $this->ils()->checkCapability('getMyTransactions', $capabilityParams)): ?>
<li class="facet"> <li class="facet">
<a href="<?=$this->url('myresearch-checkedout')?>" class="flex checkedout<?=$this->active == 'checkedout' ? ' active' : ''?>" <a href="<?=$this->url('myresearch-checkedout')?>" class="flex checkedout<?=$this->active == 'checkedout' ? ' active' : ''?>"
...@@ -45,9 +47,32 @@ ...@@ -45,9 +47,32 @@
</a> </a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<?php if ($ilsOnline && $this->ils()->checkFunction('getMyTransactionHistory', $capabilityParams)): ?> <?php /* finc: adds media ready to pickup */ ?>
<?php if ($ilsOnline && $this->ils()->checkCapability('getMyMediaReadyToPickup', $capabilityParams) && $routeExists('myresearch-mediareadytopickup')): ?>
<li class="facet"> <li class="facet">
<a href="<?=$this->url('myresearch-historicloans')?>"<?=$this->active == 'historicloans' ? ' class="active" aria-current="page"' : ''?>> <a href="<?=$this->url('myresearch-mediareadytopickup')?>" class="flex <?=$this->active == 'mediareadytopickup' ? ' active' : ''?>"
<?=$this->active == 'mediareadytopickup' ? ' aria-current="page"' : ''?>
>
<span class="flex-col"><i class="fa fa-fw fa-book" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('Ready For Collection')?></span>
<span class="mediareadytopickup-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span>
</a>
</li>
<?php endif; ?>
<?php /* finc: adds permanent loans */ ?>
<?php if ($ilsOnline && $this->ils()->checkCapability('getMyPermanentLoans', $capabilityParams) && $routeExists('myresearch-permanentloans')): ?>
<li class="facet">
<a href="<?=$this->url('myresearch-permanentloans')?>" class="flex <?=$this->active == 'permanentloans' ? ' active' : ''?>"
<?=$this->active == 'permanent' ? ' aria-current="page"' : ''?>
>
<span class="flex-col"><i class="fa fa-fw fa-book" aria-hidden="true"></i>&nbsp;<?=$this->transEsc('Permanent Checked Out Items')?></span>
<span class="permanentloans-status status hidden"><i class="fa fa-spin fa-spinner" aria-hidden="true"></i></span>
</a>
</li>
<?php endif; ?>
<?php /* finc: adds historic loans */ ?>
<?php if ($ilsOnline && $this->ils()->checkCapability('getMyLoanHistory', $capabilityParams) && $routeExists('myresearch-loanhistory')): ?>
<li class="facet">
<a href="<?=$this->url('myresearch-loanhistory')?>"<?=$this->active == 'loanhistory' ? ' class="active" aria-current="page"' : ''?>>
<i class="fa fa-fw fa-history" aria-hidden="true"></i> <?=$this->transEsc('Loan History')?> <i class="fa fa-fw fa-history" aria-hidden="true"></i> <?=$this->transEsc('Loan History')?>
</a> </a>
</li> </li>
...@@ -72,7 +97,7 @@ ...@@ -72,7 +97,7 @@
</a> </a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<?php if ($ilsOnline && $this->ils()->checkFunction('ILLRequests', $capabilityParams)): ?> <?php if ($ilsOnline && $this->ils()->checkCapability('getMyILLRequests', $capabilityParams)): ?>
<li class="facet"> <li class="facet">
<a href="<?=$this->url('myresearch-illrequests')?>" class="flex<?=$this->active == 'ILLRequests' ? ' active' : ''?>" <a href="<?=$this->url('myresearch-illrequests')?>" class="flex<?=$this->active == 'ILLRequests' ? ' active' : ''?>"
<?=$this->active == 'ILLRequests' ? ' aria-current="page"' : ''?> <?=$this->active == 'ILLRequests' ? ' aria-current="page"' : ''?>
...@@ -92,18 +117,6 @@ ...@@ -92,18 +117,6 @@
</a> </a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<li class="facet">
<a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active" aria-current="page"' : ''?>>
<i class="fa fa-fw fa-user" aria-hidden="true"></i> <?=$this->transEsc('Profile')?>
</a>
</li>
<?php if ($ilsOnline && $user && $user->libraryCardsEnabled()): ?>
<li class="facet">
<a href="<?=$this->url('librarycards-home')?>"<?=$this->active == 'librarycards' ? ' class="active" aria-current="page"' : ''?>>
<i class="fa fa-fw fa-barcode" aria-hidden="true"></i> <?=$this->transEsc('Library Cards')?>
</a>
</li>
<?php endif; ?>
<?php if ($this->overdrive()->showMyContentLink()):?> <?php if ($this->overdrive()->showMyContentLink()):?>
<li class="facet"> <li class="facet">
<a href="<?=$this->url('overdrive-mycontent')?>"<?=$this->active == 'dgcontent' ? ' class="active"' : ''?>> <a href="<?=$this->url('overdrive-mycontent')?>"<?=$this->active == 'dgcontent' ? ' class="active"' : ''?>>
...@@ -118,14 +131,42 @@ ...@@ -118,14 +131,42 @@
</a> </a>
</li> </li>
<?php endif; ?> <?php endif; ?>
<?php if ($user): ?> </ul>
<?php /* finc: adds prefences sub menu with items "profile", "change password", "change pin" and "logout" */ ?>
<?php if ($this->auth()->isLoggedIn()): ?>
<h3><?=$this->transEsc('Preferences')?></h3>
<ul class="myresearch-menu account-menu facet-group">
<li class="facet"> <li class="facet">
<a href="<?=$this->url('myresearch-logout')?>"> <a href="<?=$this->url('myresearch-profile')?>"<?=$this->active == 'profile' ? ' class="active" aria-current="page"' : ''?>>
<i class="fa fa-fw fa-sign-out" aria-hidden="true"></i> <?=$this->transEsc("Log Out")?> <i class="fa fa-fw fa-user" aria-hidden="true"></i>
<?=$this->transEsc('Profile')?>
</a> </a>
</li> </li>
<?php endif; ?> <?php if ($this->auth()->getManager()->supportsPasswordChange() && $routeExists('myresearch-changepassword')): ?>
</ul> <li class="facet">
<a href="<?=$this->url('myresearch-changepassword')?>" class="text<?=$this->active == 'newpassword' ? ' active' : ''?>">
<i class="fa fa-fw fa-lock" aria-hidden="true"></i>
<?=$this->transEsc('Change Password')?>
</a>
</li>
<?php endif; ?>
<?php if ($this->ils()->checkCapability('changeUserPin') && $routeExists('myresearch-setpin')): ?>
<li class="facet">
<a href="<?=$this->url('myresearch-setpin')?>" class="text<?=$this->active == 'setpin' ? ' active' : ''?>">
<i class="fa fa-fw fa-key" aria-hidden="true"></i>
<?=$this->transEsc('LiberoAccount::change_user_pin')?>
</a>
</li>
<?php endif; ?>
<li class="facet">
<a href="<?=$this->url('myresearch-logout')?>" class="text action">
<i class="fa fa-fw fa-sign-out" aria-hidden="true"></i>
<?=$this->transEsc("Log Out")?>
</a>
</li>
</ul>
<?php endif; ?>
<?php if ($user && $this->userlist()->getMode() !== 'disabled'): ?> <?php if ($user && $this->userlist()->getMode() !== 'disabled'): ?>
<?php /* finc adds '.lists-heading' for styling purposes */ ?> <?php /* finc adds '.lists-heading' for styling purposes */ ?>
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment