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,6 +150,7 @@ public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnum
|
|||||||
|
|
||||||
var envelopes = await query
|
var envelopes = await query
|
||||||
.Include(e => e.EnvelopeReceivers).ThenInclude(er => er.Receiver)
|
.Include(e => e.EnvelopeReceivers).ThenInclude(er => er.Receiver)
|
||||||
|
.Include(e => e.Histories)
|
||||||
.ToListAsync(cancel);
|
.ToListAsync(cancel);
|
||||||
|
|
||||||
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
|
||||||
|
|||||||
@@ -7,7 +7,9 @@
|
|||||||
@using DevExpress.Blazor.PdfViewer
|
@using DevExpress.Blazor.PdfViewer
|
||||||
@using EnvelopeGenerator.Server.Client.Services
|
@using EnvelopeGenerator.Server.Client.Services
|
||||||
@using EnvelopeGenerator.Application.Common.Dto
|
@using EnvelopeGenerator.Application.Common.Dto
|
||||||
|
@using EnvelopeGenerator.Application.Common.Dto.History
|
||||||
@using EnvelopeGenerator.Server.Services
|
@using EnvelopeGenerator.Server.Services
|
||||||
|
@using Microsoft.Extensions.Localization
|
||||||
@inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService
|
@inject EnvelopeGenerator.Server.Client.Services.EnvelopeService EnvelopeService
|
||||||
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
@inject EnvelopeGenerator.Server.Client.Services.AuthService AuthService
|
||||||
@inject EnvelopeGenerator.Server.Client.Services.ThemeService ThemeService
|
@inject EnvelopeGenerator.Server.Client.Services.ThemeService ThemeService
|
||||||
@@ -19,6 +21,7 @@
|
|||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject IJSRuntime JSRuntime
|
@inject IJSRuntime JSRuntime
|
||||||
@inject AppVersionService AppVersion
|
@inject AppVersionService AppVersion
|
||||||
|
@inject IStringLocalizer<My.Resources.Model> ModelLocalizer
|
||||||
|
|
||||||
<link href="@AppVersion.GetVersionedUrl("css/envelope-viewer.css")" rel="stylesheet" />
|
<link href="@AppVersion.GetVersionedUrl("css/envelope-viewer.css")" rel="stylesheet" />
|
||||||
<link href="@AppVersion.GetVersionedUrl("css/sender-page.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>
|
<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>
|
</div>
|
||||||
</DetailRowTemplate>
|
</DetailRowTemplate>
|
||||||
</DxGrid>
|
</DxGrid>
|
||||||
@@ -451,6 +486,38 @@
|
|||||||
<p style="color: #9ca3af; font-size: 0.875rem; margin: 0;">Keine Empfänger</p>
|
<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>
|
</div>
|
||||||
</DetailRowTemplate>
|
</DetailRowTemplate>
|
||||||
</DxGrid>
|
</DxGrid>
|
||||||
@@ -806,21 +873,59 @@
|
|||||||
|
|
||||||
(string Label, string CssClass, string DotColor) GetStatusInfo(EnvelopeStatus status)
|
(string Label, string CssClass, string DotColor) GetStatusInfo(EnvelopeStatus status)
|
||||||
{
|
{
|
||||||
|
var label = GetStatusLabel(status);
|
||||||
|
|
||||||
return status switch
|
return status switch
|
||||||
{
|
{
|
||||||
EnvelopeStatus.EnvelopePartlySigned => ("Teilweise unterschrieben", "partly-signed", "green"),
|
EnvelopeStatus.EnvelopePartlySigned => (label, "partly-signed", "green"),
|
||||||
EnvelopeStatus.EnvelopeQueued => ("In Warteschlange", "queued", "orange"),
|
EnvelopeStatus.EnvelopeCompletelySigned => (label, "completed", "green"),
|
||||||
EnvelopeStatus.EnvelopeSent => ("Gesendet", "sent", "orange"),
|
EnvelopeStatus.DocumentSigned => (label, "partly-signed", "green"),
|
||||||
EnvelopeStatus.EnvelopeCompletelySigned => ("Vollständig unterschrieben", "completed", "green"),
|
EnvelopeStatus.MessageCompletionSent => (label, "completed", "green"),
|
||||||
EnvelopeStatus.EnvelopeDeleted => ("Gelöscht", "deleted", "red"),
|
|
||||||
EnvelopeStatus.EnvelopeRejected => ("Abgelehnt", "rejected", "red"),
|
EnvelopeStatus.EnvelopeQueued => (label, "queued", "orange"),
|
||||||
EnvelopeStatus.EnvelopeWithdrawn => ("Zurückgezogen", "withdrawn", "red"),
|
EnvelopeStatus.EnvelopeSent => (label, "sent", "orange"),
|
||||||
EnvelopeStatus.EnvelopeCreated => ("Erstellt", "created", "blue"),
|
EnvelopeStatus.MessageInvitationSent => (label, "queued", "orange"),
|
||||||
EnvelopeStatus.EnvelopeSaved => ("Gespeichert", "saved", "blue"),
|
EnvelopeStatus.MessageAccessCodeSent => (label, "queued", "orange"),
|
||||||
_ => ("Unbekannt", "unknown", "blue")
|
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)
|
void OnCustomizeElement(GridCustomizeElementEventArgs e)
|
||||||
{
|
{
|
||||||
// Future: Add custom row coloring based on status if needed
|
// Future: Add custom row coloring based on status if needed
|
||||||
|
|||||||
@@ -381,6 +381,44 @@
|
|||||||
color: #c62828;
|
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) {
|
@media (max-width: 1320px) {
|
||||||
.sender-action-bar__inner {
|
.sender-action-bar__inner {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
Reference in New Issue
Block a user