From f9bd61af4988eb615506a30237ed109b23113a03 Mon Sep 17 00:00:00 2001 From: Brad Date: Fri, 5 Sep 2025 07:52:06 +0930 Subject: [PATCH] Fixed overrideFrequency Input Constraints (#801) * Fixed overrideFrequency to properly allow for floats with a minimum of 410 MHz and maximum of 930 MHz. Added 3 decimal point check. * Removed duplicate error message in FormInput.tsx * Added error message for overrideFrequency in several locales * Simplified check and reverted translated languages to English besides German. Also fixed a typo in src/components/UI/Input.tsx. * Let i18n handle fallback + linting --------- Co-authored-by: philon- --- packages/web/public/i18n/locales/de-DE/common.json | 3 +++ packages/web/public/i18n/locales/en/common.json | 3 +++ packages/web/src/components/Form/DynamicFormField.tsx | 1 - packages/web/src/components/Form/FormInput.tsx | 9 --------- packages/web/src/components/UI/Input.tsx | 2 +- packages/web/src/validation/config/lora.ts | 6 +++++- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/web/public/i18n/locales/de-DE/common.json b/packages/web/public/i18n/locales/de-DE/common.json index 272f5652..6b570e56 100644 --- a/packages/web/public/i18n/locales/de-DE/common.json +++ b/packages/web/public/i18n/locales/de-DE/common.json @@ -135,6 +135,9 @@ "generic": "Dies ist ein Pflichtfeld.", "managed": "Mindestens ein administrativer Schlüssel wird benötigt, um diesen Knoten zu verwalten", "key": "Schlüssel erforderlich." + }, + "invalidOverrideFreq": { + "number": "Ungültiges Format, erwartet 430-930 MHz." } }, "yes": "Ja", diff --git a/packages/web/public/i18n/locales/en/common.json b/packages/web/public/i18n/locales/en/common.json index 33aafd28..a20e78bb 100644 --- a/packages/web/public/i18n/locales/en/common.json +++ b/packages/web/public/i18n/locales/en/common.json @@ -111,6 +111,9 @@ "generic": "This field is required.", "managed": "At least one admin key is requred if the node is managed.", "key": "Key is required." + }, + "invalidOverrideFreq": { + "number": "Invalid format, expected between 430-930 MHz." } }, "yes": "Yes", diff --git a/packages/web/src/components/Form/DynamicFormField.tsx b/packages/web/src/components/Form/DynamicFormField.tsx index a5f0a60b..9452d30c 100644 --- a/packages/web/src/components/Form/DynamicFormField.tsx +++ b/packages/web/src/components/Form/DynamicFormField.tsx @@ -52,7 +52,6 @@ export function DynamicFormField({ control={control} disabled={disabled} isDirty={isDirty} - invalid={invalid} /> ); diff --git a/packages/web/src/components/Form/FormInput.tsx b/packages/web/src/components/Form/FormInput.tsx index 74e69430..487f9656 100644 --- a/packages/web/src/components/Form/FormInput.tsx +++ b/packages/web/src/components/Form/FormInput.tsx @@ -30,7 +30,6 @@ export function GenericInput({ control, disabled, field, - invalid, }: GenericFormElementProps>) { const { fieldLength, ...restProperties } = field.properties || {}; @@ -46,8 +45,6 @@ export function GenericInput({ }, }); - const isInvalid = invalid || Boolean(error?.message); - const handleInputChange = (e: React.ChangeEvent) => { const newValue = e.target.value; @@ -100,12 +97,6 @@ export function GenericInput({ {currentLength}/{fieldLength.max} )} - - {isInvalid && ( -
-

{error?.message ?? ""}

-
- )} ); } diff --git a/packages/web/src/components/UI/Input.tsx b/packages/web/src/components/UI/Input.tsx index cc557628..39359edb 100644 --- a/packages/web/src/components/UI/Input.tsx +++ b/packages/web/src/components/UI/Input.tsx @@ -10,7 +10,7 @@ const cnInvalidBase = "border-2 border-red-500 dark:border-red-500"; const cnDirtyBase = "border-2 border-sky-500 dark:border-sky-500"; const inputVariants = cva( - "flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-1 focus:ring-slate-400 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-500 dark:bg-transparet dark:text-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-600", + "flex h-10 w-full rounded-md border border-slate-300 bg-transparent py-2 px-3 text-sm placeholder:text-slate-400 focus:outline-none focus:ring-1 focus:ring-slate-400 disabled:cursor-not-allowed disabled:opacity-50 dark:border-slate-500 dark:bg-transparent dark:text-slate-100 dark:focus:ring-slate-400 dark:focus:ring-offset-slate-600", { variants: { variant: { diff --git a/packages/web/src/validation/config/lora.ts b/packages/web/src/validation/config/lora.ts index 0b10de80..743684d6 100644 --- a/packages/web/src/validation/config/lora.ts +++ b/packages/web/src/validation/config/lora.ts @@ -18,7 +18,11 @@ export const LoRaValidationSchema = z.object({ channelNum: z.coerce.number().int(), overrideDutyCycle: z.boolean(), sx126xRxBoostedGain: z.boolean(), - overrideFrequency: z.coerce.number().int(), + overrideFrequency: z.coerce + .number() + .refine((val) => val >= 410 && val <= 930, { + message: "formValidation.invalidOverrideFreq.number", + }), ignoreIncoming: z.coerce.number().array(), ignoreMqtt: z.boolean(), configOkToMqtt: z.boolean(),