fixes and improvements
This commit is contained in:
@@ -1,80 +1,108 @@
|
||||
import { Alert, Button, Chip, Stack, Typography } from "@mui/material";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Alert, Button, Stack, Tab, Typography } from "@mui/material";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import {
|
||||
useMonitoringMachines,
|
||||
useMonitoringPoller,
|
||||
} from "../hooks/useMonitoring";
|
||||
import { useMonitoringOverview } from "../hooks/useDashboard";
|
||||
import { MachineMonitoringSection } from "../components/MachineMonitoringSection";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { MonitoringOverviewTable } from "../components/MonitoringOverviewTable";
|
||||
import { SectionCard } from "../components/SectionCard";
|
||||
import { TabbedCard } from "../components/TabbedCard";
|
||||
|
||||
type MonitoringTab = "overview" | string;
|
||||
|
||||
export function Monitoring() {
|
||||
const { data: machines, isLoading, error } = useMonitoringMachines();
|
||||
const { data: machines = [], isLoading, error } = useMonitoringMachines();
|
||||
const { data: poller } = useMonitoringPoller();
|
||||
const { data: overview } = useMonitoringOverview();
|
||||
const navigate = useNavigate();
|
||||
const [tab, setTab] = useState<MonitoringTab>("overview");
|
||||
|
||||
const selectedMachine = useMemo(
|
||||
() => machines.find((machine) => machine.id === tab) ?? null,
|
||||
[machines, tab],
|
||||
);
|
||||
|
||||
return (
|
||||
<Stack spacing={3}>
|
||||
<Stack spacing={2.25}>
|
||||
<Stack spacing={0.5}>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
sx={{ alignItems: "center", flexWrap: "wrap" }}
|
||||
>
|
||||
<Typography variant="h5">Monitoring</Typography>
|
||||
{poller && (
|
||||
<Chip
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color={poller.worker_running ? "success" : "default"}
|
||||
label={
|
||||
poller.worker_running
|
||||
? `Poller running · ${poller.interval_seconds}s`
|
||||
: "Poller stopped"
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Stack>
|
||||
<Typography variant="h5" sx={{ fontWeight: 800 }}>
|
||||
Monitoring
|
||||
</Typography>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Each machine below is monitored with its own settings and collector
|
||||
state, and recent activity is gathered automatically by the backend.
|
||||
Review fleet health first, then switch to a machine-specific tab.
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{error && <Alert severity="error">{String(error)}</Alert>}
|
||||
{isLoading && (
|
||||
{error ? <Alert severity="error">{String(error)}</Alert> : null}
|
||||
{isLoading ? (
|
||||
<Alert severity="info">Loading monitoring machines...</Alert>
|
||||
)}
|
||||
{!isLoading && (machines?.length ?? 0) === 0 && (
|
||||
<Alert
|
||||
severity="warning"
|
||||
action={
|
||||
<Button
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => navigate("/settings")}
|
||||
>
|
||||
Open Settings
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
No monitoring machines are configured yet.
|
||||
</Alert>
|
||||
)}
|
||||
) : null}
|
||||
|
||||
{machines?.map((machine) => (
|
||||
<Stack
|
||||
key={machine.id}
|
||||
spacing={2}
|
||||
sx={{
|
||||
p: 2,
|
||||
border: 1,
|
||||
borderColor: "divider",
|
||||
borderRadius: 2,
|
||||
bgcolor: "background.paper",
|
||||
}}
|
||||
>
|
||||
<MachineMonitoringSection machine={machine} />
|
||||
</Stack>
|
||||
))}
|
||||
<TabbedCard
|
||||
value={tab}
|
||||
onChange={setTab}
|
||||
tabs={[
|
||||
<Tab key="overview" value="overview" label="Overview" />,
|
||||
...machines.map((machine) => (
|
||||
<Tab key={machine.id} value={machine.id} label={machine.name} />
|
||||
)),
|
||||
]}
|
||||
contentSx={{ p: 1.5 }}
|
||||
>
|
||||
{tab === "overview" ? (
|
||||
<Stack spacing={1.5}>
|
||||
<Stack
|
||||
direction="row"
|
||||
spacing={1}
|
||||
sx={{ alignItems: "center", flexWrap: "wrap" }}
|
||||
>
|
||||
<Typography variant="subtitle1" sx={{ fontWeight: 700 }}>
|
||||
Fleet overview
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{poller?.worker_running
|
||||
? `Poller running · ${poller.interval_seconds}s`
|
||||
: "Poller stopped"}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{!isLoading && machines.length === 0 ? (
|
||||
<Alert
|
||||
severity="warning"
|
||||
action={
|
||||
<Button
|
||||
color="inherit"
|
||||
size="small"
|
||||
onClick={() => navigate("/settings")}
|
||||
>
|
||||
Open Settings
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
No monitoring machines are configured yet.
|
||||
</Alert>
|
||||
) : overview ? (
|
||||
<MonitoringOverviewTable overview={overview} embedded />
|
||||
) : (
|
||||
<Alert severity="info">Loading fleet overview...</Alert>
|
||||
)}
|
||||
</Stack>
|
||||
) : selectedMachine ? (
|
||||
<SectionCard
|
||||
title={selectedMachine.name}
|
||||
description={
|
||||
selectedMachine.mode === "local"
|
||||
? "Local API host"
|
||||
: `${selectedMachine.username || "user"}@${selectedMachine.host || "host"}:${selectedMachine.port}`
|
||||
}
|
||||
>
|
||||
<MachineMonitoringSection machine={selectedMachine} />
|
||||
</SectionCard>
|
||||
) : null}
|
||||
</TabbedCard>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user