Refactor client settings fields, fix logs overwrite, improve settings modal

- Replace FieldBounds with generic ClientSettingsField<T> abstraction
- Add IClientSettingsField, ClientSettingsMinMaxField, ClientSettingsBoolField
- Put abstractions in Models/Client/Abstractions namespace
- Fields hold values; CoerceValue for clamping on set
- ClientSettingsService hydrates fields on load; ToDto for save
- Settings modal binds directly to field values, collapsible only for All context
- Add LogsPreView with ShouldRender freeze to prevent Blazor overwriting JS-owned logs DOM
- Add left margin to static group heading in single-section mode
This commit is contained in:
2026-02-11 08:28:44 +10:00
parent 5ac2006b80
commit cefc488712
18 changed files with 258 additions and 129 deletions
@@ -0,0 +1,33 @@
using DnsmasqWebUI.Models.Client.Abstractions;
namespace DnsmasqWebUI.Models.Client;
/// <summary>
/// Min/max bounded integer field with optional clamping on set.
/// </summary>
public sealed class ClientSettingsMinMaxField : ClientSettingsField<int>
{
public int Min { get; }
public int Max { get; }
public string Unit { get; }
public bool AllowClamp { get; }
public ClientSettingsMinMaxField(string displayName, int min, int max, string unit = "seconds", bool allowClamp = true)
: base(displayName)
{
Min = min;
Max = max;
Unit = unit;
AllowClamp = allowClamp;
}
public override string? Validate(int value)
{
if (value < Min || value > Max)
return $"{DisplayName} must be between {Min} and {Max} {Unit}. You entered {value}.";
return null;
}
protected override int CoerceValue(int value) =>
AllowClamp ? Math.Clamp(value, Min, Max) : value;
}