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(',')