mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
197 lines
8.0 KiB
Django/Jinja
197 lines
8.0 KiB
Django/Jinja
<script>
|
|
const keyImportButton = $("#key-import-btn");
|
|
const packageAddButton = $("#package-add-btn");
|
|
const packageRebuildButton = $("#package-rebuild-btn");
|
|
const packageRemoveButton = $("#package-remove-btn");
|
|
const packageUpdateButton = $("#package-update-btn");
|
|
|
|
const table = $("#packages");
|
|
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", () => {
|
|
packageRemoveButton.prop("disabled", !table.bootstrapTable("getSelections").length);
|
|
});
|
|
table.on("click-row.bs.table", (self, data, row, cell) => {
|
|
if (0 === cell || "base" === cell) {
|
|
const method = data[0] === true ? "uncheckBy" : "checkBy"; // fck javascript
|
|
table.bootstrapTable(method, {field: "id", values: [data.id]});
|
|
} else showLogs(data.id);
|
|
});
|
|
table.on("created-controls.bs.table", () => {
|
|
const pickerInput = $(".bootstrap-table-filter-control-timestamp");
|
|
pickerInput.daterangepicker({
|
|
autoUpdateInput: false,
|
|
locale: {
|
|
cancelLabel: "Clear",
|
|
},
|
|
});
|
|
|
|
pickerInput.on("apply.daterangepicker", (event, picker) => {
|
|
pickerInput.val(`${picker.startDate.format("YYYY-MM-DD")} - ${picker.endDate.format("YYYY-MM-DD")}`);
|
|
table.bootstrapTable("triggerSearch");
|
|
});
|
|
|
|
pickerInput.on("cancel.daterangepicker", () => {
|
|
pickerInput.val("");
|
|
table.bootstrapTable("triggerSearch");
|
|
});
|
|
});
|
|
|
|
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 message = successText(packages.join(", "));
|
|
showSuccess("Success", message);
|
|
},
|
|
error: (jqXHR, _, errorThrown) => {
|
|
showFailure("Action failed", failureText, jqXHR, errorThrown);
|
|
},
|
|
});
|
|
}
|
|
|
|
function getSelection() {
|
|
return table.bootstrapTable("getSelections").map(row => row.id);
|
|
}
|
|
|
|
function removePackages() {
|
|
const onSuccess = update => `Packages ${update} have been removed`;
|
|
const onFailure = error => `Could not remove packages: ${error}`;
|
|
doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure);
|
|
}
|
|
|
|
function updatePackages() {
|
|
const currentSelection = getSelection();
|
|
const [url, onSuccess] = currentSelection.length === 0
|
|
? ["/api/v1/service/update", _ => "Repository update has been run"]
|
|
: ["/api/v1/service/add", update => `Run update for packages ${update}`];
|
|
const onFailure = error => `Packages update failed: ${error}`;
|
|
doPackageAction(url, currentSelection, onSuccess, onFailure);
|
|
}
|
|
|
|
function hideControls(hidden) {
|
|
keyImportButton.attr("hidden", hidden);
|
|
packageAddButton.attr("hidden", hidden);
|
|
packageRebuildButton.attr("hidden", hidden);
|
|
packageRemoveButton.attr("hidden", hidden);
|
|
packageUpdateButton.attr("hidden", hidden);
|
|
}
|
|
|
|
function reload() {
|
|
table.bootstrapTable("showLoading");
|
|
|
|
const badgeClass = status => {
|
|
if (status === "pending") return "btn-outline-warning";
|
|
if (status === "building") return "btn-outline-warning";
|
|
if (status === "failed") return "btn-outline-danger";
|
|
if (status === "success") return "btn-outline-success";
|
|
return "btn-outline-secondary";
|
|
};
|
|
|
|
$.ajax({
|
|
url: "/api/v1/packages",
|
|
type: "GET",
|
|
dataType: "json",
|
|
success: response => {
|
|
const extractListProperties = (description, property) => {
|
|
return Object.values(description.packages)
|
|
.map(pkg => pkg[property])
|
|
.reduce((left, right) => left.concat(right), []);
|
|
};
|
|
const listToTable = data => {
|
|
return Array.from(new Set(data))
|
|
.sort()
|
|
.map(entry => 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),
|
|
packager: description.package.packager ? safe(description.package.packager) : "",
|
|
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
|
|
const message = error => `Could not load list of packages: ${error}`;
|
|
showFailure("Load failure", message, jqXHR, errorThrown);
|
|
}
|
|
hideControls(true);
|
|
},
|
|
});
|
|
|
|
$.ajax({
|
|
url: "/api/v1/status",
|
|
type: "GET",
|
|
dataType: "json",
|
|
success: response => {
|
|
repositoryBadge.text(`${response.repository} ${response.architecture}`);
|
|
versionBadge.html(`<i class="bi bi-github"></i> ahriman ${safe(response.version)}`);
|
|
|
|
statusBadge
|
|
.popover("dispose")
|
|
.attr("data-bs-content", `${response.status.status} at ${new Date(1000 * response.status.timestamp).toISOString()}`)
|
|
.popover();
|
|
statusBadge.removeClass();
|
|
statusBadge.addClass("btn");
|
|
statusBadge.addClass(badgeClass(response.status.status));
|
|
},
|
|
});
|
|
}
|
|
|
|
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)};
|
|
}
|
|
|
|
function filterListGroups() {
|
|
return extractDataList(table.bootstrapTable("getData"), "groups");
|
|
}
|
|
|
|
function filterListLicenses() {
|
|
return extractDataList(table.bootstrapTable("getData"), "licenses");
|
|
}
|
|
|
|
function filterListPackagers() {
|
|
return extractDataList(table.bootstrapTable("getData"), "packager");
|
|
}
|
|
|
|
$(() => {
|
|
table.bootstrapTable({});
|
|
statusBadge.popover();
|
|
reload();
|
|
});
|
|
</script> |