mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-21 13:22:35 +10:00
Assembly-scanned services, options validator marker, UI tweaks, and config fixes
- Register ISettingsModalService, INotificationService, IUpdateCheckService via assembly scanning (marker interfaces) - Add IApplicationOptionsValidator<TOptions> marker; scan only those for IValidateOptions registration - Fix ApplicationLifecycleLoggingHostedService: log RestartCommand/ReloadCommand/StatusCommand (no ApplyCommand) - NavMenu: spin animation for update-check button icon when checking; single icon with conditional nav-footer-spin class - Add NotificationHost/NotificationToast components and NotificationService for toasts - Effective config save flow, restore result, save service; various EffectiveConfig and DnsmasqOptions/validator updates - Test and script updates; docker-compose.test.yml, appsettings, DnsmasqConfKeys/tooltips/sections
This commit is contained in:
@@ -2,13 +2,36 @@
|
||||
@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" OnClose="@OnClose" OnSave="@HandleSave" OnReverted="@HandleReverted" />
|
||||
<EffectiveConfigSaveModal
|
||||
PendingChanges="@PendingChanges"
|
||||
Status="@Status"
|
||||
Session="@Session"
|
||||
SaveState="@_saveState"
|
||||
SaveResult="@_saveResult"
|
||||
RestoreResult="@_restoreResult"
|
||||
OnClose="@OnClose"
|
||||
OnSave="@HandleSave"
|
||||
OnRestore="@HandleRestore"
|
||||
OnReverted="@HandleReverted" />
|
||||
}
|
||||
|
||||
@code {
|
||||
public enum SaveUiState
|
||||
{
|
||||
Review,
|
||||
Saving,
|
||||
WriteFailed,
|
||||
ReloadFailed,
|
||||
RestoreInProgress,
|
||||
RestoreFailed
|
||||
}
|
||||
|
||||
[Parameter] public bool ShowModal { get; set; }
|
||||
[Parameter] public IReadOnlyList<PendingEffectiveConfigChange> PendingChanges { get; set; } = null!;
|
||||
[Parameter] public DnsmasqServiceStatus? Status { get; set; }
|
||||
@@ -16,6 +39,20 @@
|
||||
[Parameter] public EventCallback OnSaveCompleted { 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);
|
||||
@@ -24,15 +61,60 @@
|
||||
private async Task HandleSave()
|
||||
{
|
||||
if (Session.PendingChanges.Count == 0) return;
|
||||
try
|
||||
|
||||
_saveState = SaveUiState.Saving;
|
||||
_saveResult = null;
|
||||
_restoreResult = null;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
var result = await Session.ApplyAsync();
|
||||
|
||||
_saveResult = result;
|
||||
if (result.Saved && result.Reloaded)
|
||||
{
|
||||
await Session.ApplyAsync();
|
||||
var message = result.UserMessage ?? "Config saved and dnsmasq reloaded.";
|
||||
NotificationService.ShowSuccess(message);
|
||||
_saveState = SaveUiState.Review;
|
||||
_saveResult = null;
|
||||
await OnClose.InvokeAsync();
|
||||
await OnSaveCompleted.InvokeAsync();
|
||||
return;
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
if (result.Saved && !result.Reloaded)
|
||||
_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.Reloaded)
|
||||
{
|
||||
// TODO: show error to user (e.g. toast or modal message)
|
||||
var message = result.UserMessage ?? "Backup restored and dnsmasq reloaded.";
|
||||
NotificationService.ShowSuccess(message);
|
||||
_saveState = SaveUiState.Review;
|
||||
_saveResult = null;
|
||||
_restoreResult = null;
|
||||
await OnClose.InvokeAsync();
|
||||
await OnSaveCompleted.InvokeAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
_saveState = SaveUiState.RestoreFailed;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user