mirror of
https://github.com/arcan1s/ahriman.git
synced 2025-04-24 15:27:17 +00:00
replace alert bodals with toasts
This commit is contained in:
parent
c403c45d72
commit
0f8596db1e
@ -18,6 +18,8 @@
|
|||||||
<h1 id="badge-repository">ahriman</h1>
|
<h1 id="badge-repository">ahriman</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="alert-placeholder" class="toast-container p3 top-0 start-50 translate-middle-x"></div>
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div id="toolbar" class="dropdown">
|
<div id="toolbar" class="dropdown">
|
||||||
<a id="badge-status" tabindex="0" role="button" class="btn btn-outline-secondary" data-bs-toggle="popover" data-bs-trigger="focus" data-bs-content="no run data"><i class="bi bi-info-circle"></i></a>
|
<a id="badge-status" tabindex="0" role="button" class="btn btn-outline-secondary" data-bs-toggle="popover" data-bs-trigger="focus" data-bs-content="no run data"><i class="bi bi-info-circle"></i></a>
|
||||||
@ -126,8 +128,7 @@
|
|||||||
{% include "build-status/login-modal.jinja2" %}
|
{% include "build-status/login-modal.jinja2" %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% include "build-status/failed-modal.jinja2" %}
|
{% include "build-status/alerts.jinja2" %}
|
||||||
{% include "build-status/success-modal.jinja2" %}
|
|
||||||
|
|
||||||
{% include "build-status/package-add-modal.jinja2" %}
|
{% include "build-status/package-add-modal.jinja2" %}
|
||||||
{% include "build-status/package-rebuild-modal.jinja2" %}
|
{% include "build-status/package-rebuild-modal.jinja2" %}
|
||||||
|
45
package/share/ahriman/templates/build-status/alerts.jinja2
Normal file
45
package/share/ahriman/templates/build-status/alerts.jinja2
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<script>
|
||||||
|
const alertPlaceholder = $("#alert-placeholder");
|
||||||
|
|
||||||
|
function createAlert(title, message, clz) {
|
||||||
|
const wrapper = document.createElement("div");
|
||||||
|
wrapper.classList.add("toast", clz);
|
||||||
|
wrapper.role = "alert";
|
||||||
|
wrapper.ariaLive = "assertive";
|
||||||
|
wrapper.ariaAtomic = "true";
|
||||||
|
wrapper.style.width = "500px"; // 500px is default modal size
|
||||||
|
|
||||||
|
const header = document.createElement("div");
|
||||||
|
header.classList.add("toast-header");
|
||||||
|
header.innerHTML = `<strong class="me-auto">${safe(title)}</strong> <button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="close"></button>`;
|
||||||
|
wrapper.appendChild(header);
|
||||||
|
|
||||||
|
const body = document.createElement("div");
|
||||||
|
body.classList.add("toast-body", "text-bg-light");
|
||||||
|
body.innerText = message;
|
||||||
|
wrapper.appendChild(body);
|
||||||
|
|
||||||
|
alertPlaceholder.append(wrapper);
|
||||||
|
const toast = new bootstrap.Toast(wrapper);
|
||||||
|
wrapper.addEventListener("hidden.bs.toast", () => {
|
||||||
|
wrapper.remove(); // bootstrap doesn't remove elements
|
||||||
|
reload();
|
||||||
|
});
|
||||||
|
toast.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFailure(title, description, jqXHR, errorThrown) {
|
||||||
|
let details;
|
||||||
|
try {
|
||||||
|
details = $.parseJSON(jqXHR.responseText).error; // execution handler json error response
|
||||||
|
} catch (_) {
|
||||||
|
details = errorThrown;
|
||||||
|
}
|
||||||
|
createAlert(title, description(details), "text-bg-danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSuccess(title, description) {
|
||||||
|
createAlert(title, description, "text-bg-success");
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
@ -1,34 +0,0 @@
|
|||||||
<div id="failed-modal" tabindex="-1" role="dialog" class="modal fade">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header bg-danger text-white">
|
|
||||||
<h4 id="failed-title" class="modal-title"></h4>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p id="failed-description"></p>
|
|
||||||
<p id="failed-details"></p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i> close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const failedModal = $("#failed-modal");
|
|
||||||
failedModal.on("hidden.bs.modal", () => { reload(); });
|
|
||||||
|
|
||||||
const failedDescription = $("#failed-description");
|
|
||||||
const failedDetails = $("#failed-details");
|
|
||||||
const failedTitle = $("#failed-title");
|
|
||||||
|
|
||||||
function showFailure(title, description, details) {
|
|
||||||
failedTitle.text(title);
|
|
||||||
failedDescription.text(description);
|
|
||||||
failedDetails.text(details);
|
|
||||||
|
|
||||||
failedModal.modal("show");
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -81,10 +81,11 @@
|
|||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: _ => {
|
success: _ => {
|
||||||
keyImportModal.modal("hide");
|
keyImportModal.modal("hide");
|
||||||
showSuccess("Success", `Key ${key} has been imported`, "");
|
showSuccess("Success", `Key ${key} has been imported`);
|
||||||
},
|
},
|
||||||
error: (jqXHR, _, errorThrown) => {
|
error: (jqXHR, _, errorThrown) => {
|
||||||
showFailure("Action failed", `Could not import key ${key} from ${server}`, errorThrown);
|
const message = _ => { return `Could not import key ${key} from ${server}`; };
|
||||||
|
showFailure("Action failed", message, jqXHR, errorThrown);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,9 @@
|
|||||||
const packages = packageInput.val();
|
const packages = packageInput.val();
|
||||||
if (packages) {
|
if (packages) {
|
||||||
packageAddModal.modal("hide");
|
packageAddModal.modal("hide");
|
||||||
doPackageAction("/api/v1/service/add", [packages], "The following package has been added:", "Package addition failed:");
|
const onSuccess = update => { return `Packages ${update} have been added`; };
|
||||||
|
const onFailure = error => { return `Package addition failed: ${error}`; };
|
||||||
|
doPackageAction("/api/v1/service/add", [packages], onSuccess, onFailure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +70,9 @@
|
|||||||
const packages = packageInput.val();
|
const packages = packageInput.val();
|
||||||
if (packages) {
|
if (packages) {
|
||||||
packageAddModal.modal("hide");
|
packageAddModal.modal("hide");
|
||||||
doPackageAction("/api/v1/service/request", [packages], "The following package has been requested:", "Package request failed:");
|
const onSuccess = update => { return `Packages ${update} have been requested`; };
|
||||||
|
const onFailure = error => { return `Package request failed: ${error}`; };
|
||||||
|
doPackageAction("/api/v1/service/request", [packages], onSuccess, onFailure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -60,7 +60,10 @@
|
|||||||
},
|
},
|
||||||
error: (jqXHR, _, errorThrown) => {
|
error: (jqXHR, _, errorThrown) => {
|
||||||
// show failed modal in case if first time loading
|
// show failed modal in case if first time loading
|
||||||
if (isPackageBaseSet) showFailure("Load failure", `Could not load package ${packageBase} logs:`, errorThrown);
|
if (isPackageBaseSet) {
|
||||||
|
const message = error => { return `Could not load package ${packageBase} logs: ${error}`; };
|
||||||
|
showFailure("Load failure", message, jqXHR, errorThrown);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,9 @@
|
|||||||
const packages = dependencyInput.val();
|
const packages = dependencyInput.val();
|
||||||
if (packages) {
|
if (packages) {
|
||||||
packageRebuildModal.modal("hide");
|
packageRebuildModal.modal("hide");
|
||||||
doPackageAction("/api/v1/service/rebuild", [packages], "Repository rebuild ran for the following dependencies:", "Repository rebuild failed:");
|
const onSuccess = update => { return `Repository rebuild has been run for packages which depend on ${update}`; };
|
||||||
|
const onFailure = error => { return `Repository rebuild failed: ${error}`; };
|
||||||
|
doPackageAction("/api/v1/service/rebuild", [packages], onSuccess, onFailure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<div id="success-modal" tabindex="-1" role="dialog" class="modal fade">
|
|
||||||
<div class="modal-dialog" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header bg-success text-white">
|
|
||||||
<h4 id="success-title" class="modal-title"></h4>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p id="success-description"></p>
|
|
||||||
<ul id="success-details"></ul>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-primary" data-bs-dismiss="modal"><i class="bi bi-x"></i> close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const successModal = $("#success-modal");
|
|
||||||
successModal.on("hidden.bs.modal", () => { reload(); });
|
|
||||||
|
|
||||||
const successDescription = $("#success-description");
|
|
||||||
const successDetails = $("#success-details");
|
|
||||||
const successTitle = $("#success-title");
|
|
||||||
|
|
||||||
function showSuccess(title, description, details) {
|
|
||||||
successTitle.text(title);
|
|
||||||
successDescription.text(description);
|
|
||||||
successDetails.empty().append(details);
|
|
||||||
|
|
||||||
successModal.modal("show");
|
|
||||||
}
|
|
||||||
</script>
|
|
@ -27,15 +27,11 @@
|
|||||||
type: "POST",
|
type: "POST",
|
||||||
contentType: "application/json",
|
contentType: "application/json",
|
||||||
success: _ => {
|
success: _ => {
|
||||||
const details = packages.map(pkg => {
|
const message = successText(packages.join(", "));
|
||||||
const li = document.createElement("li");
|
showSuccess("Success", message);
|
||||||
li.innerText = pkg;
|
|
||||||
return li;
|
|
||||||
});
|
|
||||||
showSuccess("Success", successText, details);
|
|
||||||
},
|
},
|
||||||
error: (jqXHR, _, errorThrown) => {
|
error: (jqXHR, _, errorThrown) => {
|
||||||
showFailure("Action failed", failureText, errorThrown);
|
showFailure("Action failed", failureText, jqXHR, errorThrown);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -45,13 +41,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function removePackages() {
|
function removePackages() {
|
||||||
doPackageAction("/api/v1/service/remove", getSelection(), "The following packages have been removed:", "Packages removal failed:");
|
const onSuccess = update => { return `Packages ${update} have been removed`; };
|
||||||
|
const onFailure = error => { return `Could not remove packages: ${error}`; };
|
||||||
|
doPackageAction("/api/v1/service/remove", getSelection(), onSuccess, onFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePackages() {
|
function updatePackages() {
|
||||||
const currentSelection = getSelection();
|
const currentSelection = getSelection();
|
||||||
const url = currentSelection.length === 0 ? "/api/v1/service/update" : "/api/v1/service/add";
|
const [url, onSuccess] = currentSelection.length === 0
|
||||||
doPackageAction(url, getSelection(), "Packages update has been run", "Packages update failed:");
|
? ["/api/v1/service/update", _ => { return "Repository update has been run"; }]
|
||||||
|
: ["/api/v1/service/add", update => { return `Run update for packages ${update}`; }];
|
||||||
|
const onFailure = error => { return `Packages update failed: ${error}`; };
|
||||||
|
doPackageAction(url, currentSelection, onSuccess, onFailure);
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideControls(hidden) {
|
function hideControls(hidden) {
|
||||||
@ -119,7 +120,8 @@
|
|||||||
table.bootstrapTable("hideLoading");
|
table.bootstrapTable("hideLoading");
|
||||||
} else {
|
} else {
|
||||||
// other errors
|
// other errors
|
||||||
showFailure("Load failure", "Could not load list of packages:", errorThrown);
|
const messaga = error => { return `Could not load list of packages: ${error}`; };
|
||||||
|
showFailure("Load failure", messaga, jqXHR, errorThrown);
|
||||||
}
|
}
|
||||||
hideControls(true);
|
hideControls(true);
|
||||||
},
|
},
|
||||||
@ -144,14 +146,6 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function safe(string) {
|
|
||||||
return String(string)
|
|
||||||
.replace(/&/g, "&")
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">")
|
|
||||||
.replace(/"/g, """);
|
|
||||||
}
|
|
||||||
|
|
||||||
function statusFormat(value) {
|
function statusFormat(value) {
|
||||||
const cellClass = status => {
|
const cellClass = status => {
|
||||||
if (status === "pending") return "table-warning";
|
if (status === "pending") return "table-warning";
|
||||||
@ -165,7 +159,7 @@
|
|||||||
|
|
||||||
$(() => {
|
$(() => {
|
||||||
table.bootstrapTable({});
|
table.bootstrapTable({});
|
||||||
$("#status-popover").popover();
|
statusBadge.popover();
|
||||||
reload();
|
reload();
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
@ -30,4 +30,12 @@
|
|||||||
button.html("<i class=\"bi bi-clipboard\"></i> copy");
|
button.html("<i class=\"bi bi-clipboard\"></i> copy");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function safe(string) {
|
||||||
|
return String(string)
|
||||||
|
.replace(/&/g, "&")
|
||||||
|
.replace(/</g, "<")
|
||||||
|
.replace(/>/g, ">")
|
||||||
|
.replace(/"/g, """);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre[class*="language-"] button{
|
pre[class*="language-"] button {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 5px;
|
right: 5px;
|
||||||
|
3
setup.py
3
setup.py
@ -72,13 +72,12 @@ setup(
|
|||||||
"package/share/ahriman/templates/telegram-index.jinja2",
|
"package/share/ahriman/templates/telegram-index.jinja2",
|
||||||
]),
|
]),
|
||||||
("share/ahriman/templates/build-status", [
|
("share/ahriman/templates/build-status", [
|
||||||
"package/share/ahriman/templates/build-status/failed-modal.jinja2",
|
"package/share/ahriman/templates/build-status/alerts.jinja2",
|
||||||
"package/share/ahriman/templates/build-status/key-import-modal.jinja2",
|
"package/share/ahriman/templates/build-status/key-import-modal.jinja2",
|
||||||
"package/share/ahriman/templates/build-status/login-modal.jinja2",
|
"package/share/ahriman/templates/build-status/login-modal.jinja2",
|
||||||
"package/share/ahriman/templates/build-status/package-add-modal.jinja2",
|
"package/share/ahriman/templates/build-status/package-add-modal.jinja2",
|
||||||
"package/share/ahriman/templates/build-status/package-info-modal.jinja2",
|
"package/share/ahriman/templates/build-status/package-info-modal.jinja2",
|
||||||
"package/share/ahriman/templates/build-status/package-rebuild-modal.jinja2",
|
"package/share/ahriman/templates/build-status/package-rebuild-modal.jinja2",
|
||||||
"package/share/ahriman/templates/build-status/success-modal.jinja2",
|
|
||||||
"package/share/ahriman/templates/build-status/table.jinja2",
|
"package/share/ahriman/templates/build-status/table.jinja2",
|
||||||
]),
|
]),
|
||||||
("share/ahriman/templates/static", [
|
("share/ahriman/templates/static", [
|
||||||
|
@ -339,13 +339,12 @@ def test_walk(resource_path_root: Path) -> None:
|
|||||||
resource_path_root / "models" / "package_gcc10_srcinfo",
|
resource_path_root / "models" / "package_gcc10_srcinfo",
|
||||||
resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo",
|
resource_path_root / "models" / "package_tpacpi-bat-git_srcinfo",
|
||||||
resource_path_root / "models" / "package_yay_srcinfo",
|
resource_path_root / "models" / "package_yay_srcinfo",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "failed-modal.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "alerts.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "key-import-modal.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "key-import-modal.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "login-modal.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "login-modal.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "package-add-modal.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "package-add-modal.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "package-info-modal.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "package-info-modal.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "package-rebuild-modal.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "package-rebuild-modal.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "success-modal.jinja2",
|
|
||||||
resource_path_root / "web" / "templates" / "build-status" / "table.jinja2",
|
resource_path_root / "web" / "templates" / "build-status" / "table.jinja2",
|
||||||
resource_path_root / "web" / "templates" / "static" / "favicon.ico",
|
resource_path_root / "web" / "templates" / "static" / "favicon.ico",
|
||||||
resource_path_root / "web" / "templates" / "utils" / "bootstrap-scripts.jinja2",
|
resource_path_root / "web" / "templates" / "utils" / "bootstrap-scripts.jinja2",
|
||||||
|
Loading…
Reference in New Issue
Block a user