Add PageNoteButton to various components for enhanced note management

This commit is contained in:
2026-01-17 10:25:38 -05:00
parent 947d95893f
commit e6eb35ee67
15 changed files with 69 additions and 19 deletions
@@ -16,6 +16,7 @@
<AuthorizeView Roles="@AuthRoles.Administrator"> <AuthorizeView Roles="@AuthRoles.Administrator">
<MudButton StartIcon="@Icons.Material.Filled.AdminPanelSettings" Href="calendar/admin" Variant="Variant.Outlined" Color="Color.Default">Admin</MudButton> <MudButton StartIcon="@Icons.Material.Filled.AdminPanelSettings" Href="calendar/admin" Variant="Variant.Outlined" Color="Color.Default">Admin</MudButton>
</AuthorizeView> </AuthorizeView>
<PageNoteButton PageIdentifier="Event Calendar" />
</ActionButtons> </ActionButtons>
</PageHeader> </PageHeader>
@@ -1,4 +1,4 @@
@page "/meeting-schedule" @page "/meeting-schedule"
@attribute [Authorize] @attribute [Authorize]
@using System.Text @using System.Text
@using Core.Calculation @using Core.Calculation
@@ -10,7 +10,11 @@
@inject ClipboardService ClipboardService @inject ClipboardService ClipboardService
@inject LocalStorageService LocalStorage @inject LocalStorageService LocalStorage
<PageHeader Title="@($"{Configuration["ChapterSettings:Shortname"]} TSA Schedule {Configuration["ChapterSettings:CompetitionYear"]}")" /> <PageHeader Title="@($"{Configuration["ChapterSettings:Shortname"]} TSA Schedule {Configuration["ChapterSettings:CompetitionYear"]}")">
<ActionButtons>
<PageNoteButton PageIdentifier="Meeting Schedule" />
</ActionButtons>
</PageHeader>
<MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4"> <MudPaper Elevation="2" Class="pa-3 pa-md-6 mt-4">
<MudGrid> <MudGrid>
@@ -1,4 +1,4 @@
@page "/students/event-ranking" @page "/students/event-ranking"
@attribute [Authorize] @attribute [Authorize]
@using Microsoft.EntityFrameworkCore @using Microsoft.EntityFrameworkCore
@using WebApp.Models @using WebApp.Models
@@ -9,7 +9,11 @@
<PageHeader <PageHeader
Title="Student Event Ranks" Title="Student Event Ranks"
Icon="@AppIcons.EventRank" /> Icon="@AppIcons.EventRank">
<ActionButtons>
<PageNoteButton PageIdentifier="Event Ranking" />
</ActionButtons>
</PageHeader>
@if (_students == null) @if (_students == null)
{ {
@@ -17,6 +17,7 @@
OnClick="ToggleRegionalFilter"> OnClick="ToggleRegionalFilter">
@(_showRegionalOnly ? "Showing Regional Only" : "Show Regional Only") @(_showRegionalOnly ? "Showing Regional Only" : "Show Regional Only")
</MudButton> </MudButton>
<PageNoteButton PageIdentifier="Registration" />
</ActionButtons> </ActionButtons>
</PageHeader> </PageHeader>
@@ -1,4 +1,4 @@
@page "/teams/assignment" @page "/teams/assignment"
@attribute [Authorize] @attribute [Authorize]
@using Core.Calculation @using Core.Calculation
@using Core.Validation @using Core.Validation
@@ -18,6 +18,7 @@
<MudButton StartIcon="@Icons.Material.Filled.Edit" Href="students/event-ranking" Variant="Variant.Outlined"> <MudButton StartIcon="@Icons.Material.Filled.Edit" Href="students/event-ranking" Variant="Variant.Outlined">
Edit Student Event Rankings Edit Student Event Rankings
</MudButton> </MudButton>
<PageNoteButton PageIdentifier="Team Assignment" />
</ActionButtons> </ActionButtons>
</PageHeader> </PageHeader>
+5 -2
View File
@@ -6,7 +6,7 @@
@inject ISnackbar Snackbar @inject ISnackbar Snackbar
@inject IDialogService DialogService @inject IDialogService DialogService
<MudDialog> <MudDialog Class="@MarkdownHelper.GetNoteColorClass(_note.Id)">
<DialogContent> <DialogContent>
<MudStack Spacing="3"> <MudStack Spacing="3">
<MudTextField @bind-Value="_note.Title" <MudTextField @bind-Value="_note.Title"
@@ -14,7 +14,8 @@
Variant="Variant.Outlined" Variant="Variant.Outlined"
Required="true" Required="true"
RequiredError="Title is required" RequiredError="Title is required"
MaxLength="200" /> MaxLength="200"
ReadOnly="@IsPageNote" />
<MudText Typo="Typo.subtitle2" Class="mb-2">Content (Markdown)</MudText> <MudText Typo="Typo.subtitle2" Class="mb-2">Content (Markdown)</MudText>
<MarkdownEditor Value="@_note.Content" <MarkdownEditor Value="@_note.Content"
@@ -42,6 +43,8 @@
private Note _note = null!; private Note _note = null!;
private bool IsPageNote => Note?.Title?.StartsWith("@") ?? false;
protected override void OnInitialized() protected override void OnInitialized()
{ {
_note = new Note _note = new Note
@@ -4,7 +4,7 @@
@inject INotesService NotesService @inject INotesService NotesService
@inject IDialogService DialogService @inject IDialogService DialogService
<MudDialog> <MudDialog Class="@MarkdownHelper.GetNoteColorClass(NoteId)">
<DialogContent> <DialogContent>
@if (_isLoading) @if (_isLoading)
{ {
@@ -2,7 +2,7 @@
@using WebApp.Services @using WebApp.Services
@using MudBlazor @using MudBlazor
<MudDialog> <MudDialog Class="@MarkdownHelper.GetNoteColorClass(_history.NoteId)">
<DialogContent> <DialogContent>
<MudStack Spacing="3"> <MudStack Spacing="3">
<MudText Typo="Typo.h6">@_history.Title</MudText> <MudText Typo="Typo.h6">@_history.Title</MudText>
+3 -2
View File
@@ -54,7 +54,8 @@
<MudExpansionPanel @key="@($"note-{noteId}")" <MudExpansionPanel @key="@($"note-{noteId}")"
Icon="@Icons.Material.Filled.Note" Icon="@Icons.Material.Filled.Note"
IsExpanded="@isExpanded" IsExpanded="@isExpanded"
ExpandedChanged="@((bool expanded) => OnPanelExpandedChanged(noteId, expanded))"> ExpandedChanged="@((bool expanded) => OnPanelExpandedChanged(noteId, expanded))"
Class="@MarkdownHelper.GetNoteColorClass(noteId)">
<TitleContent> <TitleContent>
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2" Class="flex-grow-1"> <MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2" Class="flex-grow-1">
<MudText Typo="Typo.body1" Class="flex-grow-1" Style="min-width: 0;"> <MudText Typo="Typo.body1" Class="flex-grow-1" Style="min-width: 0;">
@@ -402,7 +403,7 @@
var result = await DialogService.ShowMessageBox( var result = await DialogService.ShowMessageBox(
"Delete Note", "Delete Note",
(MarkupString)$"Are you sure you want to delete <b>{note.Title}</b>? This cannot be undone.", (MarkupString)$"Are you sure you want to delete <b>{note.Title}</b>? You can restore it later from the 'Show Removed' view.",
yesText: "Yes", yesText: "Yes",
noText: "Cancel"); noText: "Cancel");
@@ -4,7 +4,7 @@
@* Reuse dialog options pattern - could be extracted if used in more places *@ @* Reuse dialog options pattern - could be extracted if used in more places *@
<MudItem xs="12" sm="6" md="4"> <MudItem xs="12" sm="6" md="4">
<MudCard Elevation="4" Class="pa-4" Style="cursor: pointer; height: 100%;" @onclick="OpenNoteDialog"> <MudCard Elevation="4" Class="@($"pa-4 {MarkdownHelper.GetNoteColorClass(Note.Id)}".Trim())" Style="cursor: pointer; height: 100%;" @onclick="OpenNoteDialog">
<MudCardContent> <MudCardContent>
<div class="d-flex align-center mb-2"> <div class="d-flex align-center mb-2">
<MudIcon Icon="@Icons.Material.Filled.Note" Size="Size.Medium" Class="mr-2" /> <MudIcon Icon="@Icons.Material.Filled.Note" Size="Size.Medium" Class="mr-2" />
@@ -4,7 +4,7 @@
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@implements IAsyncDisposable @implements IAsyncDisposable
<MudDialog> <MudDialog Class="@MarkdownHelper.GetNoteColorClass(NoteId)">
<DialogContent> <DialogContent>
@if (_isLoading) @if (_isLoading)
{ {
@@ -8,7 +8,8 @@
Variant="@Variant" Variant="@Variant"
Size="@Size" Size="@Size"
Color="@ButtonColor" Color="@ButtonColor"
Tooltip="@TooltipText"> Tooltip="@TooltipText"
Class="@MarkdownHelper.GetNoteColorClass(_noteId)">
@if (!string.IsNullOrEmpty(ButtonText)) @if (!string.IsNullOrEmpty(ButtonText))
{ {
@ButtonText @ButtonText
@@ -37,6 +38,7 @@
private string IconValue => Icon ?? Icons.Material.Filled.Note; private string IconValue => Icon ?? Icons.Material.Filled.Note;
private string TooltipText => Tooltip ?? $"Page notes for {PageIdentifier}"; private string TooltipText => Tooltip ?? $"Page notes for {PageIdentifier}";
private bool _hasContent = false; private bool _hasContent = false;
private int _noteId = 0;
private Color ButtonColor => _hasContent ? Color.Success : (Variant == Variant.Filled ? Color.Primary : Color.Default); private Color ButtonColor => _hasContent ? Color.Success : (Variant == Variant.Filled ? Color.Primary : Color.Default);
private CancellationTokenSource? _cancellationTokenSource; private CancellationTokenSource? _cancellationTokenSource;
private bool _isDisposed = false; private bool _isDisposed = false;
@@ -59,6 +61,7 @@
{ {
var note = await NotesService.GetPageNoteAsync(PageIdentifier); var note = await NotesService.GetPageNoteAsync(PageIdentifier);
_hasContent = note != null && !string.IsNullOrWhiteSpace(note.Content); _hasContent = note != null && !string.IsNullOrWhiteSpace(note.Content);
_noteId = note?.Id ?? 0;
if (!_isDisposed) if (!_isDisposed)
{ {
@@ -100,8 +103,9 @@
var dialog = await DialogService.ShowAsync<PageNoteDialog>($"Page Notes: {PageIdentifier}", parameters, options); var dialog = await DialogService.ShowAsync<PageNoteDialog>($"Page Notes: {PageIdentifier}", parameters, options);
var result = await dialog.Result; var result = await dialog.Result;
// Refresh content indicator after dialog closes // Always refresh content indicator after dialog closes
if (!result.Canceled && !_isDisposed) // (content may have been saved even if dialog was closed with Cancel)
if (!_isDisposed)
{ {
await CheckNoteContent(); await CheckNoteContent();
} }
@@ -3,7 +3,7 @@
@inject ISnackbar Snackbar @inject ISnackbar Snackbar
@implements IAsyncDisposable @implements IAsyncDisposable
<MudDialog> <MudDialog Class="@MarkdownHelper.GetNoteColorClass(_note.Id)">
<DialogContent> <DialogContent>
@if (_isLoading) @if (_isLoading)
{ {
@@ -167,15 +167,21 @@
} }
else else
{ {
await NotesService.CreateNoteAsync(_note); // CreateNoteAsync returns the note with the ID populated
var createdNote = await NotesService.CreateNoteAsync(_note);
// Update _note with the returned note to get the ID immediately
_note = createdNote;
_isEdit = true; // Mark as existing note now
Snackbar.Add("Page note created successfully", Severity.Success); Snackbar.Add("Page note created successfully", Severity.Success);
} }
if (!_isDisposed) if (!_isDisposed)
{ {
// After saving, switch back to view mode and reload the note // After saving, switch back to view mode and reload the note to ensure we have latest data
_isEditMode = false; _isEditMode = false;
await LoadPageNote(); await LoadPageNote();
// Ensure dialog re-renders with updated color class after note ID is set
StateHasChanged();
} }
} }
catch (TaskCanceledException) catch (TaskCanceledException)
+12
View File
@@ -92,4 +92,16 @@ public static class MarkdownHelper
return plainText; return plainText;
} }
/// <summary>
/// Gets the CSS class name for a note's color based on its ID.
/// Uses modulo 3 to cycle through 3 pastel color classes.
/// </summary>
/// <param name="noteId">The note ID.</param>
/// <returns>CSS class name (e.g., "note-color-0", "note-color-1", "note-color-2"), or empty string if noteId is 0.</returns>
public static string GetNoteColorClass(int noteId)
{
if (noteId == 0) return string.Empty;
return $"note-color-{noteId % 3}";
}
} }
+13
View File
@@ -229,4 +229,17 @@
.markdown-content img { .markdown-content img {
max-width: 100%; max-width: 100%;
height: auto; height: auto;
}
/* Note color classes - pastel background colors */
.note-color-0 {
background-color: #e3f2fd;
}
.note-color-1 {
background-color: #fff9e6;
}
.note-color-2 {
background-color: #f3e5f5;
} }