fix(dashboard): render disk chart; show server name as node label
All checks were successful
Deploy to Production / Trigger production update (push) Successful in 7s

- Dashboard "ТОП статистика по диску" was stuck on "Загрузка...": the
  node name in the dashboard_metrics WS payload is `name`, not `node`, so
  the RRD query stayed disabled. Use name fallback and unwrap the
  {data:[...]} response shape.
- Instances list + detail page: show the panel-side server name (from the
  add-server form) in the "Узел" column/label instead of the Proxmox node
  hostname. Real node is still used for all API calls.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 18:56:27 +05:00
parent fd47241394
commit 1f9a51b0be
2 changed files with 25 additions and 10 deletions

View File

@@ -226,16 +226,24 @@ function ClusterNodesSection({ serverList, nodeStats }: { serverList: Rec[]; nod
.sort((a, b) => (Number(b.disk_pct) || 0) - (Number(a.disk_pct) || 0))
.slice(0, 5)
// Fetch RRD for each of those nodes in parallel
// Fetch RRD for each of those nodes in parallel.
// Node name comes from the `dashboard_metrics` WS payload, where the field is
// `name` (not `node`); fall back to `node` for the REST `resources/all` shape.
const rrdResults = useQueries({
queries: chartNodes.map(n => ({
queryKey: ['node-rrd', Number(n.server_id) || 0, String(n.node || ''), timeframe],
queries: chartNodes.map(n => {
const nodeName = String(n.node || n.name || '')
return {
queryKey: ['node-rrd', Number(n.server_id) || 0, nodeName, timeframe],
queryFn: () =>
apiClient.get<Rec[]>(
`/proxmox/api/${n.server_id}/node/rrddata?node=${n.node}&timeframe=${timeframe}`
),
enabled: !!n.server_id && !!n.node,
})),
apiClient
.get<{ data?: Rec[] } | Rec[]>(
`/proxmox/api/${n.server_id}/node/rrddata?node=${encodeURIComponent(nodeName)}&timeframe=${timeframe}`
)
// Endpoint wraps the series in `{ data: [...] }`; tolerate both shapes.
.then(r => (Array.isArray(r) ? r : (r?.data ?? []))),
enabled: !!n.server_id && !!nodeName,
}
}),
})
// Align series by index (all PVE nodes produce same-length RRD arrays)

View File

@@ -30,6 +30,7 @@ import {
} from '@/components/ui/dropdown-menu';
import { StatusDot } from '@/components/shared/status-dot';
import { useVirtualMachines, usePowerAction, useVMInterfaces } from '@/hooks/use-instances';
import { useServers } from '@/hooks/use-nodes';
import InstanceActionDialogs, { PowerConfirmDialog, type InstanceAction, type PowerAction } from './InstanceActionDialogs';
import { vmTypeLabel } from '@/lib/format';
import { toast } from 'sonner';
@@ -57,6 +58,12 @@ export default function InstanceDetailPage() {
const { data: allVMs, isLoading } = useVirtualMachines();
const vm = allVMs?.find((v) => v.server_id === sid && v.vmid === vid);
// Show the panel-side server name (from the add-server form) instead of the
// Proxmox node hostname, matching the instances list. `node` is still used for
// all API calls below — only the displayed label changes.
const { data: servers = [] } = useServers();
const nodeLabel = servers.find((s) => s.id === sid)?.name || node;
const power = usePowerAction(sid, vid, type, node);
const isRunning = vm?.status === 'running';
@@ -131,7 +138,7 @@ export default function InstanceDetailPage() {
<StatusDot status={vm?.status || 'unknown'} pulse />
{vm?.status || 'unknown'}
</span>
<span>Node: {node}</span>
<span>{t('common.node', 'Node')}: {nodeLabel}</span>
{displayIP && <span className="font-mono">{displayIP}</span>}
</div>
</div>