Add document preview feature to wizard popup
Introduced a document preview feature in the `CreateEnvelopeWizardPopup` component. This includes: - Injected `PdfRenderService` for rendering PDF pages. - Replaced document metadata display with a preview card. - Added `SenderPdfImageEditor` for interactive PDF previews. - Implemented state management for preview pages and overlays. - Added fallback logic to estimate PDF page count. - Enhanced `ResetWizardState` to reset preview-related fields. - Styled the preview card and wrap with new CSS classes. - Added placeholder event handlers for editor interactions.
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
@inject IStringLocalizer<Model> ModelLocalizer
|
||||
@inject IStringLocalizer<Resource> UiLocalizer
|
||||
@inject ReceiverService ReceiverService
|
||||
@inject PdfRenderService PdfRenderService
|
||||
|
||||
<DxPopup Visible="@_isVisible"
|
||||
VisibleChanged="OnPopupVisibleChangedAsync"
|
||||
@@ -238,10 +239,23 @@
|
||||
|
||||
@if (_documentBytes is not null)
|
||||
{
|
||||
<div class="sender-create-wizard__document-preview-card">
|
||||
<div class="sender-create-wizard__document-meta">
|
||||
<div class="sender-create-wizard__document-name">@_documentFileName</div>
|
||||
<div class="sender-create-wizard__document-size">@_documentSizeText</div>
|
||||
</div>
|
||||
<div class="sender-create-wizard__document-preview-wrap">
|
||||
<SenderPdfImageEditor IsPlacementMode="false"
|
||||
PageCount="@_documentPreviewPageCount"
|
||||
Pages="@_documentPreviewPages"
|
||||
PdfDataUrl="@DocumentPreviewDataUrl"
|
||||
PdfFileName="@_documentFileName"
|
||||
Fields="@_documentPreviewFieldOverlays"
|
||||
EditorClick="OnDocumentPreviewEditorClickAsync"
|
||||
RemoveField="OnDocumentPreviewRemoveFieldAsync"
|
||||
MoveField="OnDocumentPreviewMoveFieldAsync" />
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -331,10 +345,14 @@
|
||||
private byte[]? _documentBytes;
|
||||
private string? _documentFileName;
|
||||
private string _documentSizeText = string.Empty;
|
||||
private int _documentPreviewPageCount;
|
||||
private List<PdfPageImageDto> _documentPreviewPages = [];
|
||||
private bool _isDocumentUploading;
|
||||
private bool _isStepActionRunning;
|
||||
private bool _isFinishing;
|
||||
|
||||
private readonly IReadOnlyList<SenderPdfFieldOverlay> _documentPreviewFieldOverlays = [];
|
||||
|
||||
private string? _validationMessage;
|
||||
|
||||
private bool IsActionLocked => _isDocumentUploading || _isStepActionRunning || _isFinishing;
|
||||
@@ -346,6 +364,10 @@
|
||||
private IReadOnlyList<RecentReceiverSuggestionDto> FilteredRecentSuggestions =>
|
||||
BuildFilteredRecentSuggestions();
|
||||
|
||||
private string? DocumentPreviewDataUrl => _documentBytes is { Length: > 0 }
|
||||
? $"data:application/pdf;base64,{Convert.ToBase64String(_documentBytes)}"
|
||||
: null;
|
||||
|
||||
private string CurrentStepTitle => _currentStep switch
|
||||
{
|
||||
0 => L("SenderWizard_Step_Basics", "Grunddaten"),
|
||||
@@ -525,6 +547,22 @@
|
||||
_documentBytes = ms.ToArray();
|
||||
_documentFileName = file.Name;
|
||||
_documentSizeText = FormatSize(_documentBytes.Length);
|
||||
|
||||
_documentPreviewPages = [];
|
||||
try
|
||||
{
|
||||
_documentPreviewPages = (await PdfRenderService.RenderPagesAsync(_documentBytes))
|
||||
.OrderBy(x => x.PageNumber)
|
||||
.ToList();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_documentPreviewPages = [];
|
||||
}
|
||||
|
||||
_documentPreviewPageCount = _documentPreviewPages.Count > 0
|
||||
? _documentPreviewPages.Count
|
||||
: EstimatePdfPageCount(_documentBytes) ?? 1;
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -771,6 +809,51 @@
|
||||
return $"{bytes} B";
|
||||
}
|
||||
|
||||
private static int? EstimatePdfPageCount(byte[]? documentBytes)
|
||||
{
|
||||
if (documentBytes is null || documentBytes.Length == 0)
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
var text = System.Text.Encoding.ASCII.GetString(documentBytes);
|
||||
const string marker = "/Type /Page";
|
||||
var count = 0;
|
||||
var index = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
index = text.IndexOf(marker, index, StringComparison.Ordinal);
|
||||
if (index < 0)
|
||||
break;
|
||||
|
||||
count++;
|
||||
index += marker.Length;
|
||||
}
|
||||
|
||||
return count > 0 ? count : null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Task OnDocumentPreviewEditorClickAsync(MouseEventArgs _)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnDocumentPreviewRemoveFieldAsync(int _)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnDocumentPreviewMoveFieldAsync(SenderPdfFieldMoveRequest _)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void ResetWizardState()
|
||||
{
|
||||
_currentStep = 0;
|
||||
@@ -792,6 +875,8 @@
|
||||
_documentBytes = null;
|
||||
_documentFileName = null;
|
||||
_documentSizeText = string.Empty;
|
||||
_documentPreviewPageCount = 0;
|
||||
_documentPreviewPages = [];
|
||||
}
|
||||
|
||||
private int? GetDefaultEnvelopeTypeId()
|
||||
|
||||
@@ -1533,6 +1533,28 @@
|
||||
padding: 0.55rem 0.7rem;
|
||||
}
|
||||
|
||||
.sender-create-wizard__document-preview-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.65rem;
|
||||
}
|
||||
|
||||
.sender-create-wizard__document-preview-wrap {
|
||||
border: 1px solid rgba(148, 163, 184, 0.38);
|
||||
border-radius: 10px;
|
||||
background: rgba(248, 250, 252, 0.96);
|
||||
height: 320px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.sender-create-wizard__document-preview-wrap .sender-image-editor-shell {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.sender-create-wizard__document-preview-wrap .sender-image-editor {
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.sender-create-wizard__document-name {
|
||||
color: #064e3b;
|
||||
font-size: 0.85rem;
|
||||
|
||||
Reference in New Issue
Block a user