mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-28 09:17:17 +00:00
234 lines
9.4 KiB
Django/Jinja
234 lines
9.4 KiB
Django/Jinja
<script>
|
|
const packageRemoveButton = document.getElementById("package-remove-button");
|
|
const packageUpdateButton = document.getElementById("package-update-button");
|
|
|
|
let repository = null;
|
|
|
|
// so far bootstrap-table only operates with jquery elements
|
|
const table = $(document.getElementById("packages"));
|
|
|
|
const statusBadge = document.getElementById("badge-status");
|
|
const versionBadge = document.getElementById("badge-version");
|
|
|
|
function doPackageAction(uri, packages, repository, successText, failureText, data) {
|
|
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 => {
|
|
showFailure("Action failed", failureText, error);
|
|
},
|
|
);
|
|
}
|
|
|
|
function filterListGroups() {
|
|
return extractDataList(table.bootstrapTable("getData"), "groups");
|
|
}
|
|
|
|
function filterListLicenses() {
|
|
return extractDataList(table.bootstrapTable("getData"), "licenses");
|
|
}
|
|
|
|
function filterListPackagers() {
|
|
return extractDataList(table.bootstrapTable("getData"), "packager");
|
|
}
|
|
|
|
function getRepositorySelector(selector) {
|
|
const selected = selector.options[selector.selectedIndex];
|
|
return {
|
|
architecture: selected.getAttribute("data-architecture"),
|
|
repository: selected.getAttribute("data-repository"),
|
|
};
|
|
}
|
|
|
|
function getSelection() {
|
|
return table.bootstrapTable("getSelections").map(row => row.id);
|
|
}
|
|
|
|
function packagesRemove(packages) {
|
|
packages = packages ?? getSelection();
|
|
const onSuccess = update => `Packages ${update} have been removed`;
|
|
const onFailure = error => `Could not remove packages: ${error}`;
|
|
|
|
doPackageAction("/api/v1/service/remove", packages, repository, onSuccess, onFailure);
|
|
}
|
|
|
|
function packagesUpdate() {
|
|
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, repository, onSuccess, onFailure);
|
|
}
|
|
|
|
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";
|
|
};
|
|
|
|
makeRequest(
|
|
"/api/v1/packages",
|
|
{
|
|
query: {
|
|
architecture: repository.architecture,
|
|
repository: repository.repository,
|
|
},
|
|
convert: response => response.json(),
|
|
},
|
|
data => {
|
|
const payload = data.map(description => {
|
|
const package_base = description.package.base;
|
|
const web_url = description.package.remote.web_url;
|
|
return {
|
|
id: package_base,
|
|
base: web_url ? safeLink(web_url, package_base, package_base).outerHTML : 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).toISOStringShort(),
|
|
status: description.status.status,
|
|
};
|
|
});
|
|
|
|
table.bootstrapTable("load", payload);
|
|
table.bootstrapTable("uncheckAll");
|
|
table.bootstrapTable("hideLoading");
|
|
},
|
|
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();
|
|
table.find("tbody").append(`<tr class="unauthorized"><td colspan="100%">${safe(text)}</td></tr>`);
|
|
table.bootstrapTable("hideLoading");
|
|
} else {
|
|
// other errors
|
|
const message = details => `Could not load list of packages: ${details}`;
|
|
showFailure("Load failure", message, error);
|
|
}
|
|
},
|
|
);
|
|
|
|
makeRequest(
|
|
"/api/v1/status",
|
|
{
|
|
query: {
|
|
architecture: repository.architecture,
|
|
repository: repository.repository,
|
|
},
|
|
convert: response => response.json(),
|
|
},
|
|
data => {
|
|
versionBadge.innerHTML = `<i class="bi bi-github"></i> ahriman ${safe(data.version)}`;
|
|
|
|
statusBadge.classList.remove(...statusBadge.classList);
|
|
statusBadge.classList.add("btn");
|
|
statusBadge.classList.add(badgeClass(data.status.status));
|
|
|
|
const popover = bootstrap.Popover.getOrCreateInstance(statusBadge);
|
|
popover.dispose();
|
|
statusBadge.dataset.bsContent = `${data.status.status} at ${new Date(1000 * data.status.timestamp).toISOStringShort()}`;
|
|
bootstrap.Popover.getOrCreateInstance(statusBadge);
|
|
},
|
|
);
|
|
}
|
|
|
|
function selectRepository() {
|
|
const fragment = window.location.hash.replace("#", "") || "{{ repositories[0].id }}";
|
|
document.getElementById(`${fragment}-link`).click();
|
|
}
|
|
|
|
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)};
|
|
}
|
|
|
|
ready(_ => {
|
|
document.querySelectorAll("#repositories a").forEach(element => {
|
|
element.onclick = _ => {
|
|
repository = {
|
|
architecture: element.dataset.architecture,
|
|
repository: element.dataset.repository,
|
|
};
|
|
if (packageUpdateButton) {
|
|
packageUpdateButton.innerHTML = `<i class="bi bi-play"></i> update<span class="d-none d-sm-inline"> ${safe(repository.repository)} (${safe(repository.architecture)})</span>`;
|
|
}
|
|
bootstrap.Tab.getOrCreateInstance(document.getElementById(element.id)).show();
|
|
reload();
|
|
};
|
|
});
|
|
|
|
table.on("check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table", _ => {
|
|
if (packageRemoveButton) {
|
|
packageRemoveButton.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 showPackageInfo(data.id);
|
|
});
|
|
table.on("created-controls.bs.table", _ => {
|
|
new easepick.create({
|
|
element: document.querySelector(".bootstrap-table-filter-control-timestamp"),
|
|
css: [
|
|
"https://cdn.jsdelivr.net/npm/@easepick/bundle@1.2.1/dist/index.css",
|
|
],
|
|
grid: 2,
|
|
calendars: 2,
|
|
autoApply: false,
|
|
locale: {
|
|
cancel: "Clear",
|
|
},
|
|
RangePlugin: {
|
|
tooltip: false,
|
|
},
|
|
plugins: [
|
|
"RangePlugin",
|
|
],
|
|
setup: picker => {
|
|
picker.on("select", _ => { table.bootstrapTable("triggerSearch"); });
|
|
// replace "Cancel" behaviour to "Clear"
|
|
picker.onClickCancelButton = element => {
|
|
if (picker.isCancelButton(element)) {
|
|
picker.clear();
|
|
picker.hide();
|
|
table.bootstrapTable("triggerSearch");
|
|
}
|
|
};
|
|
},
|
|
});
|
|
});
|
|
|
|
bootstrap.Popover.getOrCreateInstance(statusBadge);
|
|
selectRepository();
|
|
});
|
|
</script>
|