Add history display and enhance status handling
Introduced a "Historie" section in `EnvelopeSenderPage.razor` to display envelope history with status badges, actor info, and timestamps. Updated `ReadEnvelopeQueryHandler` to include histories in queries. Refactored `GetStatusInfo` to use localized labels and expanded supported statuses. Added helper methods for history processing and display. Enhanced UI with new styles for the history section in `sender-page.css` and improved responsive design. Added dependency injections for localization and history handling.
This commit is contained in:
@@ -150,8 +150,9 @@ public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnum
|
||||
|
||||
var envelopes = await query
|
||||
.Include(e => e.EnvelopeReceivers).ThenInclude(er => er.Receiver)
|
||||
.Include(e => e.Histories)
|
||||
.ToListAsync(cancel);
|
||||
|
||||
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
@using DevExpress.Blazor.PdfViewer
|
||||
@using EnvelopeGenerator.Server.Client.Services
|
||||
@using EnvelopeGenerator.Application.Common.Dto
|
||||
@using EnvelopeGenerator.Application.Common.Dto.History
|
||||
@using EnvelopeGenerator.Server.Services
|
||||
@using Microsoft.Extensions.Localization
|
||||
@inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService
|
||||
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
||||
@inject EnvelopeGenerator.Server.Client.Services.ThemeService ThemeService
|
||||
@@ -19,6 +21,7 @@
|
||||
@inject NavigationManager Navigation
|
||||
@inject IJSRuntime JSRuntime
|
||||
@inject AppVersionService AppVersion
|
||||
@inject IStringLocalizer<My.Resources.Model> ModelLocalizer
|
||||
|
||||
<link href="@AppVersion.GetVersionedUrl("css/envelope-viewer.css")" rel="stylesheet" />
|
||||
<link href="@AppVersion.GetVersionedUrl("css/sender-page.css")" rel="stylesheet" />
|
||||
@@ -329,6 +332,38 @@
|
||||
<p style="color: #9ca3af; font-size: 0.875rem; margin: 0;">Keine Empfänger</p>
|
||||
}
|
||||
}
|
||||
|
||||
<h6 style="font-weight: 600; color: #374151; margin: 1rem 0 0.75rem;">Historie</h6>
|
||||
@{
|
||||
var historyEntries = envelope is null
|
||||
? Enumerable.Empty<HistoryDto>()
|
||||
: GetOrderedHistories(envelope);
|
||||
if (historyEntries.Any())
|
||||
{
|
||||
<div class="sender-history-list">
|
||||
@foreach (var history in historyEntries)
|
||||
{
|
||||
var statusInfo = GetStatusInfo(history.Status);
|
||||
<div class="sender-history-item">
|
||||
<div class="sender-history-item__left">
|
||||
<div class="status-badge status-badge--@statusInfo.CssClass">
|
||||
<span class="status-dot status-dot--@statusInfo.DotColor"></span>
|
||||
@statusInfo.Label
|
||||
</div>
|
||||
<span class="sender-history-item__actor">@GetHistoryActor(history)</span>
|
||||
</div>
|
||||
<div class="sender-history-item__right">
|
||||
@GetHistoryDate(history).ToString("dd.MM.yyyy HH:mm")
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p style="color: #9ca3af; font-size: 0.875rem; margin: 0;">Keine Historie vorhanden</p>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</DetailRowTemplate>
|
||||
</DxGrid>
|
||||
@@ -451,6 +486,38 @@
|
||||
<p style="color: #9ca3af; font-size: 0.875rem; margin: 0;">Keine Empfänger</p>
|
||||
}
|
||||
}
|
||||
|
||||
<h6 style="font-weight: 600; color: #374151; margin: 1rem 0 0.75rem;">Historie</h6>
|
||||
@{
|
||||
var historyEntries = envelope is null
|
||||
? Enumerable.Empty<HistoryDto>()
|
||||
: GetOrderedHistories(envelope);
|
||||
if (historyEntries.Any())
|
||||
{
|
||||
<div class="sender-history-list">
|
||||
@foreach (var history in historyEntries)
|
||||
{
|
||||
var statusInfo = GetStatusInfo(history.Status);
|
||||
<div class="sender-history-item">
|
||||
<div class="sender-history-item__left">
|
||||
<div class="status-badge status-badge--@statusInfo.CssClass">
|
||||
<span class="status-dot status-dot--@statusInfo.DotColor"></span>
|
||||
@statusInfo.Label
|
||||
</div>
|
||||
<span class="sender-history-item__actor">@GetHistoryActor(history)</span>
|
||||
</div>
|
||||
<div class="sender-history-item__right">
|
||||
@GetHistoryDate(history).ToString("dd.MM.yyyy HH:mm")
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p style="color: #9ca3af; font-size: 0.875rem; margin: 0;">Keine Historie vorhanden</p>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
</DetailRowTemplate>
|
||||
</DxGrid>
|
||||
@@ -806,21 +873,59 @@
|
||||
|
||||
(string Label, string CssClass, string DotColor) GetStatusInfo(EnvelopeStatus status)
|
||||
{
|
||||
var label = GetStatusLabel(status);
|
||||
|
||||
return status switch
|
||||
{
|
||||
EnvelopeStatus.EnvelopePartlySigned => ("Teilweise unterschrieben", "partly-signed", "green"),
|
||||
EnvelopeStatus.EnvelopeQueued => ("In Warteschlange", "queued", "orange"),
|
||||
EnvelopeStatus.EnvelopeSent => ("Gesendet", "sent", "orange"),
|
||||
EnvelopeStatus.EnvelopeCompletelySigned => ("Vollständig unterschrieben", "completed", "green"),
|
||||
EnvelopeStatus.EnvelopeDeleted => ("Gelöscht", "deleted", "red"),
|
||||
EnvelopeStatus.EnvelopeRejected => ("Abgelehnt", "rejected", "red"),
|
||||
EnvelopeStatus.EnvelopeWithdrawn => ("Zurückgezogen", "withdrawn", "red"),
|
||||
EnvelopeStatus.EnvelopeCreated => ("Erstellt", "created", "blue"),
|
||||
EnvelopeStatus.EnvelopeSaved => ("Gespeichert", "saved", "blue"),
|
||||
_ => ("Unbekannt", "unknown", "blue")
|
||||
EnvelopeStatus.EnvelopePartlySigned => (label, "partly-signed", "green"),
|
||||
EnvelopeStatus.EnvelopeCompletelySigned => (label, "completed", "green"),
|
||||
EnvelopeStatus.DocumentSigned => (label, "partly-signed", "green"),
|
||||
EnvelopeStatus.MessageCompletionSent => (label, "completed", "green"),
|
||||
|
||||
EnvelopeStatus.EnvelopeQueued => (label, "queued", "orange"),
|
||||
EnvelopeStatus.EnvelopeSent => (label, "sent", "orange"),
|
||||
EnvelopeStatus.MessageInvitationSent => (label, "queued", "orange"),
|
||||
EnvelopeStatus.MessageAccessCodeSent => (label, "queued", "orange"),
|
||||
EnvelopeStatus.MessageConfirmationSent => (label, "queued", "orange"),
|
||||
|
||||
EnvelopeStatus.EnvelopeDeleted => (label, "deleted", "red"),
|
||||
EnvelopeStatus.EnvelopeRejected => (label, "rejected", "red"),
|
||||
EnvelopeStatus.EnvelopeWithdrawn => (label, "withdrawn", "red"),
|
||||
EnvelopeStatus.DocumentRejected => (label, "rejected", "red"),
|
||||
EnvelopeStatus.AccessCodeIncorrect => (label, "rejected", "red"),
|
||||
EnvelopeStatus.MessageDeletionSent => (label, "deleted", "red"),
|
||||
|
||||
_ => (label, "created", "blue")
|
||||
};
|
||||
}
|
||||
|
||||
string GetStatusLabel(EnvelopeStatus status)
|
||||
{
|
||||
var key = status.ToString();
|
||||
var localized = ModelLocalizer[key];
|
||||
return localized.ResourceNotFound ? key : localized.Value;
|
||||
}
|
||||
|
||||
IEnumerable<HistoryDto> GetOrderedHistories(EnvelopeDto envelope)
|
||||
{
|
||||
return (envelope.Histories ?? Enumerable.Empty<HistoryDto>())
|
||||
.OrderByDescending(GetHistoryDate)
|
||||
.Take(20);
|
||||
}
|
||||
|
||||
DateTime GetHistoryDate(HistoryDto history)
|
||||
{
|
||||
return history.ActionDate ?? history.AddedWhen;
|
||||
}
|
||||
|
||||
string GetHistoryActor(HistoryDto history)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(history.UserReference))
|
||||
return history.UserReference;
|
||||
|
||||
return "System";
|
||||
}
|
||||
|
||||
void OnCustomizeElement(GridCustomizeElementEventArgs e)
|
||||
{
|
||||
// Future: Add custom row coloring based on status if needed
|
||||
|
||||
@@ -381,6 +381,44 @@
|
||||
color: #c62828;
|
||||
}
|
||||
|
||||
.sender-history-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.sender-history-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
padding: 0.5rem;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #e5e7eb;
|
||||
}
|
||||
|
||||
.sender-history-item__left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sender-history-item__actor {
|
||||
color: #4b5563;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sender-history-item__right {
|
||||
color: #6b7280;
|
||||
font-size: 0.8rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@media (max-width: 1320px) {
|
||||
.sender-action-bar__inner {
|
||||
flex-wrap: wrap;
|
||||
|
||||
Reference in New Issue
Block a user