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.
125 lines
5.5 KiB
C#
125 lines
5.5 KiB
C#
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);
|
||
}
|
||
}
|