REFACTOR: add 'toast' helper response handler to produce toasts
This commit is contained in:
parent
e12f347650
commit
39c2250719
@ -34,7 +34,7 @@ func (app *Application) recoverPanic(next http.Handler) http.Handler {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
w.Header().Set("Connection", "close")
|
||||
app.error_500(w, fmt.Errorf("%s", err))
|
||||
app.error_500(w, r, fmt.Errorf("%s", err))
|
||||
}
|
||||
}()
|
||||
next.ServeHTTP(w, r)
|
||||
|
@ -28,24 +28,27 @@ func (app *Application) error_404(w http.ResponseWriter) {
|
||||
http.Error(w, "Not Found", 404)
|
||||
}
|
||||
|
||||
func (app *Application) error_500(w http.ResponseWriter, err error) {
|
||||
func (app *Application) error_500(w http.ResponseWriter, r *http.Request, err error) {
|
||||
trace := fmt.Sprintf("%s\n%s", err.Error(), debug.Stack())
|
||||
err2 := app.ErrorLog.Output(2, trace) // Magic
|
||||
if err2 != nil {
|
||||
panic(err2)
|
||||
}
|
||||
app.toast(w, r, Toast{Title: "Server error", Message: err.Error(), Type: "error"})
|
||||
}
|
||||
|
||||
func (app *Application) toast(w http.ResponseWriter, r *http.Request, t Toast) {
|
||||
// Reset the HTMX response to return an error toast and put it in the
|
||||
w.Header().Set("HX-Reswap", "beforeend")
|
||||
w.Header().Set("HX-Retarget", "#errorMessages")
|
||||
w.Header().Set("HX-Retarget", "#toasts")
|
||||
w.Header().Set("HX-Push-Url", "false")
|
||||
|
||||
r := renderer{
|
||||
Filenames: []string{get_filepath("tpl/http_500.tpl")},
|
||||
TplName: "error-toast",
|
||||
Data: struct {
|
||||
ErrorMsg string
|
||||
}{err.Error()},
|
||||
}
|
||||
r.BufferedRender(w)
|
||||
app.buffered_render_htmx(w, "toast", PageGlobalData{}, t)
|
||||
}
|
||||
|
||||
type Toast struct {
|
||||
Title string
|
||||
Message string
|
||||
Type string
|
||||
AutoCloseDelay int64
|
||||
}
|
||||
|
@ -293,7 +293,31 @@ main {
|
||||
/**
|
||||
* Toast notification popup that gets sent on HTTP 500
|
||||
*/
|
||||
.error-messages {
|
||||
.toast {
|
||||
border-radius: 1em;
|
||||
padding: 1em;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
margin: 1em;
|
||||
width: 90%;
|
||||
|
||||
/* Default: use "success" toast */
|
||||
background-color: #efe;
|
||||
border: 1px solid green;
|
||||
color: green;
|
||||
|
||||
&.toast--error {
|
||||
color: red;
|
||||
background-color: #fee;
|
||||
border-color: red;
|
||||
}
|
||||
&.toast--warning {
|
||||
color: hsl(50.59deg 75% 40%);
|
||||
background-color: #ffe;
|
||||
border-color: hsl(50.59deg 75% 40%);
|
||||
}
|
||||
}
|
||||
.toasts {
|
||||
position: fixed;
|
||||
left: var(--width-body-margins);
|
||||
top: 10em;
|
||||
@ -301,18 +325,6 @@ main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.error-messages__msg {
|
||||
background-color: #fee;
|
||||
border: 1px solid red;
|
||||
border-radius: 1em;
|
||||
padding: 1em;
|
||||
color: red;
|
||||
text-align: center;
|
||||
word-wrap: break-word;
|
||||
margin: 1em;
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -440,10 +452,12 @@ main {
|
||||
*/
|
||||
.text {
|
||||
display: block;
|
||||
margin-bottom: 0.4em;
|
||||
margin-bottom: 0.5em;
|
||||
margin-top: 0;
|
||||
overflow-wrap: anywhere;
|
||||
cursor: text;
|
||||
/* Prevent empty paragraphs from being collapsed into each other (i.e., `margin-bottom`s overlapping) */
|
||||
padding-bottom: 0.1em;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
|
@ -1,6 +0,0 @@
|
||||
{{define "error-toast"}}
|
||||
<div class="error-messages__msg" open>
|
||||
<span>{{.ErrorMsg}}</span>
|
||||
<button class="suicide" onclick="htmx.remove('.error-messages__msg')">X</button>
|
||||
</div>
|
||||
{{end}}
|
@ -43,7 +43,7 @@
|
||||
<a class="button image-carousel__close-button" onclick="image_carousel.close()">X</a>
|
||||
<img class="image-carousel__active-image" src="">
|
||||
</dialog>
|
||||
<div class="error-messages" id="errorMessages">
|
||||
<div class="toasts" id="toasts">
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
13
internal/webserver/tpl/includes/toast.tpl
Normal file
13
internal/webserver/tpl/includes/toast.tpl
Normal file
@ -0,0 +1,13 @@
|
||||
{{define "toast"}}
|
||||
<div
|
||||
class="toast toast--{{.Type}}"
|
||||
{{if .AutoCloseDelay}}
|
||||
hx-on::load="setTimeout(() => this.remove(), {{.AutoCloseDelay}} + 2000); setTimeout(() => this.classList.add('disappearing'), {{.AutoCloseDelay}})"
|
||||
{{end}}
|
||||
>
|
||||
<span class="toast__message">{{.Message}}</span>
|
||||
{{if not .AutoCloseDelay}}
|
||||
<button class="suicide" onclick="this.parentElement.remove()">X</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
Loading…
x
Reference in New Issue
Block a user