Development

This commit is contained in:
Matthew Grotke 2026-05-31 01:19:50 -04:00
parent 3e154da2aa
commit c66c2e7a4d
3 changed files with 49 additions and 4 deletions

View file

@ -775,18 +775,19 @@ def build_field(item, tokens):
_vmask = parse_validation(validate_raw) if validate_raw else 0
validate_attr = f' data-validate="{_vmask}"' if _vmask else ''
depends_attr = f' data-depends="{e(",".join(depends))}"' if depends else ''
extra_attrs = ''.join(f' {e(ak)}="{e(str(av))}"' for ak, av in item.get('attrs', {}).items())
if _vmask:
return (
f'<div class="form-group"><label class="form-label">{label}</label>'
f'<div class="field-wrap"><input type="{e(input_type)}" name="{name}" value="{e(value)}"'
f' placeholder="{placeholder}" class="form-input"{readonly}{validate_attr}{depends_attr}/>'
f' placeholder="{placeholder}" class="form-input"{readonly}{validate_attr}{depends_attr}{extra_attrs}/>'
f'<p class="form-hint field-dyn-hint hidden"></p></div>'
f'{hint_html}</div>'
)
return (
f'<div class="form-group"><label class="form-label">{label}</label>'
f'<input type="{e(input_type)}" name="{name}" value="{e(value)}"'
f' placeholder="{placeholder}" class="form-input"{readonly}{validate_attr}{depends_attr}/>'
f' placeholder="{placeholder}" class="form-input"{readonly}{validate_attr}{depends_attr}{extra_attrs}/>'
f'{hint_html}</div>'
)

View file

@ -154,6 +154,36 @@ def addvlan_add():
flash(f"'{dhcp_domain_raw}' is not a valid domain name.", 'error')
return redirect(f'/{_PAGE}')
dhcp_pool_start = sanitize.ip(request.form.get('dhcp_pool_start', ''))
dhcp_pool_end = sanitize.ip(request.form.get('dhcp_pool_end', ''))
if dhcp_pool_start and ipaddress.IPv4Address(dhcp_pool_start) not in _vlan_net:
flash(f"Pool start '{dhcp_pool_start}' is not in the VLAN subnet ({subnet}/{subnet_mask}).", 'error')
return redirect(f'/{_PAGE}')
if dhcp_pool_end and ipaddress.IPv4Address(dhcp_pool_end) not in _vlan_net:
flash(f"Pool end '{dhcp_pool_end}' is not in the VLAN subnet ({subnet}/{subnet_mask}).", 'error')
return redirect(f'/{_PAGE}')
if dhcp_pool_start and dhcp_pool_end:
if ipaddress.IPv4Address(dhcp_pool_start) > ipaddress.IPv4Address(dhcp_pool_end):
flash('Pool start must not be greater than pool end.', 'error')
return redirect(f'/{_PAGE}')
_lease_time_raw = request.form.get('dhcp_lease_time', '').strip()
_lease_unit_raw = request.form.get('dhcp_lease_unit', '').strip()
dhcp_lease_time = None
if _lease_time_raw:
try:
_lt = int(_lease_time_raw)
if _lt < 1:
raise ValueError
except ValueError:
flash('Lease time must be a positive integer.', 'error')
return redirect(f'/{_PAGE}')
_unit_suffix = {'minutes': 'm', 'hours': 'h', 'days': 'd'}.get(_lease_unit_raw)
if not _unit_suffix:
flash('Lease time unit must be minutes, hours, or days.', 'error')
return redirect(f'/{_PAGE}')
dhcp_lease_time = f'{_lt}{_unit_suffix}'
cfg = load_config()
vlans = cfg.setdefault('vlans', [])
@ -167,6 +197,12 @@ def addvlan_add():
dhcp_info = {}
if dhcp_domain and dhcp_domain != 'local':
dhcp_info['domain'] = dhcp_domain
if dhcp_pool_start:
dhcp_info['dynamic_pool_start'] = dhcp_pool_start
if dhcp_pool_end:
dhcp_info['dynamic_pool_end'] = dhcp_pool_end
if dhcp_lease_time:
dhcp_info['lease_time'] = dhcp_lease_time
dhcp_overrides = {}
if new_stored_gw:
dhcp_overrides['gateway'] = new_stored_gw

View file

@ -257,14 +257,22 @@
"label": "DHCP Dynamic Pool Start",
"name": "dhcp_pool_start",
"input_type": "text",
"placeholder": "e.g. 192.168.1.100"
"validate": "VALIDATION_ADDRESS",
"attrs": {
"data-dep-subnet": "[name='subnet']",
"data-dep-mask": ".subnet-prefix-input"
}
},
{
"type": "field",
"label": "DHCP Dynamic Pool End",
"name": "dhcp_pool_end",
"input_type": "text",
"placeholder": "e.g. 192.168.1.200"
"validate": "VALIDATION_ADDRESS",
"attrs": {
"data-dep-subnet": "[name='subnet']",
"data-dep-mask": ".subnet-prefix-input"
}
},
{
"type": "field_row",