142 lines
3.3 KiB
Go
142 lines
3.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"git.haelnorr.com/h/golib/hws"
|
|
)
|
|
|
|
// NotificationType defines the type of notification
|
|
type NotificationType string
|
|
|
|
const (
|
|
NotificationSuccess NotificationType = "success"
|
|
NotificationWarning NotificationType = "warning"
|
|
NotificationInfo NotificationType = "info"
|
|
)
|
|
|
|
// Notification represents a toast notification (success, warning, info)
|
|
type Notification struct {
|
|
Type NotificationType `json:"type"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
}
|
|
|
|
// ErrorModal represents a full-screen error modal (500, 503)
|
|
type ErrorModal struct {
|
|
Code int `json:"code"`
|
|
Title string `json:"title"`
|
|
Message string `json:"message"`
|
|
Details string `json:"details"`
|
|
}
|
|
|
|
// setHXTrigger sets the HX-Trigger header with JSON-encoded data
|
|
func setHXTrigger(w http.ResponseWriter, event string, data any) {
|
|
payload := map[string]any{
|
|
event: data,
|
|
}
|
|
|
|
jsonData, err := json.Marshal(payload)
|
|
if err != nil {
|
|
// Fallback if JSON encoding fails
|
|
w.Header().Set("HX-Trigger", event)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("HX-Trigger", string(jsonData))
|
|
}
|
|
|
|
// formatErrorDetails extracts and formats error details from wrapped errors
|
|
func formatErrorDetails(err error) string {
|
|
if err == nil {
|
|
return ""
|
|
}
|
|
|
|
// Use %+v format to get stack trace from github.com/pkg/errors
|
|
return fmt.Sprintf("%+v", err)
|
|
}
|
|
|
|
// notifyToast sends a toast notification via HX-Trigger header
|
|
func notifyToast(
|
|
w http.ResponseWriter,
|
|
notifType NotificationType,
|
|
title string,
|
|
message string,
|
|
) {
|
|
notification := Notification{
|
|
Type: notifType,
|
|
Title: title,
|
|
Message: message,
|
|
}
|
|
|
|
setHXTrigger(w, "showNotification", notification)
|
|
}
|
|
|
|
// notifyErrorModal sends a full-screen error modal via HX-Trigger header
|
|
func notifyErrorModal(
|
|
s *hws.Server,
|
|
w http.ResponseWriter,
|
|
statusCode int,
|
|
title string,
|
|
message string,
|
|
err error,
|
|
) {
|
|
modal := ErrorModal{
|
|
Code: statusCode,
|
|
Title: title,
|
|
Message: message,
|
|
Details: formatErrorDetails(err),
|
|
}
|
|
|
|
// Log the error
|
|
s.LogError(hws.HWSError{
|
|
StatusCode: statusCode,
|
|
Message: message,
|
|
Error: err,
|
|
Level: hws.ErrorERROR,
|
|
})
|
|
|
|
// Set response status
|
|
w.WriteHeader(statusCode)
|
|
|
|
// Send notification via HX-Trigger
|
|
setHXTrigger(w, "showErrorModal", modal)
|
|
}
|
|
|
|
// notifySuccess sends a success toast notification
|
|
func notifySuccess(w http.ResponseWriter, title string, message string) {
|
|
notifyToast(w, NotificationSuccess, title, message)
|
|
}
|
|
|
|
// notifyWarning sends a warning toast notification
|
|
func notifyWarning(w http.ResponseWriter, title string, message string) {
|
|
notifyToast(w, NotificationWarning, title, message)
|
|
}
|
|
|
|
// notifyInfo sends an info toast notification
|
|
func notifyInfo(w http.ResponseWriter, title string, message string) {
|
|
notifyToast(w, NotificationInfo, title, message)
|
|
}
|
|
|
|
// notifyInternalServiceError sends a 500 error modal
|
|
func notifyInternalServiceError(
|
|
s *hws.Server,
|
|
w http.ResponseWriter,
|
|
message string,
|
|
err error,
|
|
) {
|
|
notifyErrorModal(s, w, 500, "Internal Server Error", message, err)
|
|
}
|
|
|
|
// notifyServiceUnavailable sends a 503 error modal
|
|
func notifyServiceUnavailable(
|
|
s *hws.Server,
|
|
w http.ResponseWriter,
|
|
message string,
|
|
err error,
|
|
) {
|
|
notifyErrorModal(s, w, 503, "Service Unavailable", message, err)
|
|
}
|