import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Loader2 } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { useNodeMetrics } from '@/hooks/use-nodes'; import { formatBytes } from '@/lib/format'; import { ChartCard, TIMEFRAME_PRESETS, tickFormatterFor, } from '@/components/shared/MetricChart'; interface Props { serverId: number; nodeNames: string[]; } // PVE keeps a year of node RRD data, unlike the 30-day instance history. const PRESETS = [...TIMEFRAME_PRESETS, { tf: 'year', label: '1y' }]; export default function NodeGraphs({ serverId, nodeNames }: Props) { const { t } = useTranslation(); const [nodePick, setNode] = useState(''); const [timeframe, setTimeframe] = useState('hour'); // Nodes arrive asynchronously; use the first one until a node is picked, and // fall back to it if the picked node disappears from the cluster. const node = nodeNames.includes(nodePick) ? nodePick : (nodeNames[0] ?? ''); const { data: points = [], isLoading } = useNodeMetrics(serverId, node, timeframe); const xTick = tickFormatterFor(timeframe); const rows = points as unknown as Array>; return (
{nodeNames.length > 1 && ( )}
{PRESETS.map((p) => ( ))}
{isLoading ? (
) : rows.length === 0 ? (
{t('common.no_data')}
) : (
`${v.toFixed(1)}%`} unit="%" /> `${v.toFixed(2)}%`} unit="%" /> formatBytes(v)} /> v.toFixed(2)} /> `${formatBytes(v)}/s`} /> `${formatBytes(v)}/s`} /> formatBytes(v)} /> formatBytes(v)} />
)}
); }