diff --git a/beszel/internal/users/users.go b/beszel/internal/users/users.go
index ca4dfda..8ed7dda 100644
--- a/beszel/internal/users/users.go
+++ b/beszel/internal/users/users.go
@@ -14,18 +14,6 @@ type UserManager struct {
app core.App
}
-type UserSettings struct {
- ChartTime string `json:"chartTime"`
- NotificationEmails []string `json:"emails"`
- NotificationWebhooks []string `json:"webhooks"`
- // UnitTemp uint8 `json:"unitTemp"` // 0 for Celsius, 1 for Fahrenheit
- // UnitNet uint8 `json:"unitNet"` // 0 for bytes, 1 for bits
- // UnitDisk uint8 `json:"unitDisk"` // 0 for bytes, 1 for bits
-
- // New field for alert history retention (e.g., "1m", "3m", "6m", "1y")
- AlertHistoryRetention string `json:"alertHistoryRetention,omitempty"`
-}
-
func NewUserManager(app core.App) *UserManager {
return &UserManager{
app: app,
@@ -44,7 +32,10 @@ func (um *UserManager) InitializeUserRole(e *core.RecordEvent) error {
func (um *UserManager) InitializeUserSettings(e *core.RecordEvent) error {
record := e.Record
// intialize settings with defaults (zero values can be ignored)
- settings := UserSettings{
+ settings := struct {
+ ChartTime string `json:"chartTime"`
+ Emails []string `json:"emails"`
+ }{
ChartTime: "1h",
}
record.UnmarshalJSONField("settings", &settings)
@@ -59,10 +50,7 @@ func (um *UserManager) InitializeUserSettings(e *core.RecordEvent) error {
log.Println("failed to get user email", "err", err)
return err
}
- settings.NotificationEmails = []string{user.Email}
- if len(settings.NotificationWebhooks) == 0 {
- settings.NotificationWebhooks = []string{""}
- }
+ settings.Emails = []string{user.Email}
record.Set("settings", settings)
return e.Next()
}
diff --git a/beszel/site/src/components/routes/settings/general.tsx b/beszel/site/src/components/routes/settings/general.tsx
index 753bb6f..956b0ab 100644
--- a/beszel/site/src/components/routes/settings/general.tsx
+++ b/beszel/site/src/components/routes/settings/general.tsx
@@ -12,29 +12,17 @@ import languages from "@/lib/languages"
import { dynamicActivate } from "@/lib/i18n"
import { useLingui } from "@lingui/react/macro"
import { Input } from "@/components/ui/input"
-// import { setLang } from "@/lib/i18n"
import { Unit } from "@/lib/enums"
export default function SettingsProfilePage({ userSettings }: { userSettings: UserSettings }) {
const [isLoading, setIsLoading] = useState(false)
const { i18n } = useLingui()
- // Remove all per-metric threshold state and UI
- // Only keep general yellow/red threshold state and UI
- const [yellow, setYellow] = useState(userSettings.meterThresholds?.yellow ?? 65)
- const [red, setRed] = useState(userSettings.meterThresholds?.red ?? 90)
-
- function handleResetThresholds() {
- setYellow(65)
- setRed(90)
- }
-
async function handleSubmit(e: React.FormEvent) {
e.preventDefault()
setIsLoading(true)
const formData = new FormData(e.target as HTMLFormElement)
const data = Object.fromEntries(formData) as Partial
- data.meterThresholds = { yellow, red }
await saveSettings(data)
setIsLoading(false)
}
@@ -114,45 +102,6 @@ export default function SettingsProfilePage({ userSettings }: { userSettings: Us
-
-
-
- Dashboard meter thresholds
-
-
- Choose when the dashboard meters changes colors, based on percentage values.
-
-
-
-
-
- setYellow(Number(e.target.value))}
- />
-
-
-
- setRed(Number(e.target.value))}
- />
-
-
-
-
-
- {/* Unit preferences section fixed and wrapped in a div */}
@@ -232,6 +181,47 @@ export default function SettingsProfilePage({ userSettings }: { userSettings: Us
+
+
+
+ Warning thresholds
+
+
+ Set percentage thresholds for meter colors.
+
+
+
+
+
)
}
+
function CellFormatter(info: CellContext) {
+ const userSettings = useStore($userSettings)
const val = Number(info.getValue()) || 0
+ const { colorWarn = 65, colorCrit = 90 } = userSettings
return (
{decimalString(val, val >= 10 ? 1 : 2)}%
@@ -289,8 +292,8 @@ function CellFormatter(info: CellContext
) {
className={cn(
"absolute inset-0 w-full h-full origin-left",
(info.row.original.status !== "up" && "bg-primary/30") ||
- (val < 65 && "bg-green-500") ||
- (val < 90 && "bg-yellow-500") ||
+ (val < colorWarn && "bg-green-500") ||
+ (val < colorCrit && "bg-yellow-500") ||
"bg-red-600"
)}
style={{
diff --git a/beszel/site/src/components/systems-table/systems-table.tsx b/beszel/site/src/components/systems-table/systems-table.tsx
index e7fde1a..f81a0b1 100644
--- a/beszel/site/src/components/systems-table/systems-table.tsx
+++ b/beszel/site/src/components/systems-table/systems-table.tsx
@@ -51,49 +51,6 @@ import AlertButton from "../alerts/alert-button"
type ViewMode = "table" | "grid"
-function CellFormatter(info: CellContext) {
- const val = (info.getValue() as number) || 0
- const userSettings = useStore($userSettings)
- const yellow = userSettings?.meterThresholds?.yellow ?? 65
- const red = userSettings?.meterThresholds?.red ?? 90
- return (
-
- {decimalString(val, 1)}%
-
-
-
-
- )
-}
-
-function sortableHeader(context: HeaderContext) {
- const { column } = context
- // @ts-ignore
- const { Icon, hideSort, name }: { Icon: React.ElementType; name: () => string; hideSort: boolean } = column.columnDef
- return (
-
- )
-}
-
export default function SystemsTable() {
const data = useStore($systems)
const { i18n, t } = useLingui()
diff --git a/beszel/site/src/lib/stores.ts b/beszel/site/src/lib/stores.ts
index eb99aaa..e8167b0 100644
--- a/beszel/site/src/lib/stores.ts
+++ b/beszel/site/src/lib/stores.ts
@@ -24,17 +24,21 @@ export const $chartTime = atom("1h") as PreinitializedWritableAtom
/** Whether to display average or max chart values */
export const $maxValues = atom(false)
+// export const UserSettingsSchema = v.object({
+// chartTime: v.picklist(["1h", "12h", "24h", "1w", "30d"]),
+// emails: v.optional(v.array(v.pipe(v.string(), v.email())), [pb?.authStore?.record?.email ?? ""]),
+// webhooks: v.optional(v.array(v.string())),
+// colorWarn: v.optional(v.pipe(v.number(), v.minValue(1), v.maxValue(100))),
+// colorDanger: v.optional(v.pipe(v.number(), v.minValue(1), v.maxValue(100))),
+// unitTemp: v.optional(v.enum(Unit)),
+// unitNet: v.optional(v.enum(Unit)),
+// unitDisk: v.optional(v.enum(Unit)),
+// })
+
/** User settings */
export const $userSettings = map({
chartTime: "1h",
emails: [pb.authStore.record?.email || ""],
- meterThresholds: {
- yellow: 65,
- red: 90,
- },
- // unitTemp: "celsius",
- // unitNet: "mbps",
- // unitDisk: "mbps",
})
// update local storage on change
$userSettings.subscribe((value) => {
diff --git a/beszel/site/src/types.d.ts b/beszel/site/src/types.d.ts
index 9011ba5..6639daf 100644
--- a/beszel/site/src/types.d.ts
+++ b/beszel/site/src/types.d.ts
@@ -224,17 +224,14 @@ export interface ChartTimeData {
}
export interface UserSettings {
- // lang?: string
chartTime: ChartTimes
emails?: string[]
webhooks?: string[]
- meterThresholds?: {
- yellow?: number
- red?: number
- }
unitTemp?: Unit
unitNet?: Unit
unitDisk?: Unit
+ colorWarn?: number
+ colorCrit?: number
}
type ChartDataContainer = {