mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 17:59:28 +08:00
refactor: add getMeterState function
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
|||||||
decimalString,
|
decimalString,
|
||||||
formatBytes,
|
formatBytes,
|
||||||
formatTemperature,
|
formatTemperature,
|
||||||
|
getMeterState,
|
||||||
isReadOnlyUser,
|
isReadOnlyUser,
|
||||||
parseSemVer,
|
parseSemVer,
|
||||||
} from "@/lib/utils"
|
} from "@/lib/utils"
|
||||||
@@ -53,6 +54,7 @@ import {
|
|||||||
} from "../ui/alert-dialog"
|
} from "../ui/alert-dialog"
|
||||||
import { buttonVariants } from "../ui/button"
|
import { buttonVariants } from "../ui/button"
|
||||||
import { t } from "@lingui/core/macro"
|
import { t } from "@lingui/core/macro"
|
||||||
|
import { MeterState } from "@/lib/enums"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param viewMode - "table" or "grid"
|
* @param viewMode - "table" or "grid"
|
||||||
@@ -98,7 +100,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
accessorFn: ({ info }) => info.cpu,
|
accessorFn: ({ info }) => info.cpu,
|
||||||
id: "cpu",
|
id: "cpu",
|
||||||
name: () => t`CPU`,
|
name: () => t`CPU`,
|
||||||
cell: CellFormatter,
|
cell: TableCellWithMeter,
|
||||||
Icon: CpuIcon,
|
Icon: CpuIcon,
|
||||||
header: sortableHeader,
|
header: sortableHeader,
|
||||||
},
|
},
|
||||||
@@ -107,7 +109,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
accessorFn: ({ info }) => info.mp,
|
accessorFn: ({ info }) => info.mp,
|
||||||
id: "memory",
|
id: "memory",
|
||||||
name: () => t`Memory`,
|
name: () => t`Memory`,
|
||||||
cell: CellFormatter,
|
cell: TableCellWithMeter,
|
||||||
Icon: MemoryStickIcon,
|
Icon: MemoryStickIcon,
|
||||||
header: sortableHeader,
|
header: sortableHeader,
|
||||||
},
|
},
|
||||||
@@ -115,7 +117,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
accessorFn: ({ info }) => info.dp,
|
accessorFn: ({ info }) => info.dp,
|
||||||
id: "disk",
|
id: "disk",
|
||||||
name: () => t`Disk`,
|
name: () => t`Disk`,
|
||||||
cell: CellFormatter,
|
cell: TableCellWithMeter,
|
||||||
Icon: HardDriveIcon,
|
Icon: HardDriveIcon,
|
||||||
header: sortableHeader,
|
header: sortableHeader,
|
||||||
},
|
},
|
||||||
@@ -123,7 +125,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
accessorFn: ({ info }) => info.g,
|
accessorFn: ({ info }) => info.g,
|
||||||
id: "gpu",
|
id: "gpu",
|
||||||
name: () => "GPU",
|
name: () => "GPU",
|
||||||
cell: CellFormatter,
|
cell: TableCellWithMeter,
|
||||||
Icon: GpuIcon,
|
Icon: GpuIcon,
|
||||||
header: sortableHeader,
|
header: sortableHeader,
|
||||||
},
|
},
|
||||||
@@ -157,17 +159,18 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDotColor() {
|
const normalizedLoad = max / (sysInfo.t ?? 1)
|
||||||
const normalized = max / (sysInfo.t ?? 1)
|
const threshold = getMeterState(normalizedLoad * 100)
|
||||||
if (status !== "up") return "bg-primary/30"
|
|
||||||
if (normalized < 0.7) return "bg-green-500"
|
|
||||||
if (normalized < 1) return "bg-yellow-500"
|
|
||||||
return "bg-red-600"
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-[.35em] w-full tabular-nums tracking-tight">
|
<div className="flex items-center gap-[.35em] w-full tabular-nums tracking-tight">
|
||||||
<span className={cn("inline-block size-2 rounded-full me-0.5", getDotColor())} />
|
<span
|
||||||
|
className={cn("inline-block size-2 rounded-full me-0.5", {
|
||||||
|
"bg-green-500": threshold === MeterState.Good,
|
||||||
|
"bg-yellow-500": threshold === MeterState.Warn,
|
||||||
|
"bg-red-600": threshold === MeterState.Crit,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
{loadAverages?.map((la, i) => (
|
{loadAverages?.map((la, i) => (
|
||||||
<span key={i}>{decimalString(la, la >= 10 ? 1 : 2)}</span>
|
<span key={i}>{decimalString(la, la >= 10 ? 1 : 2)}</span>
|
||||||
))}
|
))}
|
||||||
@@ -280,10 +283,9 @@ function sortableHeader(context: HeaderContext<SystemRecord, unknown>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function CellFormatter(info: CellContext<SystemRecord, unknown>) {
|
function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) {
|
||||||
const userSettings = useStore($userSettings)
|
|
||||||
const val = Number(info.getValue()) || 0
|
const val = Number(info.getValue()) || 0
|
||||||
const { colorWarn = 65, colorCrit = 90 } = userSettings
|
const threshold = getMeterState(val)
|
||||||
return (
|
return (
|
||||||
<div className="flex gap-2 items-center tabular-nums tracking-tight">
|
<div className="flex gap-2 items-center tabular-nums tracking-tight">
|
||||||
<span className="min-w-8">{decimalString(val, val >= 10 ? 1 : 2)}%</span>
|
<span className="min-w-8">{decimalString(val, val >= 10 ? 1 : 2)}%</span>
|
||||||
@@ -292,8 +294,8 @@ function CellFormatter(info: CellContext<SystemRecord, unknown>) {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"absolute inset-0 w-full h-full origin-left",
|
"absolute inset-0 w-full h-full origin-left",
|
||||||
(info.row.original.status !== "up" && "bg-primary/30") ||
|
(info.row.original.status !== "up" && "bg-primary/30") ||
|
||||||
(val < colorWarn && "bg-green-500") ||
|
(threshold === MeterState.Good && "bg-green-500") ||
|
||||||
(val < colorCrit && "bg-yellow-500") ||
|
(threshold === MeterState.Warn && "bg-yellow-500") ||
|
||||||
"bg-red-600"
|
"bg-red-600"
|
||||||
)}
|
)}
|
||||||
style={{
|
style={{
|
||||||
|
@@ -21,3 +21,10 @@ export enum Unit {
|
|||||||
Celsius,
|
Celsius,
|
||||||
Fahrenheit,
|
Fahrenheit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Meter state for color */
|
||||||
|
export enum MeterState {
|
||||||
|
Good,
|
||||||
|
Warn,
|
||||||
|
Crit,
|
||||||
|
}
|
||||||
|
@@ -20,7 +20,7 @@ import { useEffect, useState } from "react"
|
|||||||
import { CpuIcon, HardDriveIcon, MemoryStickIcon, ServerIcon } from "lucide-react"
|
import { CpuIcon, HardDriveIcon, MemoryStickIcon, ServerIcon } from "lucide-react"
|
||||||
import { EthernetIcon, HourglassIcon, ThermometerIcon } from "@/components/ui/icons"
|
import { EthernetIcon, HourglassIcon, ThermometerIcon } from "@/components/ui/icons"
|
||||||
import { prependBasePath } from "@/components/router"
|
import { prependBasePath } from "@/components/router"
|
||||||
import { Unit } from "./enums"
|
import { MeterState, Unit } from "./enums"
|
||||||
|
|
||||||
export function cn(...inputs: ClassValue[]) {
|
export function cn(...inputs: ClassValue[]) {
|
||||||
return twMerge(clsx(inputs))
|
return twMerge(clsx(inputs))
|
||||||
@@ -507,3 +507,9 @@ export const parseSemVer = (semVer = ""): SemVer => {
|
|||||||
const parts = semVer.split(".").map(Number)
|
const parts = semVer.split(".").map(Number)
|
||||||
return { major: parts?.[0] ?? 0, minor: parts?.[1] ?? 0, patch: parts?.[2] ?? 0 }
|
return { major: parts?.[0] ?? 0, minor: parts?.[1] ?? 0, patch: parts?.[2] ?? 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get meter state from 0-100 value. Used for color coding meters. */
|
||||||
|
export function getMeterState(value: number): MeterState {
|
||||||
|
const { colorWarn = 65, colorCrit = 90 } = $userSettings.get()
|
||||||
|
return value >= colorCrit ? MeterState.Crit : value >= colorWarn ? MeterState.Warn : MeterState.Good
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user