Show request errors as a toast

Or at least they will once we add the required CSS, but there is at
least the JavaScript behaviour in place now.
This commit is contained in:
jordi fita mas 2023-07-26 18:52:32 +02:00
parent b0317f1051
commit cab949f8a6
2 changed files with 69 additions and 0 deletions

68
web/static/camper.js Normal file
View File

@ -0,0 +1,68 @@
function ready(fn) {
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
ready(function () {
const snackBar = Object.assign(
document.body.appendChild(document.createElement('section')),
{
id: 'snackbar',
}
);
const errorMessage = snackBar.appendChild(document.createElement('div'));
errorMessage.setAttribute('role', 'alert');
const openClass = 'open';
const toasts = [];
let timeoutId = null;
function showError(message) {
toasts.push(message);
popUp();
}
function popUp() {
if (toasts.length === 0) {
return;
}
if (errorMessage.classList.contains(openClass)) {
dismiss();
return;
}
if (errorMessage.innerText !== "") {
// it will show after remove calls popUp again.
return;
}
errorMessage.innerText = toasts[0];
errorMessage.classList.add(openClass);
timeoutId = setTimeout(dismiss, 4000);
}
function dismiss() {
if (!errorMessage.classList.contains(openClass)) {
// already dismissed
return;
}
errorMessage.classList.remove(openClass);
clearTimeout(timeoutId);
timeoutId = setTimeout(remove, 350);
}
function remove() {
clearTimeout(timeoutId);
toasts.splice(0, 1);
errorMessage.innerText = "";
popUp();
}
document.body.addEventListener('htmx:error', function (evt) {
const errorInfo = evt.detail.errorInfo;
const error = errorInfo.xhr && errorInfo.xhr.responseText || errorInfo.error;
showError(error);
});
})

View File

@ -9,6 +9,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{ template "title" . }} — Camper</title>
<link rel="stylesheet" media="screen" href="/static/camper.css">
<script type="module" src="/static/camper.js"></script>
<script src="/static/htmx@1.9.3.min.js"></script>
</head>
<body>