Commit Graph
90 Commits
Author SHA1 Message Date
alex 43ba5116ac Make specialized DNS and resolver views draft-aware for release v0.0.9.
Project current effective multi-value edits back onto source-aware rows, add occurrence-based targeting for duplicate records, and bump the app version so the curated pages stay consistent with Effective configuration during editing.
2026-04-11 21:35:52 +10:00
alex b24ca17779 Add structured DNS, DHCP, and resolver policy editing flows.
Unify the pages around the effective-config save workflow, source-aware projections, and hosts-style table UX so draft changes are easier to understand and the specialized editors stay consistent and better covered by tests.
2026-04-11 20:25:28 +10:00
alex e86a2b6bd9 Extract hosts file filter into GroupedSelectDropdown and builder
Add shared Models.Ui grouped-select model, IGroupedSelectBuilder, optional
trigger summary API, and GroupedSelectDropdown component. Hosts page uses
HostsFileFilterBuilder and hosts-specific option row styling for full paths.

Remove HostsSourcePathDisplay and file filter menu records in favor of the
builder. Bump version to 0.0.8.
v0.0.8
2026-04-07 18:15:23 +10:00
alex 002e9a5db5 Polish multi-value editors and hosts inline editing.
Align the domain custom editor with the default multi-value layout, keep item numbering in edit mode, and restore unaffected single-value editor styling. Refine hosts inline editing with safer blur handling, explicit cancel actions, and better behavior when blank edits are abandoned.
2026-04-07 17:36:52 +10:00
alex 02a840799b Hosts page: grouped file filter with counts and source-path projection
Add SourcePathFilter to HostsPageQueryState and apply it in HostsPageProjectionService.
Replace the native select with a grouped menu (managed/system/additional/hostsdir),
per-file non-comment counts, toolbar layout, and full-path labels with end-anchored
ellipsis plus title tooltips. Include HostsSourcePathDisplay helpers, menu models,
and tests for grouping and projection filtering.
2026-04-07 16:00:25 +10:00
alex 2e713f0e3c Hosts UX, effective names, JS interop, domain UI
- Hosts: delete confirmation modal, shift range select, keyboard shortcuts,
  effective-name suffix tooltips, conditional modern header actions
- Align EffectiveNames on rows with scoped domain= + pending preview;
  unified hosts API uses full DomainValues from config snapshot
- Harden Blazor JS interop (safe helpers, IAsyncDisposable, disposal order)
- Effective config: domain multi-value display/editor, parsers, tests
- Misc: docs/testdata/docker script updates
2026-04-05 14:46:17 +10:00
alex 9627926a6a Hosts page UX, effective names, and draft sync
- Managed hosts: add slot row, selection with Ctrl/Cmd, Edit toggles to Save
  while editing, Remove, double-click to edit; header toolbar layout
- Column order: Address, Names, Effective names (when expand-hosts + domains),
  Comment; scroll cue radius and table styling tweaks
- Effective names: resolve domain suffix per row IPv4 from scoped domain=
  rules (CIDR/range) with dnsmasq-style precedence; IPv6 uses default;
  preview uses pending domain option when present
- Enter edit mode on Remove; clear stale inline edit when row disappears;
  deactivate effective-config field when interacting with hosts table
