Files
dnsmasq-webui/src/DnsmasqWebUI/Components/EffectiveConfig/CustomDisplays/Do0x20EncodeDisplay.razor
T
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

61 lines
2.4 KiB
Plaintext

@namespace DnsmasqWebUI.Components.EffectiveConfig.CustomDisplays
@using DnsmasqWebUI.Models.Dnsmasq
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
@inherits EffectiveConfigValueDisplayBase
@* do-0x20-encode / no-0x20-encode: tri-state. Checkbox shows Enabled vs not-Enabled; uncheck maps back to Default when that was the value at activation, else Disabled. *@
@if (IsActiveEditor && Descriptor.GetSource()?.IsReadOnly != true)
{
var isOn = GetState() == ExplicitToggleState.Enabled;
<input type="checkbox" class="form-check-input" checked="@isOn" @onchange="OnCheckedChange" @onfocusout="OnCommitRequested" />
}
else
{
@* Intentionally show both Default and Disabled as "Disabled" (product choice: collapse unset and off). Do not "fix" to show "Default" for unset. *@
@(GetState() == ExplicitToggleState.Enabled ? "Enabled" : "Disabled")
}
@code {
private ExplicitToggleState _stateAtActivation;
private bool _wasActiveEditor;
private ExplicitToggleState GetState()
{
var v = GetEffectiveDisplayValue();
if (v is ExplicitToggleState s) return s;
return ExplicitToggleState.Default;
}
protected override void OnParametersSet()
{
if (!IsActiveEditor)
_stateAtActivation = GetState();
else if (!_wasActiveEditor)
_stateAtActivation = GetState();
_wasActiveEditor = IsActiveEditor;
}
private async Task OnCheckedChange(ChangeEventArgs e)
{
var isChecked = e.Value is true;
if (isChecked)
{
await NotifyValueChanged(ExplicitToggleState.Enabled);
return;
}
var pending = Session?.PendingChanges.FirstOrDefault(c =>
string.Equals(c.SectionId, Descriptor.SectionId, StringComparison.OrdinalIgnoreCase) &&
string.Equals(c.OptionName, Descriptor.OptionName, StringComparison.OrdinalIgnoreCase));
if (pending?.OldValue is ExplicitToggleState previousState)
{
await NotifyValueChanged(previousState);
return;
}
// No existing pending edit for this field: map unchecked based on the state at activation.
// Default and Disabled both display as "Disabled" in view mode, so we preserve true intent here.
await NotifyValueChanged(_stateAtActivation == ExplicitToggleState.Default ? ExplicitToggleState.Default : ExplicitToggleState.Disabled);
}
}