- Introduce ActionPanel, EnvelopeInfoCard, TfaForm, ConfirmDialog, StatusPage, and Toast components for modular, presentational UI - Add ToastService for pub/sub toast notifications; register in DI - Refactor AccessCodeForm for improved UX and parameterization - Enhance MainLayout with Toast integration and better error handling - Standardize and extend app.css for new components and responsive design - All new components are "dumb" (no service/API knowledge), using EventCallbacks for parent interaction - ConfirmDialog supports awaitable user confirmation via TaskCompletionSource
70 lines
2.6 KiB
Plaintext
70 lines
2.6 KiB
Plaintext
@* Toast: Zeigt kurze Benachrichtigungen an. Ersetzt AlertifyJS aus dem Web-Projekt.
|
|
|
|
Wird einmal im MainLayout platziert. Hört auf den ToastService.
|
|
Wenn eine Komponente irgendwo _toast.ShowSuccess("Text") aufruft,
|
|
erscheint hier ein Toast und verschwindet nach 4 Sekunden automatisch.
|
|
|
|
Bootstrap Toast-Klassen werden genutzt:
|
|
- toast-container: Positionierung (oben rechts)
|
|
- toast: Einzelner Toast
|
|
- bg-success/bg-danger/etc: Farbe basierend auf Typ *@
|
|
|
|
@inject ToastService ToastService
|
|
@implements IDisposable
|
|
|
|
@if (ToastService.Messages.Count > 0)
|
|
{
|
|
@* toast-container: Bootstrap-Klasse die Toasts oben rechts positioniert.
|
|
position-fixed: Bleibt an der Stelle auch beim Scrollen.
|
|
z-index 1080: Über dem Modal-Backdrop (1070) damit Toasts
|
|
auch während eines ConfirmDialogs sichtbar sind. *@
|
|
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1080;">
|
|
@foreach (var message in ToastService.Messages)
|
|
{
|
|
<div class="toast show align-items-center text-white bg-@message.Type border-0"
|
|
role="alert">
|
|
<div class="d-flex">
|
|
<div class="toast-body">
|
|
<i class="bi @message.IconClass me-2"></i>
|
|
@message.Text
|
|
</div>
|
|
<button type="button"
|
|
class="btn-close btn-close-white me-2 m-auto"
|
|
@onclick="() => ToastService.Dismiss(message)">
|
|
</button>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
@code {
|
|
protected override void OnInitialized()
|
|
{
|
|
// Subscriber: Wenn der ToastService eine Änderung meldet,
|
|
// zeichnet diese Komponente sich neu (StateHasChanged).
|
|
// So erscheinen/verschwinden Toasts automatisch.
|
|
ToastService.OnChange += HandleChange;
|
|
}
|
|
|
|
/// <summary>
|
|
/// InvokeAsync ist nötig weil OnChange von einem
|
|
/// async void (dem Timer im ToastService) ausgelöst wird.
|
|
/// Das kann auf einem anderen Thread passieren.
|
|
/// InvokeAsync wechselt zurück auf den Blazor UI-Thread.
|
|
/// </summary>
|
|
private async void HandleChange()
|
|
{
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Event-Handler abmelden wenn die Komponente entfernt wird.
|
|
/// Ohne das würde der ToastService eine Referenz auf eine
|
|
/// nicht mehr existierende Komponente halten → Memory Leak.
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
ToastService.OnChange -= HandleChange;
|
|
}
|
|
} |