feat: add Dashboard tab with live GPU overview
Add a new Dashboard tab as the default/first tab (Dashboard - Curve - Performance - Fans) showing a full GPU overview. Backend: - New hal/dashboard.py: one-shot static GPU info via NVML (VBIOS, CUDA cores, compute capability, bus width, BAR1/CPU-accessible VRAM, Resizable BAR, PCIe max, max clocks, power limits, temp thresholds, persistence mode, fan count, serial, board part number, UUID). ROP count and VRAM type are best-effort from a per-model table since NVML does not expose them. - New /api/dashboard endpoint. - MonitoringSample gains live throttle_reasons (+label), PCIe link width/generation (downclocks when idle, so read per poll), and VRAM temp (from the MEMORY thermal sensor, if exposed). Frontend: - New Dashboard component: critical top row (throttling, voltage, GPU/VRAM temps), full live-monitor grid with sparklines, and a static GPU-information grid. Unavailable fields are omitted. - useDashboard hook + DashboardInfo type + api.client dashboard(). Also: restrict CORS to localhost origins (end-anchored), make _int_key_deltas fail closed on bad keys, and clean up lint blockers in server.py/monitoring.py.
This commit is contained in:
1 parent
3c55263250
commit
da507d55bb
11 files changed
+907
-72
No files matched your search
@@ -0,0 +1,47 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { api } from "../api/client";
|
||||
import { useCurveStore } from "../store/curveStore";
|
||||
import type { DashboardInfo } from "../types";
|
||||
|
||||
interface DashboardState {
|
||||
gpuIndex: number;
|
||||
data: DashboardInfo | null;
|
||||
done: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch static GPU info for the Dashboard tab.
|
||||
* Re-fetches when the selected GPU changes.
|
||||
*/
|
||||
export function useDashboard() {
|
||||
const { selectedGpuIndex } = useCurveStore();
|
||||
const [state, setState] = useState<DashboardState>({
|
||||
gpuIndex: -1,
|
||||
data: null,
|
||||
done: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
api
|
||||
.dashboard(selectedGpuIndex)
|
||||
.then((data) => {
|
||||
if (!cancelled)
|
||||
setState({ gpuIndex: selectedGpuIndex, data, done: true });
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error("Failed to load dashboard info:", err);
|
||||
if (!cancelled)
|
||||
setState({ gpuIndex: selectedGpuIndex, data: null, done: true });
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, [selectedGpuIndex]);
|
||||
|
||||
const isCurrent = state.gpuIndex === selectedGpuIndex;
|
||||
return {
|
||||
dashboard: isCurrent ? state.data : null,
|
||||
loading: !isCurrent || !state.done,
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user