Add support for signed PDF previews

Integrated `PdfSignatureService` to enable fetching and previewing signed PDFs for completed envelopes. Updated `SenderPage.razor` to dynamically adjust popup headers and filenames based on the envelope's status. Enhanced `OpenPreviewAsync` to conditionally fetch signed or original PDFs.

Registered `PdfSignatureService` and DevExpress PDF Viewer in `Program.cs`. Implemented `PdfSignatureService` to handle API calls for retrieving signed PDFs with error handling.
This commit is contained in:
2026-10-21 17:46:38 +02:00
parent e423c6d751
commit 26beae0d14
4 changed files with 35 additions and 3 deletions

View File

@@ -19,6 +19,7 @@
@inject EnvelopeGenerator.Server.Client.Services.ThemeService ThemeService
@inject EnvelopeGenerator.Server.Client.Services.UserPreferencesService UserPreferencesService
@inject EnvelopeGenerator.Server.Client.Services.CustomImagesService CustomImagesService
@inject EnvelopeGenerator.Server.Client.Services.PdfSignatureService PdfSignatureService
@inject EnvelopeGenerator.Server.Client.Services.CreateEnvelopeBootstrapStorageService CreateEnvelopeBootstrapStorageService
@inject ILogger<SenderPage> Logger
@inject NavigationManager Navigation
@@ -424,7 +425,7 @@
@* ── PDF Vorschau Popup ────────────────────────────────────────────────── *@
<DxPopup @bind-Visible="@_previewVisible"
HeaderText="@($"{L("Preview", "Vorschau")} — {_selectedEnvelope?.Title} (#{_selectedEnvelope?.Id})")"
HeaderText="@($"{(_activeTab == "completed" && _selectedEnvelope?.Status == EnvelopeStatus.EnvelopeCompletelySigned ? L("SignedPdf", "Signiertes PDF") : L("Preview", "Vorschau"))} — {_selectedEnvelope?.Title} (#{_selectedEnvelope?.Id})")"
Width="80vw"
MaxWidth="80vw"
Height="90vh"
@@ -1024,12 +1025,14 @@
private async Task OpenPreviewAsync(EnvelopeDto envelope)
{
var showSigned = _activeTab == "completed" && envelope.Status == EnvelopeStatus.EnvelopeCompletelySigned;
// Unmount the viewer first — let the previous instance fully dispose
_previewViewerMounted = false;
_previewPdfBytes = null;
_previewPageCount = 0;
_previewPagePreviews = [];
_previewFileName = $"envelope-{envelope.Id}.pdf";
_previewFileName = showSigned ? $"envelope-{envelope.Id}-signed.pdf" : $"envelope-{envelope.Id}.pdf";
_previewErrorMessage = null;
_previewLoading = true;
_previewVisible = true;
@@ -1037,7 +1040,10 @@
try
{
_previewPdfBytes = await DocumentService.GetSenderDocumentBytesByEnvelopeIdAsync(envelope.Id);
_previewPdfBytes = showSigned
? await PdfSignatureService.GetSignedPdfAsync(envelope.Id)
: await DocumentService.GetSenderDocumentBytesByEnvelopeIdAsync(envelope.Id);
if (_previewPdfBytes is null || _previewPdfBytes.Length == 0)
{
_previewErrorMessage = L("DocumentCouldNotBeLoaded", "Dokument konnte nicht geladen werden");

View File

@@ -53,6 +53,7 @@ builder.Services.AddScoped<ThemeService>();
// Logo configuration (loaded once after login, in-memory cached)
builder.Services.AddScoped<CustomImagesService>();
builder.Services.AddScoped<PdfSignatureService>();
// DevExpress WASM
builder.Services.AddDevExpressWebAssemblyBlazorPdfViewer();

View File

@@ -0,0 +1,24 @@
using System.Net;
using System.Net.Http.Json;
namespace EnvelopeGenerator.Server.Client.Services;
public class PdfSignatureService(IHttpClientFactory httpClientFactory)
{
/// <summary>
/// Calls POST /api/PdfSignature with the envelope id and returns the fully signed PDF bytes.
/// </summary>
public async Task<byte[]> GetSignedPdfAsync(int envelopeId, CancellationToken cancel = default)
{
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var response = await http.PostAsJsonAsync("/api/PdfSignature", new { Id = envelopeId }, cancel);
if (!response.IsSuccessStatusCode)
throw new HttpRequestException(
$"Failed to load signed PDF. Status: {(int)response.StatusCode} ({response.ReasonPhrase ?? "Unknown"})",
null,
response.StatusCode);
return await response.Content.ReadAsByteArrayAsync(cancel);
}
}