Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87db67f979 | ||
|
|
2aaefb2491 |
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Paste Event Occurrence Data</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Paste Event Occurrence Data</MudText>
|
||||||
<MudStack Spacing="3">
|
<MudStack Spacing="3">
|
||||||
<MudTextField
|
<MudTextField
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
</MudItem>
|
</MudItem>
|
||||||
|
|
||||||
<MudItem xs="12" md="6">
|
<MudItem xs="12" md="6">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Parsed Results</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Parsed Results</MudText>
|
||||||
|
|
||||||
@if (_isParsing)
|
@if (_isParsing)
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
@using WebApp.Models
|
@using WebApp.Models
|
||||||
@using WebApp.Services
|
@using WebApp.Services
|
||||||
@using Heron.MudCalendar
|
@using Heron.MudCalendar
|
||||||
|
@using Microsoft.Extensions.Logging
|
||||||
@inject IEventOccurrenceService EventOccurrenceService
|
@inject IEventOccurrenceService EventOccurrenceService
|
||||||
|
@inject ILogger<Index> Logger
|
||||||
|
|
||||||
<PageHeader Title="Event Calendar" Description="View competition schedules and event occurrences" Icon="@AppIcons.EventCalendar">
|
<PageHeader Title="Event Calendar" Description="View competition schedules and event occurrences" Icon="@AppIcons.EventCalendar">
|
||||||
<ActionButtons>
|
<ActionButtons>
|
||||||
@@ -12,7 +14,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
@if (_calendarItems == null)
|
@if (_calendarItems == null)
|
||||||
{
|
{
|
||||||
<MudProgressLinear Indeterminate="true" />
|
<MudProgressLinear Indeterminate="true" />
|
||||||
@@ -23,7 +25,7 @@
|
|||||||
<MudCalendar T="CalendarEventItem"
|
<MudCalendar T="CalendarEventItem"
|
||||||
Items="_calendarItems"
|
Items="_calendarItems"
|
||||||
View="CalendarView.Day"
|
View="CalendarView.Day"
|
||||||
CurrentDay=_calendarDate
|
CurrentDay="@_calendarDate"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
@@ -39,29 +41,115 @@
|
|||||||
|
|
||||||
private async Task LoadCalendarEvents()
|
private async Task LoadCalendarEvents()
|
||||||
{
|
{
|
||||||
var occurrences = await EventOccurrenceService.GetEventOccurrencesAsync();
|
try
|
||||||
_calendarItems = occurrences
|
{
|
||||||
.Select(occ => new CalendarEventItem(occ))
|
Logger.LogInformation("Loading calendar events");
|
||||||
.ToList();
|
var occurrences = await EventOccurrenceService.GetEventOccurrencesAsync();
|
||||||
|
|
||||||
// Find the next date with events
|
if (occurrences == null)
|
||||||
_calendarDate = GetNextDateWithEvents();
|
{
|
||||||
|
Logger.LogWarning("Service returned null occurrences");
|
||||||
|
_calendarItems = new List<CalendarEventItem>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.LogDebug("Received {Count} occurrences from service", occurrences.Count());
|
||||||
|
|
||||||
|
var items = new List<CalendarEventItem>();
|
||||||
|
foreach (var occ in occurrences)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (occ == null)
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Null occurrence found, skipping");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(occ.Name))
|
||||||
|
{
|
||||||
|
Logger.LogWarning("Occurrence with Id={Id} has null or empty Name", occ.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
var calendarItem = new CalendarEventItem(occ, occ.EventDefinition);
|
||||||
|
items.Add(calendarItem);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "Error creating CalendarEventItem for occurrence Id={Id}, Name={Name}",
|
||||||
|
occ?.Id, occ?.Name);
|
||||||
|
// Continue processing other items
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_calendarItems = items;
|
||||||
|
Logger.LogInformation("Created {Count} calendar items from {OccurrenceCount} occurrences",
|
||||||
|
_calendarItems.Count, occurrences.Count());
|
||||||
|
|
||||||
|
// Find the next date with events
|
||||||
|
_calendarDate = GetNextDateWithEvents();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "Error loading calendar events");
|
||||||
|
_calendarItems = new List<CalendarEventItem>();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime GetNextDateWithEvents()
|
private DateTime GetNextDateWithEvents()
|
||||||
{
|
{
|
||||||
if (_calendarItems == null || !_calendarItems.Any())
|
try
|
||||||
{
|
{
|
||||||
|
if (_calendarItems == null || !_calendarItems.Any())
|
||||||
|
{
|
||||||
|
Logger.LogDebug("No calendar items available, returning today's date");
|
||||||
|
return DateTime.Today;
|
||||||
|
}
|
||||||
|
|
||||||
|
var today = DateTime.Today;
|
||||||
|
var nextEvent = _calendarItems
|
||||||
|
.Where(item =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return item != null && item.Start.Date >= today;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogWarning(ex, "Error checking item date, skipping item");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.OrderBy(item => item.Start)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (nextEvent != null)
|
||||||
|
{
|
||||||
|
return nextEvent.Start.Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback to first event if no future events
|
||||||
|
var firstEvent = _calendarItems
|
||||||
|
.Where(item => item != null)
|
||||||
|
.OrderBy(item => item.Start)
|
||||||
|
.FirstOrDefault();
|
||||||
|
|
||||||
|
if (firstEvent != null)
|
||||||
|
{
|
||||||
|
return firstEvent.Start.Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DateTime.Today;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError(ex, "Error in GetNextDateWithEvents");
|
||||||
return DateTime.Today;
|
return DateTime.Today;
|
||||||
}
|
}
|
||||||
|
|
||||||
var today = DateTime.Today;
|
|
||||||
var nextEvent = _calendarItems
|
|
||||||
.Where(item => item.Start.Date >= today)
|
|
||||||
.OrderBy(item => item.Start)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
return nextEvent?.Start.Date ?? _calendarItems.OrderBy(item => item.Start).First().Start.Date;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,14 @@
|
|||||||
|
|
||||||
@if (_isLoading)
|
@if (_isLoading)
|
||||||
{
|
{
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudProgressLinear Indeterminate="true" Color="Color.Primary"/>
|
<MudProgressLinear Indeterminate="true" Color="Color.Primary"/>
|
||||||
<MudText Typo="Typo.body1" Class="mt-4">Loading career mapping data...</MudText>
|
<MudText Typo="Typo.body1" Class="mt-4">Loading career mapping data...</MudText>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
}
|
}
|
||||||
else if (_networkData == null || !_networkData.Nodes.Any())
|
else if (_networkData == null || !_networkData.Nodes.Any())
|
||||||
{
|
{
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h6" Class="mb-4">No Career Field Mappings Found</MudText>
|
<MudText Typo="Typo.h6" Class="mb-4">No Career Field Mappings Found</MudText>
|
||||||
<MudText Typo="Typo.body1" Class="mud-text-secondary">
|
<MudText Typo="Typo.body1" Class="mud-text-secondary">
|
||||||
No events have related careers assigned that match any career fields. Edit events to add related careers.
|
No events have related careers assigned that match any career fields. Edit events to add related careers.
|
||||||
@@ -30,7 +30,7 @@ else if (_networkData == null || !_networkData.Nodes.Any())
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h6" Class="mb-4">Event-Career Field Relationships</MudText>
|
<MudText Typo="Typo.h6" Class="mb-4">Event-Career Field Relationships</MudText>
|
||||||
<MudText Typo="Typo.body2" Class="mb-4 mud-text-secondary">
|
<MudText Typo="Typo.body2" Class="mb-4 mud-text-secondary">
|
||||||
This diagram shows the connections between events and their related career fields.
|
This diagram shows the connections between events and their related career fields.
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<ValidationErrorDisplay Errors="_validationErrors" />
|
<ValidationErrorDisplay Errors="_validationErrors" />
|
||||||
|
|
||||||
<MudStack Spacing="4">
|
<MudStack Spacing="4">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12" sm="6">
|
<MudItem xs="12" sm="6">
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12" sm="6" md="4">
|
<MudItem xs="12" sm="6" md="4">
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<ValidationErrorDisplay Errors="_validationErrors" />
|
<ValidationErrorDisplay Errors="_validationErrors" />
|
||||||
|
|
||||||
<MudStack Spacing="4">
|
<MudStack Spacing="4">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Basic Information</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12" sm="6">
|
<MudItem xs="12" sm="6">
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Event Details</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Team Configuration</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
@@ -95,7 +95,7 @@
|
|||||||
</MudGrid>
|
</MudGrid>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Competition Details</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12">
|
<MudItem xs="12">
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudDataGrid T="EventDefinition"
|
<MudDataGrid T="EventDefinition"
|
||||||
ServerData="ServerReload"
|
ServerData="ServerReload"
|
||||||
@ref="_dataGrid"
|
@ref="_dataGrid"
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
|
|
||||||
<PageHeader Title="@($"{Configuration["ChapterSettings:Shortname"]} TSA Schedule {Configuration["ChapterSettings:CompetitionYear"]}")" />
|
<PageHeader Title="@($"{Configuration["ChapterSettings:Shortname"]} TSA Schedule {Configuration["ChapterSettings:CompetitionYear"]}")" />
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6 mt-4">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="7" sm="8" lg="9">
|
<MudItem xs="12" sm="8" lg="9">
|
||||||
<MudText Typo="Typo.h4">Time Slots</MudText>
|
<MudText Typo="Typo.h4">Time Slots</MudText>
|
||||||
<MudPaper Class="pa-2 ma-2" Elevation="3">
|
<MudPaper Class="pa-2 ma-2" Elevation="3">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
</RowTemplate>
|
</RowTemplate>
|
||||||
</MudTable>
|
</MudTable>
|
||||||
</MudItem>
|
</MudItem>
|
||||||
<MudItem xs="5" sm="4" lg="3">
|
<MudItem xs="12" sm="4" lg="3">
|
||||||
<MudStack>
|
<MudStack>
|
||||||
<StudentTextBoxSelector Students="@_students"
|
<StudentTextBoxSelector Students="@_students"
|
||||||
SelectedStudents="_absentStudents"
|
SelectedStudents="_absentStudents"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<ValidationErrorDisplay Errors="_validationErrors" />
|
<ValidationErrorDisplay Errors="_validationErrors" />
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Student Information</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Student Information</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12" sm="6">
|
<MudItem xs="12" sm="6">
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Student Information</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Student Information</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12" sm="6" md="4">
|
<MudItem xs="12" sm="6" md="4">
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12" sm="7">
|
<MudItem xs="12" sm="7">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudTextField T="string" Label="First Name" @bind-Value="Student.FirstName" For="@(() => Student.FirstName)"></MudTextField>
|
<MudTextField T="string" Label="First Name" @bind-Value="Student.FirstName" For="@(() => Student.FirstName)"></MudTextField>
|
||||||
<MudTextField T="string" Label="Last Name" @bind-Value="Student.LastName" For="@(() => Student.LastName)"></MudTextField>
|
<MudTextField T="string" Label="Last Name" @bind-Value="Student.LastName" For="@(() => Student.LastName)"></MudTextField>
|
||||||
<MudTextField T="string" Label="Email Adress" @bind-Value="Student.Email" For="@(() => Student.Email)"></MudTextField>
|
<MudTextField T="string" Label="Email Adress" @bind-Value="Student.Email" For="@(() => Student.Email)"></MudTextField>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudStack Spacing="4">
|
<MudStack Spacing="4">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Students by Rank</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Students by Rank</MudText>
|
||||||
<MudTable Items="_students" Hover="true" Striped="true" Breakpoint="Breakpoint.Sm" LoadingProgressColor="Color.Info">
|
<MudTable Items="_students" Hover="true" Striped="true" Breakpoint="Breakpoint.Sm" LoadingProgressColor="Color.Info">
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
@@ -64,7 +64,7 @@ else
|
|||||||
</MudTable>
|
</MudTable>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Events by Student</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Events by Student</MudText>
|
||||||
<MudTable Items="_eventStudentRankings" Hover="true" Striped="true" Breakpoint="Breakpoint.Sm" LoadingProgressColor="Color.Info">
|
<MudTable Items="_eventStudentRankings" Hover="true" Striped="true" Breakpoint="Breakpoint.Sm" LoadingProgressColor="Color.Info">
|
||||||
<HeaderContent>
|
<HeaderContent>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudDataGrid T="Student"
|
<MudDataGrid T="Student"
|
||||||
ServerData="ServerReload"
|
ServerData="ServerReload"
|
||||||
@ref="_dataGrid"
|
@ref="_dataGrid"
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<PropertyColumn Property="@(e => e.LastName)" Title="Name" Sortable="true">
|
<PropertyColumn Property="@(e => e.LastName)" Title="Name" Sortable="true">
|
||||||
<CellTemplate>
|
<CellTemplate>
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Spacing="1">
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
<div class="d-flex align-center flex-wrap" style="gap: 0.25rem;">
|
||||||
<MudLink Href="@($"/students/details?id={context.Item.Id}&returnUrl=/students")"
|
<MudLink Href="@($"/students/details?id={context.Item.Id}&returnUrl=/students")"
|
||||||
Underline="Underline.Hover"
|
Underline="Underline.Hover"
|
||||||
Color="Color.Primary">
|
Color="Color.Primary">
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
{
|
{
|
||||||
<MudChip T="string" Size="Size.Small" Icon="@(AppIcons.OfficerRoleIcon(context.Item.OfficerRole.Value))">@context.Item.OfficerRole</MudChip>
|
<MudChip T="string" Size="Size.Small" Icon="@(AppIcons.OfficerRoleIcon(context.Item.OfficerRole.Value))">@context.Item.OfficerRole</MudChip>
|
||||||
}
|
}
|
||||||
</MudStack>
|
</div>
|
||||||
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
||||||
<IconButtonWithTooltip Icon="@Icons.Material.Filled.Edit"
|
<IconButtonWithTooltip Icon="@Icons.Material.Filled.Edit"
|
||||||
TooltipText="Edit"
|
TooltipText="Edit"
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.body2" Class="mb-2">
|
<MudText Typo="Typo.body2" Class="mb-2">
|
||||||
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" /> = Team Captain
|
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" /> = Team Captain
|
||||||
</MudText>
|
</MudText>
|
||||||
@@ -78,8 +78,9 @@
|
|||||||
var teamsToDisplay = _showRegionalOnly
|
var teamsToDisplay = _showRegionalOnly
|
||||||
? context.Item.Teams.Where(t => t?.Event is { RegionalEvent: true }).OrderBy(t => t.Event.Name)
|
? context.Item.Teams.Where(t => t?.Event is { RegionalEvent: true }).OrderBy(t => t.Event.Name)
|
||||||
: context.Item.Teams.Where(t => t?.Event != null).OrderBy(t => t.Event.Name);
|
: context.Item.Teams.Where(t => t?.Event != null).OrderBy(t => t.Event.Name);
|
||||||
|
}
|
||||||
foreach (var team in teamsToDisplay)
|
<div class="d-flex flex-wrap" style="gap: 0.25rem;">
|
||||||
|
@foreach (var team in teamsToDisplay)
|
||||||
{
|
{
|
||||||
var isCaptain = team.Captain != null && team.Captain.Equals(context.Item.Student);
|
var isCaptain = team.Captain != null && team.Captain.Equals(context.Item.Student);
|
||||||
var teamMembers = string.Join(", ", team.Students.Select(s => s.FirstName));
|
var teamMembers = string.Join(", ", team.Students.Select(s => s.FirstName));
|
||||||
@@ -97,7 +98,7 @@
|
|||||||
</MudChip>
|
</MudChip>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
}
|
}
|
||||||
}
|
</div>
|
||||||
</CellTemplate>
|
</CellTemplate>
|
||||||
</TemplateColumn>
|
</TemplateColumn>
|
||||||
</Columns>
|
</Columns>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6 mt-4">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem Style="width:160px;">
|
<MudItem Style="width:160px;">
|
||||||
<MudNumericField @bind-Value="_parameters.TeamSizeLimit"
|
<MudNumericField @bind-Value="_parameters.TeamSizeLimit"
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
<MudButton Class="ma-3" OnClick="Solve" Variant="Variant.Filled" Color="Color.Primary" Disabled="@_isSolving">Solve</MudButton>
|
<MudButton Class="ma-3" OnClick="Solve" Variant="Variant.Filled" Color="Color.Primary" Disabled="@_isSolving">Solve</MudButton>
|
||||||
</MudPaper>
|
</MudPaper>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6 mt-4">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12" lg="8">
|
<MudItem xs="12" lg="8">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Students</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Students</MudText>
|
||||||
|
|||||||
@@ -1,35 +1,37 @@
|
|||||||
@using WebApp.Models
|
@using WebApp.Models
|
||||||
@foreach (var student in
|
<div class="d-flex flex-wrap" style="gap: 0.25rem;">
|
||||||
Team.Students
|
@foreach (var student in
|
||||||
.OrderBy(e =>
|
Team.Students
|
||||||
e.EventRankings
|
.OrderBy(e =>
|
||||||
.Find(er => er.EventDefinition == Team.Event)?.Rank ?? 10)
|
e.EventRankings
|
||||||
.ThenBy(s => s.Grade + s.TsaYear))
|
.Find(er => er.EventDefinition == Team.Event)?.Rank ?? 10)
|
||||||
{
|
.ThenBy(s => s.Grade + s.TsaYear))
|
||||||
var eventRank =
|
{
|
||||||
student.EventRankings
|
var eventRank =
|
||||||
.Find(e => e.EventDefinition == Team.Event)?.Rank;
|
student.EventRankings
|
||||||
var color = AppIcons.RankedEventColor(eventRank ?? 0);
|
.Find(e => e.EventDefinition == Team.Event)?.Rank;
|
||||||
var captain = Team.Captain != null && Team.Captain.Equals(student);
|
var color = AppIcons.RankedEventColor(eventRank ?? 0);
|
||||||
var rankLabel = eventRank.HasValue ? $"Rank {eventRank}" : "Unranked";
|
var captain = Team.Captain != null && Team.Captain.Equals(student);
|
||||||
|
var rankLabel = eventRank.HasValue ? $"Rank {eventRank}" : "Unranked";
|
||||||
|
|
||||||
<MudTooltip Text="@rankLabel">
|
<MudTooltip Text="@rankLabel">
|
||||||
<MudChip T="string"
|
<MudChip T="string"
|
||||||
Size="Size.Medium"
|
Size="Size.Medium"
|
||||||
Variant="Variant.Outlined"
|
Variant="Variant.Outlined"
|
||||||
Class="mx-1 my-1">
|
Class="mx-1 my-1">
|
||||||
@if (eventRank.HasValue)
|
@if (eventRank.HasValue)
|
||||||
{
|
{
|
||||||
<span style="@($"display: inline-block; width: 12px; height: 12px; border-radius: 50%; background-color: {color}; margin-right: 6px;")")></span>
|
<span style="@($"display: inline-block; width: 12px; height: 12px; border-radius: 50%; background-color: {color}; margin-right: 6px;")")"></span>
|
||||||
}
|
}
|
||||||
@student.FirstName
|
@student.FirstName
|
||||||
@if (captain && Team.Event.EventFormat != EventFormat.Individual)
|
@if (captain && Team.Event.EventFormat != EventFormat.Individual)
|
||||||
{
|
{
|
||||||
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" Style="margin-left: 4px;" />
|
<MudIcon Icon="@AppIcons.Captain" Size="Size.Small" Style="margin-left: 4px;" />
|
||||||
}
|
}
|
||||||
</MudChip>
|
</MudChip>
|
||||||
</MudTooltip>
|
</MudTooltip>
|
||||||
}
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12" sm="7">
|
<MudItem xs="12" sm="7">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudSelect T="EventDefinition" Value="@Team.Event" ValueChanged="OnEventChanged" Label="Event">
|
<MudSelect T="EventDefinition" Value="@Team.Event" ValueChanged="OnEventChanged" Label="Event">
|
||||||
|
|
||||||
@foreach (var evt in _events)
|
@foreach (var evt in _events)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudText Typo="Typo.h5" Class="mb-4">Team Information</MudText>
|
<MudText Typo="Typo.h5" Class="mb-4">Team Information</MudText>
|
||||||
<MudGrid Spacing="3">
|
<MudGrid Spacing="3">
|
||||||
<MudItem xs="12" sm="6">
|
<MudItem xs="12" sm="6">
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
<MudItem xs="12" sm="7">
|
<MudItem xs="12" sm="7">
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<StudentToggleSelector Students="@_students"
|
<StudentToggleSelector Students="@_students"
|
||||||
@bind-SelectedStudents="_selectedStudents"
|
@bind-SelectedStudents="_selectedStudents"
|
||||||
Title="Students"
|
Title="Students"
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
@foreach (var student in _students)
|
@foreach (var student in _students)
|
||||||
{
|
{
|
||||||
<MudContainer Class="pagebreak">
|
<MudContainer Class="pagebreak">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
</ActionButtons>
|
</ActionButtons>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
|
|
||||||
<MudPaper Elevation="2" Class="pa-6">
|
<MudPaper Elevation="2" Class="pa-3 pa-md-6">
|
||||||
<MudDataGrid T="Team"
|
<MudDataGrid T="Team"
|
||||||
ServerData="ServerReload"
|
ServerData="ServerReload"
|
||||||
@ref="_dataGrid"
|
@ref="_dataGrid"
|
||||||
|
|||||||
@@ -9,7 +9,9 @@
|
|||||||
<MudLayout>
|
<MudLayout>
|
||||||
<MudAppBar Class="no-print">
|
<MudAppBar Class="no-print">
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
|
<MudIconButton Icon="@Icons.Material.Filled.Menu" Color="Color.Inherit" Edge="Edge.Start" OnClick="@((e) => DrawerToggle())" />
|
||||||
TSA Chapter Organizer - @Configuration["ChapterSettings:Name"]
|
<MudText Typo="Typo.h6" Class="text-truncate appbar-title">
|
||||||
|
TSA Chapter Organizer - @Configuration["ChapterSettings:Name"]
|
||||||
|
</MudText>
|
||||||
<MudSpacer />
|
<MudSpacer />
|
||||||
<AuthorizeView>
|
<AuthorizeView>
|
||||||
<form action="Auth/CookieLogout" method="post">
|
<form action="Auth/CookieLogout" method="post">
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ public class CalendarEventItem : CalendarItem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public CalendarEventItem()
|
public CalendarEventItem()
|
||||||
{
|
{
|
||||||
|
// Initialize base class properties to avoid null reference issues
|
||||||
|
Text = string.Empty;
|
||||||
|
Start = DateTime.MinValue;
|
||||||
|
End = DateTime.MinValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CalendarEventItem(Core.Entities.EventOccurrence occurrence, Core.Entities.EventDefinition? eventDefinition = null)
|
public CalendarEventItem(Core.Entities.EventOccurrence occurrence, Core.Entities.EventDefinition? eventDefinition = null)
|
||||||
|
|||||||
+26
-1
@@ -1,5 +1,6 @@
|
|||||||
using Data;
|
using Data;
|
||||||
using Microsoft.AspNetCore.DataProtection;
|
using Microsoft.AspNetCore.DataProtection;
|
||||||
|
using Microsoft.AspNetCore.StaticFiles;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using MudBlazor.Services;
|
using MudBlazor.Services;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@@ -268,7 +269,31 @@ app.UseRouting();
|
|||||||
app.UseAuthentication();
|
app.UseAuthentication();
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
app.UseStaticFiles();
|
// Configure static files with proper cache headers for Blazor assets
|
||||||
|
app.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
OnPrepareResponse = ctx =>
|
||||||
|
{
|
||||||
|
// Blazor framework files: Use ETags with short cache and revalidation
|
||||||
|
// This allows caching for performance but ensures fresh files after deployments
|
||||||
|
// Browser will check ETag on each request (304 Not Modified if unchanged)
|
||||||
|
if (ctx.File.Name.Contains("_framework") ||
|
||||||
|
ctx.File.Name.Contains("blazor") ||
|
||||||
|
ctx.File.Name.EndsWith(".dll") ||
|
||||||
|
ctx.File.Name.EndsWith(".wasm"))
|
||||||
|
{
|
||||||
|
// Cache for 12 hours, but must revalidate (check ETag) before using
|
||||||
|
// If file hasn't changed, browser gets 304 Not Modified (no download)
|
||||||
|
// If file changed, browser downloads new version
|
||||||
|
ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=43200, must-revalidate");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Other static files (CSS, images, etc.) can be cached long-term
|
||||||
|
ctx.Context.Response.Headers.Append("Cache-Control", "public, max-age=31536000");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
app.UseAntiforgery();
|
app.UseAntiforgery();
|
||||||
|
|
||||||
app.MapRazorComponents<App>()
|
app.MapRazorComponents<App>()
|
||||||
|
|||||||
@@ -56,6 +56,19 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.page-header-actions {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page-header > div > div:first-of-type {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-actions {
|
.form-actions {
|
||||||
@@ -66,6 +79,17 @@
|
|||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.form-actions {
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions > * {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.icon-button-hover-error:hover {
|
.icon-button-hover-error:hover {
|
||||||
color: var(--mud-palette-error) !important;
|
color: var(--mud-palette-error) !important;
|
||||||
}
|
}
|
||||||
@@ -88,3 +112,20 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Toolbar title responsive styling */
|
||||||
|
.appbar-title {
|
||||||
|
max-width: calc(100vw - 150px);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.appbar-title {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
max-width: calc(100vw - 120px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reduce base font size on mobile */
|
||||||
|
body {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user