78 lines
2.6 KiB
TypeScript
78 lines
2.6 KiB
TypeScript
import { useApi } from '../../hooks/useApi'
|
|
import { ProxmoxData } from '../../types'
|
|
import { formatBytes, formatUptime, pct, barColor } from '../../utils'
|
|
|
|
function ProgressBar({ label, value, total, color, valueLabel }: {
|
|
label: string; value: number; total: number; color: string; valueLabel?: string
|
|
}) {
|
|
const p = pct(value, total)
|
|
return (
|
|
<div>
|
|
<div className="progress-header">
|
|
<span className="progress-name">{label}</span>
|
|
<span className="progress-val">{valueLabel ?? `${p}% · ${formatBytes(value)} / ${formatBytes(total)}`}</span>
|
|
</div>
|
|
<div className="progress-track">
|
|
<div className={`progress-fill ${color}`} style={{ width: `${p}%` }} />
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function ProxmoxWidget() {
|
|
const { data, loading, error } = useApi<ProxmoxData>('/api/proxmox/status')
|
|
|
|
return (
|
|
<div className="card">
|
|
<div className="widget-header">
|
|
<div className="widget-title">
|
|
<span className="dot" style={{ background: 'var(--accent)' }} />
|
|
Proxmox VE
|
|
</div>
|
|
<div className="widget-badge">M920q</div>
|
|
</div>
|
|
|
|
{loading && <div className="widget-loading">Connecting…</div>}
|
|
{error && <div className="widget-error">⚠ {error}</div>}
|
|
|
|
{data && (
|
|
<>
|
|
<div className="node-name">{data.node}</div>
|
|
<div className="node-uptime">↑ {formatUptime(data.uptime)}</div>
|
|
|
|
<div className="progress-group">
|
|
<ProgressBar
|
|
label="CPU"
|
|
value={data.cpu}
|
|
total={1}
|
|
color={barColor(Math.round(data.cpu * 100))}
|
|
valueLabel={`${Math.round(data.cpu * 100)}%`}
|
|
/>
|
|
<ProgressBar label="RAM" value={data.memory.used} total={data.memory.total} color={barColor(pct(data.memory.used, data.memory.total))} />
|
|
{data.storages.map(st => (
|
|
<ProgressBar
|
|
key={st.name}
|
|
label={st.name}
|
|
value={st.used}
|
|
total={st.total}
|
|
color={barColor(pct(st.used, st.total))}
|
|
/>
|
|
))}
|
|
</div>
|
|
|
|
<div className="stat-row" style={{ marginTop: 14 }}>
|
|
<div className="stat-item">
|
|
<div className="stat-value accent">{data.lxcCount}</div>
|
|
<div className="stat-label">LXC running</div>
|
|
</div>
|
|
<div className="stat-item">
|
|
<div className="stat-value">{data.vmCount}</div>
|
|
<div className="stat-label">VMs</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|