Files
EnvelopeGenerator/EnvelopeGenerator.Server/EnvelopeGenerator.Server.Client/Services/EnvelopeReceiverService.cs
TekH fc5ad7ea3c 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.
2026-10-27 19:02:22 +01:00

125 lines
5.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Net;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using EnvelopeGenerator.Application.EnvelopeReceivers.Commands.CreateEnvelopeReceiver;
using EnvelopeGenerator.Server.Client.Models;
using Microsoft.AspNetCore.WebUtilities;
namespace EnvelopeGenerator.Server.Client.Services;
/// <summary>
/// Retrieves the <see cref="EnvelopeReceiverDto"/> for the authenticated receiver
/// from <c>GET /api/EnvelopeReceiver/{envelopeKey}</c>.
/// Also creates new envelopes via <c>POST /api/EnvelopeReceiver</c>.
/// </summary>
public class EnvelopeReceiverService(IHttpClientFactory httpClientFactory)
{
private static readonly JsonSerializerOptions _jsonOptions = new(JsonSerializerDefaults.Web);
private sealed record ReceiverEnvelopeUrlResponse(string Url);
private sealed record ReceiverEnvelopeUrlEnabledResponse(bool Enabled);
/// <summary>
/// Fetches the envelope receiver data for the given envelope key from the API.
/// Throws HttpRequestException on failure with appropriate status code.
/// </summary>
/// <exception cref="HttpRequestException">Thrown when the API request fails.</exception>
public async Task<EnvelopeReceiverDto?> GetAsync(string envelopeKey, CancellationToken cancel = default)
{
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var url = $"/api/EnvelopeReceiver/{Uri.EscapeDataString(envelopeKey)}";
var response = await http.GetAsync(url, cancel);
if (!response.IsSuccessStatusCode)
{
var statusCode = (int)response.StatusCode;
var reasonPhrase = response.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to load envelope receiver data. Status: {statusCode} ({reasonPhrase})",
null,
response.StatusCode);
}
return await response.Content.ReadFromJsonAsync<EnvelopeReceiverDto>(_jsonOptions, cancel);
}
/// <summary>
/// Creates a new envelope with document and receivers via <c>POST /api/EnvelopeReceiver</c>.
/// Requires sender authentication cookie to be present in the request.
/// </summary>
/// <exception cref="HttpRequestException">Thrown when the API request fails.</exception>
public async Task<CreateEnvelopeReceiverResponse?> CreateAsync(
CreateEnvelopeReceiverCommand request,
CancellationToken cancel = default)
{
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var response = await http.PostAsJsonAsync("/api/EnvelopeReceiver", request, _jsonOptions, cancel);
if (!response.IsSuccessStatusCode)
{
var body = await response.Content.ReadAsStringAsync(cancel);
throw new HttpRequestException(
$"Fehler beim Erstellen des Umschlags. Status: {(int)response.StatusCode} – {body}",
null,
response.StatusCode);
}
return await response.Content.ReadFromJsonAsync<CreateEnvelopeReceiverResponse>(_jsonOptions, cancel);
}
public async Task<string?> GetReceiverEnvelopeUrlAsync(string envelopeUuid, string receiverSignature, CancellationToken cancel = default)
{
if (string.IsNullOrWhiteSpace(envelopeUuid) || string.IsNullOrWhiteSpace(receiverSignature))
return null;
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var url = $"/api/EnvelopeReceiver/receiver-envelope-url?envelopeUuid={Uri.EscapeDataString(envelopeUuid)}&receiverSignature={Uri.EscapeDataString(receiverSignature)}";
var response = await http.GetAsync(url, cancel);
if (!response.IsSuccessStatusCode)
return null;
var payload = await response.Content.ReadFromJsonAsync<ReceiverEnvelopeUrlResponse>(_jsonOptions, cancel);
return payload?.Url;
}
public async Task<bool> GetReceiverEnvelopeUrlFeatureEnabledAsync(CancellationToken cancel = default)
{
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var response = await http.GetAsync("/api/EnvelopeReceiver/receiver-envelope-url/enabled", cancel);
if (!response.IsSuccessStatusCode)
return false;
var payload = await response.Content.ReadFromJsonAsync<ReceiverEnvelopeUrlEnabledResponse>(_jsonOptions, cancel);
return payload?.Enabled == true;
}
public async Task DeleteAsync(int envelopeId, int receiverId, CancellationToken cancel = default)
{
if (envelopeId <= 0)
throw new ArgumentOutOfRangeException(nameof(envelopeId));
if (receiverId <= 0)
throw new ArgumentOutOfRangeException(nameof(receiverId));
using var http = httpClientFactory.CreateClient("EnvelopeGenerator.Server");
var url = QueryHelpers.AddQueryString("/api/EnvelopeReceiver", new Dictionary<string, string?>
{
["EnvelopeId"] = envelopeId.ToString(),
["ReceiverId"] = receiverId.ToString()
});
var response = await http.DeleteAsync(url, cancel);
if (response.IsSuccessStatusCode)
return;
var body = await response.Content.ReadAsStringAsync(cancel);
var statusCode = (int)response.StatusCode;
var reasonPhrase = response.ReasonPhrase ?? "Unknown error";
throw new HttpRequestException(
$"Failed to remove receiver. Status: {statusCode} ({reasonPhrase}){(string.IsNullOrWhiteSpace(body) ? string.Empty : $" - {body}")}",
null,
response.StatusCode);
}
}