feat: add a Tools page printer for note merge and print presets

Chapter officers can merge a markdown note onto filtered students, teams, or events and save the recipe. Extra student-note columns are additional fields (any ## … fields heading) so they work as print tokens whether imported or typed by hand.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-30 15:38:43 -04:00
co-authored by Cursor
parent 4cfd85b902
commit 3f50d6e635
39 changed files with 2199 additions and 69 deletions
@@ -95,7 +95,7 @@
<MudPaper Class="pa-6 mb-4">
<MudText Typo="Typo.h5" Class="mb-4">Student Index Columns</MudText>
<MudText Typo="Typo.body2" Class="mb-3">
Field names from each student's imported notes table to show as extra Students index columns. Click a field found in notes to add or remove it, or type names (one per line).
Field names from each student's additional-fields table to show as extra Students index columns. Click a field found in notes to add or remove it, or type names (one per line).
</MudText>
@if (_availableFields.Count > 0)
{
@@ -117,11 +117,11 @@
else
{
<MudText Typo="Typo.caption" Class="mud-text-secondary mb-3">
No imported fields found in student notes yet.
No additional fields found in student notes yet.
</MudText>
}
<MudTextField @bind-Value="_noteFieldsText"
Label="Imported field columns"
Label="Additional field columns"
Variant="Variant.Outlined"
Lines="5"
HelperText="Example: Interview Time" />
@@ -80,7 +80,7 @@
{
_history = (await NotesService.GetNoteHistoryAsync(NoteId)).ToList();
}
catch (Exception ex)
catch (Exception)
{
// Error handling - could show snackbar if we had access
}
+13 -12
View File
@@ -59,7 +59,7 @@
var isExpanded = GetNoteExpanded(noteId);
<MudExpansionPanel @key="@($"note-{noteId}")"
Icon="@Icons.Material.Filled.Note"
IsExpanded="@isExpanded"
Expanded="@isExpanded"
ExpandedChanged="@((bool expanded) => OnPanelExpandedChanged(noteId, expanded))"
Class="@MarkdownHelper.GetNoteColorClass(noteId)">
<TitleContent>
@@ -71,15 +71,16 @@
</MudText>
@if (!NoteNamingService.IsPageNote(note.Title) && !note.IsDeleted && !isExpanded)
{
<MudButton StartIcon="@(note.IsPinned ? Icons.Material.Filled.PushPin : Icons.Material.Outlined.PushPin)"
OnClick="() => TogglePin(note)"
OnClick:StopPropagation="true"
Variant="Variant.Text"
Size="Size.Small"
Color="@(note.IsPinned ? Color.Primary : Color.Default)"
Disabled="@(IsPinDisabled(note))"
Title="@(note.IsPinned ? "Unpin note" : "Pin note")"
Class="flex-shrink-0" />
<div @onclick:stopPropagation="true" class="flex-shrink-0">
<MudTooltip Text="@(note.IsPinned ? "Unpin note" : "Pin note")">
<MudButton StartIcon="@(note.IsPinned ? Icons.Material.Filled.PushPin : Icons.Material.Outlined.PushPin)"
OnClick="() => TogglePin(note)"
Variant="Variant.Text"
Size="Size.Small"
Color="@(note.IsPinned ? Color.Primary : Color.Default)"
Disabled="@(IsPinDisabled(note))" />
</MudTooltip>
</div>
}
</MudStack>
</TitleContent>
@@ -301,7 +302,7 @@
var dialog = await DialogService.ShowAsync<NoteEditDialog>("Create Note", parameters, GetDefaultDialogOptions());
var result = await dialog.Result;
if (!result.Canceled && !_isDisposed)
if (result is { Canceled: false } && !_isDisposed)
{
await LoadNotes();
}
@@ -327,7 +328,7 @@
var dialog = await DialogService.ShowAsync<NoteEditDialog>("Edit Note", parameters, options);
var result = await dialog.Result;
if (!result.Canceled && !_isDisposed)
if (result is { Canceled: false } && !_isDisposed)
{
await LoadNotes();
}