CI / build-and-test (push) Canceled after 0s
- Mitarbeit: Tagesflagge (👑 Spitzentag / 😴 Schlaftag / ⚡ Schlechter Tag) je Schüler und Sitzung. Primär im Sitzplatz-Dialog (⇧1/2/3, ⇧X) mit Badge auf der Sitzplatz-Kachel; Fallback in der Schnelleingabe für Lerngruppen ohne Sitzplan. - Noten: neuer Dialog "Überblick" in der Notenübersicht zeigt Klausuren, Mitarbeit- und sonstige Noten eines Schülers samt berechneter Zeugnisnote. Zielnoten-Rechner (ReportGradeTargetCalculator) beantwortet "was brauche ich noch für Note X", ein Was-wäre-wenn-Rechner simuliert eine zusätzliche Klausurnote. Bewerter-/Schülermodus per Umschalter im selben Fenster — Bewertermodus zeigt zusätzlich Kursdurchschnitt je Klausur und erlaubt das Bearbeiten von Mitarbeit-/Sonstige-Noten. Klausurverlauf als Balken-Sparkline wie die bestehende Notenentwicklung. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
147 lines
5.9 KiB
C#
147 lines
5.9 KiB
C#
using Avalonia.Controls;
|
|
using Avalonia.Data;
|
|
using Avalonia.Interactivity;
|
|
using LehrerApp.Core.Interfaces;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels.Groups;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
namespace LehrerApp.Desktop.Views.Groups;
|
|
|
|
public partial class GradeOverviewTabView : UserControl
|
|
{
|
|
private GradeOverviewTabViewModel? _vm;
|
|
|
|
public GradeOverviewTabView() => InitializeComponent();
|
|
|
|
protected override void OnDataContextChanged(EventArgs e)
|
|
{
|
|
base.OnDataContextChanged(e);
|
|
|
|
if (DataContext is GradeOverviewTabViewModel vm)
|
|
{
|
|
_vm = vm;
|
|
vm.OnManageStudentGrades = ShowStudentGradesDialog;
|
|
vm.OnCollectiveGrade = ShowCollectiveGradeDialog;
|
|
vm.OnReportGrades = ShowReportGradesDialog;
|
|
vm.OnShowPerformanceOverview = ShowPerformanceOverviewDialog;
|
|
vm.PropertyChanged += (_, pe) =>
|
|
{
|
|
if (pe.PropertyName == nameof(GradeOverviewTabViewModel.RebuildColumnsSignal))
|
|
BuildColumns();
|
|
};
|
|
BuildColumns();
|
|
}
|
|
}
|
|
|
|
private async Task ShowStudentGradesDialog(GradeOverviewRow row)
|
|
{
|
|
var dialogVm = new StudentGradesDialogViewModel(
|
|
App.Services.GetRequiredService<IGradeRepository>(),
|
|
row.StudentId, _vm!.GroupId, row.Name);
|
|
|
|
var dialog = new StudentGradesDialog { DataContext = dialogVm };
|
|
var owner = TopLevel.GetTopLevel(this) as Window;
|
|
if (owner is not null) await dialog.ShowDialog(owner);
|
|
}
|
|
|
|
private async Task ShowCollectiveGradeDialog()
|
|
{
|
|
var dialogVm = new CollectiveGradeDialogViewModel(
|
|
App.Services.GetRequiredService<IGradeRepository>(),
|
|
App.Services.GetRequiredService<IStudentRepository>(),
|
|
App.Services.GetRequiredService<IGroupMembershipRepository>(),
|
|
_vm!.GroupId);
|
|
|
|
var dialog = new CollectiveGradeDialog { DataContext = dialogVm };
|
|
var owner = TopLevel.GetTopLevel(this) as Window;
|
|
if (owner is not null) await dialog.ShowDialog(owner);
|
|
}
|
|
|
|
private async Task ShowReportGradesDialog()
|
|
{
|
|
var dialogVm = new ReportGradeDialogViewModel(
|
|
App.Services.GetRequiredService<IGradeRepository>(),
|
|
App.Services.GetRequiredService<IExamRepository>(),
|
|
App.Services.GetRequiredService<IExamResultRepository>(),
|
|
App.Services.GetRequiredService<IStudentRepository>(),
|
|
App.Services.GetRequiredService<IGroupMembershipRepository>(),
|
|
App.Services.GetRequiredService<IGradingSchemeRepository>(),
|
|
App.Services.GetRequiredService<IReportGradeRepository>(),
|
|
App.Services.GetRequiredService<IParticipationSessionRepository>(),
|
|
App.Services.GetRequiredService<IParticipationRepository>(),
|
|
App.Services.GetRequiredService<AttendanceBalanceService>(),
|
|
App.Services.GetRequiredService<GradingService>(),
|
|
_vm!.GroupId, _vm.GroupType, _vm.GradingSystem, _vm.GroupLabel, _vm.SchoolYear);
|
|
|
|
var dialog = new ReportGradeDialog { DataContext = dialogVm };
|
|
var owner = TopLevel.GetTopLevel(this) as Window;
|
|
if (owner is not null) await dialog.ShowDialog(owner);
|
|
}
|
|
|
|
private async Task ShowPerformanceOverviewDialog(GradeOverviewRow row)
|
|
{
|
|
var dialogVm = new StudentPerformanceOverviewViewModel(
|
|
App.Services.GetRequiredService<IGradeRepository>(),
|
|
App.Services.GetRequiredService<IExamRepository>(),
|
|
App.Services.GetRequiredService<IExamResultRepository>(),
|
|
App.Services.GetRequiredService<IGroupMembershipRepository>(),
|
|
App.Services.GetRequiredService<IGradingSchemeRepository>(),
|
|
App.Services.GetRequiredService<GradingService>(),
|
|
_vm!.GroupId, row.StudentId, _vm.GroupType, _vm.GradingSystem, row.Name, _vm.GroupLabel, _vm.SchoolYear);
|
|
|
|
var dialog = new StudentPerformanceOverviewDialog { DataContext = dialogVm };
|
|
var owner = TopLevel.GetTopLevel(this) as Window;
|
|
if (owner is not null) await dialog.ShowDialog(owner);
|
|
}
|
|
|
|
private async void OnExportPdfClick(object? sender, RoutedEventArgs e)
|
|
{
|
|
var topLevel = TopLevel.GetTopLevel(this);
|
|
if (topLevel is null || _vm is null) return;
|
|
|
|
var data = new GradeListPrintData(
|
|
_vm.GroupLabel, _vm.SchoolYear, _vm.SelectedPeriod.Label,
|
|
_vm.Columns.Select(c => c.Header).ToList(),
|
|
_vm.Rows.Select(r => new GradeListPrintRow(r.Name, r.Cells, r.TotalDisplay)).ToList());
|
|
var pdf = App.Services.GetRequiredService<PdfExportService>().BuildGradeListPdf(data);
|
|
|
|
await App.Services.GetRequiredService<ExportService>().SaveAsync(topLevel.StorageProvider,
|
|
ExportFile.Pdf("Notenliste als PDF speichern",
|
|
$"Notenliste_{_vm.GroupLabel}_{_vm.SchoolYear.Replace('/', '-')}", pdf));
|
|
}
|
|
|
|
private void BuildColumns()
|
|
{
|
|
var grid = this.FindControl<DataGrid>("GradesGrid");
|
|
if (grid is null || _vm is null) return;
|
|
|
|
grid.Columns.Clear();
|
|
grid.Columns.Add(new DataGridTextColumn
|
|
{
|
|
Header = "Schüler",
|
|
Binding = new Binding("Name"),
|
|
Width = new DataGridLength(160, DataGridLengthUnitType.Pixel),
|
|
});
|
|
|
|
foreach (var (col, i) in _vm.Columns.Select((c, i) => (c, i)))
|
|
{
|
|
var idx = i;
|
|
grid.Columns.Add(new DataGridTextColumn
|
|
{
|
|
Header = col.Header,
|
|
Binding = new Binding($"Cells[{idx}]"),
|
|
Width = new DataGridLength(120, DataGridLengthUnitType.Pixel),
|
|
});
|
|
}
|
|
|
|
grid.Columns.Add(new DataGridTextColumn
|
|
{
|
|
Header = "Gesamt",
|
|
Binding = new Binding("TotalDisplay"),
|
|
Width = new DataGridLength(80, DataGridLengthUnitType.Pixel),
|
|
});
|
|
}
|
|
}
|