refactor: replace status strings with systemstatus enum

- also small style changes after tailwind update
This commit is contained in:
henrygd
2025-08-23 20:35:18 -04:00
parent 3c4ae46f50
commit 0f5b1b5157
8 changed files with 50 additions and 72 deletions

View File

@@ -20,6 +20,7 @@ import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react"
import { memo, useEffect, useRef, useState } from "react"
import { $router, basePath, Link, navigate } from "./router"
import { SystemRecord } from "@/types"
import { SystemStatus } from "@/lib/enums"
import { AppleIcon, DockerIcon, TuxIcon, WindowsIcon } from "./ui/icons"
import { InputCopy } from "./ui/input-copy"
import { getPagePath } from "@nanostores/router"
@@ -105,7 +106,7 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
try {
setOpen(false)
if (system) {
await pb.collection("systems").update(system.id, { ...data, status: "pending" })
await pb.collection("systems").update(system.id, { ...data, status: SystemStatus.Pending })
} else {
const createdSystem = await pb.collection("systems").create(data)
await pb.collection("fingerprints").create({

View File

@@ -11,7 +11,7 @@ import {
$temperatureFilter,
} from "@/lib/stores"
import { ChartData, ChartTimes, ContainerStatsRecord, GPUData, SystemRecord, SystemStatsRecord } from "@/types"
import { ChartType, Unit, Os } from "@/lib/enums"
import { ChartType, Unit, Os, SystemStatus } from "@/lib/enums"
import React, { lazy, memo, useCallback, useEffect, useMemo, useRef, useState, type JSX } from "react"
import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card"
import { useStore } from "@nanostores/react"
@@ -382,9 +382,9 @@ export default function SystemDetail({ name }: { name: string }) {
const hasGpuPowerData = lastGpuVals.some((gpu) => gpu.p !== undefined)
let translatedStatus: string = system.status
if (system.status === "up") {
if (system.status === SystemStatus.Up) {
translatedStatus = t({ message: "Up", comment: "Context: System is up" })
} else if (system.status === "down") {
} else if (system.status === SystemStatus.Down) {
translatedStatus = t({ message: "Down", comment: "Context: System is down" })
}
@@ -399,7 +399,7 @@ export default function SystemDetail({ name }: { name: string }) {
<div className="flex flex-wrap items-center gap-3 gap-y-2 text-sm opacity-90">
<div className="capitalize flex gap-2 items-center">
<span className={cn("relative flex h-3 w-3")}>
{system.status === "up" && (
{system.status === SystemStatus.Up && (
<span
className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"
style={{ animationDuration: "1.5s" }}
@@ -407,10 +407,10 @@ export default function SystemDetail({ name }: { name: string }) {
)}
<span
className={cn("relative inline-flex rounded-full h-3 w-3", {
"bg-green-500": system.status === "up",
"bg-red-500": system.status === "down",
"bg-primary/40": system.status === "paused",
"bg-yellow-500": system.status === "pending",
"bg-green-500": system.status === SystemStatus.Up,
"bg-red-500": system.status === SystemStatus.Down,
"bg-primary/40": system.status === SystemStatus.Paused,
"bg-yellow-500": system.status === SystemStatus.Pending,
})}
></span>
</span>

View File

@@ -54,15 +54,15 @@ import {
} from "../ui/alert-dialog"
import { buttonVariants } from "../ui/button"
import { t } from "@lingui/core/macro"
import { MeterState } from "@/lib/enums"
import { MeterState, SystemStatus } from "@/lib/enums"
import { $router, Link } from "../router"
import { getPagePath } from "@nanostores/router"
const STATUS_COLORS = {
up: "bg-green-500",
down: "bg-red-500",
paused: "bg-primary/40",
pending: "bg-yellow-500",
[SystemStatus.Up]: "bg-green-500",
[SystemStatus.Down]: "bg-red-500",
[SystemStatus.Paused]: "bg-primary/40",
[SystemStatus.Pending]: "bg-yellow-500",
} as const
/**
@@ -82,9 +82,9 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
let filterInputLower = ""
const nameCache = new Map<string, string>()
const statusTranslations = {
up: t`Up`.toLowerCase(),
down: t`Down`.toLowerCase(),
paused: t`Paused`.toLowerCase(),
[SystemStatus.Up]: t`Up`.toLowerCase(),
[SystemStatus.Down]: t`Down`.toLowerCase(),
[SystemStatus.Paused]: t`Paused`.toLowerCase(),
} as const
// match filter value against name or translated status
@@ -186,7 +186,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
}
const max = Math.max(...loadAverages)
if (max === 0 && (status === "paused" || minor < 12)) {
if (max === 0 && (status === SystemStatus.Paused || minor < 12)) {
return null
}
@@ -197,10 +197,10 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
<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", {
[STATUS_COLORS.up]: threshold === MeterState.Good,
[STATUS_COLORS.pending]: threshold === MeterState.Warn,
[STATUS_COLORS.down]: threshold === MeterState.Crit,
[STATUS_COLORS.paused]: status !== "up",
[STATUS_COLORS[SystemStatus.Up]]: threshold === MeterState.Good,
[STATUS_COLORS[SystemStatus.Pending]]: threshold === MeterState.Warn,
[STATUS_COLORS[SystemStatus.Down]]: threshold === MeterState.Crit,
[STATUS_COLORS[SystemStatus.Paused]]: status !== SystemStatus.Up,
})}
/>
{loadAverages?.map((la, i) => (
@@ -220,7 +220,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
cell(info) {
const sys = info.row.original
const userSettings = useStore($userSettings, { keys: ["unitNet"] })
if (sys.status === "paused") {
if (sys.status === SystemStatus.Paused) {
return null
}
const { value, unit } = formatBytes(info.getValue() as number, true, userSettings.unitNet, false)
@@ -273,9 +273,9 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
<IndicatorDot
system={system}
className={
(system.status !== "up" && STATUS_COLORS.paused) ||
(version === globalThis.BESZEL.HUB_VERSION && STATUS_COLORS.up) ||
STATUS_COLORS.pending
(system.status !== SystemStatus.Up && STATUS_COLORS[SystemStatus.Paused]) ||
(version === globalThis.BESZEL.HUB_VERSION && STATUS_COLORS[SystemStatus.Up]) ||
STATUS_COLORS[SystemStatus.Pending]
}
/>
<span className="truncate max-w-14">{info.getValue() as string}</span>
@@ -325,7 +325,7 @@ function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) {
<span
className={cn(
"absolute inset-0 w-full h-full origin-left",
(info.row.original.status !== "up" && STATUS_COLORS.paused) ||
(info.row.original.status !== SystemStatus.Up && STATUS_COLORS.paused) ||
(threshold === MeterState.Good && STATUS_COLORS.up) ||
(threshold === MeterState.Warn && STATUS_COLORS.pending) ||
STATUS_COLORS.down
@@ -384,11 +384,11 @@ export const ActionsButton = memo(({ system }: { system: SystemRecord }) => {
className={cn(isReadOnlyUser() && "hidden")}
onClick={() => {
pb.collection("systems").update(id, {
status: status === "paused" ? "pending" : "paused",
status: status === SystemStatus.Paused ? SystemStatus.Pending : SystemStatus.Paused,
})
}}
>
{status === "paused" ? (
{status === SystemStatus.Paused ? (
<>
<PlayCircleIcon className="me-2.5 size-4" />
<Trans>Resume</Trans>

View File

@@ -48,6 +48,7 @@ import { Input } from "../ui/input"
import { getPagePath } from "@nanostores/router"
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
import AlertButton from "../alerts/alert-button"
import { SystemStatus } from "@/lib/enums"
type ViewMode = "table" | "grid"
@@ -292,7 +293,7 @@ const SystemTableRow = memo(
<TableRow
// data-state={row.getIsSelected() && "selected"}
className={cn("cursor-pointer transition-opacity relative", {
"opacity-50": system.status === "paused",
"opacity-50": system.status === SystemStatus.Paused,
})}
>
{row.getVisibleCells().map((cell) => (
@@ -324,7 +325,7 @@ const SystemCard = memo(
className={cn(
"cursor-pointer hover:shadow-md transition-all bg-transparent w-full dark:border-border duration-200 relative",
{
"opacity-50": system.status === "paused",
"opacity-50": system.status === SystemStatus.Paused,
}
)}
>

View File

@@ -25,7 +25,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 data-[state=open]:bg-accent/70",
"flex select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 data-[state=open]:bg-accent/70",
inset && "ps-8",
className
)}
@@ -79,7 +79,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"relative flex select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
inset && "ps-8",
className
)}
@@ -95,7 +95,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
"relative flex select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className
)}
checked={checked}

View File

@@ -3,24 +3,6 @@
@config '../tailwind.config.js';
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
@utility link {
@apply text-primary font-medium underline-offset-4 hover:underline;
}
@@ -33,24 +15,6 @@
}
}
/*
The default border color has changed to `currentcolor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentcolor);
}
}
@layer base {
:root {
--background: 30 8% 98%;
@@ -130,6 +94,9 @@
body {
@apply bg-background text-foreground;
}
button {
cursor: pointer;
}
}
.recharts-tooltip-wrapper {

View File

@@ -28,3 +28,11 @@ export enum MeterState {
Warn,
Crit,
}
/** System status states */
export enum SystemStatus {
Up = "up",
Down = "down",
Pending = "pending",
Paused = "paused",
}

View File

@@ -15,6 +15,7 @@ import Navbar from "./components/navbar.tsx"
import { I18nProvider } from "@lingui/react"
import { i18n } from "@lingui/core"
import { getLocale, dynamicActivate } from "./lib/i18n.ts"
import { SystemStatus } from "./lib/enums.ts"
// const ServerDetail = lazy(() => import('./components/routes/system.tsx'))
const LoginPage = lazy(() => import("./components/login/login.tsx"))
@@ -50,10 +51,10 @@ const App = memo(() => {
} else {
let up = false
for (const system of systems) {
if (system.status === "down") {
if (system.status === SystemStatus.Down) {
updateFavicon("favicon-red.svg")
return
} else if (system.status === "up") {
} else if (system.status === SystemStatus.Up) {
up = true
}
}