140 lines
4.3 KiB
JavaScript
140 lines
4.3 KiB
JavaScript
const apiPrefix = 'api/v0';
|
|
let authError = false;
|
|
|
|
/// \brief Makes an AJAX query with basic error handling.
|
|
function queryRoute(method, path, callback)
|
|
{
|
|
const ajaxRequest = new XMLHttpRequest();
|
|
ajaxRequest.onreadystatechange = function() {
|
|
if (this.readyState === 4) {
|
|
const status = this.status;
|
|
authError = status === 403;
|
|
switch (status) {
|
|
case 401:
|
|
return queryRoute(method, path, callback);
|
|
case 403:
|
|
return window.alert('Authentication failed. Try again.');
|
|
default:
|
|
try {
|
|
return callback(this, status === 200);
|
|
} catch (e) {
|
|
window.alert('Unable to process server response: ' + e);
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
const args = [method, apiPrefix + path, true];
|
|
if (authError) {
|
|
args.push('try', 'again');
|
|
}
|
|
ajaxRequest.open(...args);
|
|
ajaxRequest.send();
|
|
return ajaxRequest;
|
|
}
|
|
|
|
/// \brief Makes an AJAX query for the specified form.
|
|
function startFormQuery(formId, handler)
|
|
{
|
|
return startFormQueryEx(formId, handler).ajaxRequest;
|
|
}
|
|
|
|
/// \brief Makes an AJAX query for the specified form.
|
|
function startFormQueryEx(formId, handler)
|
|
{
|
|
const form = document.getElementById(formId);
|
|
const params = makeFormQueryParameter(form);
|
|
return {
|
|
ajaxRequest: queryRoute(form.method, form.getAttribute('action') + params, handler),
|
|
form: form,
|
|
params, params,
|
|
};
|
|
}
|
|
|
|
/// \brief Returns the query parameter for the specified \a form element.
|
|
function makeFormQueryParameter(form)
|
|
{
|
|
const params = [];
|
|
const formElements = form.elements;
|
|
for (let i = 0, count = formElements.length; i != count; ++i) {
|
|
const formElement = formElements[i];
|
|
if (formElement.disabled || formElement.style.display === 'none') {
|
|
continue; // if we disable a form element or hide it via CSS we also don't want to submit its data
|
|
}
|
|
const type = formElement.type;
|
|
if ((type === 'checkbox' || type === 'radio') && !formElement.checked) {
|
|
continue;
|
|
}
|
|
const name = formElement.name;
|
|
if (name === undefined || name.length < 1) {
|
|
continue;
|
|
}
|
|
else if (name === 'package-names') {
|
|
const packageNames = formElement.value.split(/[,\s]+/);
|
|
packageNames.forEach(function (packageName) {
|
|
if (packageName.length <= 0) {
|
|
return;
|
|
}
|
|
params.push(['package', encodeURIComponent(packageName)].join("="));
|
|
});
|
|
continue;
|
|
}
|
|
const values = [];
|
|
const options = formElement.options;
|
|
if (options !== undefined) {
|
|
for (let i = 0, end = options.length; i != end; ++i) {
|
|
const option = options[i];
|
|
if (option.selected && option.dataset.ignore) {
|
|
continue;
|
|
}
|
|
const value = option.value;
|
|
if (option.selected && value !== undefined && value !== 'none' && value !== 'None') {
|
|
values.push(value);
|
|
}
|
|
}
|
|
} else if (formElement.value !== undefined) {
|
|
values.push(formElement.value);
|
|
}
|
|
values.forEach(function(value) {
|
|
params.push([encodeURIComponent(name), encodeURIComponent(value)].join("="));
|
|
});
|
|
}
|
|
if (params.length < 1) {
|
|
return "";
|
|
}
|
|
return "?" + params.join("&");
|
|
}
|
|
|
|
function makeIdParams(ids)
|
|
{
|
|
if (!Array.isArray(ids)) {
|
|
ids = [ids];
|
|
}
|
|
return ids.map(id => 'id=' + encodeURIComponent(id)).join('&');
|
|
}
|
|
|
|
/// \brief Shows an alert for the specified AJAX request.
|
|
function showAjaxError(xhr, action)
|
|
{
|
|
let errorMessage;
|
|
try {
|
|
errorMessage = JSON.parse(xhr.responseText).error;
|
|
} catch (e) {
|
|
errorMessage = xhr.responseText;
|
|
}
|
|
if (!errorMessage) {
|
|
errorMessage = 'unknown error';
|
|
}
|
|
window.alert('Unable to ' + action + ': ' + errorMessage);
|
|
}
|
|
|
|
/// \brief Returns whether the specified AJAX request failed and shows an alert it it did.
|
|
function checkForAjaxError(xhr, action)
|
|
{
|
|
if (xhr.status === 200) {
|
|
return false;
|
|
}
|
|
showAjaxError(xhr, action);
|
|
return true;
|
|
}
|