From 22c7ce29e3c4dcff5009ca4033ff465a2f3549ed Mon Sep 17 00:00:00 2001 From: headlesdev Date: Mon, 26 May 2025 15:29:20 +0200 Subject: [PATCH] Finisch Notification Settings System --- .../cards/settings/NotificationSettings.tsx | 431 ++++++++++++------ hooks/useNotifications.ts | 4 +- 2 files changed, 292 insertions(+), 143 deletions(-) diff --git a/components/cards/settings/NotificationSettings.tsx b/components/cards/settings/NotificationSettings.tsx index 6fb7abd..ad0990a 100644 --- a/components/cards/settings/NotificationSettings.tsx +++ b/components/cards/settings/NotificationSettings.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react" import useNotifications from "@/hooks/useNotifications" -import { CircleHelp, Server, Smartphone } from "lucide-react" +import { Check, CircleHelp, Copy, Server, Smartphone } from "lucide-react" interface NotificationSettingsProps { onError: (message: string) => void @@ -18,6 +18,9 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting } = useNotifications() const [applicationsSettings, setApplicationsSettings] = useState(null) const [serverSettings, setServerSettings] = useState(null) + const [copiedVariable, setCopiedVariable] = useState(null) + const [serverCollapsed, setServerCollapsed] = useState(true) + const [applicationCollapsed, setApplicationCollapsed] = useState(true) const fetchNotificationSettings = async () => { const applicationsSettings = await getNotificationApplicationsSettings() @@ -26,23 +29,23 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting setServerSettings( serverSettings || { enabled: false, - statusChange: false, - cpuLimit: 0, - gpuLimit: 0, - memoryLimit: 0, - diskLimit: 0, - temperatureLimit: 0, - notificationTextStatus: "", - notificationTextCpu: "", - notificationTextGpu: "", - notificationTextMemory: "", - notificationTextDisk: "", - notificationTextTemperature: "", - notificationCpu: false, - notificationGpu: false, - notificationMemory: false, - notificationDisk: false, - notificationTemperature: false, + statusChange: true, + cpuLimit: 80, + gpuLimit: 80, + memoryLimit: 80, + diskLimit: 80, + temperatureLimit: 80, + notificationTextStatus: "{servername} went {status}", + notificationTextCpu: "{servername} CPU usage is high at {cpu}%", + notificationTextGpu: "{servername} GPU usage is high at {gpu}%", + notificationTextMemory: "{servername} Memory usage is high at {memory}%", + notificationTextDisk: "{servername} Disk usage is high at {disk}%", + notificationTextTemperature: "{servername} Temperature is high at {temperature}°C", + notificationCpu: true, + notificationGpu: true, + notificationMemory: true, + notificationDisk: true, + notificationTemperature: true, }, ) @@ -50,10 +53,10 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting applicationsSettings || { enabled: false, statusChange: false, - latencyLimit: 0, - notificationTextStatus: "", - notificationTextLatency: "", - notificationLatency: false, + latencyLimit: 1000, + notificationTextStatus: "{appname} went {status}", + notificationTextLatency: "{appname} latency is high at {latency}ms", + notificationLatency: true, }, ) } @@ -63,8 +66,37 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting }, []) const saveNotificationSettings = async () => { - await editNotificationServerSettings(serverSettings) - await editNotificationApplicationsSettings(applicationsSettings) + const response = editNotificationServerSettings(serverSettings) + if (typeof response === "string") { + onError && onError(response) + return + } + + const response2 = editNotificationApplicationsSettings(applicationsSettings) + if (typeof response2 === "string") { + onError && onError(response2) + return + } + try { + const successMessage = await response + const successMessage2 = await response2 + console.log(successMessage, successMessage2) + if (onSuccess && successMessage && successMessage2) { + onSuccess("Notification settings saved successfully") + } + } catch (apiError: any) { + onError && onError(apiError) + } + } + + const copyToClipboard = async (text: string) => { + try { + await navigator.clipboard.writeText(text) + setCopiedVariable(text) + setTimeout(() => setCopiedVariable(null), 2000) + } catch (err) { + console.error("Failed to copy text: ", err) + } } const ResourceThresholdRow = ({ @@ -88,43 +120,58 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting onMessageChange: (value: string) => void disabled: boolean }) => ( -
+
-
-
- - {label} +
+ {/* Header Row - Checkbox and Threshold */} +
+
+ + {label} +
+ +
+ Threshold: +
+ onValueChange(e.target.value)} + disabled={disabled} + min="0" + max={unit === "°C" ? "200" : "100"} + /> + {unit} +
+
-
- onValueChange(e.target.value)} - disabled={disabled} - /> - {unit} -
- -
+ {/* Message Template Row */} +
+
+ Notification Message: +
+ +
+
onMessageChange(e.target.value)} disabled={disabled} /> -
- -
@@ -132,54 +179,66 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting ) return ( -
-
- {/* Header */} -
-

Notification Settings

-

Configure monitoring alerts for your servers and applications

-
+
+ {/* Header */} +
+

Notification Settings

+

Configure monitoring alerts for your servers and applications

+
- {/* Main Content */} -
- {/* Server Monitoring Section */} -
-
-
-
- -
-
-

Server Monitoring

-

Monitor server resources and performance

-
+
+ {/* Server Monitoring Section */} +
+
+
setServerCollapsed(!serverCollapsed)} + > +
+
+
+

Server Monitoring

+

Monitor server resources and performance

