/*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 = {};
var _pendingNotifications = {};
// Account Icons
var ICON_LEVELS = {
"NONE": 0,
"GOOD": 1,
"WARNING": 2,
"DANGER": 3
};
var _accountIcons = {};
// [icon, additional class]
_accountIcons[ICON_LEVELS.NONE] = ["my-account", "account-status-none"];
_accountIcons[ICON_LEVELS.GOOD] = ["my-account-notification", "account-status-good text-success"];
_accountIcons[ICON_LEVELS.WARNING] = ["my-account-notification", "account-status-warning text-warning"];
_accountIcons[ICON_LEVELS.DANGER] = ["my-account-warning", "account-status-danger text-danger"];
var _submodules = [];
var _clearCaches = false;
var _sessionDataPrefix = "vf-account-status-";
var _save = function _save(module) {
sessionStorage.setItem(
_sessionDataPrefix + module,
JSON.stringify(_statuses[module])
);
};
// Forward declaration for clearAllCaches
var clearAllCaches = function clearAllCachesForward() {};
// Clearing save forces AJAX update next page load
var clearCache = function clearCache(name) {
if (typeof name === "undefined" || name === '') {
clearAllCaches();
} 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 status = _getStatus(sub);
if (status === INACTIVE) {
continue;
}
var $element = $(_submodules[sub].selector);
if ($element.length === 0) {
// This could happen if the DOM is changed dynamically
_statuses[sub] = INACTIVE;
continue;
}
if (status === MISSING) {
$element.addClass('hidden');
} else {
$element.removeClass('hidden');
if (status === LOADING) {
$element.html(VuFind.spinner());
} else {
var moduleStatus = _submodules[sub].render($element, _statuses[sub], ICON_LEVELS);
if (moduleStatus > accountStatus) {
accountStatus = moduleStatus;
}
}
}
}
}
const accountIconEl = document.querySelector('#account-icon');
if (accountIconEl) {
accountIconEl.innerHTML = VuFind.icon(..._accountIcons[accountStatus]);
if (accountStatus > ICON_LEVELS.NONE) {
accountIconEl.dataset.toggle = 'tooltip';
accountIconEl.dataset.placement = 'bottom';
accountIconEl.title = VuFind.translate('account_has_alerts');
$(accountIconEl).tooltip();
} else {
$(accountIconEl).tooltip('destroy');
}
Object.entries(ICON_LEVELS).forEach(([, level]) => {
accountIconEl.classList.remove('notification-level-' + level);
});
accountIconEl.classList.add('notification-level-' + accountStatus);
}
};
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) {
if (_clearCaches) {
sessionStorage.removeItem(_sessionDataPrefix + 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 notify = function notify(module, status) {
if (Object.prototype.hasOwnProperty.call(_submodules, module) && typeof _submodules[module].updateNeeded !== 'undefined') {
if (_submodules[module].updateNeeded(_getStatus(module), status)) {
clearCache(module);
_load(module);
}
} else {
// We currently support only a single pending notification for each module
_pendingNotifications[module] = status;
}
};
var init = function init() {
// Update information when certain actions are performed
$("form[data-clear-account-cache]").on("submit", function dataClearCacheForm() {
clearCache($(this).attr("data-clear-account-cache"));
});
$("a[data-clear-account-cache]").on("click", function dataClearCacheLink() {
clearCache($(this).attr("data-clear-account-cache"));
});
$("select[data-clear-account-cache]").on("change", function dataClearCacheSelect() {
clearCache($(this).attr("data-clear-account-cache"));
});
};
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;
}
if (typeof _pendingNotifications[name] !== 'undefined' && _pendingNotifications[name] !== null) {
var status = _pendingNotifications[name];
_pendingNotifications[name] = null;
notify(name, status);
}
};
clearAllCaches = function clearAllCachesReal() {
// Set a flag so that any modules yet to be loaded are cleared as well
_clearCaches = true;
for (var sub in _submodules) {
if (Object.prototype.hasOwnProperty.call(_submodules, sub)) {
_load(sub);
}
}
};
return {
init: init,
clearCache: clearCache,
clearAllCaches: clearAllCaches,
notify: notify,
// if user is logged out, clear cache instead of register
register: userIsLoggedIn ? register : clearCache
};
});
$(function registerAccountAjax() {
VuFind.account.register("fines", {
selector: ".fines-status",
ajaxMethod: "getUserFines",
render: function render($element, status, ICON_LEVELS) {
if (status.total === 0) {
$element.addClass("hidden");
return ICON_LEVELS.NONE;
}
$element.html('' + status.display + '');
return ICON_LEVELS.DANGER;
},
updateNeeded: function updateNeeded(currentStatus, status) {
return status.total !== currentStatus.total;
}
});
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 += '' + status.ok + '';
}
if (status.warn > 0) {
html += '' + status.warn + '';
level = ICON_LEVELS.WARNING;
}
if (status.overdue > 0) {
html += '' + status.overdue + '';
level = ICON_LEVELS.DANGER;
}
$element.html(html);
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
},
updateNeeded: function updateNeeded(currentStatus, status) {
return status.ok !== currentStatus.ok || status.warn !== currentStatus.warn || status.overdue !== currentStatus.overdue;
}
});
VuFind.account.register("holds", {
selector: ".holds-status",
ajaxMethod: "getUserHolds",
render: function render($element, status, ICON_LEVELS) {
var html = '';
var level = ICON_LEVELS.NONE;
if (status.available > 0) {
html += '' + status.available + '';
level = ICON_LEVELS.GOOD;
}
if (status.in_transit > 0) {
html += '' + status.in_transit + '';
}
if (status.other > 0) {
html += '' + status.other + '';
}
if (html !== '') {
$element.html(html);
} else {
$element.addClass("holds-status hidden");
}
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
},
updateNeeded: function updateNeeded(currentStatus, status) {
return status.available !== currentStatus.available || status.in_transit !== currentStatus.in_transit || status.other !== currentStatus.other;
}
});
VuFind.account.register("illRequests", {
selector: ".illrequests-status",
ajaxMethod: "getUserILLRequests",
render: function render($element, status, ICON_LEVELS) {
var html = '';
var level = ICON_LEVELS.NONE;
if (status.available > 0) {
html += '' + status.available + '';
level = ICON_LEVELS.GOOD;
}
if (status.in_transit > 0) {
html += '' + status.in_transit + '';
}
if (status.other > 0) {
html += '' + status.other + '';
}
if (html !== '') {
$element.html(html);
} else {
$element.addClass("holds-status hidden");
}
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
},
updateNeeded: function updateNeeded(currentStatus, status) {
return status.available !== currentStatus.available || status.in_transit !== currentStatus.in_transit || status.other !== currentStatus.other;
}
});
VuFind.account.register("storageRetrievalRequests", {
selector: ".storageretrievalrequests-status",
ajaxMethod: "getUserStorageRetrievalRequests",
render: function render($element, status, ICON_LEVELS) {
var html = '';
var level = ICON_LEVELS.NONE;
if (status.available > 0) {
html += '' + status.available + '';
level = ICON_LEVELS.GOOD;
}
if (status.in_transit > 0) {
html += '' + status.in_transit + '';
}
if (status.other > 0) {
html += '' + status.other + '';
}
if (html !== '') {
$element.html(html);
} else {
$element.addClass("holds-status hidden");
}
$('[data-toggle="tooltip"]', $element).tooltip();
return level;
},
updateNeeded: function updateNeeded(currentStatus, status) {
return status.available !== currentStatus.available || status.in_transit !== currentStatus.in_transit || status.other !== currentStatus.other;
}
});
});