- Remove hosts-ui.js; effective names help uses notifications always
- Tests for HostsEffectiveNames domain rule resolution
2026-04-01 23:50:21 +10:00
alex eae29de045 Hosts: inline file comments (hosts(5)) and Comment column
- HostEntry.InlineComment; parse at first # on data lines; ToLine + SanitizeInlineComment
- HostsPageRow + HostsCache; pending change equality and save diff include comments
- Hosts table: dedicated Comment column; edit in own cell; empty shown as em dash
- Parser and pending-change tests
2026-04-01 11:52:21 +10:00
alex f0b4ea97a4 Hosts page UX, draft/UI split, and managed hosts save summary
- Split effective-config session into Draft + Ui (IEffectiveConfigDraft, IEffectiveConfigUiState)
- Hosts: managed overlay, edit mode from table, validation deferred to blur/Escape/Enter
- Managed hosts save modal: line-level diff (add/remove/modify/order)
- Hosts group headers: editable/read-only badges, empty-group row, Effective names help
- hosts-ui.js for touch vs hover help; table inline bind oninput for live preview
- HostsEntryEditValidator and ManagedHostsPendingChangeDiff with tests
2026-04-01 11:27:55 +10:00
alex 1bbab1c8c3 Fix address/local rule: skip NXDOMAIN address=/domain/ form
GetDomainsFromAddressDirective only considers lines with a non-empty
target after the final slash; address=/domain/ applies to all RR types
and should not require local=. Add tests for trailing-slash and # forms.
2026-03-30 19:41:08 +10:00
alex 5702844cea Cross-option rules: rev-server+bogus-priv, DHCP, port 0 netboot
- Extend bogus-priv private-reverse check to rev-server= RFC1918 IPv4
  targets (CIDR overlap); separate FieldIssues for server vs rev-server.
- Add no-ping + dhcp-sequential-ip warning (man/2.80).
- Add port=0 + enable-tftp/pxe-service warning.
- Clarify address/local 2.86+ message; comment deferring dhcp-authoritative
  DHCPv6 REBIND rule until doc/heuristics justify it.
- Tests for new behavior, pending rev-server overlay, field keys.
2026-03-30 19:29:30 +10:00
alex 84c58ccec7 Cross-option validation: field keys, bogus-priv zones, edit UX
- 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.
2026-03-30 11:31:02 +10:00
alex a3dc5ac45c EffectiveConfig: replace cross-option evaluator with rule service
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.
2026-03-29 21:35:30 +10:00
alex 31c0f65c86 Hosts page UX: simpler table, projection, and effective-config tweaks
Remove the Status column and row-level badges/actions; keep source-level
Editable on group headers. Double-click managed rows to edit; commit staged
drafts when focus leaves the row via isFocusOutsideElement in the shared
scroll-cue module. Hide inactive system-host rows when dnsmasq ignores them
and move system-hosts / expand-hosts notes below the content area.

Memoize VisibleGroups so BuildGroups runs once per render during search.
Move read-ethers metadata to the DHCP section; adjust Hosts page state copy
and related effective-config tooltips/builders where needed.
2026-03-29 09:31:29 +10:00
alex c7e7844ce7 Update hosts workflow and align DHCP metadata.
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.
2026-03-26 00:24:21 +10:00
alex 333566554c Update hosts file section 2026-03-18 12:41:34 +10:00
alex 1b3a09996f Effective config: unified save pipeline, descriptors, serialization, WriteFailed rollback
- 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
2026-03-12 01:48:19 +10:00
alex 3ca935e551 Tests: add real-world config coverage and prune brittle cases
Reduce presentation-focused test churn while adding corpus-based parser, validator, capability-guard, and round-trip save coverage to better protect future refactors.
2026-03-11 11:44:01 +10:00
alex e33402467f Reorganise codebase: EffectiveConfig, parsers, tests; move tooltips to Metadata
Infrastructure:
- Parsers under Serialization/Parsers: Dnsmasq, DnsmasqConfig, EffectiveConfig
- EffectiveConfig: Abstractions, Metadata (keys, views, field builder, tooltips,
  placeholders, write semantics), Rendering, Editing, Validation/Handlers, Readonly
- Helpers/Config: only DnsmasqFileEncoding; DnsmasqOptionTooltips moved to Metadata
- Remove empty Infrastructure/Parsers and Helpers/Dnsmasq

Tests:
- Mirror main project: Serialization/Parsers (Dnsmasq, DnsmasqConfig),
  Services/Dnsmasq/Config, Services/EffectiveConfig, Models, Helpers (TestDataHelper)
- Namespaces updated; usings for TestDataHelper and Metadata where needed

