import React, { useEffect, useState } from "react"; import { Link } from "react-router-dom"; import { apiFetch } from "../api"; import { useAuth } from "../state"; function getTargetGroupMeta(target) { const tags = target?.tags || {}; if (tags.monitor_mode !== "all_databases" || !tags.monitor_group_id) return null; return { id: tags.monitor_group_id, name: tags.monitor_group_name || target.name || "All databases", }; } export function DashboardPage() { const { tokens, refresh, alertStatus } = useAuth(); const [targets, setTargets] = useState([]); const [search, setSearch] = useState(""); const [openGroups, setOpenGroups] = useState({}); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); useEffect(() => { let active = true; (async () => { try { const targetRows = await apiFetch("/targets", {}, tokens, refresh); if (active) { setTargets(targetRows); } } catch (e) { if (active) setError(String(e.message || e)); } finally { if (active) setLoading(false); } })(); return () => { active = false; }; }, [tokens, refresh]); if (loading) return
Loading dashboard...
; if (error) return
{error}
; const targetSeverities = new Map(); for (const item of alertStatus.warnings || []) { if (!targetSeverities.has(item.target_id)) targetSeverities.set(item.target_id, "warning"); } for (const item of alertStatus.alerts || []) { targetSeverities.set(item.target_id, "alert"); } const affectedTargetCount = targetSeverities.size; const okCount = Math.max(0, targets.length - affectedTargetCount); const filteredTargets = targets.filter((t) => { const q = search.trim().toLowerCase(); if (!q) return true; return ( (t.name || "").toLowerCase().includes(q) || (t.host || "").toLowerCase().includes(q) || (t.dbname || "").toLowerCase().includes(q) ); }); const groupedRows = []; const groupedMap = new Map(); for (const t of filteredTargets) { const meta = getTargetGroupMeta(t); if (!meta) { groupedRows.push({ type: "single", target: t }); continue; } if (!groupedMap.has(meta.id)) { const groupRow = { type: "group", groupId: meta.id, groupName: meta.name, targets: [] }; groupedMap.set(meta.id, groupRow); groupedRows.push(groupRow); } groupedMap.get(meta.id).targets.push(t); } return (

Dashboard Overview

Real-time snapshot of monitored PostgreSQL targets.

{targets.length} Total Targets
{okCount} Status OK
{alertStatus.warning_count || 0} Warnings
{alertStatus.alert_count || 0} Alerts

Targets

{filteredTargets.length} shown of {targets.length} registered
setSearch(e.target.value)} placeholder="Search by name, host, or database..." />
{groupedRows.map((row) => { if (row.type === "single") { const t = row.target; const severity = targetSeverities.get(t.id) || "ok"; return (

{t.name}

{severity === "alert" ? "Alert" : severity === "warning" ? "Warning" : "OK"}

Host: {t.host}:{t.port}

DB: {t.dbname}

Details
); } const highestSeverity = row.targets.some((t) => targetSeverities.get(t.id) === "alert") ? "alert" : row.targets.some((t) => targetSeverities.get(t.id) === "warning") ? "warning" : "ok"; const first = row.targets[0]; const isOpen = !!openGroups[row.groupId]; return (

{row.groupName}

{highestSeverity === "alert" ? "Alert" : highestSeverity === "warning" ? "Warning" : "OK"}

Host: {first.host}:{first.port}

DB: All databases ({row.targets.length})

{isOpen && (
{row.targets.map((t) => { const severity = targetSeverities.get(t.id) || "ok"; return (
{t.dbname} {severity === "alert" ? "Alert" : severity === "warning" ? "Warning" : "OK"}
Details
); })}
)}
); })} {filteredTargets.length === 0 && (
No targets match your search.
)}
); }