Add receiver removal functionality to SenderEditor
Enhanced the `SenderEditorPage.razor` by injecting the `EnvelopeReceiverService` to manage envelope receivers. Updated the UI to include a remove button for each receiver, invoking the new `RemoveReceiverAsync` method. This method handles the deletion of receivers from both the UI and the server. Modified `ReceiverDraft` and `SignatureFieldDraft` models to include `ReceiverId` and `ReceiverDraftId` for better tracking. Updated logic for identifying receivers without signature fields and creating receiver commands to use these new identifiers. Added `DeleteAsync` method in `EnvelopeReceiverService.cs` to send DELETE requests for removing receivers. Updated `envelope-viewer.css` to style the new remove button with distinct appearance and hover effects.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
@inject DocumentService DocumentService
|
||||
@inject PdfRenderService PdfRenderService
|
||||
@inject ReceiverService ReceiverService
|
||||
@inject EnvelopeReceiverService EnvelopeReceiverService
|
||||
@inject EnvelopeService EnvelopeService
|
||||
@inject EnvelopeTypeService EnvelopeTypeService
|
||||
@inject CreateEnvelopeBootstrapStorageService CreateEnvelopeBootstrapStorageService
|
||||
@@ -224,20 +225,28 @@
|
||||
{
|
||||
<div class="sender-receivers-list">
|
||||
@foreach (var receiver in _receivers)
|
||||
{
|
||||
<div class="sender-receiver-chip" style="--receiver-color:@receiver.Color;">
|
||||
<div class="sender-receiver-chip__body">
|
||||
<div class="sender-receiver-chip__name">@receiver.FullName</div>
|
||||
<div class="sender-receiver-chip__email">@receiver.Email</div>
|
||||
{
|
||||
<div class="sender-receiver-chip" style="--receiver-color:@receiver.Color;">
|
||||
<div class="sender-receiver-chip__body">
|
||||
<div class="sender-receiver-chip__name">@receiver.FullName</div>
|
||||
<div class="sender-receiver-chip__email">@receiver.Email</div>
|
||||
@if (!string.IsNullOrWhiteSpace(receiver.PhoneNumber))
|
||||
{
|
||||
<div class="sender-receiver-chip__phone">@receiver.PhoneNumber</div>
|
||||
}
|
||||
</div>
|
||||
<div class="sender-receiver-chip__phone">@receiver.PhoneNumber</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<button class="pdf-toolbar__btn pdf-toolbar__btn--signature-change sender-toolbar-action-btn sender-toolbar-action-btn--compact sender-receiver-chip__place-btn
|
||||
@(_pendingReceiverForPlacement?.Id == receiver.Id ? "sender-receiver-chip__place-btn--active" : "sender-receiver-chip__place-btn--idle")"
|
||||
@onclick="() => ActivatePlacementForReceiver(receiver)"
|
||||
<button class="pdf-toolbar__btn pdf-toolbar__btn--reset sender-toolbar-action-btn sender-toolbar-action-btn--compact sender-receiver-chip__action sender-receiver-chip__remove-btn"
|
||||
@onclick="() => RemoveReceiverAsync(receiver)"
|
||||
title='@L("Delete", "Loeschen")'>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16">
|
||||
<path d="M4 4L12 12M12 4L4 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button class="pdf-toolbar__btn pdf-toolbar__btn--signature-change sender-toolbar-action-btn sender-toolbar-action-btn--compact sender-receiver-chip__place-btn
|
||||
@(_pendingReceiverForPlacement?.Id == receiver.Id ? "sender-receiver-chip__place-btn--active" : "sender-receiver-chip__place-btn--idle")"
|
||||
@onclick="() => ActivatePlacementForReceiver(receiver)"
|
||||
style="--receiver-color:@receiver.Color;"
|
||||
title='@L("SenderEditor_PlaceSignatureField", "Signaturfeld platzieren")'>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="currentColor" viewBox="0 0 16 16">
|
||||
@@ -762,6 +771,7 @@
|
||||
_receivers = payload.Receivers
|
||||
.Select((receiver, index) => new ReceiverDraft(
|
||||
Guid.NewGuid(),
|
||||
null,
|
||||
receiver.FullName,
|
||||
receiver.EmailAddress,
|
||||
string.Empty,
|
||||
@@ -872,12 +882,17 @@
|
||||
_receivers = envelopeReceivers
|
||||
.Select((er, index) => new ReceiverDraft(
|
||||
Guid.NewGuid(),
|
||||
er.ReceiverId,
|
||||
er.Name ?? er.Receiver?.EmailAddress ?? $"Receiver {er.ReceiverId}",
|
||||
er.Receiver?.EmailAddress ?? string.Empty,
|
||||
string.Empty,
|
||||
ReceiverPalette[index % ReceiverPalette.Length]))
|
||||
.ToList();
|
||||
|
||||
var receiverDraftByReceiverId = _receivers
|
||||
.Where(r => r.ReceiverId.HasValue)
|
||||
.ToDictionary(r => r.ReceiverId!.Value, r => r);
|
||||
|
||||
var receiverById = envelopeReceivers.ToDictionary(er => er.ReceiverId, er => er);
|
||||
var colorByEmail = _receivers
|
||||
.Where(r => !string.IsNullOrWhiteSpace(r.Email))
|
||||
@@ -899,10 +914,17 @@
|
||||
? receiverColor
|
||||
: ReceiverPalette[Math.Abs(element.ReceiverId) % ReceiverPalette.Length];
|
||||
|
||||
var receiverDraft = receiverDraftByReceiverId.TryGetValue(element.ReceiverId, out var draft)
|
||||
? draft
|
||||
: _receivers.FirstOrDefault(r =>
|
||||
(!string.IsNullOrWhiteSpace(receiverEmail) && string.Equals(r.Email, receiverEmail, StringComparison.OrdinalIgnoreCase))
|
||||
|| string.Equals(r.FullName, receiverName, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
return new SignatureFieldDraft(
|
||||
XPt: element.X * 72.0,
|
||||
YPt: element.Y * 72.0,
|
||||
Page: element.Page,
|
||||
ReceiverDraftId: receiverDraft?.Id ?? Guid.Empty,
|
||||
ReceiverName: receiverName,
|
||||
Color: color);
|
||||
})
|
||||
@@ -1138,6 +1160,7 @@
|
||||
XPt: xPt,
|
||||
YPt: yPt,
|
||||
Page: page1Based,
|
||||
ReceiverDraftId: _pendingReceiverForPlacement.Id,
|
||||
ReceiverName: _pendingReceiverForPlacement.FullName,
|
||||
Color: _pendingReceiverForPlacement.Color);
|
||||
|
||||
@@ -1322,7 +1345,7 @@
|
||||
|
||||
// Warn if any receiver has no signature field, but don't block
|
||||
var receiversWithoutField = _receivers
|
||||
.Where(r => !_signatureFields.Any(f => f.ReceiverName == r.FullName))
|
||||
.Where(r => !_signatureFields.Any(f => f.ReceiverDraftId == r.Id))
|
||||
.ToList();
|
||||
if (receiversWithoutField.Count > 0)
|
||||
{
|
||||
@@ -1397,7 +1420,7 @@
|
||||
var receiverCommands = _receivers.Select(receiver =>
|
||||
{
|
||||
var fields = _signatureFields
|
||||
.Where(f => f.ReceiverName == receiver.FullName)
|
||||
.Where(f => f.ReceiverDraftId == receiver.Id)
|
||||
.Select(f => new CreateEnvelopeFieldDto(
|
||||
X: f.XPt / 72.0,
|
||||
Y: f.YPt / 72.0,
|
||||
@@ -1659,18 +1682,52 @@
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
_receivers.Add(new ReceiverDraft(Guid.NewGuid(), fullName, email, phoneNumber,
|
||||
_receivers.Add(new ReceiverDraft(Guid.NewGuid(), null, fullName, email, phoneNumber,
|
||||
ReceiverPalette[_receivers.Count % ReceiverPalette.Length]));
|
||||
CloseAddReceiverPopup();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
async Task RemoveReceiverAsync(ReceiverDraft receiver)
|
||||
{
|
||||
if (_isSaving)
|
||||
return;
|
||||
|
||||
var envelopeId = _editingEnvelopeId
|
||||
?? EnvelopeId
|
||||
?? _loadedEnvelopeId
|
||||
?? GetEnvelopeIdFromCurrentUri();
|
||||
|
||||
if (envelopeId is int persistedEnvelopeId && persistedEnvelopeId > 0 && receiver.ReceiverId is int persistedReceiverId && persistedReceiverId > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
await EnvelopeReceiverService.DeleteAsync(persistedEnvelopeId, persistedReceiverId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "[SenderEditor] Failed to remove receiver {ReceiverId} from envelope {EnvelopeId}", persistedReceiverId, persistedEnvelopeId);
|
||||
_saveErrorMessage = string.Format(
|
||||
L("SenderEditor_RemoveReceiverError", "Empfaenger konnte nicht entfernt werden: {0}"),
|
||||
ex.Message);
|
||||
_savePopupVisible = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_receivers.RemoveAll(r => r.Id == receiver.Id);
|
||||
_signatureFields.RemoveAll(f => f.ReceiverDraftId == receiver.Id);
|
||||
|
||||
if (_pendingReceiverForPlacement?.Id == receiver.Id)
|
||||
_pendingReceiverForPlacement = null;
|
||||
}
|
||||
|
||||
// ── Models ──
|
||||
record SignatureFieldDraft(double XPt, double YPt, int Page, string ReceiverName, string Color);
|
||||
record SignatureFieldDraft(double XPt, double YPt, int Page, Guid ReceiverDraftId, string ReceiverName, string Color);
|
||||
|
||||
record NormalisedCoords(double NormX, double NormY, int PageIndex);
|
||||
|
||||
record ReceiverDraft(Guid Id, string FullName, string Email, string PhoneNumber, string Color);
|
||||
record ReceiverDraft(Guid Id, int? ReceiverId, string FullName, string Email, string PhoneNumber, string Color);
|
||||
|
||||
// ── Receiver colour palette (cycles when > 8 receivers) ──
|
||||
static readonly string[] ReceiverPalette =
|
||||
|
||||
Reference in New Issue
Block a user