-
-
- @Configuration["ChapterSettings:Name"]
-
+
+
+
+ @Configuration["ChapterSettings:Name"]
+
+
+
+
+ @Configuration["ChapterSettings:Name"]
+
+
@Configuration["ChapterSettings:CompetitionYear"] Competition Year
@@ -25,7 +32,7 @@
Title="Events"
Count="@_eventCount"
Subtitle="Total Events"
- Caption="@($"{_individualEventsCount} Individual | {_teamEventsCount} Team")"
+ Caption="@($"{_teamEventsCount} Team | {_individualEventsCount} Individual")"
NavigateUrl="/events" />
@@ -51,6 +58,7 @@
Title="Teams"
Count="@_teamCount"
Subtitle="Total Teams"
+ Caption="@($"{_groupTeamsCount} Team | {_individualTeamsCount} Individual")"
NavigateUrl="/teams" />
@@ -67,6 +75,8 @@
private int _studentCount;
private string _gradeDistribution = "";
private int _teamCount;
+ private int _individualTeamsCount;
+ private int _groupTeamsCount;
protected override async Task OnInitializedAsync()
{
@@ -102,6 +112,9 @@
}
// Teams statistics
- _teamCount = await Context.Teams.CountAsync();
+ var contextTeams = await Context.Teams.ToListAsync();
+ _teamCount = contextTeams.Count;
+ _individualTeamsCount = contextTeams.Count(e => e.Event.EventFormat == EventFormat.Individual);
+ _groupTeamsCount = contextTeams.Count(e => e.Event.EventFormat == EventFormat.Team);
}
}
diff --git a/WebApp/Models/AppIcons.cs b/WebApp/Models/AppIcons.cs
index a97f166..f0e8917 100644
--- a/WebApp/Models/AppIcons.cs
+++ b/WebApp/Models/AppIcons.cs
@@ -16,9 +16,9 @@ namespace WebApp.Models
return loe switch
{
- 1 => "①",
- 2 => "②",
- 3 => "③",
+ 1 => "‧",
+ 2 => "⁚",
+ 3 => "⁝",
_ => Icons.Material.Filled.QuestionMark
};
}
@@ -31,6 +31,19 @@ namespace WebApp.Models
public static string PresentationEvent = "";
public static string QuestionMark = "❔";
+ // Tooltip mapping for icon unicode characters
+ public static Dictionary IconTooltips => new()
+ {
+ { OnSiteActivity, "On-Site Activity" },
+ { RegionalEvent, "Regional Event" },
+ { IndividualEvent, "Individual Event" },
+ { PresubmissionEvent, "Presubmission" },
+ { PresentationEvent, "Presentation/Interview" },
+ { "①", "Level of Effort: 1" },
+ { "②", "Level of Effort: 2" },
+ { "③", "Level of Effort: 3" }
+ };
+
public static string EventEffort(EventDefinition eventDefinition)
{
return LevelOfEffortIcon(eventDefinition.LevelOfEffort);
diff --git a/WebApp/Program.cs b/WebApp/Program.cs
index 1710056..14fa215 100644
--- a/WebApp/Program.cs
+++ b/WebApp/Program.cs
@@ -7,6 +7,7 @@ using System.Text.Json;
using WebApp;
using WebApp.Authentication;
using WebApp.Components;
+using WebApp.Logging;
var builder = WebApplication.CreateBuilder(args);
@@ -66,18 +67,32 @@ if (builder.Environment.IsProduction())
}
}
-// Configure Serilog
+// Configure Serilog with custom handling for antiforgery errors
builder.Host.UseSerilog((context, configuration) =>
- configuration
- .ReadFrom.Configuration(context.Configuration)
- .Enrich.FromLogContext()
- .WriteTo.Console(
- outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}")
+{
+ var consoleOutputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}";
+ var fileOutputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}";
+
+ // Create console logger with antiforgery error handling
+ var consoleConfig = new LoggerConfiguration()
+ .WriteTo.Console(outputTemplate: consoleOutputTemplate);
+ var consoleLogger = consoleConfig.CreateLogger();
+
+ // Create file logger with antiforgery error handling
+ var fileConfig = new LoggerConfiguration()
.WriteTo.File(
path: "logs/webapp-.txt",
rollingInterval: RollingInterval.Day,
retainedFileCountLimit: 30,
- outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj} {Properties:j}{NewLine}{Exception}"));
+ outputTemplate: fileOutputTemplate);
+ var fileLogger = fileConfig.CreateLogger();
+
+ configuration
+ .ReadFrom.Configuration(context.Configuration)
+ .Enrich.FromLogContext()
+ .WriteTo.Sink(new AntiforgeryLogEventSink(consoleLogger))
+ .WriteTo.Sink(new AntiforgeryLogEventSink(fileLogger));
+});
// Configure authentication secrets for production (Docker, etc.)
if (builder.Environment.IsProduction())