From ce6e887d1bb084b06751b07e679251527083e3fd Mon Sep 17 00:00:00 2001 From: Henry Dollman Date: Wed, 11 Sep 2024 15:50:15 -0400 Subject: [PATCH] progress on settings / alerts --- beszel/internal/alerts/alerts.go | 45 +++---- .../components/routes/settings/general.tsx | 15 ++- .../src/components/routes/settings/layout.tsx | 4 +- .../routes/settings/notifications.tsx | 120 ++++++++++++------ beszel/site/src/index.css | 3 + 5 files changed, 118 insertions(+), 69 deletions(-) diff --git a/beszel/internal/alerts/alerts.go b/beszel/internal/alerts/alerts.go index 77422b3..e2c5550 100644 --- a/beszel/internal/alerts/alerts.go +++ b/beszel/internal/alerts/alerts.go @@ -185,46 +185,47 @@ func (am *AlertManager) sendAlert(data AlertData) { } func (am *AlertManager) SendShoutrrrAlert(notificationUrl, title, message, link, linkText string) error { + // services that support title param supportsTitle := []string{"bark", "discord", "gotify", "ifttt", "join", "matrix", "ntfy", "opsgenie", "pushbullet", "pushover", "slack", "teams", "telegram", "zulip"} - supportsLink := []string{"ntfy"} + // Parse the URL parsedURL, err := url.Parse(notificationUrl) if err != nil { return fmt.Errorf("error parsing URL: %v", err) } - scheme := parsedURL.Scheme - - // // Get query parameters queryParams := parsedURL.Query() // Add title - if !sliceContains(supportsTitle, scheme) { - message = title + "\n\n" + message - } else { + if sliceContains(supportsTitle, scheme) { queryParams.Add("title", title) - - } - // Add link - if !sliceContains(supportsLink, scheme) { - // add link to the message - message += "\n\n" + link - } else { - // ntfy link - if scheme == "ntfy" { - queryParams.Add("Actions", fmt.Sprintf("view, %s, %s", linkText, link)) + } else if scheme == "mattermost" { + // use markdown title for mattermost + message = "##### " + title + "\n\n" + message + } else if scheme == "generic" && queryParams.Has("template") { + // add title as property if using generic with template json + titleKey := queryParams.Get("titlekey") + if titleKey == "" { + titleKey = "title" } + queryParams.Add("$"+titleKey, title) + } else { + // otherwise just add title to message + message = title + "\n\n" + message } - // - if scheme == "generic" { - queryParams.Add("template", "json") - queryParams.Add("$title", title) + // Add link + if scheme == "ntfy" { + // if ntfy, add link to actions + queryParams.Add("Actions", fmt.Sprintf("view, %s, %s", linkText, link)) + } else { + // else add link directly to the message + message += "\n\n" + link } // Encode the modified query parameters back into the URL parsedURL.RawQuery = queryParams.Encode() - log.Println("URL after modification:", parsedURL.String()) + // log.Println("URL after modification:", parsedURL.String()) err = shoutrrr.Send(parsedURL.String(), message) diff --git a/beszel/site/src/components/routes/settings/general.tsx b/beszel/site/src/components/routes/settings/general.tsx index 71c9bfb..00dea21 100644 --- a/beszel/site/src/components/routes/settings/general.tsx +++ b/beszel/site/src/components/routes/settings/general.tsx @@ -9,6 +9,7 @@ import { } from '@/components/ui/select' import { chartTimeData } from '@/lib/utils' import { Separator } from '@/components/ui/separator' +import { SaveIcon } from 'lucide-react' export default function SettingsProfilePage() { return ( @@ -20,8 +21,11 @@ export default function SettingsProfilePage() { */}
- - {/* */} +
+

Chart options

+

Adjust display options for charts.

+
+

- Sets the default time range for charts. + Sets the default time range for charts when a system is viewed.

- +
) diff --git a/beszel/site/src/components/routes/settings/layout.tsx b/beszel/site/src/components/routes/settings/layout.tsx index 9f5b6dd..57b0f98 100644 --- a/beszel/site/src/components/routes/settings/layout.tsx +++ b/beszel/site/src/components/routes/settings/layout.tsx @@ -35,10 +35,10 @@ export default function SettingsLayout() { }, []) return ( - + Settings - Manage your account settings and set e-mail preferences. + Manage notification and display preferences. diff --git a/beszel/site/src/components/routes/settings/notifications.tsx b/beszel/site/src/components/routes/settings/notifications.tsx index d340ea7..d023188 100644 --- a/beszel/site/src/components/routes/settings/notifications.tsx +++ b/beszel/site/src/components/routes/settings/notifications.tsx @@ -5,7 +5,9 @@ import { pb } from '@/lib/stores' import { Separator } from '@/components/ui/separator' import { Card } from '@/components/ui/card' // import { Switch } from '@/components/ui/switch' -import { Trash2Icon } from 'lucide-react' +import { LoaderCircleIcon, PlusIcon, SaveIcon, Trash2Icon } from 'lucide-react' +import { useState } from 'react' +import { toast } from '@/components/ui/use-toast' export default function SettingsNotificationsPage() { return ( @@ -20,7 +22,7 @@ export default function SettingsNotificationsPage() {

Email notifications

- Get notified when new alerts are created. + Leave the emails field to disable email notifications.

@@ -36,63 +38,99 @@ export default function SettingsNotificationsPage() {

Beszel uses{' '} Shoutrrr {' '} to integrate with popular notification services.

- -
- - - - - {/* - */} -
-
+ - + ) } + +async function sendTestNotification(url: string) { + const res = await pb.send('/api/beszel/send-test-notification', { url }) + if ('err' in res && !res.err) { + toast({ + title: 'Test notification sent', + description: 'Check your notification service', + }) + } else { + toast({ + title: 'Error', + description: res.err ?? 'Failed to send test notification', + variant: 'destructive', + }) + } +} + +// todo unique ids +function ShoutrrrUrlCard() { + const [url, setUrl] = useState('') + const [isLoading, setIsLoading] = useState(false) + + return ( + +
+ + setUrl(e.target.value)} + /> + + + {/* + */} +
+
+ ) +} diff --git a/beszel/site/src/index.css b/beszel/site/src/index.css index 36bc611..d46b356 100644 --- a/beszel/site/src/index.css +++ b/beszel/site/src/index.css @@ -78,6 +78,9 @@ body { @apply bg-background text-foreground; } + .link { + @apply text-primary font-medium underline-offset-4 hover:underline; + } } .recharts-tooltip-wrapper {