Add envelope preview feature with popup and row events

Enhanced the UI with a "Vorschau" (Preview) button to display
PDF previews of selected envelopes. Introduced a `DxPopup`
to show envelope details, including ID and title, with a
"Schließen" (Close) button.

Replaced `SelectedDataItemChanged` with `RowClick` and
`RowDoubleClick` events for improved row selection.
Single-click toggles row selection, while double-click opens
the preview popup. Added `_previewVisible` to manage popup
visibility and implemented `ShowPreview` for button-triggered
previews. Removed `OnSelectedEnvelopeChanged` as it is now
handled by the new row events. Updated grid layout persistence
to align with the new event structure.
This commit is contained in:
2026-09-21 17:07:20 +02:00
parent 80f08b393c
commit ec3a15a467

View File

@@ -91,6 +91,14 @@
} }
</button> </button>
<button class="sender-btn" @onclick="ShowPreview" disabled="@(_selectedEnvelope == null)" title="Ausgewählten Umschlag als PDF anzeigen">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16">
<path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/>
<path d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8zm8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>
</svg>
Vorschau
</button>
<button class="sender-btn sender-btn--logout" @onclick="LogoutAsync" disabled="@_isLoggingOut" title="Abmelden"> <button class="sender-btn sender-btn--logout" @onclick="LogoutAsync" disabled="@_isLoggingOut" title="Abmelden">
@if (_isLoggingOut) @if (_isLoggingOut)
{ {
@@ -180,7 +188,8 @@
PagerVisible="true" PagerVisible="true"
SelectionMode="GridSelectionMode.Single" SelectionMode="GridSelectionMode.Single"
SelectedDataItem="@_selectedEnvelope" SelectedDataItem="@_selectedEnvelope"
SelectedDataItemChanged="@OnSelectedEnvelopeChanged" RowClick="OnRowClick"
RowDoubleClick="OnRowDoubleClick"
CustomizeElement="OnCustomizeElement" CustomizeElement="OnCustomizeElement"
LayoutAutoLoading="OnActiveGridLayoutAutoLoading" LayoutAutoLoading="OnActiveGridLayoutAutoLoading"
LayoutAutoSaving="OnActiveGridLayoutAutoSaving"> LayoutAutoSaving="OnActiveGridLayoutAutoSaving">
@@ -298,7 +307,8 @@
PagerVisible="true" PagerVisible="true"
SelectionMode="GridSelectionMode.Single" SelectionMode="GridSelectionMode.Single"
SelectedDataItem="@_selectedEnvelope" SelectedDataItem="@_selectedEnvelope"
SelectedDataItemChanged="@OnSelectedEnvelopeChanged" RowClick="OnRowClick"
RowDoubleClick="OnRowDoubleClick"
CustomizeElement="OnCustomizeElement" CustomizeElement="OnCustomizeElement"
LayoutAutoLoading="OnCompletedGridLayoutAutoLoading" LayoutAutoLoading="OnCompletedGridLayoutAutoLoading"
LayoutAutoSaving="OnCompletedGridLayoutAutoSaving"> LayoutAutoSaving="OnCompletedGridLayoutAutoSaving">
@@ -412,6 +422,26 @@
</div> </div>
</div> </div>
@* ── PDF Vorschau Popup ────────────────────────────────────────────────── *@
<DxPopup @bind-Visible="@_previewVisible"
HeaderText="@($"Vorschau — Umschlag #{_selectedEnvelope?.Id}")"
Width="480px"
CloseOnOutsideClick="true"
ShowFooter="true">
<BodyContentTemplate>
<div style="padding: 1rem;">
<p><strong>Umschlag-ID:</strong> @_selectedEnvelope?.Id</p>
<p><strong>Titel:</strong> @_selectedEnvelope?.Title</p>
</div>
</BodyContentTemplate>
<FooterContentTemplate>
<DxButton CssClass="popup-button my-1 ms-2"
RenderStyle="ButtonRenderStyle.Secondary"
Text="Schließen"
Click="@(() => _previewVisible = false)" />
</FooterContentTemplate>
</DxPopup>
@code { @code {
private IEnumerable<EnvelopeDto>? _allEnvelopes; private IEnumerable<EnvelopeDto>? _allEnvelopes;
private IEnumerable<EnvelopeDto>? _activeEnvelopes; private IEnumerable<EnvelopeDto>? _activeEnvelopes;
@@ -428,6 +458,9 @@
private EnvelopeGenerator.Server.Client.Services.CustomImageDto? _appLogo; private EnvelopeGenerator.Server.Client.Services.CustomImageDto? _appLogo;
private EnvelopeGenerator.Server.Client.Services.CustomImageDto? _companyLogo; private EnvelopeGenerator.Server.Client.Services.CustomImageDto? _companyLogo;
// Preview popup
private bool _previewVisible = false;
// Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts // Stable keys used to store/restore each grid's layout in UserPreferences.GridLayouts
private const string GridKeyActive = "sender.active-envelopes"; private const string GridKeyActive = "sender.active-envelopes";
private const string GridKeyCompleted = "sender.completed-envelopes"; private const string GridKeyCompleted = "sender.completed-envelopes";
@@ -540,9 +573,39 @@
// Future: Add custom row coloring based on status if needed // Future: Add custom row coloring based on status if needed
} }
void OnSelectedEnvelopeChanged(object envelope) // Single click: select row, or deselect if already selected (toggle)
void OnRowClick(GridRowClickEventArgs e)
{ {
_selectedEnvelope = envelope as EnvelopeDto; var clicked = e.Grid.GetDataItem(e.VisibleIndex) as EnvelopeDto;
if (clicked == null) return;
if (_selectedEnvelope?.Id == clicked.Id)
{
// Already selected → deselect
_selectedEnvelope = null;
e.Grid.DeselectDataItem(clicked);
}
else
{
// New row → select
_selectedEnvelope = clicked;
e.Grid.SelectDataItem(clicked);
}
}
// Double-click: select the row and open preview popup
void OnRowDoubleClick(GridRowClickEventArgs e)
{
var clicked = e.Grid.GetDataItem(e.VisibleIndex) as EnvelopeDto;
if (clicked == null) return;
_selectedEnvelope = clicked;
_previewVisible = true;
}
void ShowPreview()
{
if (_selectedEnvelope == null) return;
_previewVisible = true;
} }
// ── Grid Layout Persistence ─────────────────────────────────────────────── // ── Grid Layout Persistence ───────────────────────────────────────────────