Docs: README codebase overview and test layout updated.
2026-03-11 10:50:23 +10:00
alex 9809ce9f7b Bump version to 0.0.7 v0.0.7 2026-03-11 09:44:40 +10:00
alex 181cbbed48 Option semantics: handlers, shared syntax, RaParam interface validation
- Add IOptionSemanticHandler implementations for DNS/DHCP/auth/interface options
- Add shared syntax helpers (DnsmasqRrTypeSyntax, DnsmasqScopedDomainSyntax, etc.)
- Wire semantics and registry for multi/single options; metadata-only semantics
- RaParam: use DnsmasqRelaySyntax.IsInterfaceNameWithOptionalTrailingWildcard so
  interface names allow only trailing *, not asterisks in the middle (eth*0, *eth0)
- Tests: RaParam trailing-wildcard and invalid-asterisk cases
2026-03-11 09:38:36 +10:00
alex 36a160dfc7 Refactor: option semantics to metadata + handlers, shared syntax, registry/save single path
- OptionSemantics: metadata only (no validator delegates); OptionValidationKind + PathPolicy
- IOptionSemanticHandler: handler-first validation; handlers registered via IApplicationMultiSingleton
- OptionSemanticValidator: single engine, handler dispatch then generic kind-based validation
- Shared syntax: DnsmasqScopedDomainSyntax, DnsmasqDhcpRangeValueParser, DnsmasqDhcpOptionSyntax,
  DnsmasqRelaySyntax, DnsmasqDhcpTagSyntax, DnsmasqIpPrefixSyntax for reuse across handlers
- New handlers: Server, Local, RevServer, Address, Alias, Ipset, Nftset, DhcpRange, DhcpHost,
  DhcpOption, DhcpRelay, DhcpProxy, IgnoreAddress, ConnmarkAllowlist, DhcpMatch, DhcpMac,
  PxeService, TrustAnchor, RebindDomainOk, BogusNxdomain, DhcpIgnoreNames, DhcpBoot, Slaac,
  BridgeInterface, SharedNetwork, DhcpOptionPxe, DhcpNameMatch, DhcpIgnore, DhcpVendorclass, DhcpUserclass, TagIf
