diff --git a/.gitignore b/.gitignore index 9202ae2..a703f29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /node_modules/ /tse_events.* -/.env \ No newline at end of file +/.env +monitor.db* \ No newline at end of file diff --git a/dashboard/src/App.jsx b/dashboard/src/App.jsx index 65ba4c0..84b9110 100644 --- a/dashboard/src/App.jsx +++ b/dashboard/src/App.jsx @@ -2,8 +2,7 @@ import { useState, useEffect, useCallback } from 'react'; import { ThemeProvider, CssBaseline, Box, Container, Grid, Typography, ToggleButton, ToggleButtonGroup, - Chip, CircularProgress, Alert, IconButton, Tooltip, - Select, MenuItem, FormControl + Chip, CircularProgress, Alert, IconButton, Tooltip } from '@mui/material'; import RefreshIcon from '@mui/icons-material/Refresh'; import { theme } from './theme.js'; @@ -16,34 +15,23 @@ import { fetchSummary, fetchHourly, fetchOutages, fetchLive, fetchEndpoints } fr const RANGE_DAYS = { '24h': 1, '7d': 7, '30d': 30 }; const REFRESH_MS = 60_000; -export default function App() { - const [endpoints, setEndpoints] = useState([]); - const [selectedEndpoint, setSelectedEndpoint] = useState(''); +function EndpointDashboard({ endpoint, range }) { const [summary, setSummary] = useState(null); const [hourly, setHourly] = useState([]); const [outages, setOutages] = useState([]); const [live, setLive] = useState(null); - const [range, setRange] = useState('7d'); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [lastRefresh, setLastRefresh] = useState(null); - useEffect(() => { - fetchEndpoints().then(eps => { - setEndpoints(eps); - if (eps.length > 0) setSelectedEndpoint(eps[0].id); - }).catch(e => setError(e.message)); - }, []); - const refresh = useCallback(async () => { - if (!selectedEndpoint) return; const days = RANGE_DAYS[range] ?? 7; try { const [s, h, o, l] = await Promise.all([ - fetchSummary(selectedEndpoint), - fetchHourly(selectedEndpoint, days), - fetchOutages(selectedEndpoint, 50), - fetchLive(selectedEndpoint), + fetchSummary(endpoint.id), + fetchHourly(endpoint.id, days), + fetchOutages(endpoint.id, 50), + fetchLive(endpoint.id), ]); setSummary(s); setHourly(h); setOutages(o); setLive(l); setError(null); @@ -53,7 +41,7 @@ export default function App() { } finally { setLoading(false); } - }, [range, selectedEndpoint]); + }, [range, endpoint.id]); useEffect(() => { setLoading(true); @@ -64,6 +52,76 @@ export default function App() { const isOnline = live && (Date.now() - new Date(live.ts).getTime()) < 180_000; + return ( + + + + {endpoint.id} + + ({endpoint.url}) + + + + {live && ( + + )} + + + + {lastRefresh && ( + + updated {lastRefresh.toLocaleTimeString()} + + )} + + + + + + + + {error && API error: {error}} + + {loading && !summary ? ( + + + + ) : ( + + + + + + + + + + + + + + + )} + + ); +} + +export default function App() { + const [endpoints, setEndpoints] = useState([]); + const [range, setRange] = useState('7d'); + const [error, setError] = useState(null); + + useEffect(() => { + fetchEndpoints() + .then(setEndpoints) + .catch(e => setError(e.message)); + }, []); + return ( @@ -78,94 +136,34 @@ export default function App() { }}> - - ⚡ TSE Monitor + + ⚡ Monitor - {endpoints.length > 0 && ( - - - - )} - - - - {live && ( - <> - - - )} - - {lastRefresh && ( - - updated {lastRefresh.toLocaleTimeString()} - - )} - - - - - - + v && setRange(v)} + > + {['24h','7d','30d'].map(v => ( + {v} + ))} + - {error && API error: {error}} - - {loading && !summary ? ( + {error && Failed to load endpoints: {error}} + + {!error && endpoints.length === 0 && ( - ) : ( - - {/* Summary cards */} - - - - - {/* Time-range toggle */} - - v && setRange(v)} - > - {['24h','7d','30d'].map(v => ( - {v} - ))} - - - - {/* Availability chart */} - - - - - {/* Response-time chart */} - - - - - {/* Outage table */} - - - - )} + + {endpoints.map(ep => ( + + ))}