Update release notes and deploy workspace
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using Backend.Contracts;
|
||||
using Backend.Common;
|
||||
using Backend.Data;
|
||||
using Backend.Security;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
@@ -20,37 +21,39 @@ public static class AdminDashboardEndpoints
|
||||
return group;
|
||||
}
|
||||
|
||||
private static async Task<IResult> GetDashboard(AwardsDbContext db, HttpContext context)
|
||||
private static async Task<IResult> GetDashboard(int? seasonId, AwardsDbContext db, HttpContext context)
|
||||
{
|
||||
var canViewAuditIp = CanViewAuditIp(context);
|
||||
var currentSeason = await db.Seasons.AsNoTracking().FirstOrDefaultAsync(item => item.IsCurrent);
|
||||
if (currentSeason is null)
|
||||
var selectedSeason = seasonId.HasValue
|
||||
? await db.Seasons.AsNoTracking().FirstOrDefaultAsync(item => item.Id == seasonId.Value)
|
||||
: await db.Seasons.AsNoTracking().FirstOrDefaultAsync(item => item.IsCurrent);
|
||||
if (selectedSeason is null)
|
||||
{
|
||||
return Results.NotFound();
|
||||
}
|
||||
|
||||
var nominationCount = await db.Nominations.CountAsync(item => item.SeasonId == currentSeason.Id);
|
||||
var voteCount = await db.VoteEntries.CountAsync(item => item.Ballot.SeasonId == currentSeason.Id);
|
||||
var categoryCount = await db.Categories.CountAsync(item => item.SeasonId == currentSeason.Id);
|
||||
var reviewCount = await db.Nominations.CountAsync(item => item.SeasonId == currentSeason.Id && item.Status == "pending");
|
||||
var riskFlagCount = await db.RiskFlags.CountAsync(item => item.Status == "open");
|
||||
var selectedSeasonId = selectedSeason.Id;
|
||||
var phaseKey = SeasonMappings.NormalizePhaseKey(selectedSeason.CurrentPhase);
|
||||
var nominationCount = await db.Nominations.CountAsync(item => item.SeasonId == selectedSeasonId);
|
||||
var voteCount = await db.VoteEntries.CountAsync(item => item.Ballot.SeasonId == selectedSeasonId);
|
||||
var categoryCount = await db.Categories.CountAsync(item => item.SeasonId == selectedSeasonId);
|
||||
var reviewCount = await db.Nominations.CountAsync(item => item.SeasonId == selectedSeasonId && item.Status == "pending");
|
||||
var riskFlagCount = await db.RiskFlags.CountAsync(item =>
|
||||
item.Status == "open" &&
|
||||
(item.SeasonId == selectedSeasonId || item.SeasonId == null));
|
||||
var globalRiskFlagCount = await db.RiskFlags.CountAsync(item =>
|
||||
item.Status == "open" &&
|
||||
item.SeasonId == null);
|
||||
|
||||
var topCategoryNames = await db.VoteEntries
|
||||
.AsNoTracking()
|
||||
.Where(item => item.Ballot.SeasonId == currentSeason.Id)
|
||||
.Select(item => item.Category.Name)
|
||||
.ToListAsync();
|
||||
|
||||
var topCategories = topCategoryNames
|
||||
.GroupBy(name => name)
|
||||
.Select(grouping => new AdminTopCategoryDto(grouping.Key, grouping.Count()))
|
||||
.OrderByDescending(item => item.Votes)
|
||||
.Take(5)
|
||||
.ToArray();
|
||||
var topCategories = phaseKey == "nomination"
|
||||
? await BuildTopNominationCategoriesAsync(db, selectedSeasonId)
|
||||
: await BuildTopVotingCategoriesAsync(db, selectedSeasonId);
|
||||
|
||||
var riskFlags = await db.RiskFlags
|
||||
.AsNoTracking()
|
||||
.Where(item => item.Status == "open")
|
||||
.Where(item =>
|
||||
item.Status == "open" &&
|
||||
(item.SeasonId == selectedSeasonId || item.SeasonId == null))
|
||||
.OrderByDescending(item => item.CreatedAt)
|
||||
.Take(8)
|
||||
.ToArrayAsync();
|
||||
@@ -74,18 +77,27 @@ public static class AdminDashboardEndpoints
|
||||
.ToArrayAsync();
|
||||
|
||||
var activityItems = auditEntries
|
||||
.Take(3)
|
||||
.Take(6)
|
||||
.Select(item => new AdminActivityDto(item.Summary, $"{Math.Max(1, (int)Math.Round((DateTimeOffset.UtcNow - item.CreatedAt).TotalMinutes))} Min."))
|
||||
.ToArray();
|
||||
|
||||
return Results.Ok(new AdminDashboardResponse(
|
||||
selectedSeason.Id,
|
||||
selectedSeason.Year,
|
||||
selectedSeason.Name,
|
||||
selectedSeason.IsCurrent,
|
||||
new[]
|
||||
{
|
||||
new AdminMetricDto("Nominierungen", nominationCount, "Gespeicherte Einreichungen im aktuellen Public-Jahr"),
|
||||
new AdminMetricDto("Stimmen", voteCount, "Abgegebene Stimmen im aktuellen Public-Jahr"),
|
||||
new AdminMetricDto("Kategorien", categoryCount, "Aktive Kategorien im aktuellen Public-Jahr"),
|
||||
new AdminMetricDto("Reviews offen", reviewCount, "Offene Nominierungen mit Review-Bedarf"),
|
||||
new AdminMetricDto("Risikohinweise", riskFlagCount, "Offene Risk Flags ueber alle Quellen"),
|
||||
new AdminMetricDto("Nominierungen", nominationCount, $"Gespeicherte Einreichungen im Award-Jahr {selectedSeason.Year}"),
|
||||
new AdminMetricDto("Stimmen", voteCount, $"Abgegebene Stimmen im Award-Jahr {selectedSeason.Year}"),
|
||||
new AdminMetricDto("Kategorien", categoryCount, $"Aktive Kategorien im Award-Jahr {selectedSeason.Year}"),
|
||||
new AdminMetricDto("Reviews offen", reviewCount, "Offene Nominierungen mit Review-Bedarf in diesem Jahr"),
|
||||
new AdminMetricDto(
|
||||
"Risikohinweise",
|
||||
riskFlagCount,
|
||||
globalRiskFlagCount > 0
|
||||
? $"Offene Hinweise fuer {selectedSeason.Year}, inklusive {globalRiskFlagCount} globaler Hinweise"
|
||||
: $"Offene Hinweise fuer {selectedSeason.Year}"),
|
||||
},
|
||||
activityItems,
|
||||
topCategories,
|
||||
@@ -93,6 +105,45 @@ public static class AdminDashboardEndpoints
|
||||
auditEntries));
|
||||
}
|
||||
|
||||
private static async Task<AdminTopCategoryDto[]> BuildTopVotingCategoriesAsync(AwardsDbContext db, int seasonId)
|
||||
{
|
||||
var categoryNames = await db.VoteEntries
|
||||
.AsNoTracking()
|
||||
.Where(item => item.Ballot.SeasonId == seasonId)
|
||||
.Select(item => item.Category.Name)
|
||||
.ToListAsync();
|
||||
|
||||
return categoryNames
|
||||
.GroupBy(name => name)
|
||||
.Select(grouping => new AdminTopCategoryDto(grouping.Key, grouping.Count(), "Stimmen"))
|
||||
.OrderByDescending(item => item.Value)
|
||||
.Take(5)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static async Task<AdminTopCategoryDto[]> BuildTopNominationCategoriesAsync(AwardsDbContext db, int seasonId)
|
||||
{
|
||||
var nominationCategories = await db.Nominations
|
||||
.AsNoTracking()
|
||||
.Where(item => item.SeasonId == seasonId)
|
||||
.Select(item => new
|
||||
{
|
||||
CategoryName = item.Category != null ? item.Category.Name : null,
|
||||
item.CategoryGroupName,
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
return nominationCategories
|
||||
.Select(item => string.IsNullOrWhiteSpace(item.CategoryName)
|
||||
? string.IsNullOrWhiteSpace(item.CategoryGroupName) ? "Ohne Kategorie" : item.CategoryGroupName
|
||||
: item.CategoryName)
|
||||
.GroupBy(name => name)
|
||||
.Select(grouping => new AdminTopCategoryDto(grouping.Key, grouping.Count(), "Nominierungen"))
|
||||
.OrderByDescending(item => item.Value)
|
||||
.Take(5)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private static async Task<IResult> GetAuditEntries(
|
||||
int? limit,
|
||||
string? query,
|
||||
|
||||
Reference in New Issue
Block a user