+
+ + {serverSettings?.enabled ? "Active" : "Inactive"} + +
+ + + +
+
+
{/* Master Toggle */}
-
-
- setServerSettings({ ...serverSettings, enabled: !serverSettings.enabled })} - /> -
-

Enable Server Monitoring

-

Turn on global server monitoring

-
-
-
- {serverSettings?.enabled ? "Active" : "Inactive"} +
+ setServerSettings({ ...serverSettings, enabled: !serverSettings.enabled })} + /> +
+

Enable Server Monitoring

+

Turn on global server monitoring notifications

- {/* Status Change Alerts */} -
+ {/* Settings Content */} +
+ {/* Status Change Alerts */}
@@ -209,7 +268,7 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting } disabled={!serverSettings?.enabled} /> -
+
@@ -218,13 +277,9 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting
{/* Resource Thresholds */} -
-
-

Resource Thresholds

-
Configure limits
-
- -
+
+

Resource Thresholds

+
setServerSettings({ ...serverSettings, memoryLimit: value })} - unit="GB" + unit="%" message={serverSettings?.notificationTextMemory} - onMessageChange={(value) => setServerSettings({ ...serverSettings, notificationTextMemory: value })} + onMessageChange={(value) => + setServerSettings({ ...serverSettings, notificationTextMemory: value }) + } disabled={!serverSettings?.enabled} /> @@ -301,50 +358,105 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting />
+ + {/* Server Variables Reference */} +
+
+
+ +
Available Server Variables
+
+
+ {[ + { var: "{servername}", desc: "Server name or hostname" }, + { var: "{status}", desc: "Current server status" }, + { var: "{cpu}", desc: "CPU usage percentage" }, + { var: "{gpu}", desc: "GPU usage percentage" }, + { var: "{memory}", desc: "Memory usage percentage" }, + { var: "{disk}", desc: "Disk usage percentage" }, + { var: "{temperature}", desc: "Temperature in Celsius" }, + ].map((item) => ( +
copyToClipboard(item.var)} + > +
+
+
{item.var}
+
{item.desc}
+
+
+ {copiedVariable === item.var ? ( + + ) : ( + + )} +
+
+
+ ))} +
+
+
+
- {/* Application Monitoring Section */} -
-
-
-
- -
-
-

Application Monitoring

-

Monitor application performance and availability

-
+ {/* Application Monitoring Section */} +
+
+
setApplicationCollapsed(!applicationCollapsed)} + > +
+
+
+

Application Monitoring

+

Configure application monitoring notifications

+
+ + {applicationsSettings?.enabled ? "Active" : "Inactive"} + +
+ + + +
+
+
{/* Master Toggle */}
-
-
- - setApplicationsSettings({ ...applicationsSettings, enabled: !applicationsSettings.enabled }) - } - /> -
-

Enable Application Monitoring

-

Turn on global application monitoring

-
-
-
- {applicationsSettings?.enabled ? "Active" : "Inactive"} +
+ + setApplicationsSettings({ ...applicationsSettings, enabled: !applicationsSettings.enabled }) + } + /> +
+

Enable Application Monitoring

+

Turn on global application monitoring

{/* Application Settings */} -
+
{/* Status Change Alerts */}
@@ -378,7 +490,7 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting } disabled={!applicationsSettings?.enabled} /> -
+
@@ -386,13 +498,9 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting
- {/* Latency Threshold */} -
-
-

Performance Thresholds

-
Configure limits
-
- + {/* Performance Thresholds */} +
+

Performance Thresholds

setApplicationsSettings({ ...applicationsSettings, latencyLimit: Number(value) })} + onValueChange={(value) => + setApplicationsSettings({ ...applicationsSettings, latencyLimit: Number(value) }) + } unit="ms" message={applicationsSettings?.notificationTextLatency} onMessageChange={(value) => @@ -412,14 +522,53 @@ export const NotificationSettings = ({ onError, onSuccess }: NotificationSetting disabled={!applicationsSettings?.enabled} />
+ + {/* Application Variables Reference */} +
+
+
+ +
Available Application Variables
+
+
+ {[ + { var: "{appname}", desc: "Application name" }, + { var: "{status}", desc: "Application status" }, + { var: "{latency}", desc: "Application latency in ms" }, + ].map((item) => ( +
copyToClipboard(item.var)} + > +
+
+
{item.var}
+
{item.desc}
+
+
+ {copiedVariable === item.var ? ( + + ) : ( + + )} +
+
+
+ ))} +
+
+
+
- {/* Action Buttons */} -
- -
+ {/* Action Buttons */} +
+
diff --git a/hooks/useNotifications.ts b/hooks/useNotifications.ts index d47eaa9..ddddae9 100644 --- a/hooks/useNotifications.ts +++ b/hooks/useNotifications.ts @@ -97,7 +97,7 @@ const useNotifications = () => { const editNotificationApplicationsSettings = (settings: any): Promise | string => { return axios.post('/api/notifications/settings_applications_edit', settings) .then((response) => { - return response.data.notificationSettings; + return response.data.notification; }) .catch(err => { throw err.response?.data?.error || 'An error occurred'; @@ -107,7 +107,7 @@ const useNotifications = () => { const editNotificationServerSettings = (settings: any): Promise | string => { return axios.post('/api/notifications/settings_server_edit', settings) .then((response) => { - return response.data.notificationSettings; + return response.data.notification; }) .catch(err => { throw err.response?.data?.error || 'An error occurred';