mirror of
https://github.com/fankes/beszel.git
synced 2025-10-19 01:39:34 +08:00
refactor: replace status strings with systemstatus enum
- also small style changes after tailwind update
This commit is contained in:
@@ -20,6 +20,7 @@ import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react"
|
|||||||
import { memo, useEffect, useRef, useState } from "react"
|
import { memo, useEffect, useRef, useState } from "react"
|
||||||
import { $router, basePath, Link, navigate } from "./router"
|
import { $router, basePath, Link, navigate } from "./router"
|
||||||
import { SystemRecord } from "@/types"
|
import { SystemRecord } from "@/types"
|
||||||
|
import { SystemStatus } from "@/lib/enums"
|
||||||
import { AppleIcon, DockerIcon, TuxIcon, WindowsIcon } from "./ui/icons"
|
import { AppleIcon, DockerIcon, TuxIcon, WindowsIcon } from "./ui/icons"
|
||||||
import { InputCopy } from "./ui/input-copy"
|
import { InputCopy } from "./ui/input-copy"
|
||||||
import { getPagePath } from "@nanostores/router"
|
import { getPagePath } from "@nanostores/router"
|
||||||
@@ -105,7 +106,7 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
|
|||||||
try {
|
try {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
if (system) {
|
if (system) {
|
||||||
await pb.collection("systems").update(system.id, { ...data, status: "pending" })
|
await pb.collection("systems").update(system.id, { ...data, status: SystemStatus.Pending })
|
||||||
} else {
|
} else {
|
||||||
const createdSystem = await pb.collection("systems").create(data)
|
const createdSystem = await pb.collection("systems").create(data)
|
||||||
await pb.collection("fingerprints").create({
|
await pb.collection("fingerprints").create({
|
||||||
|
@@ -11,7 +11,7 @@ import {
|
|||||||
$temperatureFilter,
|
$temperatureFilter,
|
||||||
} from "@/lib/stores"
|
} from "@/lib/stores"
|
||||||
import { ChartData, ChartTimes, ContainerStatsRecord, GPUData, SystemRecord, SystemStatsRecord } from "@/types"
|
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 React, { lazy, memo, useCallback, useEffect, useMemo, useRef, useState, type JSX } from "react"
|
||||||
import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card"
|
import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card"
|
||||||
import { useStore } from "@nanostores/react"
|
import { useStore } from "@nanostores/react"
|
||||||
@@ -382,9 +382,9 @@ export default function SystemDetail({ name }: { name: string }) {
|
|||||||
const hasGpuPowerData = lastGpuVals.some((gpu) => gpu.p !== undefined)
|
const hasGpuPowerData = lastGpuVals.some((gpu) => gpu.p !== undefined)
|
||||||
|
|
||||||
let translatedStatus: string = system.status
|
let translatedStatus: string = system.status
|
||||||
if (system.status === "up") {
|
if (system.status === SystemStatus.Up) {
|
||||||
translatedStatus = t({ message: "Up", comment: "Context: System is 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" })
|
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="flex flex-wrap items-center gap-3 gap-y-2 text-sm opacity-90">
|
||||||
<div className="capitalize flex gap-2 items-center">
|
<div className="capitalize flex gap-2 items-center">
|
||||||
<span className={cn("relative flex h-3 w-3")}>
|
<span className={cn("relative flex h-3 w-3")}>
|
||||||
{system.status === "up" && (
|
{system.status === SystemStatus.Up && (
|
||||||
<span
|
<span
|
||||||
className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"
|
className="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"
|
||||||
style={{ animationDuration: "1.5s" }}
|
style={{ animationDuration: "1.5s" }}
|
||||||
@@ -407,10 +407,10 @@ export default function SystemDetail({ name }: { name: string }) {
|
|||||||
)}
|
)}
|
||||||
<span
|
<span
|
||||||
className={cn("relative inline-flex rounded-full h-3 w-3", {
|
className={cn("relative inline-flex rounded-full h-3 w-3", {
|
||||||
"bg-green-500": system.status === "up",
|
"bg-green-500": system.status === SystemStatus.Up,
|
||||||
"bg-red-500": system.status === "down",
|
"bg-red-500": system.status === SystemStatus.Down,
|
||||||
"bg-primary/40": system.status === "paused",
|
"bg-primary/40": system.status === SystemStatus.Paused,
|
||||||
"bg-yellow-500": system.status === "pending",
|
"bg-yellow-500": system.status === SystemStatus.Pending,
|
||||||
})}
|
})}
|
||||||
></span>
|
></span>
|
||||||
</span>
|
</span>
|
||||||
|
@@ -54,15 +54,15 @@ 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"
|
import { MeterState, SystemStatus } from "@/lib/enums"
|
||||||
import { $router, Link } from "../router"
|
import { $router, Link } from "../router"
|
||||||
import { getPagePath } from "@nanostores/router"
|
import { getPagePath } from "@nanostores/router"
|
||||||
|
|
||||||
const STATUS_COLORS = {
|
const STATUS_COLORS = {
|
||||||
up: "bg-green-500",
|
[SystemStatus.Up]: "bg-green-500",
|
||||||
down: "bg-red-500",
|
[SystemStatus.Down]: "bg-red-500",
|
||||||
paused: "bg-primary/40",
|
[SystemStatus.Paused]: "bg-primary/40",
|
||||||
pending: "bg-yellow-500",
|
[SystemStatus.Pending]: "bg-yellow-500",
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,9 +82,9 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
let filterInputLower = ""
|
let filterInputLower = ""
|
||||||
const nameCache = new Map<string, string>()
|
const nameCache = new Map<string, string>()
|
||||||
const statusTranslations = {
|
const statusTranslations = {
|
||||||
up: t`Up`.toLowerCase(),
|
[SystemStatus.Up]: t`Up`.toLowerCase(),
|
||||||
down: t`Down`.toLowerCase(),
|
[SystemStatus.Down]: t`Down`.toLowerCase(),
|
||||||
paused: t`Paused`.toLowerCase(),
|
[SystemStatus.Paused]: t`Paused`.toLowerCase(),
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
// match filter value against name or translated status
|
// 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)
|
const max = Math.max(...loadAverages)
|
||||||
if (max === 0 && (status === "paused" || minor < 12)) {
|
if (max === 0 && (status === SystemStatus.Paused || minor < 12)) {
|
||||||
return null
|
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">
|
<div className="flex items-center gap-[.35em] w-full tabular-nums tracking-tight">
|
||||||
<span
|
<span
|
||||||
className={cn("inline-block size-2 rounded-full me-0.5", {
|
className={cn("inline-block size-2 rounded-full me-0.5", {
|
||||||
[STATUS_COLORS.up]: threshold === MeterState.Good,
|
[STATUS_COLORS[SystemStatus.Up]]: threshold === MeterState.Good,
|
||||||
[STATUS_COLORS.pending]: threshold === MeterState.Warn,
|
[STATUS_COLORS[SystemStatus.Pending]]: threshold === MeterState.Warn,
|
||||||
[STATUS_COLORS.down]: threshold === MeterState.Crit,
|
[STATUS_COLORS[SystemStatus.Down]]: threshold === MeterState.Crit,
|
||||||
[STATUS_COLORS.paused]: status !== "up",
|
[STATUS_COLORS[SystemStatus.Paused]]: status !== SystemStatus.Up,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
{loadAverages?.map((la, i) => (
|
{loadAverages?.map((la, i) => (
|
||||||
@@ -220,7 +220,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
|
|||||||
cell(info) {
|
cell(info) {
|
||||||
const sys = info.row.original
|
const sys = info.row.original
|
||||||
const userSettings = useStore($userSettings, { keys: ["unitNet"] })
|
const userSettings = useStore($userSettings, { keys: ["unitNet"] })
|
||||||
if (sys.status === "paused") {
|
if (sys.status === SystemStatus.Paused) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
const { value, unit } = formatBytes(info.getValue() as number, true, userSettings.unitNet, false)
|
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
|
<IndicatorDot
|
||||||
system={system}
|
system={system}
|
||||||
className={
|
className={
|
||||||
(system.status !== "up" && STATUS_COLORS.paused) ||
|
(system.status !== SystemStatus.Up && STATUS_COLORS[SystemStatus.Paused]) ||
|
||||||
(version === globalThis.BESZEL.HUB_VERSION && STATUS_COLORS.up) ||
|
(version === globalThis.BESZEL.HUB_VERSION && STATUS_COLORS[SystemStatus.Up]) ||
|
||||||
STATUS_COLORS.pending
|
STATUS_COLORS[SystemStatus.Pending]
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<span className="truncate max-w-14">{info.getValue() as string}</span>
|
<span className="truncate max-w-14">{info.getValue() as string}</span>
|
||||||
@@ -325,7 +325,7 @@ function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) {
|
|||||||
<span
|
<span
|
||||||
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" && STATUS_COLORS.paused) ||
|
(info.row.original.status !== SystemStatus.Up && STATUS_COLORS.paused) ||
|
||||||
(threshold === MeterState.Good && STATUS_COLORS.up) ||
|
(threshold === MeterState.Good && STATUS_COLORS.up) ||
|
||||||
(threshold === MeterState.Warn && STATUS_COLORS.pending) ||
|
(threshold === MeterState.Warn && STATUS_COLORS.pending) ||
|
||||||
STATUS_COLORS.down
|
STATUS_COLORS.down
|
||||||
@@ -384,11 +384,11 @@ export const ActionsButton = memo(({ system }: { system: SystemRecord }) => {
|
|||||||
className={cn(isReadOnlyUser() && "hidden")}
|
className={cn(isReadOnlyUser() && "hidden")}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
pb.collection("systems").update(id, {
|
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" />
|
<PlayCircleIcon className="me-2.5 size-4" />
|
||||||
<Trans>Resume</Trans>
|
<Trans>Resume</Trans>
|
||||||
|
@@ -48,6 +48,7 @@ import { Input } from "../ui/input"
|
|||||||
import { getPagePath } from "@nanostores/router"
|
import { getPagePath } from "@nanostores/router"
|
||||||
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
|
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
|
||||||
import AlertButton from "../alerts/alert-button"
|
import AlertButton from "../alerts/alert-button"
|
||||||
|
import { SystemStatus } from "@/lib/enums"
|
||||||
|
|
||||||
type ViewMode = "table" | "grid"
|
type ViewMode = "table" | "grid"
|
||||||
|
|
||||||
@@ -292,7 +293,7 @@ const SystemTableRow = memo(
|
|||||||
<TableRow
|
<TableRow
|
||||||
// data-state={row.getIsSelected() && "selected"}
|
// data-state={row.getIsSelected() && "selected"}
|
||||||
className={cn("cursor-pointer transition-opacity relative", {
|
className={cn("cursor-pointer transition-opacity relative", {
|
||||||
"opacity-50": system.status === "paused",
|
"opacity-50": system.status === SystemStatus.Paused,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{row.getVisibleCells().map((cell) => (
|
{row.getVisibleCells().map((cell) => (
|
||||||
@@ -324,7 +325,7 @@ const SystemCard = memo(
|
|||||||
className={cn(
|
className={cn(
|
||||||
"cursor-pointer hover:shadow-md transition-all bg-transparent w-full dark:border-border duration-200 relative",
|
"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,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@@ -25,7 +25,7 @@ const DropdownMenuSubTrigger = React.forwardRef<
|
|||||||
<DropdownMenuPrimitive.SubTrigger
|
<DropdownMenuPrimitive.SubTrigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
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",
|
inset && "ps-8",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
@@ -79,7 +79,7 @@ const DropdownMenuItem = React.forwardRef<
|
|||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
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",
|
inset && "ps-8",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
@@ -95,7 +95,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
|
|||||||
<DropdownMenuPrimitive.CheckboxItem
|
<DropdownMenuPrimitive.CheckboxItem
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
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
|
className
|
||||||
)}
|
)}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
|
@@ -3,24 +3,6 @@
|
|||||||
|
|
||||||
@config '../tailwind.config.js';
|
@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 {
|
@utility link {
|
||||||
@apply text-primary font-medium underline-offset-4 hover:underline;
|
@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 {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 30 8% 98%;
|
--background: 30 8% 98%;
|
||||||
@@ -130,6 +94,9 @@
|
|||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
|
button {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.recharts-tooltip-wrapper {
|
.recharts-tooltip-wrapper {
|
||||||
|
@@ -28,3 +28,11 @@ export enum MeterState {
|
|||||||
Warn,
|
Warn,
|
||||||
Crit,
|
Crit,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** System status states */
|
||||||
|
export enum SystemStatus {
|
||||||
|
Up = "up",
|
||||||
|
Down = "down",
|
||||||
|
Pending = "pending",
|
||||||
|
Paused = "paused",
|
||||||
|
}
|
||||||
|
@@ -15,6 +15,7 @@ import Navbar from "./components/navbar.tsx"
|
|||||||
import { I18nProvider } from "@lingui/react"
|
import { I18nProvider } from "@lingui/react"
|
||||||
import { i18n } from "@lingui/core"
|
import { i18n } from "@lingui/core"
|
||||||
import { getLocale, dynamicActivate } from "./lib/i18n.ts"
|
import { getLocale, dynamicActivate } from "./lib/i18n.ts"
|
||||||
|
import { SystemStatus } from "./lib/enums.ts"
|
||||||
|
|
||||||
// const ServerDetail = lazy(() => import('./components/routes/system.tsx'))
|
// const ServerDetail = lazy(() => import('./components/routes/system.tsx'))
|
||||||
const LoginPage = lazy(() => import("./components/login/login.tsx"))
|
const LoginPage = lazy(() => import("./components/login/login.tsx"))
|
||||||
@@ -50,10 +51,10 @@ const App = memo(() => {
|
|||||||
} else {
|
} else {
|
||||||
let up = false
|
let up = false
|
||||||
for (const system of systems) {
|
for (const system of systems) {
|
||||||
if (system.status === "down") {
|
if (system.status === SystemStatus.Down) {
|
||||||
updateFavicon("favicon-red.svg")
|
updateFavicon("favicon-red.svg")
|
||||||
return
|
return
|
||||||
} else if (system.status === "up") {
|
} else if (system.status === SystemStatus.Up) {
|
||||||
up = true
|
up = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user