diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigFieldDisplay.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigFieldDisplay.razor
index c32dde4..9b2edef 100644
--- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigFieldDisplay.razor
+++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigFieldDisplay.razor
@@ -14,9 +14,9 @@
var showEditableBadge = !isReadonly;
var isActiveEditor = IsEditMode && IsActive;
var fragmentWithCallback = isActiveEditor ? _fragmentWithCallback : null;
- var effectiveValue = _effectiveValue ?? Descriptor.GetValue();
+ var effectiveValue = _effectiveValue;
- @Descriptor.OptionName:
+ @Descriptor.OptionName:
@if (isActiveEditor)
{
@@ -34,11 +34,7 @@
@fragment(Descriptor)
}
-
- @if (showEditableBadge)
- {
-
- }
+
}
@@ -49,7 +45,7 @@ else if (Descriptor.IsMultiValue)
}
else
{
- var value = _effectiveValue ?? Descriptor.GetValue();
+ var value = _effectiveValue;
var displayValue = value == null ? "(not set)" : (value is IReadOnlyList list ? (list.Count == 0 ? "(none)" : string.Join(", ", list)) : value.ToString());
var isReadonly = Descriptor.GetSource()?.IsReadOnly == true;
var showReadonlyHint = IsEditMode && isReadonly;
@@ -103,7 +99,7 @@ else
string.Equals(c.SectionId, Descriptor.SectionId, StringComparison.OrdinalIgnoreCase) &&
string.Equals(c.OptionName, Descriptor.OptionName, StringComparison.OrdinalIgnoreCase));
_hasPendingChange = pending != null;
- _effectiveValue = pending?.NewValue ?? Descriptor.GetValue();
+ _effectiveValue = pending != null ? pending.NewValue : Descriptor.GetValue();
if (!_wasActive && IsActive)
_valueAtActivation = _effectiveValue;
if (_wasActive && !IsActive)
@@ -124,7 +120,7 @@ else
private async Task CommitIfChangedAsync()
{
- var newValue = _draftValue ?? _effectiveValue ?? Descriptor.GetValue();
+ var newValue = _draftValue ?? _effectiveValue;
if (!Equals(_valueAtActivation, newValue))
{
var source = Descriptor.GetSource();
diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueItem.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueItem.razor
index dd897f8..2a8ebd8 100644
--- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueItem.razor
+++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueItem.razor
@@ -4,11 +4,7 @@
@Value
-
- @if (Source?.IsReadOnly != true && IsEditMode)
- {
- editable
- }
+
@code {
diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueRow.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueRow.razor
index b75cc1f..6e50126 100644
--- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueRow.razor
+++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigMultiValueRow.razor
@@ -3,7 +3,7 @@
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
- @Label:
+ @Label:
@if (IsActiveEditor)
{
diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigOptionItem.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigOptionItem.razor
index 6b6a868..9a10ea0 100644
--- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigOptionItem.razor
+++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigOptionItem.razor
@@ -2,26 +2,19 @@
@using DnsmasqWebUI.Models.Dnsmasq
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
-@Label:
+@Label:
@if (DisplayMode == EffectiveConfigDisplayMode.Edit && IsActive && Source?.IsReadOnly != true)
{
- @if (ShowEditableBadge)
- {
-
- }
+
}
else
{
@DisplayValue
-
- @if (ShowEditableBadge && Source?.IsReadOnly != true)
- {
-
- }
+
}
diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionHelpLabel.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionHelpLabel.razor
index c729bb0..b623743 100644
--- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionHelpLabel.razor
+++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionHelpLabel.razor
@@ -1,7 +1,7 @@
@namespace DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
-
+
@ChildContent
@@ -10,6 +10,9 @@
[Parameter] public string? HelpKey { get; set; }
[Parameter] public string OptionLabel { get; set; } = "";
[Parameter] public string? CssClass { get; set; }
+
+ private string EffectiveCssClass =>
+ CssClass ?? (!string.IsNullOrEmpty(HelpKey) ? "ec-field-label ec-field-label-help" : "ec-field-label");
[Parameter] public string? Title { get; set; }
[CascadingParameter] public EffectiveConfigUiContext? Ui { get; set; }
[Parameter] public RenderFragment? ChildContent { get; set; }
diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionStateBadge.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionStateBadge.razor
new file mode 100644
index 0000000..588ceb5
--- /dev/null
+++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/OptionStateBadge.razor
@@ -0,0 +1,65 @@
+@namespace DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig
+@using DnsmasqWebUI.Models.Dnsmasq
+@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
+
+@if (Source?.IsReadOnly == true)
+{
+ @if (IsInteractive && Ui != null)
+ {
+
+ }
+ else
+ {
+ readonly
+ }
+}
+else if (ShowEditableBadge)
+{
+ @if (EditableAsButton)
+ {
+
+ }
+ else
+ {
+ editable
+ }
+}
+
+@code {
+ [Parameter] public string AnchorId { get; set; } = "";
+ [Parameter] public ConfigValueSource? Source { get; set; }
+ [Parameter] public string OptionName { get; set; } = "";
+ [Parameter] public object? Value { get; set; }
+ /// When true, render readonly as button and raise click/mouseleave via context.
+ [Parameter] public bool IsInteractive { get; set; }
+ /// When true, show editable/pending badge for non-readonly fields.
+ [Parameter] public bool ShowEditableBadge { get; set; }
+ /// When true, badge shows "pending" and warning style.
+ [Parameter] public bool HasPendingChange { get; set; }
+ /// When true, editable badge is a button; otherwise a static span.
+ [Parameter] public bool EditableAsButton { get; set; } = true;
+ [Parameter] public EventCallback OnActivateEdit { get; set; }
+ [CascadingParameter] public EffectiveConfigUiContext? Ui { get; set; }
+
+ private Task OnReadonlyClick()
+ {
+ if (Ui == null || Source == null) return Task.CompletedTask;
+ return Ui.RequestReadonlyPopoverAsync(new ReadonlyBadgeClickedEventArgs(AnchorId, Source, OptionName, Value));
+ }
+
+ private Task OnReadonlyMouseLeave()
+ {
+ if (Ui == null) return Task.CompletedTask;
+ return Ui.ScheduleReadonlyPopoverCloseAsync();
+ }
+}
diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/ReadonlyBadge.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/ReadonlyBadge.razor
deleted file mode 100644
index b0503ef..0000000
--- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/ReadonlyBadge.razor
+++ /dev/null
@@ -1,40 +0,0 @@
-@namespace DnsmasqWebUI.Components.Dnsmasq.EffectiveConfig
-@using DnsmasqWebUI.Models.Dnsmasq
-@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
-
-@if (Source?.IsReadOnly == true)
-{
- @if (IsInteractive && Ui != null)
- {
-
- }
- else
- {
- readonly
- }
-}
-
-@code {
- [Parameter] public string AnchorId { get; set; } = "";
- [Parameter] public ConfigValueSource? Source { get; set; }
- [Parameter] public string OptionName { get; set; } = "";
- [Parameter] public object? Value { get; set; }
- /// When true, render as button and raise click/mouseleave via context.
- [Parameter] public bool IsInteractive { get; set; }
- [CascadingParameter] public EffectiveConfigUiContext? Ui { get; set; }
-
- private Task OnClick()
- {
- if (Ui == null || Source == null) return Task.CompletedTask;
- return Ui.RequestReadonlyPopoverAsync(new ReadonlyBadgeClickedEventArgs(AnchorId, Source, OptionName, Value));
- }
-
- private Task OnMouseLeave()
- {
- if (Ui == null) return Task.CompletedTask;
- return Ui.ScheduleReadonlyPopoverCloseAsync();
- }
-}