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

152 lines
4.8 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"
OnContinueEditing="@(EventCallback.Factory.Create(this, HandleContinueEditing))"
OnSave="@HandleSave"
OnRestore="@HandleRestore"
OnReverted="@HandleReverted"
OnCloseAndEndEdit="@HandleCloseAndEndEdit" />
}
@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 OnContinueEditingAfterSavedFailure { 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);
}
private async Task HandleContinueEditing()
{
if (_saveState == SaveUiState.ValidateFailed || _saveState == SaveUiState.ReloadFailed)
{
await OnContinueEditingAfterSavedFailure.InvokeAsync();
return;
}
await OnClose.InvokeAsync();
}
private async Task HandleCloseAndEndEdit()
{
await OnCloseAndEndEdit.InvokeAsync();
if (_saveState == SaveUiState.ValidateFailed || _saveState == SaveUiState.ReloadFailed)
await OnSaveCompleted.InvokeAsync();
}
}