mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-17 11:21:29 +10:00
- 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.
152 lines
4.8 KiB
Plaintext
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();
|
|
}
|
|
}
|