diff --git a/client/src/Hooks/useSettingsForm.ts b/client/src/Hooks/useSettingsForm.ts index ce04a81e2..3af8c229e 100644 --- a/client/src/Hooks/useSettingsForm.ts +++ b/client/src/Hooks/useSettingsForm.ts @@ -22,10 +22,22 @@ export const useSettingsForm = ({ data = null }: UseSettingsFormOptions = {}) => systemEmailTLSServername: data?.systemEmailTLSServername || "", systemEmailPort: data?.systemEmailPort, globalThresholds: { - cpu: data?.globalThresholds?.cpu ?? 0, - memory: data?.globalThresholds?.memory ?? 0, - disk: data?.globalThresholds?.disk ?? 0, - temperature: data?.globalThresholds?.temperature ?? 0, + cpu: + data?.globalThresholds?.cpu && data.globalThresholds.cpu >= 1 + ? data.globalThresholds.cpu + : 80, + memory: + data?.globalThresholds?.memory && data.globalThresholds.memory >= 1 + ? data.globalThresholds.memory + : 80, + disk: + data?.globalThresholds?.disk && data.globalThresholds.disk >= 1 + ? data.globalThresholds.disk + : 80, + temperature: + data?.globalThresholds?.temperature && data.globalThresholds.temperature >= 1 + ? data.globalThresholds.temperature + : 80, }, checkTTL: data?.checkTTL ?? 30, pagespeedApiKey: "", diff --git a/client/src/Pages/Settings/index.tsx b/client/src/Pages/Settings/index.tsx index 484ab3690..2f54a1235 100644 --- a/client/src/Pages/Settings/index.tsx +++ b/client/src/Pages/Settings/index.tsx @@ -14,7 +14,7 @@ import { useIsAdmin } from "@/Hooks/useIsAdmin.js"; import type { SettingsFormData } from "@/Validation/settings"; import { useState } from "react"; import { Controller } from "react-hook-form"; -import { TextField, Button, FieldLabel } from "@/Components/inputs"; +import { TextField, Button, FieldLabel, SliderWithLabel } from "@/Components/inputs"; import { Box, Typography } from "@mui/material"; import { useDelete } from "@/Hooks/UseApi"; @@ -465,24 +465,16 @@ export const SettingsPage = () => { name="globalThresholds.cpu" control={form.control} defaultValue={defaults.globalThresholds?.cpu} - render={({ field, fieldState }) => ( - ( + { - const val = e.target.value; - field.onChange(val === "" ? 0 : Number(val)); - }} fieldLabel={t("pages.settings.form.thresholds.option.cpu.label")} - type="number" - inputProps={{ min: 0 }} - placeholder={t( - "pages.settings.form.thresholds.option.cpu.placeholder" - )} - error={!!fieldState.error} - helperText={fieldState.error?.message} + min={1} + max={100} + sliderMaxWidth={{ xs: "100%", md: "50%" }} + value={field.value || 1} + onChange={(_, value) => field.onChange(value)} + valueLabelDisplay="auto" /> )} /> @@ -490,24 +482,16 @@ export const SettingsPage = () => { name="globalThresholds.memory" control={form.control} defaultValue={defaults.globalThresholds?.memory} - render={({ field, fieldState }) => ( - ( + { - const val = e.target.value; - field.onChange(val === "" ? 0 : Number(val)); - }} fieldLabel={t("pages.settings.form.thresholds.option.memory.label")} - type="number" - inputProps={{ min: 0 }} - placeholder={t( - "pages.settings.form.thresholds.option.memory.placeholder" - )} - error={!!fieldState.error} - helperText={fieldState.error?.message} + min={1} + max={100} + sliderMaxWidth={{ xs: "100%", md: "50%" }} + value={field.value || 1} + onChange={(_, value) => field.onChange(value)} + valueLabelDisplay="auto" /> )} /> @@ -515,24 +499,16 @@ export const SettingsPage = () => { name="globalThresholds.disk" control={form.control} defaultValue={defaults.globalThresholds?.disk} - render={({ field, fieldState }) => ( - ( + { - const val = e.target.value; - field.onChange(val === "" ? 0 : Number(val)); - }} fieldLabel={t("pages.settings.form.thresholds.option.disk.label")} - type="number" - inputProps={{ min: 0 }} - placeholder={t( - "pages.settings.form.thresholds.option.disk.placeholder" - )} - error={!!fieldState.error} - helperText={fieldState.error?.message} + min={1} + max={100} + sliderMaxWidth={{ xs: "100%", md: "50%" }} + value={field.value || 1} + onChange={(_, value) => field.onChange(value)} + valueLabelDisplay="auto" /> )} /> @@ -540,26 +516,18 @@ export const SettingsPage = () => { name="globalThresholds.temperature" control={form.control} defaultValue={defaults.globalThresholds?.temperature} - render={({ field, fieldState }) => ( - ( + { - const val = e.target.value; - field.onChange(val === "" ? 0 : Number(val)); - }} fieldLabel={t( "pages.settings.form.thresholds.option.temperature.label" )} - type="number" - inputProps={{ min: 0 }} - placeholder={t( - "pages.settings.form.thresholds.option.temperature.placeholder" - )} - error={!!fieldState.error} - helperText={fieldState.error?.message} + min={1} + max={100} + sliderMaxWidth={{ xs: "100%", md: "50%" }} + value={field.value || 1} + onChange={(_, value) => field.onChange(value)} + valueLabelDisplay="auto" /> )} /> diff --git a/client/src/Validation/settings.ts b/client/src/Validation/settings.ts index 4c89a4c2c..a52959ab2 100644 --- a/client/src/Validation/settings.ts +++ b/client/src/Validation/settings.ts @@ -40,34 +40,12 @@ export const settingsSchema = z.object({ .string() .transform((val) => (val.trim() === "" ? undefined : val.trim())) .optional(), - globalThresholds: z - .object({ - cpu: z - .number() - .int() - .min(1, "Please enter a valid value") - .max(100, "Maximum value is 100") - .optional(), - memory: z - .number() - .int() - .min(1, "Please enter a valid value") - .max(100, "Maximum value is 100") - .optional(), - disk: z - .number() - .int() - .min(1, "Please enter a valid value") - .max(100, "Maximum value is 100") - .optional(), - temperature: z - .number() - .int() - .min(1, "Please enter a valid value") - .max(150, "Maximum value is 150") - .optional(), - }) - .optional(), + globalThresholds: z.object({ + cpu: z.number().int().min(1).max(100), + memory: z.number().int().min(1).max(100), + disk: z.number().int().min(1).max(100), + temperature: z.number().int().min(1).max(100), + }), }); export type SettingsFormData = z.infer;