- Registry and pre-save validation use engine only; placeholders via DnsmasqOptionPlaceholders
- DnsmasqConfigSetService uses DnsmasqDhcpRangeValueParser; DhcpRangeValueParserTests added
2026-03-10 23:44:51 +10:00
alex 1bf33f1a9b EffectiveConfig: centralize semantic validation and improve editor UX
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.
2026-03-10 22:33:11 +10:00
alex b4d1f39762 EffectiveConfig: add semantics wiring, validation, and tests
- Add DelegateMultiValueOptionValidator for multi-value option validation
- Extend EffectiveConfigOptionKindMap, SpecialOptionSemantics, RenderFragmentRegistry
- Add EffectiveConfigSemanticsWiringTests
2026-03-10 18:12:28 +10:00
alex 214d6c686e dnsmasq options: dhcp-optsdir, key-only-or-value semantics, capability detection
- 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.
2026-03-10 02:23:14 +10:00
alex 4c1c19b792 EffectiveConfig section CSS/panel updates; add ConfigFileList components 2026-03-09 23:38:47 +10:00
alex 98d1bc560e Reload button labels: StatusSection shows 'Reload', Dnsmasq page button shows 'Reload config' 2026-03-09 23:36:37 +10:00
alex fd16d50107 Add DNS Records and Filters pages; unify effective config layout
- Add EffectiveConfigContext.DnsRecords and .Filters; map in EffectiveConfigViews
- Add DnsRecords.razor and Filters.razor with context-scoped effective config
- Add nav links for DNS records and Filters (icons: diagram-3-fill, funnel-fill)
- Put effective config block at top of Hosts, DHCP, DNS Records, Filters (no config file list on sub-pages)
- Hosts view: add expand-hosts to allow-list. Filters view: add domain-needed, bogus-priv, filterwin2k, no-round-robin
- Page titles: Hosts Configuration, DHCP Configuration, DNS Records Configuration, Filters Configuration
- Remove 'Config affecting...' subheadings and page intro text; add .page-intro and .page-chip styles
2026-03-09 23:22:13 +10:00
alex de8afed68c Effective config: use switch styling for flag and do-0x20-encode checkboxes
- 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.)
2026-03-09 00:29:45 +10:00
alex 9e42a4e2df Effective config: no-0x20 precedence, write semantics, validators, strip-mac/strip-subnet
- ConfigSetCache: no-0x20-encode wins per dnsmasq docs; effective state and source attribution updated
- ReadonlyConfigCommandGenerator: use EffectiveConfigWriteSemantics for inverse-pair and key-only-or-value
- SpecialOptionValidators for UseStaleCache, AddMac, AddSubnet, Umbrella; wired via RegisterValidatedSingle
- OptionSemantics + EffectiveConfigWriteSemantics (GetBehavior/GetInversePairKeys); remove EffectiveConfigWriteBehaviorMap
- strip-mac / strip-subnet: full support in EffectiveDnsmasqConfig, sources, cache, sections, field builder, registry, tests
- Multi-value editor: toasts and block commit on validation error; 2s toast dedupe
- Do0x20 view label comment + Do0x20EncodeDisplayLabelTests
- DnsmasqOptionTooltips + extract-option-help.sh for strip-mac/strip-subnet; regenerated option-help HTML
2026-03-09 00:17:29 +10:00
alex d910688742 Add dnsmasq version awareness, readiness endpoint, and Docker healthcheck
- Options: VersionCommand, VersionTimeoutSeconds, MinimumVersion, EnforceMinimumVersion
- Version probe service and parser; startup enforcement when EnforceMinimumVersion
- Save flow: block save on probe failure (VersionProbeFailed) or version below minimum (UnsupportedVersion)
- Status API and Dnsmasq page: show version with tooltip, link to CHANGELOG
- Readiness: GET /healthz/ready (version + dnsmasq running when StatusCommand set)
- MapReadyHealthCheck extension; Dockerfile HEALTHCHECK + curl; compose healthcheck and service_healthy
- Docs: README and agents.md updated
2026-03-08 23:12:38 +10:00
alex a03e93bcd3 Effective config: do-0x20-encode revert fix, validation UI, custom displays, option help
- 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
2026-03-08 12:52:46 +10:00
alex 6cf4c07695 Fix RestartTimeoutSeconds default; order-aware multi-value diff in save modal
- 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.
2026-03-07 22:31:38 +10:00
alex f2e73107d1 Effective config: editable badge in view mode, refresh on continue/stop after save failure
- 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.
2026-03-07 22:13:31 +10:00
alex ff94be87b2 Effective config: multi descriptor refactor, validation UX, restore cleanup
- 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.
2026-03-07 21:11:12 +10:00
alex a9f8961c32 App logs: add Refresh and Download logs buttons; add api/logging/logs/download endpoint 2026-03-02 23:10:39 +10:00
alex baaba38e23 Effective config: conntrack as flag; avoid key-only directives for empty non-flag values
- 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)
2026-03-02 22:52:27 +10:00
alex 5f728900dc Effective config: auto-revert flag when toggled to original; fix stale cache after restore
- 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)
2026-03-02 22:28:47 +10:00
alex 87179f0195 Effective config: empty multi-value UX, clickable changes count
- 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)
2026-03-02 22:13:07 +10:00
alex 3b22e4fb7d Bump version to 0.0.6 for release v0.0.6 2026-03-02 21:12:57 +10:00
alex a3cc3968af Effective config: multi-value editor, config service fixes, save result improvements
- 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
2026-03-02 21:10:35 +10:00
alex 8ed66cdf48 Process runner, save/restore flow, status script, listen-address IPv6
- 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.
2026-03-01 22:23:17 +10:00
alex a776f445b6 Assembly-scanned services, options validator marker, UI tweaks, and config fixes
- 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
2026-03-01 19:21:09 +10:00
alex b0ce7afb58 Reorganize: Hubs→Realtime, Dnsmasq→Status/Logs/AppLogs, Extensions→DI/Hosting/Interop, EffectiveConfig→shared feature 2026-02-28 23:17:40 +10:00
alex 2cfbaf000c Reorganise Infrastructure/Services into feature namespaces
- Move registration marker interfaces to Registration/Abstractions
- Add feature folders with Abstractions subfolders: EffectiveConfig,
  Dnsmasq/Config, Dnsmasq/Hosts, Dnsmasq/Leases, Dnsmasq/Reload,
  Logs, Updates, UI/Settings, Common/Process
