mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-04 04:18:13 +10:00
- 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.
131 lines
4.1 KiB
Plaintext
131 lines
4.1 KiB
Plaintext
@namespace DnsmasqWebUI.Components.EffectiveConfig
|
|
@using DnsmasqWebUI.Models.Dnsmasq
|
|
@using DnsmasqWebUI.Models.Dnsmasq.EffectiveConfig
|
|
@using DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Abstractions
|
|
@using DnsmasqWebUI.Infrastructure.Services.UI.Notifications.Abstractions
|
|
@inject IEffectiveConfigSaveService SaveService
|
|
@inject INotificationService NotificationService
|
|
|
|
@if (ShowModal)
|
|
{
|
|
<EffectiveConfigSaveModal
|
|
PendingChanges="@PendingChanges"
|
|
Status="@Status"
|
|
Session="@Session"
|
|
SaveState="@_saveState"
|
|
SaveResult="@_saveResult"
|
|
RestoreResult="@_restoreResult"
|
|
OnClose="@OnClose"
|
|
OnSave="@HandleSave"
|
|
OnRestore="@HandleRestore"
|
|
OnReverted="@HandleReverted"
|
|
OnCloseAndEndEdit="@OnCloseAndEndEdit" />
|
|
}
|
|
|
|
@code {
|
|
public enum SaveUiState
|
|
{
|
|
Review,
|
|
Saving,
|
|
WriteFailed,
|
|
ValidateFailed,
|
|
ReloadFailed,
|
|
RestoreInProgress,
|
|
RestoreFailed
|
|
}
|
|
|
|
[Parameter] public bool ShowModal { get; set; }
|
|
[Parameter] public IReadOnlyList<PendingEffectiveConfigChange> PendingChanges { get; set; } = null!;
|
|
[Parameter] public DnsmasqServiceStatus? Status { get; set; }
|
|
[Parameter] public EventCallback OnClose { get; set; }
|
|
[Parameter] public EventCallback OnSaveCompleted { get; set; }
|
|
[Parameter] public EventCallback OnCloseAndEndEdit { get; set; }
|
|
[Parameter] public IEffectiveConfigEditSession Session { get; set; } = null!;
|
|
|
|
private SaveUiState _saveState = SaveUiState.Review;
|
|
private EffectiveConfigSaveResult? _saveResult;
|
|
private EffectiveConfigRestoreResult? _restoreResult;
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
if (!ShowModal)
|
|
{
|
|
_saveState = SaveUiState.Review;
|
|
_saveResult = null;
|
|
_restoreResult = null;
|
|
}
|
|
}
|
|
|
|
private async Task HandleReverted()
|
|
{
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
private async Task HandleSave()
|
|
{
|
|
if (Session.PendingChanges.Count == 0) return;
|
|
if (Session.HasBlockingValidationErrors())
|
|
{
|
|
NotificationService.ShowError("Fix validation errors before saving.");
|
|
return;
|
|
}
|
|
|
|
_saveState = SaveUiState.Saving;
|
|
_saveResult = null;
|
|
_restoreResult = null;
|
|
await InvokeAsync(StateHasChanged);
|
|
|
|
var result = await Session.ApplyAsync();
|
|
|
|
_saveResult = result;
|
|
if (result.Saved && result.Restarted)
|
|
{
|
|
var message = result.UserMessage ?? "Config saved and dnsmasq restarted.";
|
|
NotificationService.ShowSuccess(message);
|
|
_saveState = SaveUiState.Review;
|
|
_saveResult = null;
|
|
await OnClose.InvokeAsync();
|
|
await OnSaveCompleted.InvokeAsync();
|
|
return;
|
|
}
|
|
|
|
if (result.Saved && result.IsValidateFailed)
|
|
_saveState = SaveUiState.ValidateFailed;
|
|
else if (result.Saved && !result.Restarted)
|
|
_saveState = SaveUiState.ReloadFailed;
|
|
else if (!result.Saved)
|
|
_saveState = SaveUiState.WriteFailed;
|
|
else
|
|
_saveState = SaveUiState.Review;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
private async Task HandleRestore(string backupPath)
|
|
{
|
|
if (string.IsNullOrEmpty(backupPath)) return;
|
|
|
|
_saveState = SaveUiState.RestoreInProgress;
|
|
_restoreResult = null;
|
|
await InvokeAsync(StateHasChanged);
|
|
|
|
var result = await SaveService.RestoreAsync(backupPath);
|
|
|
|
_restoreResult = result;
|
|
if (result.Restored && result.Restarted)
|
|
{
|
|
var message = result.UserMessage ?? "Backup restored and dnsmasq restarted.";
|
|
NotificationService.ShowSuccess(message);
|
|
_saveState = SaveUiState.Review;
|
|
_saveResult = null;
|
|
_restoreResult = null;
|
|
await OnCloseAndEndEdit.InvokeAsync();
|
|
await OnSaveCompleted.InvokeAsync();
|
|
return;
|
|
}
|
|
|
|
_saveState = SaveUiState.RestoreFailed;
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|