fixes and improvements
This commit is contained in:
@@ -50,7 +50,43 @@ function formatRate(bytes: number): string {
|
||||
|
||||
function formatTime(epochSeconds: number | null): string {
|
||||
if (!epochSeconds) return "-";
|
||||
return new Date(epochSeconds * 1000).toLocaleString();
|
||||
const date = new Date(epochSeconds * 1000);
|
||||
const yyyy = date.getFullYear();
|
||||
const mm = String(date.getMonth() + 1).padStart(2, "0");
|
||||
const dd = String(date.getDate()).padStart(2, "0");
|
||||
const hh = String(date.getHours()).padStart(2, "0");
|
||||
const min = String(date.getMinutes()).padStart(2, "0");
|
||||
return `${yyyy}-${mm}-${dd} ${hh}:${min}`;
|
||||
}
|
||||
|
||||
function formatReadableTime(epochSeconds: number | null): string {
|
||||
if (!epochSeconds) return "-";
|
||||
const date = new Date(epochSeconds * 1000);
|
||||
return date.toLocaleString("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
});
|
||||
}
|
||||
|
||||
function formatClockTime(epochSeconds: number | null): string {
|
||||
if (!epochSeconds) return "-";
|
||||
const date = new Date(epochSeconds * 1000);
|
||||
return date.toLocaleTimeString("en-US", {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
hour12: false,
|
||||
});
|
||||
}
|
||||
|
||||
function formatUpdatedDetails(epochSeconds: number | null): [string, string] {
|
||||
if (!epochSeconds) return ["-", "-"];
|
||||
return [
|
||||
formatReadableTime(epochSeconds),
|
||||
`${formatClockTime(epochSeconds)} · ${formatAge(epochSeconds)}`,
|
||||
];
|
||||
}
|
||||
|
||||
function formatAge(epochSeconds: number | null): string {
|
||||
@@ -111,40 +147,101 @@ function metricSortValue(
|
||||
}
|
||||
|
||||
function metricCell(value: string, subtext?: string) {
|
||||
const [minLine, maxLine] = (subtext || "").split("\n");
|
||||
const min = minLine?.replace(/^Low\s+/, "").trim();
|
||||
const max = maxLine?.replace(/^High\s+/, "").trim();
|
||||
return (
|
||||
<Stack
|
||||
spacing={0.1}
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
width: "100%",
|
||||
minWidth: 110,
|
||||
height: "100%",
|
||||
minHeight: 96,
|
||||
textAlign: "center",
|
||||
py: 0.4,
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
variant="body2"
|
||||
<Box
|
||||
sx={{
|
||||
fontWeight: 700,
|
||||
fontSize: "0.95rem",
|
||||
lineHeight: 1.1,
|
||||
flex: 1,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
px: 1.5,
|
||||
py: 1.15,
|
||||
borderRadius: 1,
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</Typography>
|
||||
{subtext ? (
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
whiteSpace: "pre-line",
|
||||
lineHeight: 1.0,
|
||||
fontSize: "0.64rem",
|
||||
opacity: 0.9,
|
||||
}}
|
||||
>
|
||||
{subtext}
|
||||
</Typography>
|
||||
) : null}
|
||||
<Stack spacing={0.1} sx={{ alignItems: "center" }}>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
sx={{
|
||||
fontSize: "0.62rem",
|
||||
lineHeight: 1,
|
||||
textTransform: "uppercase",
|
||||
letterSpacing: "0.04em",
|
||||
}}
|
||||
>
|
||||
10m avg
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="body1"
|
||||
sx={{
|
||||
fontWeight: 900,
|
||||
fontSize: "1.14rem",
|
||||
lineHeight: 1,
|
||||
textAlign: "center",
|
||||
whiteSpace: "nowrap",
|
||||
fontVariantNumeric: "tabular-nums",
|
||||
}}
|
||||
>
|
||||
{value}
|
||||
</Typography>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Stack
|
||||
spacing={0.25}
|
||||
sx={{
|
||||
width: "100%",
|
||||
pt: 0.1,
|
||||
}}
|
||||
>
|
||||
{min ? (
|
||||
<Chip
|
||||
size="small"
|
||||
variant="outlined"
|
||||
label={`Min ${min}`}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: 18,
|
||||
"& .MuiChip-label": {
|
||||
px: 0.5,
|
||||
py: 0,
|
||||
fontSize: "0.6rem",
|
||||
lineHeight: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
{max ? (
|
||||
<Chip
|
||||
size="small"
|
||||
variant="outlined"
|
||||
label={`Max ${max}`}
|
||||
sx={{
|
||||
width: "100%",
|
||||
height: 18,
|
||||
"& .MuiChip-label": {
|
||||
px: 0.5,
|
||||
py: 0,
|
||||
fontSize: "0.6rem",
|
||||
lineHeight: 1,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : null}
|
||||
</Stack>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
@@ -197,11 +294,7 @@ export function MonitoringOverviewTable({
|
||||
size="small"
|
||||
variant="outlined"
|
||||
color={poller?.worker_running ? "success" : "default"}
|
||||
label={
|
||||
poller?.worker_running
|
||||
? `Poller running · ${poller.interval_seconds}s`
|
||||
: "Poller stopped"
|
||||
}
|
||||
label={poller?.worker_running ? "running" : "stopped"}
|
||||
/>
|
||||
<Chip
|
||||
size="small"
|
||||
@@ -230,12 +323,30 @@ export function MonitoringOverviewTable({
|
||||
border: 1,
|
||||
borderColor: "divider",
|
||||
borderRadius: 1,
|
||||
overflow: "hidden",
|
||||
overflowX: "auto",
|
||||
overflowY: "hidden",
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<Table size="small">
|
||||
<Table
|
||||
size="small"
|
||||
sx={{
|
||||
minWidth: 1280,
|
||||
tableLayout: "fixed",
|
||||
"& .MuiTableCell-root": {
|
||||
px: 1.1,
|
||||
py: 0.9,
|
||||
verticalAlign: "middle",
|
||||
},
|
||||
"& .MuiTableHead .MuiTableCell-root": {
|
||||
fontSize: "0.7rem",
|
||||
fontWeight: 700,
|
||||
lineHeight: 1.15,
|
||||
whiteSpace: "nowrap",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell
|
||||
@@ -393,12 +504,6 @@ export function MonitoringOverviewTable({
|
||||
sortedRows.map((row) => {
|
||||
const machine = row.machine;
|
||||
const status = row.status || row.status_error || "-";
|
||||
const note =
|
||||
row.metrics_error ||
|
||||
row.disk_error ||
|
||||
machine.notes ||
|
||||
row.disk?.mount ||
|
||||
"";
|
||||
const cpu = formatSummary(
|
||||
row.cpu_summary,
|
||||
(value) => `${value.toFixed(1)}%`,
|
||||
@@ -457,28 +562,28 @@ export function MonitoringOverviewTable({
|
||||
label={status}
|
||||
/>
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(cpu.value, cpu.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(iowait.value, iowait.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(mem.value, mem.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(netDown.value, netDown.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(netUp.value, netUp.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(diskRead.value, diskRead.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{metricCell(diskWrite.value, diskWrite.subtext)}
|
||||
</TableCell>
|
||||
<TableCell align="right">
|
||||
<TableCell align="center">
|
||||
{row.disk
|
||||
? metricCell(
|
||||
row.disk.used_pct,
|
||||
@@ -487,22 +592,19 @@ export function MonitoringOverviewTable({
|
||||
: "-"}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Stack spacing={0.25}>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{formatTime(row.latest_sample?.ts ?? null)}
|
||||
</Typography>
|
||||
{note && (
|
||||
<Stack spacing={0.15} sx={{ alignItems: "center" }}>
|
||||
{formatUpdatedDetails(
|
||||
row.latest_sample?.ts ?? null,
|
||||
).map((line) => (
|
||||
<Typography
|
||||
key={line}
|
||||
variant="caption"
|
||||
color={
|
||||
row.metrics_error || row.disk_error
|
||||
? "error.main"
|
||||
: "text.secondary"
|
||||
}
|
||||
color="text.secondary"
|
||||
sx={{ lineHeight: 1.1 }}
|
||||
>
|
||||
{note}
|
||||
{line}
|
||||
</Typography>
|
||||
)}
|
||||
))}
|
||||
</Stack>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
|
||||
Reference in New Issue
Block a user