From 28f8b829e32933be6e31828188e5b32d737aeee0 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 28 Sep 2026 12:06:35 +0200 Subject: [PATCH] Refactor: Unify grid logic for active/completed tabs Replaced separate `DxGrid` components for "active" and "completed" tabs with a single unified grid. Introduced dynamic properties (`CurrentGridData` and `CurrentGridKey`) to handle data and layout switching based on the active tab. Refactored layout loading/saving methods into shared versions (`OnGridLayoutAutoLoading` and `OnGridLayoutAutoSaving`) using dynamic keys. Simplified export logic to use the unified grid instance. Removed redundant code, templates, and private fields specific to the "completed" tab. Updated status filter logic to dynamically fetch data. Improved maintainability by consolidating logic and reducing duplication. --- .../Components/Pages/EnvelopeSenderPage.razor | 215 ++---------------- 1 file changed, 19 insertions(+), 196 deletions(-) diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor index b3de0f5f..77bdbeaf 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderPage.razor @@ -214,16 +214,15 @@
- @if (_activeTab == "active") - { - + LayoutAutoLoading="OnGridLayoutAutoLoading" + LayoutAutoSaving="OnGridLayoutAutoSaving"> - - } - else - { - - - - - @((cellContext.DataItem as EnvelopeDto)?.Id) - - - - - @((cellContext.DataItem as EnvelopeDto)?.Title) - - - - - - - - @{ - var envelope = cellContext.DataItem as EnvelopeDto; - if (envelope != null) - { - var statusInfo = GetStatusInfo(envelope.Status); -
- - @statusInfo.Label -
- } - } -
-
- - - @{ - var envelope = cellContext.DataItem as EnvelopeDto; - if (envelope != null) - { - var receivers = envelope.EnvelopeReceivers?.ToList() ?? []; - var signed = GetSignedReceiverCount(envelope); - var total = receivers.Count; -
- - @signed / @total @L("Signed", "unterschrieben") - - @if (total > 0) - { -
-
-
- } -
- } - } -
-
- - - -
- -
-
@L("Receiver", "Empfänger")
- @{ - var envelope = detailContext.DataItem as EnvelopeDto; - if (envelope?.EnvelopeReceivers?.Any() == true) - { -
- @foreach (var receiver in envelope.EnvelopeReceivers) - { -
- @{ - var isSigned = IsReceiverSigned(envelope, receiver); - } - - @if (isSigned) - { - - - - @L("Signed", "Unterschrieben") - } - else - { - - - - - @L("Pending", "Ausstehend") - } - -
- @receiver.Name - @receiver.Receiver?.EmailAddress -
-
- } -
- } - else - { -

@L("Sender_NoReceivers", "Keine Empfänger")

- } - } - -
@L("History", "Historie")
- @{ - var historyEntries = envelope is null - ? Enumerable.Empty() - : GetOrderedHistories(envelope); - if (historyEntries.Any()) - { -
- @foreach (var history in historyEntries) - { - var statusInfo = GetStatusInfo(history.Status); -
-
-
- - @statusInfo.Label -
- @GetHistoryActor(history) -
-
- @GetHistoryDate(history).ToString("dd.MM.yyyy HH:mm") -
-
- } -
- } - else - { -

@L("Sender_NoHistory", "Keine Historie vorhanden")

- } - } -
-
-
- }
} @@ -673,8 +505,7 @@ private bool _isLoading = true; private bool _isLoggingOut = false; private string? _errorMessage; - private DxGrid? _gridActive; - private DxGrid? _gridCompleted; + private DxGrid? _grid; // Logo config loaded from /api/CustomImages after auth private EnvelopeGenerator.Server.Client.Services.CustomImageDto? _appLogo; @@ -697,10 +528,15 @@ private string _deleteReason = string.Empty; private string? _deleteErrorMessage; - // Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts + // Stable keys used to store/restore each tab's layout in UserPreferences.GridLayouts private const string GridKeyActive = "sender.active-envelopes"; private const string GridKeyCompleted = "sender.completed-envelopes"; + private IEnumerable CurrentGridData => + (_activeTab == "completed" ? _completedEnvelopes : _activeEnvelopes) ?? Enumerable.Empty(); + + private string CurrentGridKey => _activeTab == "completed" ? GridKeyCompleted : GridKeyActive; + protected override async Task OnInitializedAsync() { var hasAccess = await AuthService.CheckSenderAccessAsync(); @@ -765,7 +601,7 @@ async Task ExportSelectedFormatAsync() { - var grid = _activeTab == "active" ? _gridActive : _gridCompleted; + var grid = _grid; if (grid is null) return; @@ -1106,21 +942,21 @@ // UserPreferencesService.GetAsync() uses the 1h in-memory cache → 0 HTTP on restore. // UserPreferencesService.SaveGridLayoutAsync() merges the single key → 1 PUT. - async Task OnActiveGridLayoutAutoLoading(GridPersistentLayoutEventArgs e) + async Task OnGridLayoutAutoLoading(GridPersistentLayoutEventArgs e) { // Use cached preferences only — avoid HTTP during grid initialization. // If cache is empty (LoadFromServerAsync failed), skip layout restore silently. var prefs = UserPreferencesService.GetCached(); - if (prefs is not null && prefs.GridLayouts.TryGetValue(GridKeyActive, out var json)) + if (prefs is not null && prefs.GridLayouts.TryGetValue(CurrentGridKey, out var json)) e.Layout = JsonSerializer.Deserialize(json); } - async Task OnActiveGridLayoutAutoSaving(GridPersistentLayoutEventArgs e) + async Task OnGridLayoutAutoSaving(GridPersistentLayoutEventArgs e) { try { var json = JsonSerializer.Serialize(e.Layout); - await UserPreferencesService.SaveGridLayoutAsync(GridKeyActive, json); + await UserPreferencesService.SaveGridLayoutAsync(CurrentGridKey, json); } catch (Exception ex) { @@ -1128,18 +964,5 @@ } } - async Task OnCompletedGridLayoutAutoLoading(GridPersistentLayoutEventArgs e) - { - var prefs = UserPreferencesService.GetCached(); - if (prefs is not null && prefs.GridLayouts.TryGetValue(GridKeyCompleted, out var json)) - e.Layout = JsonSerializer.Deserialize(json); - } - - async Task OnCompletedGridLayoutAutoSaving(GridPersistentLayoutEventArgs e) - { - var json = JsonSerializer.Serialize(e.Layout); - await UserPreferencesService.SaveGridLayoutAsync(GridKeyCompleted, json); - } - private sealed record StatusFilterItem(EnvelopeStatus Value, string Text); }