refactor(ui/shared): introduce IDialogService + DialogHost
Eliminates the per-page <ConfirmDialog @ref="_confirmDialog" ConfirmButtonClass="btn-danger" /> boilerplate. Pages now inject IDialogService and call ConfirmAsync(title, message, danger: true) programmatically. New scoped service holds a single active dialog (throws on nested calls), with a global DialogHost mounted once in MainLayout that renders the modal markup, owns body scroll-lock via Bootstrap's modal-open class, traps focus on the modal element, and handles Escape-to-cancel. Same service also exposes PromptAsync, used to replace the bespoke NewFolderDialog. Both ConfirmDialog and NewFolderDialog components are deleted — their callers (~13 pages across Admin/Design/Deployment /Monitoring) now go through the service. DiffDialog stays as-is — different use case (before/after content). bUnit tests in TopologyPageTests, DataConnectionsPageTests, and TemplatesPageTests register IDialogService in their service collection. Also: a top-of-file Razor comment on Sites.razor pointing future implementers at it as the reference list-page pattern.
This commit is contained in:
@@ -3,6 +3,7 @@ using Bunit;
|
||||
using Microsoft.AspNetCore.Components.Authorization;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using NSubstitute;
|
||||
using ScadaLink.CentralUI.Components.Shared;
|
||||
using ScadaLink.Commons.Entities.Sites;
|
||||
using ScadaLink.Commons.Interfaces.Repositories;
|
||||
using DataConnectionsPage = ScadaLink.CentralUI.Components.Pages.Admin.DataConnections;
|
||||
@@ -21,6 +22,9 @@ public class DataConnectionsPageTests : BunitContext
|
||||
public DataConnectionsPageTests()
|
||||
{
|
||||
Services.AddSingleton(_siteRepo);
|
||||
// Satisfy the page's [Inject] IDialogService — the host that actually
|
||||
// renders the dialog lives in MainLayout, not in bUnit's render scope.
|
||||
Services.AddScoped<IDialogService, DialogService>();
|
||||
AddTestAuth();
|
||||
|
||||
JSInterop.Setup<string?>("treeviewStorage.load", _ => true).SetResult(null);
|
||||
|
||||
@@ -6,6 +6,7 @@ using NSubstitute;
|
||||
using ScadaLink.Commons.Entities.Templates;
|
||||
using ScadaLink.Commons.Interfaces.Repositories;
|
||||
using ScadaLink.Commons.Interfaces.Services;
|
||||
using ScadaLink.CentralUI.Components.Shared;
|
||||
using ScadaLink.TemplateEngine;
|
||||
using ScadaLink.TemplateEngine.Services;
|
||||
using TemplatesPage = ScadaLink.CentralUI.Components.Pages.Design.Templates;
|
||||
@@ -30,6 +31,10 @@ public class TemplatesPageTests : BunitContext
|
||||
Services.AddSingleton(_audit);
|
||||
Services.AddScoped<TemplateService>();
|
||||
Services.AddScoped<TemplateFolderService>();
|
||||
// The Templates page injects IDialogService for the new-folder prompt
|
||||
// and delete confirmations. The host is rendered in MainLayout, not
|
||||
// here, but the DI registration still has to satisfy the [Inject].
|
||||
Services.AddScoped<IDialogService, DialogService>();
|
||||
AddTestAuth();
|
||||
|
||||
// The TreeView inside the page persists expansion state via JS interop
|
||||
|
||||
@@ -14,6 +14,7 @@ using ScadaLink.Commons.Interfaces.Services;
|
||||
using ScadaLink.Commons.Types.Enums;
|
||||
using ScadaLink.Communication;
|
||||
using ScadaLink.DeploymentManager;
|
||||
using ScadaLink.CentralUI.Components.Shared;
|
||||
using ScadaLink.TemplateEngine.Services;
|
||||
using TopologyPage = ScadaLink.CentralUI.Components.Pages.Deployment.Topology;
|
||||
|
||||
@@ -59,6 +60,11 @@ public class TopologyPageTests : BunitContext
|
||||
|
||||
AddTestAuth();
|
||||
|
||||
// The page injects IDialogService for delete confirmations; the host
|
||||
// (rendered globally in MainLayout) is not present in bUnit, but the
|
||||
// DI registration still has to satisfy the [Inject].
|
||||
Services.AddScoped<IDialogService, DialogService>();
|
||||
|
||||
// TreeView persists expansion state via JS interop. Stub the calls so render doesn't throw.
|
||||
JSInterop.Setup<string?>("treeviewStorage.load", _ => true).SetResult(null);
|
||||
JSInterop.SetupVoid("treeviewStorage.save", _ => true);
|
||||
|
||||
Reference in New Issue
Block a user