SF-74: EnvelopeSenderPage — ThemeService/UserPreferencesService inject, LoadFromServerAsync, grid layout persistence (LayoutAutoLoading/Saving)
This commit is contained in:
@@ -8,6 +8,8 @@
|
|||||||
@using EnvelopeGenerator.Application.Common.Dto
|
@using EnvelopeGenerator.Application.Common.Dto
|
||||||
@inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService
|
@inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService
|
||||||
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
||||||
|
@inject EnvelopeGenerator.Server.Client.Services.ThemeService ThemeService
|
||||||
|
@inject EnvelopeGenerator.Server.Client.Services.UserPreferencesService UserPreferencesService
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject AppVersionService AppVersion
|
@inject AppVersionService AppVersion
|
||||||
@@ -130,7 +132,9 @@
|
|||||||
SelectionMode="GridSelectionMode.Single"
|
SelectionMode="GridSelectionMode.Single"
|
||||||
SelectedDataItem="@_selectedEnvelope"
|
SelectedDataItem="@_selectedEnvelope"
|
||||||
SelectedDataItemChanged="@OnSelectedEnvelopeChanged"
|
SelectedDataItemChanged="@OnSelectedEnvelopeChanged"
|
||||||
CustomizeElement="OnCustomizeElement">
|
CustomizeElement="OnCustomizeElement"
|
||||||
|
LayoutAutoLoading="OnActiveGridLayoutAutoLoading"
|
||||||
|
LayoutAutoSaving="OnActiveGridLayoutAutoSaving">
|
||||||
<Columns>
|
<Columns>
|
||||||
<DxGridDataColumn FieldName="Id" Caption="ID"
|
<DxGridDataColumn FieldName="Id" Caption="ID"
|
||||||
SortIndex="0"
|
SortIndex="0"
|
||||||
@@ -228,7 +232,9 @@
|
|||||||
SelectionMode="GridSelectionMode.Single"
|
SelectionMode="GridSelectionMode.Single"
|
||||||
SelectedDataItem="@_selectedEnvelope"
|
SelectedDataItem="@_selectedEnvelope"
|
||||||
SelectedDataItemChanged="@OnSelectedEnvelopeChanged"
|
SelectedDataItemChanged="@OnSelectedEnvelopeChanged"
|
||||||
CustomizeElement="OnCustomizeElement">
|
CustomizeElement="OnCustomizeElement"
|
||||||
|
LayoutAutoLoading="OnCompletedGridLayoutAutoLoading"
|
||||||
|
LayoutAutoSaving="OnCompletedGridLayoutAutoSaving">
|
||||||
<Columns>
|
<Columns>
|
||||||
<DxGridDataColumn FieldName="Id" Caption="ID"
|
<DxGridDataColumn FieldName="Id" Caption="ID"
|
||||||
SortIndex="0"
|
SortIndex="0"
|
||||||
@@ -335,6 +341,10 @@
|
|||||||
private DxGrid? _gridActive;
|
private DxGrid? _gridActive;
|
||||||
private DxGrid? _gridCompleted;
|
private DxGrid? _gridCompleted;
|
||||||
|
|
||||||
|
// Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts
|
||||||
|
private const string GridKeyActive = "sender.active-envelopes";
|
||||||
|
private const string GridKeyCompleted = "sender.completed-envelopes";
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
var hasAccess = await AuthService.CheckSenderAccessAsync();
|
var hasAccess = await AuthService.CheckSenderAccessAsync();
|
||||||
@@ -344,6 +354,12 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load theme + DisplayName from server after authentication.
|
||||||
|
// Non-fatal: if this fails the page still loads with default theme.
|
||||||
|
// ThemeService.ScheduleSaveAsync() already logs errors internally.
|
||||||
|
try { await ThemeService.LoadFromServerAsync(); }
|
||||||
|
catch { /* swallow — default theme remains active */ }
|
||||||
|
|
||||||
await LoadEnvelopesAsync();
|
await LoadEnvelopesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,13 +377,10 @@
|
|||||||
var envelopes = _allEnvelopes.ToList();
|
var envelopes = _allEnvelopes.ToList();
|
||||||
_activeEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsActive()).ToList();
|
_activeEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsActive()).ToList();
|
||||||
_completedEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsCompleted()).ToList();
|
_completedEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsCompleted()).ToList();
|
||||||
|
|
||||||
await JSRuntime.InvokeVoidAsync("console.log", $"Loaded {_activeEnvelopes.Count()} active and {_completedEnvelopes.Count()} completed envelopes");
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_errorMessage = ex.Message;
|
_errorMessage = ex.Message;
|
||||||
await JSRuntime.InvokeVoidAsync("console.error", "Fehler beim Laden der Umschläge:", ex.ToString());
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
@@ -390,20 +403,19 @@
|
|||||||
{
|
{
|
||||||
if (_selectedEnvelope == null) return;
|
if (_selectedEnvelope == null) return;
|
||||||
// TODO: Navigate to envelope editor
|
// TODO: Navigate to envelope editor
|
||||||
JSRuntime.InvokeVoidAsync("console.log", $"Edit envelope {_selectedEnvelope.Id} clicked - not yet implemented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DeleteEnvelope()
|
void DeleteEnvelope()
|
||||||
{
|
{
|
||||||
if (_selectedEnvelope == null) return;
|
if (_selectedEnvelope == null) return;
|
||||||
// TODO: Show delete confirmation dialog
|
// TODO: Show delete confirmation dialog
|
||||||
JSRuntime.InvokeVoidAsync("console.log", $"Delete envelope {_selectedEnvelope.Id} clicked - not yet implemented");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async Task LogoutAsync()
|
async Task LogoutAsync()
|
||||||
{
|
{
|
||||||
_isLoggingOut = true;
|
_isLoggingOut = true;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
UserPreferencesService.InvalidateCache();
|
||||||
await AuthService.LogoutSenderAsync();
|
await AuthService.LogoutSenderAsync();
|
||||||
Navigation.NavigateTo("/sender/login", forceLoad: true);
|
Navigation.NavigateTo("/sender/login", forceLoad: true);
|
||||||
}
|
}
|
||||||
@@ -440,4 +452,45 @@
|
|||||||
{
|
{
|
||||||
_selectedEnvelope = envelope as EnvelopeDto;
|
_selectedEnvelope = envelope as EnvelopeDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Grid Layout Persistence ───────────────────────────────────────────────
|
||||||
|
// LayoutAutoLoading fires when the grid initializes — restore saved layout.
|
||||||
|
// LayoutAutoSaving fires when the user changes column order/width/sort — persist it.
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
// 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))
|
||||||
|
e.Layout = JsonSerializer.Deserialize<GridPersistentLayout>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task OnActiveGridLayoutAutoSaving(GridPersistentLayoutEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(e.Layout);
|
||||||
|
await UserPreferencesService.SaveGridLayoutAsync(GridKeyActive, json);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await JSRuntime.InvokeVoidAsync("console.warn", $"[Sender] Grid layout save failed: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<GridPersistentLayout>(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task OnCompletedGridLayoutAutoSaving(GridPersistentLayoutEventArgs e)
|
||||||
|
{
|
||||||
|
var json = JsonSerializer.Serialize(e.Layout);
|
||||||
|
await UserPreferencesService.SaveGridLayoutAsync(GridKeyCompleted, json);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user