From e5402bafc9b16a5cfa07348d1a8dfacd59098d05 Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 21 Sep 2026 13:05:59 +0200 Subject: [PATCH] Refactor and cleanup EnvelopeSender components Refactored code for improved readability, consistency, and maintainability. Removed the WASM boot loading overlay and its associated styles/scripts. Updated SVG paths to use self-closing tags for HTML compliance. Reformatted conditional blocks, state management, and session data logic. Enhanced error handling, spinner visibility, and empty state displays. Removed redundant comments and unused code. Added `envelope-editor.js` for new functionality. Cleaned up CSS and JavaScript related to the removed WASM overlay. Improved grid layout persistence and signature field logic. Adjusted localization strings for better alignment with German translations. --- .../Pages/EnvelopeSenderPage.razor | 132 +++++++++----- .../Components/App.razor | 20 +-- .../Pages/EnvelopeSenderEditorPage.razor | 168 +++++++++--------- .../wwwroot/css/app.css | 36 ---- 4 files changed, 168 insertions(+), 188 deletions(-) diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor index 3ee63ef5..78227ff6 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Pages/EnvelopeSenderPage.razor @@ -34,7 +34,7 @@ else { - + } @@ -60,43 +60,47 @@
@@ -105,7 +109,8 @@
- @if (_isLoading && _allEnvelopes == null) { + @if (_isLoading && _allEnvelopes == null) + {
@@ -114,13 +119,15 @@

Umschläge werden geladen...

- } else if (_errorMessage != null) { + } + else if (_errorMessage != null) + {
- - + +
Fehler beim Laden der Umschläge
@@ -129,18 +136,22 @@
- } else { + } + else + {
@@ -151,12 +162,13 @@ @* Grid persistence hint — informs users their layout is auto-saved *@
- - + + Die Größe und Position der Spalten wird automatisch für Sie gespeichert.
- @if (_activeTab == "active") { + @if (_activeTab == "active") + { @{ var envelope = cellContext.DataItem as EnvelopeDto; - if (envelope != null) { + if (envelope != null) + { var statusInfo = GetStatusInfo(envelope.Status);
@@ -203,7 +216,8 @@ @{ var envelope = cellContext.DataItem as EnvelopeDto; - if (envelope != null) { + if (envelope != null) + { var receivers = envelope.EnvelopeReceivers?.ToList() ?? []; var signed = receivers.Count(r => r.Signed); var total = receivers.Count; @@ -211,7 +225,8 @@ @signed / @total unterschrieben - @if (total > 0) { + @if (total > 0) + {
@@ -219,7 +234,7 @@
} } - + @@ -233,20 +248,25 @@
Empfänger
@{ var envelope = detailContext.DataItem as EnvelopeDto; - if (envelope?.EnvelopeReceivers?.Any() == true) { + if (envelope?.EnvelopeReceivers?.Any() == true) + {
- @foreach (var receiver in envelope.EnvelopeReceivers) { + @foreach (var receiver in envelope.EnvelopeReceivers) + {
- @if (receiver.Signed) { + @if (receiver.Signed) + { - + Unterschrieben - } else { + } + else + { - - + + Ausstehend } @@ -258,14 +278,18 @@
}
- } else { + } + else + {

Keine Empfänger

} }
- } else { + } + else + { @{ var envelope = cellContext.DataItem as EnvelopeDto; - if (envelope != null) { + if (envelope != null) + { var statusInfo = GetStatusInfo(envelope.Status);
@@ -309,7 +334,8 @@ @{ var envelope = cellContext.DataItem as EnvelopeDto; - if (envelope != null) { + if (envelope != null) + { var receivers = envelope.EnvelopeReceivers?.ToList() ?? []; var signed = receivers.Count(r => r.Signed); var total = receivers.Count; @@ -317,7 +343,8 @@ @signed / @total unterschrieben - @if (total > 0) { + @if (total > 0) + {
@@ -339,20 +366,25 @@
Empfänger
@{ var envelope = detailContext.DataItem as EnvelopeDto; - if (envelope?.EnvelopeReceivers?.Any() == true) { + if (envelope?.EnvelopeReceivers?.Any() == true) + {
- @foreach (var receiver in envelope.EnvelopeReceivers) { + @foreach (var receiver in envelope.EnvelopeReceivers) + {
- @if (receiver.Signed) { + @if (receiver.Signed) + { - + Unterschrieben - } else { + } + else + { - - + + Ausstehend } @@ -364,7 +396,9 @@
}
- } else { + } + else + {

Keine Empfänger

} } @@ -395,7 +429,7 @@ private EnvelopeGenerator.Server.Client.Services.CustomImageDto? _companyLogo; // 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"; protected override async Task OnInitializedAsync() @@ -415,7 +449,7 @@ // Load logo config — authenticated, so this should succeed var logos = await CustomImagesService.GetAsync(); - _appLogo = logos.App; + _appLogo = logos.App; _companyLogo = logos.Company; await LoadEnvelopesAsync(); @@ -430,7 +464,7 @@ try { _allEnvelopes = await EnvelopeService.GetAsync() ?? []; - + // Split into active and completed based on status var envelopes = _allEnvelopes.ToList(); _activeEnvelopes = envelopes.Where(e => ((EnvelopeStatus)e.Status).IsActive()).ToList(); diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/App.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/App.razor index 4c61b9f4..b43f7aa6 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/App.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/App.razor @@ -30,31 +30,13 @@ - -
-
-
-
-
- + - diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderEditorPage.razor b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderEditorPage.razor index eb4bf201..b163b89f 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderEditorPage.razor +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/Components/Pages/EnvelopeSenderEditorPage.razor @@ -81,8 +81,8 @@ @if (_signatureFields.Count > 0) { + background: #ede9fe; border-radius: 0.25rem; color: #6d28d9; + font-weight: 500; font-size: 0.7rem; white-space: nowrap;"> @_signatureFields.Count Signaturfeld@(_signatureFields.Count != 1 ? "er" : "") } @@ -118,8 +118,8 @@
@foreach (var receiver in _receivers) { -
+
@receiver.FullName
@@ -130,7 +130,7 @@
} @@ -436,7 +436,7 @@ // ── Constants ── // Signature field size in PDF points (fixed): 1.77" × 1.96" - const double SigWidthPt = 1.77 * 72; // 127.44 pt + const double SigWidthPt = 1.77 * 72; // 127.44 pt const double SigHeightPt = 1.96 * 72; // 141.12 pt // CssClass for DxPdfViewer — used by JS to locate page elements @@ -447,8 +447,8 @@ // ── State ── DxPdfViewer? _pdfViewer; - bool _pdfLoaded = false; - string _fileName = string.Empty; + bool _pdfLoaded = false; + string _fileName = string.Empty; string? _errorMessage; byte[]? _pdfBytes; // Current rendered PDF (original + placeholders burned in) byte[]? _originalPdfBytes; // Pristine upload — never modified, used as base for redraw @@ -457,25 +457,25 @@ ReceiverDraft? _pendingReceiverForPlacement; // Set when user clicks "Signatur hinzufügen" // ── Save state ── - bool _isSaving = false; - bool _savePopupVisible = false; - string? _saveErrorMessage = null; + bool _isSaving = false; + bool _savePopupVisible = false; + string? _saveErrorMessage = null; // ── Envelope metadata ── - string _envelopeTitle = string.Empty; + string _envelopeTitle = string.Empty; string _envelopeMessage = string.Empty; - bool _titleTouched = false; + bool _titleTouched = false; List _receivers = []; - bool _receiverPopupVisible; - string _receiverDraftName = string.Empty; - string _receiverDraftEmail = string.Empty; + bool _receiverPopupVisible; + string _receiverDraftName = string.Empty; + string _receiverDraftEmail = string.Empty; string _receiverDraftPhoneNumber = string.Empty; string? _selectedReceiverEmailSuggestion; string? _receiverPopupValidationMessage; - bool _isReceiverEmailSearchRunning; + bool _isReceiverEmailSearchRunning; List _receiverEmailSuggestions = []; - int _receiverEmailSearchVersion; + int _receiverEmailSearchVersion; static readonly System.ComponentModel.DataAnnotations.EmailAddressAttribute ReceiverEmailValidator = new(); @@ -512,12 +512,12 @@ && cached is not null) { _originalPdfBytes = cached.OriginalPdfBytes; - _signatureFields = cached.Fields; - _fileName = cached.FileName; - _pdfLoaded = _originalPdfBytes is { Length: > 0 }; - _receivers = cached.Receivers; - _envelopeTitle = cached.Title; - _envelopeMessage = cached.Message; + _signatureFields = cached.Fields; + _fileName = cached.FileName; + _pdfLoaded = _originalPdfBytes is { Length: > 0 }; + _receivers = cached.Receivers; + _envelopeTitle = cached.Title; + _envelopeMessage = cached.Message; // Redraw placeholders onto the original PDF if (_pdfLoaded) @@ -545,8 +545,8 @@ await file.OpenReadStream(maxBytes).CopyToAsync(ms); _originalPdfBytes = ms.ToArray(); - _fileName = file.Name; - _pdfLoaded = true; + _fileName = file.Name; + _pdfLoaded = true; _signatureFields.Clear(); _pendingReceiverForPlacement = null; @@ -597,12 +597,12 @@ double pageHeightPt; try { - using var ms = new System.IO.MemoryStream(_originalPdfBytes); - var doc = PdfSharp.Pdf.IO.PdfReader.Open(ms, PdfSharp.Pdf.IO.PdfDocumentOpenMode.Import); + using var ms = new System.IO.MemoryStream(_originalPdfBytes); + var doc = PdfSharp.Pdf.IO.PdfReader.Open(ms, PdfSharp.Pdf.IO.PdfDocumentOpenMode.Import); int pageIndex = Math.Max(0, Math.Min(coords.PageIndex, doc.PageCount - 1)); - var page = doc.Pages[pageIndex]; - pageWidthPt = page.Width.Point; - pageHeightPt = page.Height.Point; + var page = doc.Pages[pageIndex]; + pageWidthPt = page.Width.Point; + pageHeightPt = page.Height.Point; } catch (Exception ex) { @@ -614,17 +614,17 @@ double xPt = coords.NormX * pageWidthPt; double yPt = coords.NormY * pageHeightPt; - xPt = Math.Max(0, Math.Min(xPt, pageWidthPt - SigWidthPt)); + xPt = Math.Max(0, Math.Min(xPt, pageWidthPt - SigWidthPt)); yPt = Math.Max(0, Math.Min(yPt, pageHeightPt - SigHeightPt)); int page1Based = coords.PageIndex + 1; var field = new SignatureFieldDraft( - XPt: xPt, - YPt: yPt, - Page: page1Based, + XPt: xPt, + YPt: yPt, + Page: page1Based, ReceiverName: _pendingReceiverForPlacement.FullName, - Color: _pendingReceiverForPlacement.Color); + Color: _pendingReceiverForPlacement.Color); _signatureFields.Add(field); _pendingReceiverForPlacement = null; @@ -711,7 +711,7 @@ string.Join(", ", receiversWithoutField.Select(r => r.FullName))); } - _isSaving = true; + _isSaving = true; _saveErrorMessage = null; await InvokeAsync(StateHasChanged); @@ -728,16 +728,16 @@ var fields = _signatureFields .Where(f => f.ReceiverName == receiver.FullName) .Select(f => new DocReceiverElementCreateDto( - X: f.XPt / 72.0, - Y: f.YPt / 72.0, + X: f.XPt / 72.0, + Y: f.YPt / 72.0, Page: f.Page)) .ToList(); return new ReceiverGetOrCreateCommand { - EmailAddress = receiver.Email, - Salution = receiver.FullName, - PhoneNumber = string.IsNullOrWhiteSpace(receiver.PhoneNumber) + EmailAddress = receiver.Email, + Salution = receiver.FullName, + PhoneNumber = string.IsNullOrWhiteSpace(receiver.PhoneNumber) ? null : receiver.PhoneNumber, DocReceiverElements = fields, @@ -746,13 +746,13 @@ var command = new CreateEnvelopeReceiverCommand { - Title = _envelopeTitle.Trim(), - Message = string.IsNullOrWhiteSpace(_envelopeMessage) + Title = _envelopeTitle.Trim(), + Message = string.IsNullOrWhiteSpace(_envelopeMessage) ? "Bitte unterzeichnen Sie das beigefügte Dokument." : _envelopeMessage.Trim(), TFAEnabled = false, - Document = new DocumentCreateCommand { DataAsBase64 = docBase64 }, - Receivers = receiversCmd, + Document = new DocumentCreateCommand { DataAsBase64 = docBase64 }, + Receivers = receiversCmd, }; var result = await EnvelopeReceiverService.CreateAsync(command); @@ -784,11 +784,11 @@ var data = new EditorSessionData( OriginalPdfBytes: _originalPdfBytes ?? [], - Fields: [.. _signatureFields], - FileName: _fileName, - Receivers: [.. _receivers], - Title: _envelopeTitle, - Message: _envelopeMessage); + Fields: [.. _signatureFields], + FileName: _fileName, + Receivers: [.. _receivers], + Title: _envelopeTitle, + Message: _envelopeMessage); MemoryCache.Set(SessionKey, data, SessionTtl); } @@ -798,7 +798,7 @@ { if (fields.Count == 0) return originalPdf; - using var inputMs = new System.IO.MemoryStream(originalPdf); + using var inputMs = new System.IO.MemoryStream(originalPdf); using var outputMs = new System.IO.MemoryStream(); var document = PdfSharp.Pdf.IO.PdfReader.Open( @@ -819,11 +819,11 @@ var nameBrush = new PdfSharp.Drawing.XSolidBrush(HexToXColor(field.Color, alpha: 230)); var fontLabel = new PdfSharp.Drawing.XFont("Arial", 9, PdfSharp.Drawing.XFontStyleEx.Bold); - var fontName = new PdfSharp.Drawing.XFont("Arial", 7, PdfSharp.Drawing.XFontStyleEx.Regular); + var fontName = new PdfSharp.Drawing.XFont("Arial", 7, PdfSharp.Drawing.XFontStyleEx.Regular); var fmtCenter = new PdfSharp.Drawing.XStringFormat { - Alignment = PdfSharp.Drawing.XStringAlignment.Center, + Alignment = PdfSharp.Drawing.XStringAlignment.Center, LineAlignment = PdfSharp.Drawing.XLineAlignment.Center, }; @@ -861,11 +861,11 @@ // ── Receiver popup ── void OpenAddReceiverPopup() { - _receiverDraftName = string.Empty; - _receiverDraftEmail = string.Empty; + _receiverDraftName = string.Empty; + _receiverDraftEmail = string.Empty; _receiverDraftPhoneNumber = string.Empty; _selectedReceiverEmailSuggestion = null; - _receiverPopupValidationMessage = null; + _receiverPopupValidationMessage = null; _receiverEmailSuggestions.Clear(); _receiverPopupVisible = true; } @@ -873,9 +873,9 @@ void CloseAddReceiverPopup() { _receiverPopupVisible = false; - _receiverPopupValidationMessage = null; + _receiverPopupValidationMessage = null; _selectedReceiverEmailSuggestion = null; - _isReceiverEmailSearchRunning = false; + _isReceiverEmailSearchRunning = false; } void OnReceiverNameChanged(string? value) @@ -947,7 +947,7 @@ { _receiverDraftEmail = value?.Trim() ?? string.Empty; _selectedReceiverEmailSuggestion = _receiverDraftEmail; - _receiverPopupValidationMessage = null; + _receiverPopupValidationMessage = null; var searchVersion = ++_receiverEmailSearchVersion; @@ -955,7 +955,7 @@ { _receiverEmailSuggestions.Clear(); _selectedReceiverEmailSuggestion = null; - _isReceiverEmailSearchRunning = false; + _isReceiverEmailSearchRunning = false; return; } @@ -994,8 +994,8 @@ Task SaveReceiverAsync() { - var fullName = _receiverDraftName.Trim(); - var email = _receiverDraftEmail.Trim(); + var fullName = _receiverDraftName.Trim(); + var email = _receiverDraftEmail.Trim(); var phoneNumber = _receiverDraftPhoneNumber.Trim(); if (string.IsNullOrWhiteSpace(fullName)) @@ -1034,12 +1034,12 @@ record ReceiverDraft(Guid Id, string FullName, string Email, string PhoneNumber, string Color); record EditorSessionData( - byte[] OriginalPdfBytes, + byte[] OriginalPdfBytes, List Fields, - string FileName, - List Receivers, - string Title, - string Message); + string FileName, + List Receivers, + string Title, + string Message); // ── Receiver colour palette (cycles when > 8 receivers) ── static readonly string[] ReceiverPalette = diff --git a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/app.css b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/app.css index 74741102..f67a5d5f 100644 --- a/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/app.css +++ b/EnvelopeGenerator.Server/EnvelopeGenerator.Server/wwwroot/css/app.css @@ -56,42 +56,6 @@ article { color: red; } -/* ── WASM Boot Loading Overlay ───────────────────────────────────────────── */ -/* Shown immediately on page load, removed once Blazor circuit connects. */ -/* Prevents white/unstyled flash while WASM boots (~1-2s on first load). */ - -#sf-boot-overlay { - position: fixed; - inset: 0; - z-index: 9999; - display: flex; - align-items: center; - justify-content: center; - background: linear-gradient(135deg, #1e3c72 0%, #2a5298 50%, #7e22ce 100%); - transition: opacity 0.25s ease; - pointer-events: none; /* don't block clicks once fading out */ -} - -.sf-boot-spinner { - display: flex; - flex-direction: column; - align-items: center; - gap: 1.25rem; -} - -.sf-boot-ring { - width: 44px; - height: 44px; - border: 3px solid rgba(255, 255, 255, 0.2); - border-top-color: rgba(255, 255, 255, 0.85); - border-radius: 50%; - animation: sf-boot-spin 0.8s linear infinite; -} - -@keyframes sf-boot-spin { - to { transform: rotate(360deg); } -} - #blazor-error-ui { background: lightyellow; bottom: 0;