- Place interfaces in each feature's Abstractions namespace; align
  implementation namespaces to folder paths
- Update Program, extensions, controllers, hubs, helpers, components,
  and tests to use new namespaces
- Remove old flat Services/Abstractions and root-level service files
2026-02-28 22:17:20 +10:00
alex f8754d8d6e Shared StatusBadge, OK/Cancel/Revert, fixes, badge styling
- Add Components/Shared/StatusBadge + StatusBadgeKind; centralize badge
  styles and map Kind to Bootstrap classes. Refactor OptionStateBadge to
  compose StatusBadge; add OK/Cancel/Revert when active with
  OnConfirm/OnCancel/OnRevert callbacks and exit-action flag in
  EffectiveConfigFieldDisplay.
- Fix _valueAtActivation to use Descriptor.GetValue() (persisted value)
  so save modal shows correct before/after and no phantom pending on
  revert-to-original.
- OptionHelpController: add CancelCloseFromLabelEnter() and call when
  opening/switching help so pending 300ms close does not dismiss new help.
- Migrate Dnsmasq.razor and HostsFileSection to StatusBadge; save modal
  option chip uses NeutralPill. Centralize badge CSS in StatusBadge.
- Badge styling: font-size/weight/padding, hover lift+shadow, active
  press with visible release animation.
2026-02-28 21:34:12 +10:00
alex 71a8a61cb3 EffectiveConfig: toolbar, save modal, cancel/revert UX
- Toolbar: single expand/collapse toggle; change count after Save/Exit.
- Save modal: selective revert per change; modern list styling, empty state;
  Session + OnReverted; Save disabled when no changes.
- Cancel: prevent blur-before-click (mousedown preventDefault on cancel
  badge); _cancelRequested so cancel never commits.
- DeactivateFieldAsync in UiContext + Section; OptionStateBadge cancel
  clears draft and deactivates.
2026-02-28 20:06:10 +10:00
alex bf1f6a0d82 EffectiveConfig: migrate edit activation/commit to shared UiContext
- OptionStateBadge: add FieldKey param, call Ui.ActivateFieldAsync instead of OnActivateEdit
- EffectiveConfigOptionItem: add FieldKey, pass to badge; remove OnActivateEdit
- EffectiveConfigFieldDisplay: add FieldKey, commit only via Ui.CommitFieldAsync; remove ActiveFieldKey, OnActivateEdit, OnEditCommitted
- EffectiveConfigSectionPanel: pass FieldKey to FieldDisplay; remove OnActivateField, OnFieldEditCommitted
- EffectiveConfigPanels: remove OnActivateField, OnFieldEditCommitted params and relay
- EffectiveConfigSection: stop passing callback props to Panels (Session + UiContext drive behavior)
2026-02-28 19:25:25 +10:00
alex 91beb9d181 EffectiveConfig: single expand/collapse toolbar button
Replace separate Expand all / Collapse all buttons with one toggle button.
Icon and label switch based on AllSectionsExpanded (expand when any
section collapsed, collapse when all expanded).
2026-02-28 19:13:42 +10:00
alex 4e122ba439 EffectiveConfig: fix pending null display, OptionStateBadge, OptionHelpLabel
- Use pending != null ? pending.NewValue : Descriptor.GetValue() so clearing
  a value (port, log-queries, local-service) shows '(not set)' instead of
  reverting to the old value; fix effective value and commit logic in
  EffectiveConfigFieldDisplay.
- Rename ReadonlyBadge to OptionStateBadge; add editable/pending state and
  use it from EffectiveConfigOptionItem, EffectiveConfigFieldDisplay,
  EffectiveConfigMultiValueItem.
- OptionHelpLabel: default CssClass from HelpKey (EffectiveCssClass).
2026-02-28 19:04:38 +10:00