diff --git a/AppImage/components/hardware.tsx b/AppImage/components/hardware.tsx
index 2ff78e8..3e06c48 100644
--- a/AppImage/components/hardware.tsx
+++ b/AppImage/components/hardware.tsx
@@ -64,9 +64,12 @@ const formatMemory = (memoryKB: number | string): string => {
return `${tb.toFixed(1)} TB`
}
- // Convert to GB if >= 1024 MB
if (mb >= 1024) {
const gb = mb / 1024
+ // If GB value is greater than 999, convert to TB
+ if (gb > 999) {
+ return `${(gb / 1024).toFixed(2)} TB`
+ }
return `${gb.toFixed(1)} GB`
}
@@ -1658,6 +1661,62 @@ export default function Hardware() {
const diskBadge = getDiskTypeBadge(device.name, device.rotation_rate)
+ const getLinkSpeedInfo = (device: StorageDevice) => {
+ // NVMe PCIe information
+ if (device.name.startsWith("nvme") && (device.pcie_gen || device.pcie_width)) {
+ const current = `${device.pcie_gen || ""} ${device.pcie_width || ""}`.trim()
+ const max =
+ device.pcie_max_gen && device.pcie_max_width
+ ? `${device.pcie_max_gen} ${device.pcie_max_width}`.trim()
+ : null
+
+ // Check if running at lower speed than maximum
+ const isLowerSpeed = max && current !== max
+
+ return {
+ text: current || null,
+ maxText: max,
+ isWarning: isLowerSpeed,
+ color: isLowerSpeed ? "text-orange-500" : "text-blue-500",
+ }
+ }
+
+ // SATA information
+ if (device.sata_version) {
+ return {
+ text: device.sata_version,
+ maxText: null,
+ isWarning: false,
+ color: "text-blue-500",
+ }
+ }
+
+ // SAS information
+ if (device.sas_version || device.sas_speed) {
+ const text = [device.sas_version, device.sas_speed].filter(Boolean).join(" ")
+ return {
+ text: text || null,
+ maxText: null,
+ isWarning: false,
+ color: "text-blue-500",
+ }
+ }
+
+ // Generic link speed
+ if (device.link_speed) {
+ return {
+ text: device.link_speed,
+ maxText: null,
+ isWarning: false,
+ color: "text-blue-500",
+ }
+ }
+
+ return null
+ }
+
+ const linkSpeed = getLinkSpeedInfo(device)
+
return (
{device.model}
)}
+ {linkSpeed && (
+
+ {linkSpeed.text}
+ {linkSpeed.isWarning && linkSpeed.maxText && (
+ (max: {linkSpeed.maxText})
+ )}
+
+ )}
)
})}
@@ -1743,6 +1810,102 @@ export default function Hardware() {
)}
+ {(selectedDisk.pcie_gen ||
+ selectedDisk.pcie_width ||
+ selectedDisk.sata_version ||
+ selectedDisk.sas_version ||
+ selectedDisk.link_speed) && (
+ <>
+
+
+ Interface Information
+
+
+
+ {/* NVMe PCIe Information */}
+ {selectedDisk.name.startsWith("nvme") && (selectedDisk.pcie_gen || selectedDisk.pcie_width) && (
+ <>
+
+ Current Link Speed
+
+ {selectedDisk.pcie_gen} {selectedDisk.pcie_width}
+
+
+ {selectedDisk.pcie_max_gen && selectedDisk.pcie_max_width && (
+
+ Maximum Link Speed
+
+ {selectedDisk.pcie_max_gen} {selectedDisk.pcie_max_width}
+
+
+ )}
+ {/* Warning if running at lower speed */}
+ {selectedDisk.pcie_max_gen &&
+ selectedDisk.pcie_max_width &&
+ `${selectedDisk.pcie_gen} ${selectedDisk.pcie_width}` !==
+ `${selectedDisk.pcie_max_gen} ${selectedDisk.pcie_max_width}` && (
+
+
+
+
+
+
+
Performance Notice
+
+ This drive is running at {selectedDisk.pcie_gen} {selectedDisk.pcie_width} but
+ supports up to {selectedDisk.pcie_max_gen} {selectedDisk.pcie_max_width}. Check if the
+ slot supports the maximum speed or if the drive is properly seated.
+
+
+
+
+ )}
+ >
+ )}
+
+ {/* SATA Information */}
+ {selectedDisk.sata_version && (
+
+ SATA Version
+ {selectedDisk.sata_version}
+
+ )}
+
+ {/* SAS Information */}
+ {selectedDisk.sas_version && (
+
+ SAS Version
+ {selectedDisk.sas_version}
+
+ )}
+ {selectedDisk.sas_speed && (
+
+ SAS Speed
+ {selectedDisk.sas_speed}
+
+ )}
+
+ {/* Generic Link Speed */}
+ {selectedDisk.link_speed &&
+ !selectedDisk.pcie_gen &&
+ !selectedDisk.sata_version &&
+ !selectedDisk.sas_version && (
+
+ Link Speed
+ {selectedDisk.link_speed}
+
+ )}
+ >
+ )}
+
{selectedDisk.model && (
Model
@@ -1806,13 +1969,6 @@ export default function Hardware() {
{selectedDisk.form_factor}
)}
-
- {selectedDisk.sata_version && (
-
- SATA Version
- {selectedDisk.sata_version}
-
- )}
)}
diff --git a/AppImage/components/storage-metrics.tsx b/AppImage/components/storage-metrics.tsx
index abc5c0a..cc8b976 100644
--- a/AppImage/components/storage-metrics.tsx
+++ b/AppImage/components/storage-metrics.tsx
@@ -5,6 +5,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "./ui/card"
import { Progress } from "./ui/progress"
import { Badge } from "./ui/badge"
import { HardDrive, Database, Archive, AlertTriangle, CheckCircle, Activity, AlertCircle } from "lucide-react"
+import { formatStorage } from "@/lib/utils"
interface StorageData {
total: number
@@ -116,10 +117,10 @@ export function StorageMetrics() {
- {storageData.total.toFixed(1)} GB
+ {formatStorage(storageData.total)}
- {storageData.used.toFixed(1)} GB used • {storageData.available.toFixed(1)} GB available
+ {formatStorage(storageData.used)} used • {formatStorage(storageData.available)} available
@@ -130,7 +131,7 @@ export function StorageMetrics() {
- {storageData.used.toFixed(1)} GB
+ {formatStorage(storageData.used)}
{usagePercent.toFixed(1)}% of total space
@@ -144,7 +145,7 @@ export function StorageMetrics() {
- {storageData.available.toFixed(1)} GB
+ {formatStorage(storageData.available)}
{((storageData.available / storageData.total) * 100).toFixed(1)}% Free
@@ -201,7 +202,7 @@ export function StorageMetrics() {
- {disk.used.toFixed(1)} GB / {disk.total.toFixed(1)} GB
+ {formatStorage(disk.used)} / {formatStorage(disk.total)}
diff --git a/AppImage/components/storage-overview.tsx b/AppImage/components/storage-overview.tsx
index 5252189..70ba7eb 100644
--- a/AppImage/components/storage-overview.tsx
+++ b/AppImage/components/storage-overview.tsx
@@ -76,12 +76,11 @@ const formatStorage = (sizeInGB: number): string => {
if (sizeInGB < 1) {
// Less than 1 GB, show in MB
return `${(sizeInGB * 1024).toFixed(1)} MB`
- } else if (sizeInGB < 1024) {
- // Less than 1024 GB, show in GB
- return `${sizeInGB.toFixed(1)} GB`
+ } else if (sizeInGB > 999) {
+ return `${(sizeInGB / 1024).toFixed(2)} TB`
} else {
- // 1024 GB or more, show in TB
- return `${(sizeInGB / 1024).toFixed(1)} TB`
+ // Between 1 and 999 GB, show in GB
+ return `${sizeInGB.toFixed(2)} GB`
}
}
@@ -598,7 +597,7 @@ export function StorageOverview() {
Total
-
{storage.total.toLocaleString()} GB
+
{formatStorage(storage.total)}
Used
@@ -611,12 +610,12 @@ export function StorageOverview() {
: "text-blue-400"
}`}
>
- {storage.used.toLocaleString()} GB
+ {formatStorage(storage.used)}
Available
-
{storage.available.toLocaleString()} GB
+
{formatStorage(storage.available)}
diff --git a/AppImage/components/system-overview.tsx b/AppImage/components/system-overview.tsx
index 850e1ac..20204f4 100644
--- a/AppImage/components/system-overview.tsx
+++ b/AppImage/components/system-overview.tsx
@@ -388,12 +388,11 @@ export function SystemOverview() {
if (sizeInGB < 1) {
// Less than 1 GB, show in MB
return `${(sizeInGB * 1024).toFixed(1)} MB`
- } else if (sizeInGB < 1024) {
- // Less than 1024 GB, show in GB
- return `${sizeInGB.toFixed(1)} GB`
- } else {
- // 1024 GB or more, show in TB
+ } else if (sizeInGB > 999) {
return `${(sizeInGB / 1024).toFixed(2)} TB`
+ } else {
+ // Between 1 and 999 GB, show in GB
+ return `${sizeInGB.toFixed(2)} GB`
}
}
diff --git a/AppImage/components/virtual-machines.tsx b/AppImage/components/virtual-machines.tsx
index d6ebc19..fd5cc4b 100644
--- a/AppImage/components/virtual-machines.tsx
+++ b/AppImage/components/virtual-machines.tsx
@@ -25,6 +25,7 @@ import {
} from "lucide-react"
import useSWR from "swr"
import { MetricsView } from "./metrics-dialog"
+import { formatStorage } from "@/lib/utils" // Import formatStorage utility
interface VMData {
vmid: number
@@ -194,18 +195,18 @@ const extractIPFromConfig = (config?: VMConfig, lxcIPInfo?: VMDetails["lxc_ip_in
return "DHCP"
}
-const formatStorage = (sizeInGB: number): string => {
- if (sizeInGB < 1) {
- // Less than 1 GB, show in MB
- return `${(sizeInGB * 1024).toFixed(1)} MB`
- } else if (sizeInGB < 1024) {
- // Less than 1024 GB, show in GB
- return `${sizeInGB.toFixed(1)} GB`
- } else {
- // 1024 GB or more, show in TB
- return `${(sizeInGB / 1024).toFixed(1)} TB`
- }
-}
+// const formatStorage = (sizeInGB: number): string => {
+// if (sizeInGB < 1) {
+// // Less than 1 GB, show in MB
+// return `${(sizeInGB * 1024).toFixed(1)} MB`
+// } else if (sizeInGB < 1024) {
+// // Less than 1024 GB, show in GB
+// return `${sizeInGB.toFixed(1)} GB`
+// } else {
+// // 1024 GB or more, show in TB
+// return `${(sizeInGB / 1024).toFixed(1)} TB`
+// }
+// }
const getUsageColor = (percent: number): string => {
if (percent >= 95) return "text-red-500"
diff --git a/AppImage/lib/utils.ts b/AppImage/lib/utils.ts
index d084cca..4024e48 100644
--- a/AppImage/lib/utils.ts
+++ b/AppImage/lib/utils.ts
@@ -4,3 +4,18 @@ import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
+
+export function formatStorage(sizeInGB: number): string {
+ if (sizeInGB < 1) {
+ // Less than 1 GB, show in MB
+ const mb = sizeInGB * 1024
+ return `${mb % 1 === 0 ? mb.toFixed(0) : mb.toFixed(1)} MB`
+ } else if (sizeInGB < 1024) {
+ // Less than 1024 GB, show in GB
+ return `${sizeInGB % 1 === 0 ? sizeInGB.toFixed(0) : sizeInGB.toFixed(1)} GB`
+ } else {
+ // 1024 GB or more, show in TB
+ const tb = sizeInGB / 1024
+ return `${tb % 1 === 0 ? tb.toFixed(0) : tb.toFixed(1)} TB`
+ }
+}
diff --git a/AppImage/types/hardware.ts b/AppImage/types/hardware.ts
index 6907646..c31de3c 100644
--- a/AppImage/types/hardware.ts
+++ b/AppImage/types/hardware.ts
@@ -33,6 +33,13 @@ export interface StorageDevice {
rotation_rate?: number | string
form_factor?: string
sata_version?: string
+ pcie_gen?: string // e.g., "PCIe 4.0"
+ pcie_width?: string // e.g., "x4"
+ pcie_max_gen?: string // Maximum supported PCIe generation
+ pcie_max_width?: string // Maximum supported PCIe lanes
+ sas_version?: string // e.g., "SAS-3"
+ sas_speed?: string // e.g., "12Gb/s"
+ link_speed?: string // Generic link speed info
}
export interface PCIDevice {