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> <span>Unterschrift &auml;ndern</span>
} }
</button> </button>
@if (_annotations.Count > 0) { @if (_annotations.Count > 0 && !SignatureApplied) {
@if (_capturedSignature is not null && !SignatureApplied) { <div class="d-flex flex-column gap-1 align-self-center">
<span class="text-muted small fst-italic align-self-center"> <span class="text-muted small">
@_checkedAnnotations.Count von @_annotations.Count @(_annotations.Count == 1 ? "Feld" : "Felder") markiert <strong>@_annotations.Count</strong> @(_annotations.Count == 1 ? "Unterschriftsfeld" : "Unterschriftsfelder")
&nbsp;&middot;&nbsp;
Seite@(AnnotationPages.Count() == 1 ? "" : "n"): <strong>@string.Join(", ", AnnotationPages)</strong>
</span> </span>
<button class="btn btn-primary" @onclick="SubmitSignaturesAsync"> @if (_capturedSignature is not null) {
Unterschriften anwenden <div class="d-flex align-items-center gap-2">
</button> <div class="progress flex-grow-1" style="height:6px; min-width:80px;">
} else if (!SignatureApplied) { <div class="progress-bar @(_checkedAnnotations.Count == _annotations.Count ? "bg-success" : "bg-primary")"
<span class="text-muted small fst-italic align-self-center"> style="width:@(_annotations.Count > 0 ? (_checkedAnnotations.Count * 100 / _annotations.Count) : 0)%"
Bitte zuerst eine Unterschrift erstellen, dann die Felder im Dokument markieren. role="progressbar"></div>
</span> </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> <button class="btn btn-success" disabled="@(!SignatureApplied)" @onclick="ExportSignedPdfAsync">Signiertes PDF exportieren</button>
@if (!string.IsNullOrWhiteSpace(EnvelopeKey)) { @if (!string.IsNullOrWhiteSpace(EnvelopeKey)) {
@@ -210,6 +224,7 @@ Shown="OnPopupShownAsync">
bool IsLoggingOut; bool IsLoggingOut;
IReadOnlyList<AnnotationDto> _annotations = []; 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); record SignatureCapture(string DataUrl, string FullName, string Position, string Place);
SignatureCapture? _capturedSignature; SignatureCapture? _capturedSignature;
byte[]? _basePdfBytes; byte[]? _basePdfBytes;
@@ -277,6 +292,15 @@ Shown="OnPopupShownAsync">
else else
_checkedAnnotations.Remove(annotationId); _checkedAnnotations.Remove(annotationId);
await InvokeAsync(StateHasChanged); 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() { void OpenSignaturePopupAsync() {