u
This commit is contained in:
@@ -3,6 +3,7 @@ import {
|
||||
ThemeProvider, CssBaseline, Box, Container, Grid,
|
||||
Typography, ToggleButton, ToggleButtonGroup,
|
||||
Chip, CircularProgress, Alert, IconButton, Tooltip,
|
||||
Select, MenuItem, FormControl
|
||||
} from '@mui/material';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import { theme } from './theme.js';
|
||||
@@ -10,12 +11,14 @@ import SummaryCards from './components/SummaryCards.jsx';
|
||||
import AvailabilityChart from './components/AvailabilityChart.jsx';
|
||||
import ResponseTimeChart from './components/ResponseTimeChart.jsx';
|
||||
import OutageTable from './components/OutageTable.jsx';
|
||||
import { fetchSummary, fetchHourly, fetchOutages, fetchLive } from './api.js';
|
||||
import { fetchSummary, fetchHourly, fetchOutages, fetchLive, fetchEndpoints } from './api.js';
|
||||
|
||||
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('');
|
||||
const [summary, setSummary] = useState(null);
|
||||
const [hourly, setHourly] = useState([]);
|
||||
const [outages, setOutages] = useState([]);
|
||||
@@ -25,14 +28,22 @@ export default function App() {
|
||||
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(),
|
||||
fetchHourly(days),
|
||||
fetchOutages(50),
|
||||
fetchLive(),
|
||||
fetchSummary(selectedEndpoint),
|
||||
fetchHourly(selectedEndpoint, days),
|
||||
fetchOutages(selectedEndpoint, 50),
|
||||
fetchLive(selectedEndpoint),
|
||||
]);
|
||||
setSummary(s); setHourly(h); setOutages(o); setLive(l);
|
||||
setError(null);
|
||||
@@ -42,7 +53,7 @@ export default function App() {
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [range]);
|
||||
}, [range, selectedEndpoint]);
|
||||
|
||||
useEffect(() => {
|
||||
setLoading(true);
|
||||
@@ -67,10 +78,26 @@ export default function App() {
|
||||
}}>
|
||||
<Container maxWidth="xl">
|
||||
<Box sx={{ py: 1.5, display: 'flex', alignItems: 'center', gap: 2, flexWrap: 'wrap' }}>
|
||||
<Typography variant="h5" sx={{ flexGrow: 1, letterSpacing: '-0.5px' }}>
|
||||
<Typography variant="h5" sx={{ letterSpacing: '-0.5px' }}>
|
||||
⚡ TSE Monitor
|
||||
</Typography>
|
||||
|
||||
{endpoints.length > 0 && (
|
||||
<FormControl size="small" sx={{ minWidth: 120 }}>
|
||||
<Select
|
||||
value={selectedEndpoint}
|
||||
onChange={(e) => setSelectedEndpoint(e.target.value)}
|
||||
sx={{ color: 'white', '& .MuiSelect-icon': { color: 'white' }, '& .MuiOutlinedInput-notchedOutline': { borderColor: 'rgba(255,255,255,0.3)' } }}
|
||||
>
|
||||
{endpoints.map(ep => (
|
||||
<MenuItem key={ep.id} value={ep.id}>{ep.id}</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
|
||||
<Box sx={{ flexGrow: 1 }} />
|
||||
|
||||
{live && (
|
||||
<>
|
||||
<Chip
|
||||
@@ -79,8 +106,6 @@ export default function App() {
|
||||
size="small"
|
||||
sx={{ fontWeight: 700 }}
|
||||
/>
|
||||
<Chip label={`sig #${live.signature_counter}`} variant="outlined" size="small" />
|
||||
<Chip label={`tx #${live.transaction_counter}`} variant="outlined" size="small" />
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
@@ -6,8 +6,9 @@ async function get(path) {
|
||||
return r.json();
|
||||
}
|
||||
|
||||
export const fetchSummary = () => get('/api/summary');
|
||||
export const fetchHourly = (days = 7) => get(`/api/hourly?days=${days}`);
|
||||
export const fetchDaily = (days = 30)=> get(`/api/daily?days=${days}`);
|
||||
export const fetchOutages = (limit=50) => get(`/api/outages?limit=${limit}`);
|
||||
export const fetchLive = () => get('/api/live');
|
||||
export const fetchEndpoints = () => get('/api/endpoints');
|
||||
export const fetchSummary = (ep) => get(`/api/summary?endpoint=${encodeURIComponent(ep)}`);
|
||||
export const fetchHourly = (ep, days = 7) => get(`/api/hourly?endpoint=${encodeURIComponent(ep)}&days=${days}`);
|
||||
export const fetchDaily = (ep, days = 30) => get(`/api/daily?endpoint=${encodeURIComponent(ep)}&days=${days}`);
|
||||
export const fetchOutages = (ep, limit = 50) => get(`/api/outages?endpoint=${encodeURIComponent(ep)}&limit=${limit}`);
|
||||
export const fetchLive = (ep) => get(`/api/live?endpoint=${encodeURIComponent(ep)}`);
|
||||
|
||||
Reference in New Issue
Block a user