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() {