- Add FieldKeyForOption() using EffectiveConfigSections.GetSectionId so
cross-option issues match UI field keys; tighten RFC1918 in-addr.arpa
detection for bogus-priv vs server=.
- GetMulti: pending change always wins; empty list when NewValue is not
a string list (with tests).
- EffectiveConfigSection: re-run cross-option when entering edit mode or
continuing after save failure; allow opening save modal when only
validation summary is present.
- Toolbar: validation link aria-label describes opening the summary.
Move cross-option checks to DI-backed rules and shared context so editor and quick-add flows use one validation pipeline. Improve warning copy and save-modal messaging to clarify that validation reflects both on-disk config and pending edits.
Redesign the Hosts page around source-aware grouped rows with shared table shell styling, fix effective-config save session synchronization, and move read-ethers into the DHCP model where dnsmasq actually applies it.
- EffectiveConfigFieldRef as value type; PendingDnsmasqChange/PendingOptionChange/PendingManagedHostsChange
- Multi-file save plan (DnsmasqSaveWritePlan, DnsmasqManagedBackup) and backup/restore in save flow
- Hosts integrated into effective-config save; Hosts.razor uses shared save modal
- IEffectiveConfigDescriptorProvider + IEffectiveConfigFieldBuilder (DI); descriptors from EffectiveConfigSections
- IEffectiveConfigPageEditor, shared descriptor resolution; addn-hosts/dhcp-host descriptor fix
- DnsmasqConfText, IEffectiveConfigDirectiveSerializer; DnsmasqConfigService uses serializer for writes
- IStructuredOptionValueHandler/Registry, DhcpHostOptionValueHandler; Dhcp.razor index-based DeleteRow fix
- SaveService: roll back partial writes on failure; SaveModal: WriteFailed shows backups and Restore button
Unify parser, editor, and save-time validation around semantic metadata and handlers, add path-aware and structured option checks, and improve effective-config editing placeholders and unset behavior.
- Add dhcp-optsdir support (model, sections, parser, UI multi-value).
- Model leasequery, connmark-allowlist-enable, dhcp-generate-names, dhcp-broadcast,
bootp-dynamic, dnssec-check-unsigned as key-only-or-value with validation.
- Parse compile-time capabilities from dnsmasq --version (DHCP, TFTP, DNSSEC, DBus).
- Expose capabilities via DnsmasqVersionInfo and status API (DnsmasqSupports*).
- Map options to required features; disable unsupported option editors with badge + tooltip.
- Save guard: reject changes for unsupported options; use UnsupportedCapabilities error code.
- MultiKeyOnlyOrValue write path: filter out readonly values to avoid duplicating in managed file.
- User-friendly tooltips for disabled options; dedicated UnsupportedCapabilities vs WriteFailed.
- Add shared .ec-effective-switch styles in app.css for consistent switch look
- Wrap flag and do-0x20-encode checkboxes in form-check form-switch
- Add aria-label and title for accessibility
- Matches existing KeyOnlyOrValueDisplay (use-stale-cache, add-mac, etc.)
- Fix do-0x20-encode: clearing pending when toggling back to original (Disabled/Default)
- Do0x20EncodeDisplay: uncheck uses pending.OldValue when present
- EffectiveConfigFieldDisplay: use pending.OldValue as _valueAtActivation when re-entering with pending
- Effective config: validation errors/warnings in toolbar and save modal, revert from modal
- Custom displays: Do0x20EncodeDisplay (tri-state), KeyOnlyOrValueDisplay
- ExplicitToggleState, config/apply support for do-0x20-encode, option help and tests
- DnsmasqOptions: set RestartTimeoutSeconds default to 30 to match XML comment
and original reload timeout (avoids halving timeout for restart/reload).
- Save modal: multi-value diff no longer uses set-only Except(); when lists
have same items but different order (or duplicate count), show 'Order or
duplicates changed' with before/after so reorders (e.g. server=) are visible.
- Multi-value items: EditableAsButton=true so 'editable' badge is clickable in view
mode and activates the field like other editable badges.
- Save modal: 'Continue editing' after ValidateFailed/ReloadFailed now discards
session, refreshes config from disk, then re-enters edit mode so remove/UI
work correctly.
- 'Stop editing' after ValidateFailed/ReloadFailed now triggers config refresh
so the invalid value on disk is shown instead of stale UI.
- SaveFlow: HandleCloseAndEndEdit invokes OnSaveCompleted when in failed state;
OnContinueEditing uses EventCallback.Factory.Create to fix method-group
conversion warning.
- All multi fields use EffectiveMultiValueConfigFieldDescriptor; registry has
RegisterMultiDescriptor/RegisterMultiComponent/RegisterMulti; every multi
option registered; plain multi fallback removed (AddMultiDescriptor throws).
- Descriptor-driven validation: base descriptor ValidateValue + Validate();
integer descriptor enforces Min/Max; ListenAddressMultiValidator for
listen-address; single/flag commit uses Descriptor.Validate (no session
field issues for inline edits).
- Multi list editor: local _displayItems so remove/add/edit update UI
immediately; remove button PreventBlurOnMouseDown; inline validation
message under input (ec-multi-list-input-group); root div not span.
- Save flow: on successful backup restore call OnCloseAndEndEdit then
OnSaveCompleted so session and pending changes are cleared and config
is reloaded.
- Server uses descriptor-only (no custom multi component); ServerMultiValueDisplay
removed. RegisterValidatedSingle added for future single-field validation.
- Model conntrack as Flag (parser, config bool, cache, registry FlagValueDisplay)
- Apply: for non-flag options with empty/invalid value, remove existing line
and never write key-only directive (was producing malformed option= without value)
- Flag options: when user toggles value back to original, clear pending change (same as revert button); trigger revert immediately on change so UI updates without blur
- UiContext: add RevertFieldAsync so section can revert a field and refresh; section wires it to Session.RevertChange + StateHasChanged
- RestoreAsync: call config cache Invalidate() after File.Copy so next read sees restored file (fixes validate-fail → restore showing pre-restore data)
- Multi-value: show editable badge next to (none); clicking activates edit and opens add row
- List editor: when empty and add allowed, do not show (none) row; auto-focus new-item input on open and when clicking add item
- Toolbar: make 'X change(s)' clickable to open save dialog (keyboard accessible)
- Add EffectiveConfigMultiValueListEditor with badge-style actions, draft merge,
and display-mode editable badges; fix row callback capture and bounds checks
- EffectiveConfigFieldDisplay: compute multi-value state in OnParametersSet +
HandleMultiValueChanged; BuildItemsWithSource preserves readonly/editable;
dedupe list on commit; defensive copy for multi-value commit
- DnsmasqConfigService: generic MatchesOption via key parsing; FilterManagedOnly
+ ReadReadonlyMultiValuesByOptionAsync (single-pass readonly); EnsureManagedConfigInvariants
+ EnsureUniqueDirective; fix DHCP write cache notification (re-parse written output)
- EffectiveConfigSaveResult: ErrorCodes constants, IsValidateFailed; set Validated=false
when validation fails; EffectiveConfigSaveFlow use IsValidateFailed; save service
use ErrorCodes
- OptionStateBadge: OnEditableClickRequested for list-editor per-item edit
- Validation service and config save flow updates
- Process: Add IProcessHandle, ProcessOutputLine, StartAsync; RunAsync via StartAsync+WaitForExitAsync. Wait for stdout/stderr stream close before reading to fix empty restart output. ProcessTimeouts; ReloadService/StatusController/LogsService use config timeouts.
- Effective config: Rename reload→restart in save/restore result types and UI. Save modal: show restart output, danger alert, Stop editing/Continue editing (yellow), footer one-line; fallback exit code when no output; ensure pre visibility (CSS). Restore failed: combined output helper.
- Status script: When dnsmasq dead, run dnsmasq --test and show config error in status block (Docker harness; DNSMASQ_CONF).
- listen-address: Allow IPv6 (ValidateDraftValue accepts InterNetworkV6).
- Docker test: RestartCommand uses DnsmasqOptions timeout; DnsmasqOptions RestartTimeoutSeconds.
- Register ISettingsModalService, INotificationService, IUpdateCheckService via assembly scanning (marker interfaces)
- Add IApplicationOptionsValidator<TOptions> marker; scan only those for IValidateOptions registration
- Fix ApplicationLifecycleLoggingHostedService: log RestartCommand/ReloadCommand/StatusCommand (no ApplyCommand)
- NavMenu: spin animation for update-check button icon when checking; single icon with conditional nav-footer-spin class
- Add NotificationHost/NotificationToast components and NotificationService for toasts
- Effective config save flow, restore result, save service; various EffectiveConfig and DnsmasqOptions/validator updates
- Test and script updates; docker-compose.test.yml, appsettings, DnsmasqConfKeys/tooltips/sections