>({})
+
+ const push = useCallback((config: ToastConfig) => {
+ const item = { ...config, id: ID_COUNTER++ }
+ const timeout = config.timeoutInMs ?? 5000
+
+ setToasts((prev) => [...prev, item])
+
+ setTimeout(() => {
+ setFading((prev) => ({ ...prev, [item.id]: true }))
+ }, Math.max(0, timeout - 500))
+
+ setTimeout(() => {
+ setToasts((prev) => prev.filter((t) => t.id !== item.id))
+
+ setFading((prev) => {
+ const result = { ...prev }
+ delete result[item.id]
+
+ return result
+ })
+ }, timeout)
+ }, [])
+
+ pushRef.current = push
+
+ return (
+
+ {toasts.map((t) => (
+
+ ))}
+
+ )
+}
diff --git a/client/src/contexts/ToastsContext/types.ts b/client/src/contexts/ToastsContext/types.ts
new file mode 100644
index 0000000..dfdd13b
--- /dev/null
+++ b/client/src/contexts/ToastsContext/types.ts
@@ -0,0 +1,15 @@
+import { ComponentChildren } from 'preact'
+
+export type ToastConfig = {
+ message: ComponentChildren
+ timeoutInMs?: number
+ variant?: 'success' | 'info' | 'error'
+}
+
+export type ToastConfigWithUniqueId = ToastConfig & {
+ id: number
+}
+
+export type ToastsContextType = {
+ push: (config: ToastConfig) => void
+}
diff --git a/client/src/utils/hooks/useForm.tsx b/client/src/utils/hooks/useForm.tsx
index af6d054..70e614a 100644
--- a/client/src/utils/hooks/useForm.tsx
+++ b/client/src/utils/hooks/useForm.tsx
@@ -270,6 +270,7 @@ export const useForm = ({
) => {
return {
name,
+ id: name,
ref: handleInputRef,
onChange: (e: Event) => handleInputChange(e, options),
value: `${internalRef.current.value[name] ?? ''}`,
diff --git a/server/routes/mqtt_brokers.go b/server/routes/mqtt_brokers.go
index e1279fd..6e7cff9 100644
--- a/server/routes/mqtt_brokers.go
+++ b/server/routes/mqtt_brokers.go
@@ -137,7 +137,7 @@ func PostMQTTBrokerPublish(s *app.Server) gin.HandlerFunc {
}
if err := s.Services.MQTTBrokers.PublishTopic(brokerId, body.Topic, body.Message, qos, retain); err != nil {
- c.AbortWithError(http.StatusInternalServerError, err)
+ c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}