From 7cd4abb6946a9c1a306918b6ee326279bc87f0a2 Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Sat, 21 Mar 2026 14:07:30 -0500 Subject: [PATCH] Enhancement: Network Access settings: leaving a field blank no longer shows a validation error. The default CIDR range for that field is saved automatically and a "Defaults Restored" warning is displayed listing which fields were reset. (Closes #726) --- CHANGELOG.md | 3 ++ .../forms/settings/NetworkAccessForm.jsx | 43 +++++++++++++++++-- .../forms/settings/NetworkAccessFormUtils.js | 4 ++ 3 files changed, 46 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2300474..bbc76777 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Frontend cleanup: removed unused imports from `M3UGroupFilter`, `LiveGroupFilter`, and `VODCategoryFilter` (`Yup`, `M3UProfiles`, several unused Mantine components, dead `OptionWithTooltip` component, duplicate lucide-react imports, and `Divider` in `VODCategoryFilter`). No behaviour changes. +- Network Access settings: leaving a field blank no longer shows a validation error. The default CIDR range for that field is saved automatically and a "Defaults Restored" warning is displayed listing which fields were reset. (Closes #726) + +### Fixed ## [0.21.1] - 2026-03-18 diff --git a/frontend/src/components/forms/settings/NetworkAccessForm.jsx b/frontend/src/components/forms/settings/NetworkAccessForm.jsx index 04ab60b0..ca165ce6 100644 --- a/frontend/src/components/forms/settings/NetworkAccessForm.jsx +++ b/frontend/src/components/forms/settings/NetworkAccessForm.jsx @@ -1,6 +1,6 @@ import { NETWORK_ACCESS_OPTIONS } from '../../../constants.js'; import useSettingsStore from '../../../store/settings.jsx'; -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useForm } from '@mantine/form'; import { checkSetting, @@ -19,12 +19,14 @@ const NetworkAccessForm = React.memo(({ active }) => { const [networkAccessError, setNetworkAccessError] = useState(null); const [saved, setSaved] = useState(false); + const [restoredDefaults, setRestoredDefaults] = useState([]); const [networkAccessConfirmOpen, setNetworkAccessConfirmOpen] = useState(false); const [saving, setSaving] = useState(false); const [netNetworkAccessConfirmCIDRs, setNetNetworkAccessConfirmCIDRs] = useState([]); const [clientIpAddress, setClientIpAddress] = useState(null); + const pendingSaveValuesRef = useRef(null); const networkAccessForm = useForm({ mode: 'controlled', @@ -33,7 +35,10 @@ const NetworkAccessForm = React.memo(({ active }) => { }); useEffect(() => { - if (!active) setSaved(false); + if (!active) { + setSaved(false); + setRestoredDefaults([]); + } }, [active]); useEffect(() => { @@ -58,9 +63,31 @@ const NetworkAccessForm = React.memo(({ active }) => { const onNetworkAccessSubmit = async () => { setSaved(false); setNetworkAccessError(null); + setRestoredDefaults([]); + + // Check for blank fields and substitute defaults before saving + const currentValues = networkAccessForm.getValues(); + const defaults = getNetworkAccessDefaults(); + const restoredLabels = []; + const submitValues = { ...currentValues }; + + Object.keys(currentValues).forEach((key) => { + if (!currentValues[key] || currentValues[key].trim() === '') { + submitValues[key] = defaults[key]; + restoredLabels.push(NETWORK_ACCESS_OPTIONS[key]?.label || key); + } + }); + + if (restoredLabels.length > 0) { + networkAccessForm.setValues(submitValues); + setRestoredDefaults(restoredLabels); + } + + pendingSaveValuesRef.current = submitValues; + const check = await checkSetting({ ...settings['network_access'], - value: networkAccessForm.getValues(), // Send as object + value: submitValues, }); if (check.error && check.message) { @@ -84,10 +111,12 @@ const NetworkAccessForm = React.memo(({ active }) => { const saveNetworkAccess = async () => { setSaved(false); setSaving(true); + const values = + pendingSaveValuesRef.current || networkAccessForm.getValues(); try { await updateSetting({ ...settings['network_access'], - value: networkAccessForm.getValues(), // Send as object + value: values, }); setSaved(true); } catch (e) { @@ -113,6 +142,12 @@ const NetworkAccessForm = React.memo(({ active }) => { title="Saved Successfully" > )} + {restoredDefaults.length > 0 && ( + + The following fields were empty and have been restored to their + defaults: {restoredDefaults.join(', ')} + + )} {networkAccessError && ( { export const getNetworkAccessFormValidation = () => { return Object.keys(NETWORK_ACCESS_OPTIONS).reduce((acc, key) => { acc[key] = (value) => { + if (!value || value.trim() === '') { + return null; // Empty values will be replaced with defaults on submit + } + if ( value .split(',')