Improve signature workflow in ReportViewer.razor

Enhance the user interface and functionality for applying signatures:
- Add detailed display of signature fields and their pages.
- Introduce a progress bar to show marking progress visually.
- Display success message when all fields are marked.
- Automatically submit signatures when all fields are marked.
- Provide guidance for creating a signature if none exists.
- Disable "Export Signed PDF" button until signature is applied.
- Refactor code to simplify logic and remove redundancy.

These changes improve usability and provide clearer feedback to users.
This commit is contained in:
2026-06-01 03:25:35 +02:00
parent d657f3825c
commit 683f1eaf13

View File

@@ -57,19 +57,33 @@
<span>Unterschrift &auml;ndern</span>
}
</button>
@if (_annotations.Count > 0) {
@if (_capturedSignature is not null && !SignatureApplied) {
<span class="text-muted small fst-italic align-self-center">
@_checkedAnnotations.Count von @_annotations.Count @(_annotations.Count == 1 ? "Feld" : "Felder") markiert
@if (_annotations.Count > 0 && !SignatureApplied) {
<div class="d-flex flex-column gap-1 align-self-center">
<span class="text-muted small">
<strong>@_annotations.Count</strong> @(_annotations.Count == 1 ? "Unterschriftsfeld" : "Unterschriftsfelder")
&nbsp;&middot;&nbsp;
Seite@(AnnotationPages.Count() == 1 ? "" : "n"): <strong>@string.Join(", ", AnnotationPages)</strong>
</span>
<button class="btn btn-primary" @onclick="SubmitSignaturesAsync">
Unterschriften anwenden
</button>
} else if (!SignatureApplied) {
<span class="text-muted small fst-italic align-self-center">
Bitte zuerst eine Unterschrift erstellen, dann die Felder im Dokument markieren.
</span>
}
@if (_capturedSignature is not null) {
<div class="d-flex align-items-center gap-2">
<div class="progress flex-grow-1" style="height:6px; min-width:80px;">
<div class="progress-bar @(_checkedAnnotations.Count == _annotations.Count ? "bg-success" : "bg-primary")"
style="width:@(_annotations.Count > 0 ? (_checkedAnnotations.Count * 100 / _annotations.Count) : 0)%"
role="progressbar"></div>
</div>
<span class="text-muted small fst-italic">
@_checkedAnnotations.Count / @_annotations.Count @(_annotations.Count == 1 ? "Feld" : "Felder") markiert
</span>
</div>
@if (_checkedAnnotations.Count == _annotations.Count) {
<span class="text-success small fw-semibold">&#10003; Alle Felder markiert &ndash; Unterschriften werden angewendet&hellip;</span>
}
} else {
<span class="text-muted small fst-italic">
Bitte zuerst eine Unterschrift erstellen, dann die Felder im Dokument markieren.
</span>
}
</div>
}
<button class="btn btn-success" disabled="@(!SignatureApplied)" @onclick="ExportSignedPdfAsync">Signiertes PDF exportieren</button>
@if (!string.IsNullOrWhiteSpace(EnvelopeKey)) {
@@ -210,6 +224,7 @@ Shown="OnPopupShownAsync">
bool IsLoggingOut;
IReadOnlyList<AnnotationDto> _annotations = [];
IEnumerable<int> AnnotationPages => _annotations.Select(a => a.Page).Distinct().OrderBy(p => p);
record SignatureCapture(string DataUrl, string FullName, string Position, string Place);
SignatureCapture? _capturedSignature;
byte[]? _basePdfBytes;
@@ -277,6 +292,15 @@ Shown="OnPopupShownAsync">
else
_checkedAnnotations.Remove(annotationId);
await InvokeAsync(StateHasChanged);
if (_capturedSignature is not null
&& !SignatureApplied
&& _annotations.Count > 0
&& _checkedAnnotations.Count == _annotations.Count) {
// K?sa bekleme: kullan?c? son tick'in görsel feedback'ini görsün
await Task.Delay(400);
await SubmitSignaturesAsync();
}
}
void OpenSignaturePopupAsync() {