From d0e8154c21aad71e28b8c3a8e0a018f5ea743566 Mon Sep 17 00:00:00 2001 From: nessi Date: Thu, 12 Feb 2026 13:01:08 +0100 Subject: [PATCH] Improve alert handling and UI for Alerts and Dashboard pages Added expandable alert details to the Alerts page, providing more insights into each warning or alert. Enhanced the Dashboard to display distinct counts for warnings and alerts, along with updated KPIs and improved styling for better visual hierarchy. These changes improve usability and clarity in monitoring alert statuses. --- frontend/src/pages/AlertsPage.jsx | 125 ++++++++++++++++++++------- frontend/src/pages/DashboardPage.jsx | 42 ++++++--- frontend/src/styles.css | 117 ++++++++++++++++++++----- 3 files changed, 221 insertions(+), 63 deletions(-) diff --git a/frontend/src/pages/AlertsPage.jsx b/frontend/src/pages/AlertsPage.jsx index cb6ceaa..2d96407 100644 --- a/frontend/src/pages/AlertsPage.jsx +++ b/frontend/src/pages/AlertsPage.jsx @@ -19,12 +19,18 @@ function formatAlertValue(value) { return Number(value).toFixed(2); } +function formatTs(ts) { + if (!ts) return "-"; + return new Date(ts).toLocaleString(); +} + export function AlertsPage() { const { tokens, refresh, me } = useAuth(); const [targets, setTargets] = useState([]); const [status, setStatus] = useState({ warnings: [], alerts: [], warning_count: 0, alert_count: 0 }); const [definitions, setDefinitions] = useState([]); const [form, setForm] = useState(initialForm); + const [expandedKey, setExpandedKey] = useState(""); const [error, setError] = useState(""); const [loading, setLoading] = useState(true); const [testing, setTesting] = useState(false); @@ -160,6 +166,10 @@ export function AlertsPage() { } }; + const toggleExpanded = (key) => { + setExpandedKey((prev) => (prev === key ? "" : key)); + }; + if (loading) return
Loading alerts...
; return ( @@ -184,17 +194,39 @@ export function AlertsPage() {

Warnings

{status.warnings?.length ? (
- {status.warnings.map((item) => ( -
-
- Warning - {item.name} - {item.target_name} -
-

{item.description}

-

{item.message}

-
- ))} + {status.warnings.map((item) => { + const isOpen = expandedKey === item.alert_key; + return ( +
toggleExpanded(item.alert_key)} + role="button" + tabIndex={0} + > +
+ Warning + {item.name} + {item.target_name} +
+

{item.description}

+

{item.message}

+ {isOpen && ( +
+
Source{item.source}
+
Category{item.category}
+
Current Value{formatAlertValue(item.value)}
+
Comparison{item.comparison}
+
Warning Threshold{formatAlertValue(item.warning_threshold)}
+
Alert Threshold{formatAlertValue(item.alert_threshold)}
+
Checked At{formatTs(item.checked_at)}
+
Target ID{item.target_id}
+ {item.sql_text &&
{item.sql_text}
} +
+ )} +
+ ); + })}
) : (

No warning-level alerts right now.

@@ -205,17 +237,39 @@ export function AlertsPage() {

Alerts

{status.alerts?.length ? (
- {status.alerts.map((item) => ( -
-
- Alert - {item.name} - {item.target_name} -
-

{item.description}

-

{item.message}

-
- ))} + {status.alerts.map((item) => { + const isOpen = expandedKey === item.alert_key; + return ( +
toggleExpanded(item.alert_key)} + role="button" + tabIndex={0} + > +
+ Alert + {item.name} + {item.target_name} +
+

{item.description}

+

{item.message}

+ {isOpen && ( +
+
Source{item.source}
+
Category{item.category}
+
Current Value{formatAlertValue(item.value)}
+
Comparison{item.comparison}
+
Warning Threshold{formatAlertValue(item.warning_threshold)}
+
Alert Threshold{formatAlertValue(item.alert_threshold)}
+
Checked At{formatTs(item.checked_at)}
+
Target ID{item.target_id}
+ {item.sql_text &&
{item.sql_text}
} +
+ )} +
+ ); + })}
) : (

No critical alerts right now.

@@ -225,9 +279,14 @@ export function AlertsPage() { {canManageAlerts && ( <> -
-

Create Custom Alert

-

Admins and operators can add SQL-based checks with warning and alert thresholds.

+
+ +
+

Create Custom Alert

+

Admins and operators can add SQL-based checks with warning and alert thresholds.

+
+ +
@@ -246,7 +305,7 @@ export function AlertsPage() {