From 8e8be8a62254498784f1fab47149193f709b169f Mon Sep 17 00:00:00 2001 From: Evgenii Alekseev Date: Wed, 4 Sep 2024 18:38:24 +0300 Subject: [PATCH] remove ajax and md5 --- .../templates/build-status/alerts.jinja2 | 8 +- .../build-status/key-import-modal.jinja2 | 40 +++-- .../templates/build-status/login-modal.jinja2 | 22 +-- .../build-status/package-add-modal.jinja2 | 17 ++- .../build-status/package-info-modal.jinja2 | 140 +++++++++--------- .../templates/build-status/table.jinja2 | 82 +++++----- .../templates/utils/bootstrap-scripts.jinja2 | 35 ++++- 7 files changed, 201 insertions(+), 143 deletions(-) diff --git a/package/share/ahriman/templates/build-status/alerts.jinja2 b/package/share/ahriman/templates/build-status/alerts.jinja2 index 54f98567..ec70d464 100644 --- a/package/share/ahriman/templates/build-status/alerts.jinja2 +++ b/package/share/ahriman/templates/build-status/alerts.jinja2 @@ -2,7 +2,7 @@ const alertPlaceholder = document.getElementById("alert-placeholder"); function createAlert(title, message, clz, action, id) { - if (!id) id = $.md5(title + message); // MD5 id from the content + id ??= md5(title + message); // MD5 id from the content if (alertPlaceholder.querySelector(`#alert-${id}`)) return; // check if there are duplicates const wrapper = document.createElement("div"); @@ -32,12 +32,12 @@ toast.show(); } - function showFailure(title, description, jqXHR, errorThrown) { + function showFailure(title, description, error) { let details; try { - details = JSON.parse(jqXHR.responseText).error; // execution handler json error response + details = JSON.parse(error.text).error; // execution handler json error response } catch (_) { - details = errorThrown; + details = error.text ?? error; } createAlert(title, description(details), "text-bg-danger"); } diff --git a/package/share/ahriman/templates/build-status/key-import-modal.jinja2 b/package/share/ahriman/templates/build-status/key-import-modal.jinja2 index 4a9f9bb3..ca18c0e4 100644 --- a/package/share/ahriman/templates/build-status/key-import-modal.jinja2 +++ b/package/share/ahriman/templates/build-status/key-import-modal.jinja2 @@ -55,13 +55,17 @@ const server = keyImportServerInput.value; if (key && server) { - $.ajax({ - url: "/api/v1/service/pgp", - data: {"key": key, "server": server}, - type: "GET", - dataType: "json", - success: response => { keyImportBodyInput.textContent = response.key; }, - }); + makeRequest( + "/api/v1/service/pgp", + { + query: { + key: key, + server: server, + }, + convert: response => response.json(), + }, + data => { keyImportBodyInput.textContent = data.key; }, + ); } } @@ -70,20 +74,24 @@ const server = keyImportServerInput.value; if (key && server) { - $.ajax({ - url: "/api/v1/service/pgp", - data: JSON.stringify({key: key, server: server}), - type: "POST", - contentType: "application/json", - success: _ => { + makeRequest( + "/api/v1/service/pgp", + { + method: "POST", + json: { + key: key, + server: server, + }, + }, + _ => { bootstrap.Modal.getOrCreateInstance(keyImportModal).hide(); showSuccess("Success", `Key ${key} has been imported`); }, - error: (jqXHR, _, errorThrown) => { + error => { const message = _ => `Could not import key ${key} from ${server}`; - showFailure("Action failed", message, jqXHR, errorThrown); + showFailure("Action failed", message, error); }, - }); + ); } } diff --git a/package/share/ahriman/templates/build-status/login-modal.jinja2 b/package/share/ahriman/templates/build-status/login-modal.jinja2 index a4412ced..ec137d53 100644 --- a/package/share/ahriman/templates/build-status/login-modal.jinja2 +++ b/package/share/ahriman/templates/build-status/login-modal.jinja2 @@ -46,23 +46,27 @@ const username = loginUsernameInput.value; if (username && password) { - $.ajax({ - url: "/api/v1/login", - data: JSON.stringify({username: username, password: password}), - type: "POST", - contentType: "application/json", - success: _ => { + makeRequest( + "/api/v1/login", + { + method: "POST", + json: { + username: username, + password: password, + }, + }, + _ => { bootstrap.Modal.getOrCreateInstance(loginModal).hide(); showSuccess("Logged in", `Successfully logged in as ${username}`, _ => location.href = "/"); }, - error: (jqXHR, _, errorThrown) => { + error => { const message = _ => username === "admin" && password === "admin" ? "You've entered a password for user \"root\", did you make a typo in username?" : `Could not login as ${username}`; - showFailure("Login error", message, jqXHR, errorThrown); + showFailure("Login error", message, error); }, - }); + ); } } diff --git a/package/share/ahriman/templates/build-status/package-add-modal.jinja2 b/package/share/ahriman/templates/build-status/package-add-modal.jinja2 index 5a7638fa..328f6b19 100644 --- a/package/share/ahriman/templates/build-status/package-add-modal.jinja2 +++ b/package/share/ahriman/templates/build-status/package-add-modal.jinja2 @@ -141,10 +141,15 @@ const value = packageAddInput.value; if (value.length >= 3) { - const query = new URLSearchParams({for: value}); - fetch(`/api/v1/service/search?${query.toString()}`) - .then(response => response.json()) - .then(data => { + makeRequest( + "/api/v1/service/search", + { + query: { + for: value, + }, + convert: response => response.json(), + }, + data => { const options = data.map(pkg => { const option = document.createElement("option"); option.value = pkg.package; @@ -152,8 +157,8 @@ return option; }); packageAddKnownPackagesList.replaceChildren(...options); - }) - .catch(_ => {}); + }, + ); } }, 500); }); diff --git a/package/share/ahriman/templates/build-status/package-info-modal.jinja2 b/package/share/ahriman/templates/build-status/package-info-modal.jinja2 index f92eedfc..bde98ad3 100644 --- a/package/share/ahriman/templates/build-status/package-info-modal.jinja2 +++ b/package/share/ahriman/templates/build-status/package-info-modal.jinja2 @@ -163,12 +163,13 @@ variableButtonRemove.classList.add("btn-outline-danger"); variableButtonRemove.innerHTML = ""; variableButtonRemove.onclick = _ => { - $.ajax({ - url: `/api/v1/packages/${packageBase}/patches/${variable.key}`, - type: "DELETE", - dataType: "json", - success: _ => variableInput.remove(), - }); + makeRequest( + `/api/v1/packages/${packageBase}/patches/${variable.key}`, + { + method: "DELETE", + }, + _ => variableInput.remove(), + ); }; // bring them together @@ -181,39 +182,41 @@ } function loadChanges(packageBase, onFailure) { - $.ajax({ - url: `/api/v1/packages/${packageBase}/changes`, - data: { - architecture: repository.architecture, - repository: repository.repository, + makeRequest( + `/api/v1/packages/${packageBase}/changes`, + { + query: { + architecture: repository.architecture, + repository: repository.repository, + }, + convert: response => response.json(), }, - type: "GET", - dataType: "json", - success: response => { - const changes = response.changes; + data => { + const changes = data.changes; packageInfoChangesInput.textContent = changes ?? ""; highlight(packageInfoChangesInput); }, - error: onFailure, - }); + onFailure, + ); } function loadEvents(packageBase, onFailure) { packageInfoEventsTable.bootstrapTable("showLoading"); clearChart(); - $.ajax({ - url: `/api/v1/events`, - data: { - architecture: repository.architecture, - repository: repository.repository, - object_id: packageBase, - limit: 30, + makeRequest( + "/api/v1/events", + { + query: { + architecture: repository.architecture, + repository: repository.repository, + object_id: packageBase, + limit: 30, + }, + convert: response => response.json(), }, - type: "GET", - dataType: "json", - success: response => { - const events = response.map(event => { + data => { + const events = data.map(event => { return { timestamp: new Date(1000 * event.created).toISOStringShort(), event: event.event, @@ -225,7 +228,7 @@ packageInfoEventsTable.bootstrapTable("hideLoading"); if (packageInfoEventsUpdateChart) { - const chart = response.filter(event => event.event === "package-updated"); + const chart = data.filter(event => event.event === "package-updated"); packageInfoEventsUpdateChart.config.data = { labels: chart.map(event => new Date(1000 * event.created).toISOStringShort()), datasets: [{ @@ -237,30 +240,31 @@ }; packageInfoEventsUpdateChart.update(); } - packageInfoEventsUpdateChart.hidden = !events.length; + packageInfoEventsUpdateChartCanvas.hidden = !events.length; }, - error: onFailure, - }); + onFailure, + ); } function loadLogs(packageBase, onFailure) { - $.ajax({ - url: `/api/v2/packages/${packageBase}/logs`, - data: { - architecture: repository.architecture, - repository: repository.repository, + makeRequest( + `/api/v2/packages/${packageBase}/logs`, + { + query: { + architecture: repository.architecture, + repository: repository.repository, + }, + convert: response => response.json(), }, - type: "GET", - dataType: "json", - success: response => { - const logs = response.map(log_record => { + data => { + const logs = data.map(log_record => { return `[${new Date(1000 * log_record.created).toISOString()}] ${log_record.message}`; }); packageInfoLogsInput.textContent = logs.join("\n"); highlight(packageInfoLogsInput); }, - error: onFailure, - }); + onFailure, + ); } function loadPackage(packageBase, onFailure) { @@ -272,16 +276,17 @@ return ["bg-secondary", "text-white"]; }; - $.ajax({ - url: `/api/v1/packages/${packageBase}`, - data: { - architecture: repository.architecture, - repository: repository.repository, + makeRequest( + `/api/v1/packages/${packageBase}`, + { + query: { + architecture: repository.architecture, + repository: repository.repository, + }, + convert: response => response.json(), }, - type: "GET", - dataType: "json", - success: response => { - const description = response.find(Boolean); + data => { + const description = data.find(Boolean); const packages = Object.keys(description.package.packages); const aurUrl = description.package.remote.web_url; const upstreamUrls = Array.from( @@ -313,22 +318,23 @@ packageInfoUpstreamUrl.innerHTML = upstreamUrls.map(url => safeLink(url, url, "upstream link").outerHTML).join("
"); packageInfoVersion.textContent = description.package.version; }, - error: onFailure, - }); + onFailure, + ); } function loadPatches(packageBase, onFailure) { - $.ajax({ - url: `/api/v1/packages/${packageBase}/patches`, - type: "GET", - dataType: "json", - success: response => { - packageInfoVariablesDiv.replaceChildren(); - response.map(patch => insertVariable(packageBase, patch)); - packageInfoVariablesBlock.hidden = !response.length; + makeRequest( + `/api/v1/packages/${packageBase}/patches`, + { + convert: response => response.json(), }, - error: onFailure, - }); + data => { + packageInfoVariablesDiv.replaceChildren(); + data.map(patch => insertVariable(packageBase, patch)); + packageInfoVariablesBlock.hidden = !data.length; + }, + onFailure, + ); } function packageInfoRemove() { @@ -348,10 +354,10 @@ else packageBase = packageInfoModal.package; // read package base from the current window attribute - const onFailure = (jqXHR, _, errorThrown) => { + const onFailure = error => { if (isPackageBaseSet) { - const message = error => `Could not load package ${packageBase} info: ${error}`; - showFailure("Load failure", message, jqXHR, errorThrown); + const message = details => `Could not load package ${packageBase} info: ${details}`; + showFailure("Load failure", message, error); } }; diff --git a/package/share/ahriman/templates/build-status/table.jinja2 b/package/share/ahriman/templates/build-status/table.jinja2 index b5f282b6..88dd1a78 100644 --- a/package/share/ahriman/templates/build-status/table.jinja2 +++ b/package/share/ahriman/templates/build-status/table.jinja2 @@ -11,24 +11,24 @@ const versionBadge = document.getElementById("badge-version"); function doPackageAction(uri, packages, repository, successText, failureText, data) { - const queryParams = $.param({ - architecture: repository.architecture, - repository: repository.repository, - }); // it will never be empty btw - - $.ajax({ - url: `${uri}?${queryParams}`, - data: JSON.stringify(Object.assign({}, {packages: packages}, data || {})), - type: "POST", - contentType: "application/json", - success: _ => { + makeRequest( + uri, + { + method: "POST", + query: { + architecture: repository.architecture, + repository: repository.repository, + }, + json: Object.assign({}, {packages: packages}, data || {}), + }, + _ => { const message = successText(packages.join(", ")); showSuccess("Success", message); }, - error: (jqXHR, _, errorThrown) => { - showFailure("Action failed", failureText, jqXHR, errorThrown); + error => { + showFailure("Action failed", failureText, error); }, - }); + ); } function filterListGroups() { @@ -84,16 +84,17 @@ return "btn-outline-secondary"; }; - $.ajax({ - url: "/api/v1/packages", - data: { - architecture: repository.architecture, - repository: repository.repository, + makeRequest( + "/api/v1/packages", + { + query: { + architecture: repository.architecture, + repository: repository.repository, + }, + convert: response => response.json(), }, - type: "GET", - dataType: "json", - success: response => { - const payload = response.map(description => { + data => { + const payload = data.map(description => { const package_base = description.package.base; const web_url = description.package.remote.web_url; return { @@ -113,8 +114,8 @@ table.bootstrapTable("uncheckAll"); table.bootstrapTable("hideLoading"); }, - error: (jqXHR, _, errorThrown) => { - if ((jqXHR.status === 401) || (jqXHR.status === 403)) { + error => { + if ((error.status === 401) || (error.status === 403)) { // authorization error const text = "In order to see statuses you must login first."; table.find("tr.unauthorized").remove(); @@ -122,33 +123,34 @@ table.bootstrapTable("hideLoading"); } else { // other errors - const message = error => `Could not load list of packages: ${error}`; - showFailure("Load failure", message, jqXHR, errorThrown); + const message = details => `Could not load list of packages: ${details}`; + showFailure("Load failure", message, error); } }, - }); + ); - $.ajax({ - url: "/api/v1/status", - data: { - architecture: repository.architecture, - repository: repository.repository, + makeRequest( + "/api/v1/status", + { + query: { + architecture: repository.architecture, + repository: repository.repository, + }, + convert: response => response.json(), }, - type: "GET", - dataType: "json", - success: response => { - versionBadge.innerHTML = ` ahriman ${safe(response.version)}`; + data => { + versionBadge.innerHTML = ` ahriman ${safe(data.version)}`; statusBadge.classList.remove(...statusBadge.classList); statusBadge.classList.add("btn"); - statusBadge.classList.add(badgeClass(response.status.status)); + statusBadge.classList.add(badgeClass(data.status.status)); const popover = bootstrap.Popover.getOrCreateInstance(statusBadge); popover.dispose(); - statusBadge.dataset.bsContent = `${response.status.status} at ${new Date(1000 * response.status.timestamp).toISOStringShort()}`; + statusBadge.dataset.bsContent = `${data.status.status} at ${new Date(1000 * data.status.timestamp).toISOStringShort()}`; bootstrap.Popover.getOrCreateInstance(statusBadge); }, - }); + ); } function selectRepository() { diff --git a/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 b/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 index f2321486..b27f0de8 100644 --- a/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 +++ b/package/share/ahriman/templates/utils/bootstrap-scripts.jinja2 @@ -1,5 +1,5 @@ - + @@ -66,6 +66,39 @@ .join("
"); } + function makeRequest(url, params, onSuccess, onFailure) { + const requestParams = { + method: params.method, + body: params.json ? JSON.stringify(params.json) : params.json, + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + }, + }; + if (params.query) { + const query = new URLSearchParams(params.query); + url += `?${query.toString()}`; + } + convert = params.convert ?? (response => response.text()); + + return fetch(url, requestParams) + .then(response => { + if (response.ok) { + return convert(response); + } else { + const error = new Error("Network request error"); + error.status = response.status; + error.statusText = response.statusText; + return response.text().then(text => { + error.text = text; + throw error; + }); + } + }) + .then(data => onSuccess && onSuccess(data)) + .catch(error => onFailure && onFailure(error)); + } + function safe(string) { return String(string) .replace(/&/g, "&")