Middleware+View+UserState: Add toast messages

This commit is contained in:
Riyyi
2024-11-21 22:48:01 +01:00
parent 6b93045514
commit 7f1e78fa08
10 changed files with 225 additions and 10 deletions
+16 -5
View File
@@ -19,17 +19,24 @@ struct MainLayout<Body: HTML>: HTMLDocument {
.href("https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css"),
.integrity("sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH"),
.crossorigin(.anonymous))
link(
.rel(.stylesheet),
.href("https://cdnjs.cloudflare.com/ajax/libs/bootstrap-icons/1.11.3/font/bootstrap-icons.min.css"),
.integrity("sha384-XGjxtQfXaH2tnPFa9x+ruJTuLE3Aa6LhHSWRr1XeTyhezb4abCG4ccI5AkVDxqC+"),
.crossorigin(.anonymous))
link(.rel(.stylesheet), .href("/css/style.css"))
// ---------------------------------
// Style
style {
"""
body {
padding-top: 56px;
}
"""
"""
body {
padding-top: 56px;
}
"""
}
}
@@ -50,6 +57,9 @@ body {
pageContent
}
}
// Placeholder for all toast messages
ToastView()
}
// ---------------------------------
@@ -76,6 +86,7 @@ body {
.integrity("sha384-yhWpPsq2os1hEnx1I8cH7Ius6rclwTm3G2fhXDLF6Pzv7UnSsXY7BAj4fB6PIgSz"),
.crossorigin(.anonymous)
) {}
script(.src("/js/site.js")) {}
}
+53
View File
@@ -0,0 +1,53 @@
import Elementary
import ElementaryHTMX
// Usage:
//
// let state = try getState(request: req)
// state.toast = ToastState(message: "", title: "", level: ToastState.Level.error)
// throw Abort(.badRequest, headers: ["HX-Trigger": "toast"])
//
// The header "HX-Trigger" will make the part refresh and show the toast message
struct ToastView: HTML {
var state: ToastState = ToastState()
// -------------------------------------
var content: some HTML {
div(
.class("toast-container"), .id("cdiv_toast"),
.hx.get("/toast"),
.hx.trigger(HTMLAttributeValue.HTMX.EventTrigger(rawValue: "toast from:body")),
.hx.swap(.outerHTML)
) {
div(.class("toast"), .id("toast")) {
div(.class("toast-header bg-\(state.level.rawValue) text-white")) {
strong(.class("me-auto")) { state.title }
button(
.class("btn-close btn-close-white"), .type(.button),
.data("bs-dismiss", value: "toast")
) {}
}
div(.class("toast-body")) { state.message }
}
if !state.message.isEmpty {
script {
"""
runOnceAfterSettle(function () {
const element = document.getElementById("toast");
const toast = new bootstrap.Toast(element, { autohide: true, delay: 5000 });
toast.show();
element.addEventListener("hidden.bs.toast", function () {
element.remove();
});
});
"""
}
}
}
}
}