94 lines
4.8 KiB
C#
94 lines
4.8 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.CentralUI.Components.Shared;
|
|
|
|
/// <summary>
|
|
/// Centralised dialog/modal service. Pages inject this service and call
|
|
/// <see cref="ConfirmAsync"/>, <see cref="PromptAsync"/>, or
|
|
/// <see cref="ShowAsync{TResult}"/> programmatically instead of embedding
|
|
/// per-page modal components. A single <c>DialogHost</c> rendered in
|
|
/// <c>MainLayout</c> displays the resulting dialog state.
|
|
/// </summary>
|
|
public interface IDialogService
|
|
{
|
|
/// <summary>
|
|
/// Shows a confirmation dialog and resolves to <c>true</c> when the user
|
|
/// confirms, or <c>false</c> when the user cancels (button click, Escape,
|
|
/// or backdrop dismiss).
|
|
/// </summary>
|
|
/// <param name="title">Modal title text.</param>
|
|
/// <param name="message">Body text shown to the user.</param>
|
|
/// <param name="danger">When <c>true</c>, the confirm button renders in
|
|
/// <c>btn-danger</c> styling with the label "Delete"; otherwise a primary
|
|
/// "Confirm" button is shown.</param>
|
|
/// <returns>A task that resolves to <c>true</c> when the user confirms, or <c>false</c> when cancelled.</returns>
|
|
Task<bool> ConfirmAsync(string title, string message, bool danger = false);
|
|
|
|
/// <summary>
|
|
/// Shows a single-line text prompt and resolves to the entered value, or
|
|
/// <c>null</c> if the user cancels.
|
|
/// </summary>
|
|
/// <param name="title">Modal title text.</param>
|
|
/// <param name="label">Label rendered above the input field.</param>
|
|
/// <param name="initialValue">Pre-populated value for the input field.</param>
|
|
/// <param name="placeholder">Optional placeholder shown when the input is empty.</param>
|
|
/// <returns>A task that resolves to the entered string, or <c>null</c> if the user cancels.</returns>
|
|
Task<string?> PromptAsync(string title, string label, string initialValue = "", string? placeholder = null);
|
|
|
|
/// <summary>
|
|
/// Shows a modal hosting arbitrary custom body content and resolves to the
|
|
/// value the body closes with, or <c>default</c> (<c>null</c> for reference
|
|
/// types) if the user cancels (the body's own cancel path, the header close
|
|
/// button, or Escape). The body fragment receives a
|
|
/// <see cref="DialogContext{TResult}"/> and supplies its own action buttons —
|
|
/// the standard Cancel/Confirm footer is NOT rendered for this kind. Use this
|
|
/// to centralise modal chrome (backdrop, focus trap, focus restoration) while
|
|
/// keeping page-specific form content inside the body.
|
|
/// </summary>
|
|
/// <typeparam name="TResult">The type the body closes the dialog with.</typeparam>
|
|
/// <param name="title">Modal title text.</param>
|
|
/// <param name="body">Renders the modal body; receives the context whose
|
|
/// <c>Close</c>/<c>Cancel</c> methods resolve the returned task.</param>
|
|
/// <param name="size">Optional Bootstrap modal-dialog size modifier applied to
|
|
/// the <c>modal-dialog</c> element (e.g. <c>modal-lg</c>, <c>modal-sm</c>).
|
|
/// <c>null</c> leaves the default width.</param>
|
|
/// <returns>A task that resolves to the value passed to
|
|
/// <see cref="DialogContext{TResult}.Close"/>, or <c>default</c> on cancel.</returns>
|
|
Task<TResult?> ShowAsync<TResult>(string title, RenderFragment<DialogContext<TResult>> body, string? size = null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handed to the body fragment of a <see cref="IDialogService.ShowAsync{TResult}"/>
|
|
/// dialog so the body can close itself with a typed result or cancel. Both
|
|
/// methods route back through the owning <see cref="DialogService"/> to complete
|
|
/// the awaited <c>ShowAsync</c> task and tear down the modal.
|
|
/// </summary>
|
|
/// <typeparam name="TResult">The type the dialog resolves with.</typeparam>
|
|
public sealed class DialogContext<TResult>
|
|
{
|
|
// Routes the close back to the owning service's Resolve(). Held as a typed
|
|
// delegate rather than a service reference so the context stays a small,
|
|
// self-contained closure handle and never widens the body's surface.
|
|
private readonly Action<object?> _resolve;
|
|
|
|
/// <summary>
|
|
/// Creates a context bound to the given resolve callback. The callback boxes
|
|
/// the result and forwards it to <see cref="DialogService.Resolve"/>.
|
|
/// </summary>
|
|
/// <param name="resolve">Invoked with the boxed result (<c>null</c> = cancel).</param>
|
|
internal DialogContext(Action<object?> resolve) => _resolve = resolve;
|
|
|
|
/// <summary>
|
|
/// Closes the dialog and resolves the awaited <c>ShowAsync</c> task with
|
|
/// <paramref name="result"/>.
|
|
/// </summary>
|
|
/// <param name="result">The value the caller awaits.</param>
|
|
public void Close(TResult result) => _resolve(result);
|
|
|
|
/// <summary>
|
|
/// Cancels the dialog and resolves the awaited <c>ShowAsync</c> task with
|
|
/// <c>default</c> (<c>null</c> for reference types).
|
|
/// </summary>
|
|
public void Cancel() => _resolve(null);
|
|
}
|