mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
166 lines
6.8 KiB
Django/Jinja
166 lines
6.8 KiB
Django/Jinja
<script>
|
|
const addButton = $("#add-btn");
|
|
const removeButton = $("#remove-btn");
|
|
const updateButton = $("#update-btn");
|
|
|
|
const table = $("#packages");
|
|
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table",
|
|
() => {
|
|
removeButton.prop("disabled", !table.bootstrapTable("getSelections").length);
|
|
});
|
|
table.on("click-row.bs.table", (_, row) => { showLogs(row.id); });
|
|
|
|
const architectureBadge = $("#badge-architecture");
|
|
const repositoryBadge = $("#badge-repository");
|
|
const statusBadge = $("#badge-status");
|
|
const versionBadge = $("#badge-version");
|
|
|
|
function doPackageAction(uri, packages, successText, failureText) {
|
|
$.ajax({
|
|
url: uri,
|
|
data: JSON.stringify({packages: packages}),
|
|
type: "POST",
|
|
contentType: "application/json",
|
|
success: _ => {
|
|
const details = packages.map(pkg => {
|
|
const li = document.createElement("li");
|
|
li.innerText = pkg;
|
|
return li;
|
|
});
|
|
showSuccess("Success", successText, details);
|
|
},
|
|
error: (jqXHR, _, errorThrown) => {
|
|
showFailure("Action failed", failureText, errorThrown);
|
|
},
|
|
});
|
|
}
|
|
|
|
function getSelection() {
|
|
return table.bootstrapTable("getSelections").map(row => { return row.id; });
|
|
}
|
|
|
|
function removePackages() {
|
|
doPackageAction("/api/v1/service/remove", getSelection(), "The following packages have been removed:", "Packages removal failed:");
|
|
}
|
|
|
|
function updatePackages() {
|
|
const currentSelection = getSelection();
|
|
const url = currentSelection.length === 0 ? "/api/v1/service/update" : "/api/v1/service/add";
|
|
doPackageAction(url, getSelection(), "Packages update has been run", "Packages update failed:");
|
|
}
|
|
|
|
function hideControls(hidden) {
|
|
addButton.attr("hidden", hidden);
|
|
removeButton.attr("hidden", hidden);
|
|
updateButton.attr("hidden", hidden);
|
|
}
|
|
|
|
function reload() {
|
|
table.bootstrapTable("showLoading");
|
|
|
|
$.ajax({
|
|
url: "/api/v1/packages",
|
|
type: "GET",
|
|
dataType: "json",
|
|
success: response => {
|
|
const extractListProperties = (description, property) => {
|
|
return Object.values(description.packages)
|
|
.map(pkg => { return pkg[property]; })
|
|
.reduce((left, right) => { return left.concat(right); }, []);
|
|
};
|
|
const listToTable = data => {
|
|
return Array.from(new Set(data))
|
|
.sort()
|
|
.map(entry => { return safe(entry); })
|
|
.join("<br>");
|
|
};
|
|
|
|
const payload = response.map(description => {
|
|
const package_base = description.package.base;
|
|
const web_url = description.package.remote?.web_url;
|
|
return {
|
|
id: package_base,
|
|
base: web_url ? `<a href="${safe(web_url)}" title="${safe(package_base)}">${safe(package_base)}</a>` : safe(package_base),
|
|
version: safe(description.package.version),
|
|
packages: listToTable(Object.keys(description.package.packages)),
|
|
groups: listToTable(extractListProperties(description.package, "groups")),
|
|
licenses: listToTable(extractListProperties(description.package, "licenses")),
|
|
timestamp: new Date(1000 * description.status.timestamp).toISOString(),
|
|
status: description.status.status,
|
|
};
|
|
});
|
|
|
|
table.bootstrapTable("load", payload);
|
|
table.bootstrapTable("uncheckAll");
|
|
table.bootstrapTable("hideLoading");
|
|
hideControls(false);
|
|
},
|
|
error: (jqXHR, _, errorThrown) => {
|
|
if ((jqXHR.status === 401) || (jqXHR.status === 403)) {
|
|
// authorization error
|
|
const text = "In order to see statuses you must login first.";
|
|
table.find("tr.unauthorized").remove();
|
|
table.find("tbody").append(`<tr class="unauthorized"><td colspan="100%">${safe(text)}</td></tr>`);
|
|
table.bootstrapTable("hideLoading");
|
|
} else {
|
|
// other errors
|
|
showFailure("Load failure", "Could not load list of packages:", errorThrown);
|
|
}
|
|
hideControls(true);
|
|
},
|
|
});
|
|
|
|
$.ajax({
|
|
url: "/api/v1/status",
|
|
type: "GET",
|
|
dataType: "json",
|
|
success: response => {
|
|
const badgeColor = status => {
|
|
if (status === "pending") return "yellow";
|
|
if (status === "building") return "yellow";
|
|
if (status === "failed") return "critical";
|
|
if (status === "success") return "success";
|
|
return "inactive";
|
|
};
|
|
|
|
architectureBadge
|
|
.attr("src", `https://img.shields.io/badge/architecture-${response.architecture}-informational`)
|
|
.attr("alt", response.architecture);
|
|
repositoryBadge
|
|
.attr("src", `https://img.shields.io/badge/repository-${response.repository.replace(/-/g, "--")}-informational`)
|
|
.attr("alt", response.repository);
|
|
statusBadge
|
|
.attr("src", `https://img.shields.io/badge/service%20status-${response.status.status}-${badgeColor(response.status.status)}`)
|
|
.attr("alt", response.status.status)
|
|
.attr("title", `at ${new Date(1000 * response.status.timestamp).toISOString()}`);
|
|
versionBadge
|
|
.attr("src", `https://img.shields.io/badge/version-${response.version}-informational`)
|
|
.attr("alt", response.version);
|
|
},
|
|
});
|
|
}
|
|
|
|
function safe(string) {
|
|
return String(string)
|
|
.replace(/&/g, "&")
|
|
.replace(/</g, "<")
|
|
.replace(/>/g, ">")
|
|
.replace(/"/g, """);
|
|
}
|
|
|
|
function statusFormat(value) {
|
|
const cellClass = status => {
|
|
if (status === "pending") return "table-warning";
|
|
if (status === "building") return "table-warning";
|
|
if (status === "failed") return "table-danger";
|
|
if (status === "success") return "table-success";
|
|
return "table-secondary";
|
|
};
|
|
return {classes: cellClass(value)};
|
|
}
|
|
|
|
$(() => {
|
|
table.bootstrapTable({});
|
|
reload();
|
|
});
|
|
</script> |