mirror of
https://github.com/MacRimi/ProxMenux.git
synced 2025-11-18 19:46:18 +00:00
Update hardware.tsx
This commit is contained in:
@@ -102,6 +102,35 @@ const getMonitoringToolRecommendation = (vendor: string): string => {
|
|||||||
return "To get extended GPU monitoring information, please install the appropriate GPU monitoring tools for your hardware."
|
return "To get extended GPU monitoring information, please install the appropriate GPU monitoring tools for your hardware."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const groupAndSortTemperatures = (temperatures: any[]) => {
|
||||||
|
const groups = {
|
||||||
|
CPU: [] as any[],
|
||||||
|
GPU: [] as any[],
|
||||||
|
NVME: [] as any[],
|
||||||
|
PCI: [] as any[],
|
||||||
|
OTHER: [] as any[],
|
||||||
|
}
|
||||||
|
|
||||||
|
temperatures.forEach((temp) => {
|
||||||
|
const nameLower = temp.name.toLowerCase()
|
||||||
|
const adapterLower = temp.adapter?.toLowerCase() || ""
|
||||||
|
|
||||||
|
if (nameLower.includes("cpu") || nameLower.includes("core") || nameLower.includes("package")) {
|
||||||
|
groups.CPU.push(temp)
|
||||||
|
} else if (nameLower.includes("gpu") || adapterLower.includes("gpu")) {
|
||||||
|
groups.GPU.push(temp)
|
||||||
|
} else if (nameLower.includes("nvme") || adapterLower.includes("nvme")) {
|
||||||
|
groups.NVME.push(temp)
|
||||||
|
} else if (adapterLower.includes("pci")) {
|
||||||
|
groups.PCI.push(temp)
|
||||||
|
} else {
|
||||||
|
groups.OTHER.push(temp)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return groups
|
||||||
|
}
|
||||||
|
|
||||||
export default function Hardware() {
|
export default function Hardware() {
|
||||||
const { data: hardwareData, error } = useSWR<HardwareData>("/api/hardware", fetcher, {
|
const { data: hardwareData, error } = useSWR<HardwareData>("/api/hardware", fetcher, {
|
||||||
refreshInterval: 5000,
|
refreshInterval: 5000,
|
||||||
@@ -357,9 +386,25 @@ export default function Hardware() {
|
|||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{(() => {
|
||||||
|
const groupedTemps = groupAndSortTemperatures(hardwareData.temperatures)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-6">
|
||||||
|
{/* CPU Sensors */}
|
||||||
|
{groupedTemps.CPU.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<div className="mb-3 flex items-center gap-2">
|
||||||
|
<CpuIcon className="h-4 w-4 text-muted-foreground" />
|
||||||
|
<h3 className="text-sm font-semibold">CPU</h3>
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
{groupedTemps.CPU.length}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
{hardwareData.temperatures.map((temp, index) => {
|
{groupedTemps.CPU.map((temp, index) => {
|
||||||
const percentage = temp.critical > 0 ? (temp.current / temp.critical) * 100 : (temp.current / 100) * 100
|
const percentage =
|
||||||
|
temp.critical > 0 ? (temp.current / temp.critical) * 100 : (temp.current / 100) * 100
|
||||||
const isHot = temp.current > (temp.high || 80)
|
const isHot = temp.current > (temp.high || 80)
|
||||||
const isCritical = temp.current > (temp.critical || 90)
|
const isCritical = temp.current > (temp.critical || 90)
|
||||||
|
|
||||||
@@ -384,6 +429,175 @@ export default function Hardware() {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* GPU Sensors */}
|
||||||
|
{groupedTemps.GPU.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<div className="mb-3 flex items-center gap-2">
|
||||||
|
<Gpu className="h-4 w-4 text-muted-foreground" />
|
||||||
|
<h3 className="text-sm font-semibold">GPU</h3>
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
{groupedTemps.GPU.length}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
|
{groupedTemps.GPU.map((temp, index) => {
|
||||||
|
const percentage =
|
||||||
|
temp.critical > 0 ? (temp.current / temp.critical) * 100 : (temp.current / 100) * 100
|
||||||
|
const isHot = temp.current > (temp.high || 80)
|
||||||
|
const isCritical = temp.current > (temp.critical || 90)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="space-y-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm font-medium">{temp.name}</span>
|
||||||
|
<span
|
||||||
|
className={`text-sm font-semibold ${isCritical ? "text-red-500" : isHot ? "text-orange-500" : "text-green-500"}`}
|
||||||
|
>
|
||||||
|
{temp.current.toFixed(1)}°C
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary">
|
||||||
|
<div
|
||||||
|
className="h-full bg-blue-500 transition-all"
|
||||||
|
style={{ width: `${Math.min(percentage, 100)}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{temp.adapter && <span className="text-xs text-muted-foreground">{temp.adapter}</span>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* NVME Sensors */}
|
||||||
|
{groupedTemps.NVME.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<div className="mb-3 flex items-center gap-2">
|
||||||
|
<HardDrive className="h-4 w-4 text-muted-foreground" />
|
||||||
|
<h3 className="text-sm font-semibold">NVME</h3>
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
{groupedTemps.NVME.length}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
|
{groupedTemps.NVME.map((temp, index) => {
|
||||||
|
const percentage =
|
||||||
|
temp.critical > 0 ? (temp.current / temp.critical) * 100 : (temp.current / 100) * 100
|
||||||
|
const isHot = temp.current > (temp.high || 80)
|
||||||
|
const isCritical = temp.current > (temp.critical || 90)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="space-y-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm font-medium">{temp.name}</span>
|
||||||
|
<span
|
||||||
|
className={`text-sm font-semibold ${isCritical ? "text-red-500" : isHot ? "text-orange-500" : "text-green-500"}`}
|
||||||
|
>
|
||||||
|
{temp.current.toFixed(1)}°C
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary">
|
||||||
|
<div
|
||||||
|
className="h-full bg-blue-500 transition-all"
|
||||||
|
style={{ width: `${Math.min(percentage, 100)}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{temp.adapter && <span className="text-xs text-muted-foreground">{temp.adapter}</span>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* PCI Sensors */}
|
||||||
|
{groupedTemps.PCI.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<div className="mb-3 flex items-center gap-2">
|
||||||
|
<CpuIcon className="h-4 w-4 text-muted-foreground" />
|
||||||
|
<h3 className="text-sm font-semibold">PCI</h3>
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
{groupedTemps.PCI.length}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
|
{groupedTemps.PCI.map((temp, index) => {
|
||||||
|
const percentage =
|
||||||
|
temp.critical > 0 ? (temp.current / temp.critical) * 100 : (temp.current / 100) * 100
|
||||||
|
const isHot = temp.current > (temp.high || 80)
|
||||||
|
const isCritical = temp.current > (temp.critical || 90)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="space-y-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm font-medium">{temp.name}</span>
|
||||||
|
<span
|
||||||
|
className={`text-sm font-semibold ${isCritical ? "text-red-500" : isHot ? "text-orange-500" : "text-green-500"}`}
|
||||||
|
>
|
||||||
|
{temp.current.toFixed(1)}°C
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary">
|
||||||
|
<div
|
||||||
|
className="h-full bg-blue-500 transition-all"
|
||||||
|
style={{ width: `${Math.min(percentage, 100)}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{temp.adapter && <span className="text-xs text-muted-foreground">{temp.adapter}</span>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* OTHER Sensors */}
|
||||||
|
{groupedTemps.OTHER.length > 0 && (
|
||||||
|
<div>
|
||||||
|
<div className="mb-3 flex items-center gap-2">
|
||||||
|
<Thermometer className="h-4 w-4 text-muted-foreground" />
|
||||||
|
<h3 className="text-sm font-semibold">OTHER</h3>
|
||||||
|
<Badge variant="outline" className="text-xs">
|
||||||
|
{groupedTemps.OTHER.length}
|
||||||
|
</Badge>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
|
{groupedTemps.OTHER.map((temp, index) => {
|
||||||
|
const percentage =
|
||||||
|
temp.critical > 0 ? (temp.current / temp.critical) * 100 : (temp.current / 100) * 100
|
||||||
|
const isHot = temp.current > (temp.high || 80)
|
||||||
|
const isCritical = temp.current > (temp.critical || 90)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={index} className="space-y-2">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<span className="text-sm font-medium">{temp.name}</span>
|
||||||
|
<span
|
||||||
|
className={`text-sm font-semibold ${isCritical ? "text-red-500" : isHot ? "text-orange-500" : "text-green-500"}`}
|
||||||
|
>
|
||||||
|
{temp.current.toFixed(1)}°C
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="h-2 w-full overflow-hidden rounded-full bg-secondary">
|
||||||
|
<div
|
||||||
|
className="h-full bg-blue-500 transition-all"
|
||||||
|
style={{ width: `${Math.min(percentage, 100)}%` }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{temp.adapter && <span className="text-xs text-muted-foreground">{temp.adapter}</span>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
</Card>
|
</Card>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user