diff --git a/src/AliasVault.Admin/Main/Pages/Emails.razor b/src/AliasVault.Admin/Main/Pages/Emails.razor index 21d33a74e..0cd61ee51 100644 --- a/src/AliasVault.Admin/Main/Pages/Emails.razor +++ b/src/AliasVault.Admin/Main/Pages/Emails.razor @@ -1,4 +1,5 @@ @page "/emails" +@using AliasVault.RazorComponents.Tables @inherits MainBase Emails @@ -6,7 +7,7 @@ + Description="This page gives an overview of recently received mails by this AliasVault server. Note that all email fields except 'To' are encrypted with the public key of the user and cannot be decrypted by the server."> @@ -21,59 +22,66 @@ else
- - - - - - - - - - + + @foreach (var email in EmailList) + { + + + + + + + + - - - @foreach (var email in EmailList) - { - - - - - - - - - - } - -
IDTimeFromToSubjectPreviewAttachments
+ @email.Id + + @email.DateSystem.ToString("yyyy-MM-dd HH:mm") + + @(email.FromLocal.Length > 15 ? email.FromLocal.Substring(0, 15) : email.FromLocal)@@@(email.FromDomain.Length > 15 ? email.FromDomain.Substring(0, 15) : email.FromDomain) + + @email.ToLocal@@@email.ToDomain + + @(email.Subject.Length > 30 ? email.Subject.Substring(0, 30) : email.Subject) + + + @(email.MessagePreview?.Length > 30 ? email.MessagePreview.Substring(0, 30) : email.MessagePreview) + + + @email.Attachments.Count +
- @email.Id - - @email.DateSystem.ToString("yyyy-MM-dd HH:mm") - - @(email.FromLocal.Length > 15 ? email.FromLocal.Substring(0, 15) : email.FromLocal)@@@(email.FromDomain.Length > 15 ? email.FromDomain.Substring(0, 15) : email.FromDomain) - - @email.ToLocal@@@email.ToDomain - - @(email.Subject.Length > 30 ? email.Subject.Substring(0, 30) : email.Subject) - - - @(email.MessagePreview?.Length > 30 ? email.MessagePreview.Substring(0, 30) : email.MessagePreview) - - - @email.Attachments.Count -
+ } +
} @code { + private readonly List _tableColumns = [ + new TableColumn { Title = "ID", PropertyName = "Id" }, + new TableColumn { Title = "Time", PropertyName = "DateSystem" }, + new TableColumn { Title = "From", PropertyName = "From" }, + new TableColumn { Title = "To", PropertyName = "To" }, + new TableColumn { Title = "Subject", PropertyName = "Subject" }, + new TableColumn { Title = "Preview", PropertyName = "MessagePreview" }, + new TableColumn { Title = "Attachments", PropertyName = "Attachments" }, + ]; + private List EmailList { get; set; } = []; private bool IsLoading { get; set; } = true; private int CurrentPage { get; set; } = 1; private int PageSize { get; set; } = 50; private int TotalRecords { get; set; } + private string SortColumn { get; set; } = "Id"; + private SortDirection SortDirection { get; set; } = SortDirection.Descending; + + private async Task HandleSortChanged((string column, SortDirection direction) sort) + { + SortColumn = sort.column; + SortDirection = sort.direction; + await RefreshData(); + } + /// protected override async Task OnAfterRenderAsync(bool firstRender) { @@ -94,9 +102,53 @@ else IsLoading = true; StateHasChanged(); - TotalRecords = await DbContext.Emails.CountAsync(); - EmailList = await DbContext.Emails - .OrderByDescending(x => x.DateSystem) + IQueryable query = DbContext.Emails; + + // Apply sort + switch (SortColumn) + { + case "Id": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Id) + : query.OrderByDescending(x => x.Id); + break; + case "DateSystem": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.DateSystem) + : query.OrderByDescending(x => x.DateSystem); + break; + case "From": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.FromLocal + "@" + x.FromDomain) + : query.OrderByDescending(x => x.FromLocal + "@" + x.FromDomain); + break; + case "To": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.ToLocal + "@" + x.ToDomain) + : query.OrderByDescending(x => x.ToLocal + "@" + x.ToDomain); + break; + case "Subject": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Subject) + : query.OrderByDescending(x => x.Subject); + break; + case "MessagePreview": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.MessagePreview) + : query.OrderByDescending(x => x.MessagePreview); + break; + case "Attachments": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Attachments.Count) + : query.OrderByDescending(x => x.Attachments.Count); + break; + default: + query = query.OrderByDescending(x => x.DateSystem); + break; + } + + TotalRecords = await query.CountAsync(); + EmailList = await query .Skip((CurrentPage - 1) * PageSize) .Take(PageSize) .ToListAsync(); diff --git a/src/AliasVault.Admin/Main/Pages/Users/Users.razor b/src/AliasVault.Admin/Main/Pages/Users/Users.razor index 1063b4957..6041ef9a1 100644 --- a/src/AliasVault.Admin/Main/Pages/Users/Users.razor +++ b/src/AliasVault.Admin/Main/Pages/Users/Users.razor @@ -1,4 +1,5 @@ @page "/users" +@using AliasVault.RazorComponents.Tables @inherits MainBase Users @@ -24,43 +25,40 @@ else
- - - - - - - - - - - - - - - - @foreach (var user in UserList) - { - - - - - - - - - - - - } - -
IDRegisteredUsername# Vaults# Email claimsStorage2FALast vault updateActions
@user.Id@user.CreatedAt.ToString("yyyy-MM-dd HH:mm")@user.UserName@user.VaultCount@user.EmailClaimCount@Math.Round((double)user.VaultStorageInKb / 1024, 1) MB@user.LastVaultUpdate.ToString("yyyy-MM-dd HH:mm") - -
+ + + @foreach (var user in UserList) + { + + @user.Id + @user.CreatedAt.ToString("yyyy-MM-dd HH:mm") + @user.UserName + @user.VaultCount + @user.EmailClaimCount + @Math.Round((double)user.VaultStorageInKb / 1024, 1) MB + + @user.LastVaultUpdate.ToString("yyyy-MM-dd HH:mm") + + + + + } + } @code { + private readonly List _tableColumns = [ + new TableColumn { Title = "ID", PropertyName = "Id" }, + new TableColumn { Title = "Registered", PropertyName = "CreatedAt" }, + new TableColumn { Title = "Username", PropertyName = "UserName" }, + new TableColumn { Title = "# Vaults", PropertyName = "VaultCount" }, + new TableColumn { Title = "# Email claims", PropertyName = "EmailClaimCount" }, + new TableColumn { Title = "Storage", PropertyName = "VaultStorageInKb" }, + new TableColumn { Title = "2FA", PropertyName = "TwoFactorEnabled" }, + new TableColumn { Title = "LastVaultUpdate", PropertyName = "LastVaultUpdate" }, + ]; + private List UserList { get; set; } = []; private bool IsLoading { get; set; } = true; private int CurrentPage { get; set; } = 1; @@ -81,6 +79,16 @@ else } } + private string SortColumn { get; set; } = "CreatedAt"; + private SortDirection SortDirection { get; set; } = SortDirection.Descending; + + private async Task HandleSortChanged((string column, SortDirection direction) sort) + { + SortColumn = sort.column; + SortDirection = sort.direction; + await RefreshData(); + } + /// protected override async Task OnAfterRenderAsync(bool firstRender) { @@ -108,10 +116,59 @@ else query = query.Where(x => EF.Functions.Like(x.UserName!.ToLower(), "%" + SearchTerm.ToLower() + "%")); } + // Apply sort. + switch (SortColumn) + { + case "Id": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Id) + : query.OrderByDescending(x => x.Id); + break; + case "CreatedAt": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.CreatedAt) + : query.OrderByDescending(x => x.CreatedAt); + break; + case "UserName": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.UserName) + : query.OrderByDescending(x => x.UserName); + break; + case "VaultCount": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Vaults.Count()) + : query.OrderByDescending(x => x.Vaults.Count()); + break; + case "EmailClaimCount": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.EmailClaims.Count()) + : query.OrderByDescending(x => x.EmailClaims.Count()); + break; + case "VaultStorageInKb": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Vaults.Sum(v => v.FileSize)) + : query.OrderByDescending(x => x.Vaults.Sum(v => v.FileSize)); + break; + case "TwoFactorEnabled": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.TwoFactorEnabled) + : query.OrderByDescending(x => x.TwoFactorEnabled); + break; + case "LastVaultUpdate": + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Vaults.Max(v => v.CreatedAt)) + : query.OrderByDescending(x => x.Vaults.Max(v => v.CreatedAt)); + break; + default: + query = SortDirection == SortDirection.Ascending + ? query.OrderBy(x => x.Id) + : query.OrderByDescending(x => x.Id); + break; + } + TotalRecords = await query.CountAsync(); var users = await query - .OrderBy(x => x.CreatedAt) .Skip((CurrentPage - 1) * PageSize) .Take(PageSize) .Select(u => new