Der interne Klausurtitel passt nicht immer aufs Deckblatt. Das neue Feld ist mit ihm vorbelegt, ändert nur Exam.Title für diesen Druck und fällt leer gelassen auf den internen Titel zurück. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2293ddb84d
commit
24a30881f3
5 files changed
+53
-7
No files matched your search
@@ -204,6 +204,35 @@ public sealed class ExamCoverSheetTests : IDisposable
|
||||
Assert.Equal(new TextValue("G-Kurs"), Values(Niveau.E)["Exam.Course"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Platzhalter_TitelAusDemDialog_LeerNimmtDenKlausurtitel()
|
||||
{
|
||||
var store = Store();
|
||||
Import(store, "deckblatt", "Deckblatt", TemplateReportTypes.ExamCover);
|
||||
var template = store.Load(store.GetTemplates().Single());
|
||||
|
||||
Dictionary<string, PlaceholderValue> Values(string? title) => ExamCoverPlaceholderBuilder.Build(
|
||||
_exam, _group, "Chemie", _anna, null, false, new GradingService(), template, new DateOnly(2026, 1, 1),
|
||||
title: title);
|
||||
|
||||
Assert.Equal(new TextValue("Klassenarbeit Nr. 1"), Values(" Klassenarbeit Nr. 1 ")["Exam.Title"]);
|
||||
Assert.Equal(new TextValue("Atombau und PSE"), Values(" ")["Exam.Title"]);
|
||||
Assert.Equal(new TextValue("Atombau und PSE"), Values(null)["Exam.Title"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dialog_TitelIstMitDemKlausurtitelVorbelegt()
|
||||
{
|
||||
var store = Store();
|
||||
Import(store, "deckblatt", "Deckblatt", TemplateReportTypes.ExamCover);
|
||||
|
||||
var vm = Build([store]);
|
||||
|
||||
Assert.Equal("Atombau und PSE", vm.CoverTitle);
|
||||
vm.CoverTitle = "Klassenarbeit Nr. 1";
|
||||
Assert.Equal("Atombau und PSE", _exam.Title);
|
||||
}
|
||||
|
||||
// Der Vorlagen-Designer bietet genau diesen Katalog an - liefert die Hauptapp einen Namen
|
||||
// nicht oder mit anderem Typ, scheitert die Vorlage erst beim Drucken.
|
||||
[Fact]
|
||||
|
||||
@@ -22,9 +22,12 @@ public static class ExamCoverPlaceholderBuilder
|
||||
/// eingetragen, wenn <paramref name="fillResults"/> gesetzt und das Ergebnis korrigiert ist.</param>
|
||||
/// <param name="studentNiveau">Niveau des Schülers in dieser Lerngruppe, falls die Arbeit
|
||||
/// selbst keinem Niveau zugeordnet ist.</param>
|
||||
/// <param name="title">Titel für das Deckblatt, falls er vom internen Klausurtitel abweichen
|
||||
/// soll; null oder leer nimmt den Klausurtitel.</param>
|
||||
public static Dictionary<string, PlaceholderValue> Build(Exam exam, LearningGroup group, string subjectName,
|
||||
Student student, ExamResult? result, bool fillResults, GradingService grading, LoadedTemplate template,
|
||||
DateOnly today, Niveau? studentNiveau = null, string teacherAbbreviation = "")
|
||||
DateOnly today, Niveau? studentNiveau = null, string teacherAbbreviation = "",
|
||||
string? title = null)
|
||||
{
|
||||
var tasks = exam.Tasks.OrderBy(t => t.Nr).ToList();
|
||||
var variant = result?.Variant ?? ExamVariant.A;
|
||||
@@ -34,7 +37,7 @@ public static class ExamCoverPlaceholderBuilder
|
||||
var values = LetterPlaceholderBuilder.BuildStandardValues(student, contact: null, group, today, "", "");
|
||||
values["Group.GradeLevel"] = new TextValue(group.GradeLevel > 0 ? group.GradeLevel.ToString() : "");
|
||||
values["Subject.Name"] = new TextValue(subjectName);
|
||||
values["Exam.Title"] = new TextValue(exam.Title);
|
||||
values["Exam.Title"] = new TextValue(string.IsNullOrWhiteSpace(title) ? exam.Title : title.Trim());
|
||||
values["Exam.Date"] = new DateValue(exam.Date);
|
||||
values["Exam.Number"] = new TextValue(exam.ExamNumber?.ToString() ?? "");
|
||||
values["Exam.Kind"] = new TextValue(exam.Kind.Label());
|
||||
|
||||
@@ -28,7 +28,11 @@ public partial class ExamCoverSheetDialogViewModel : ObservableObject
|
||||
/// <summary>Vorbelegt aus den Einstellungen, hier nur für diesen Druck änderbar (z. B. zwei
|
||||
/// Kürzel bei einem gemeinsam unterrichteten Kurs) — die Einstellung bleibt unberührt.</summary>
|
||||
[ObservableProperty] private string _teacherAbbreviation;
|
||||
/// <summary>Vorbelegt mit dem internen Klausurtitel, hier nur für diesen Druck änderbar — der
|
||||
/// Titel der Klausur bleibt unberührt. Leer gelassen gilt wieder der interne Titel.</summary>
|
||||
[ObservableProperty] private string _coverTitle;
|
||||
|
||||
public string ExamTitle => _exam.Title;
|
||||
public string ExamLabel => $"{_exam.Title} · {_group.Name} · {_exam.Date:dd.MM.yyyy}";
|
||||
public ObservableCollection<LetterTemplateChoice> Templates { get; } = [];
|
||||
public ObservableCollection<ExamCoverStudentChoice> Students { get; } = [];
|
||||
@@ -41,6 +45,7 @@ public partial class ExamCoverSheetDialogViewModel : ObservableObject
|
||||
string teacherAbbreviation = "")
|
||||
{
|
||||
_teacherAbbreviation = teacherAbbreviation;
|
||||
_coverTitle = exam.Title;
|
||||
_exam = exam; _group = group; _subjectName = subjectName; _grading = grading; _renderer = renderer;
|
||||
_loader = templateStores[0];
|
||||
foreach (var template in templateStores.SelectMany(x => x.GetTemplates()).Where(x => x.IsExamCover)
|
||||
@@ -76,7 +81,7 @@ public partial class ExamCoverSheetDialogViewModel : ObservableObject
|
||||
var today = DateOnly.FromDateTime(DateTime.Now);
|
||||
var data = included.Select(s => (ITemplateDataProvider)new LetterDataProvider(
|
||||
ExamCoverPlaceholderBuilder.Build(_exam, _group, _subjectName, s.Model, s.Result, FillResults,
|
||||
_grading, loaded, today, s.Niveau, TeacherAbbreviation))).ToList();
|
||||
_grading, loaded, today, s.Niveau, TeacherAbbreviation, CoverTitle))).ToList();
|
||||
var result = _renderer.RenderBatchToPdf(loaded, data);
|
||||
File.WriteAllBytes(outputPath, result.Pdf);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
x:Class="LehrerApp.Desktop.Views.Groups.ExamCoverSheetDialog"
|
||||
x:DataType="vm:ExamCoverSheetDialogViewModel"
|
||||
Title="Deckblätter drucken"
|
||||
Width="460" Height="640"
|
||||
Width="460" Height="680"
|
||||
CanResize="False" WindowStartupLocation="CenterOwner">
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,*,Auto,Auto" Margin="24">
|
||||
@@ -21,9 +21,12 @@
|
||||
<TextBlock Text="Noch keine Deckblatt-Vorlage importiert — in den Einstellungen unter „Briefvorlagen“ eine .lavorlage-Datei mit dem Metadatum report-type=exam-cover hinzufügen."
|
||||
Classes="emptyhint" TextWrapping="Wrap"
|
||||
IsVisible="{Binding HasNoTemplates}"/>
|
||||
<Grid ColumnDefinitions="Auto,*" ColumnSpacing="12">
|
||||
<TextBlock Grid.Column="0" Text="Kürzel" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Column="1" Text="{Binding TeacherAbbreviation}" PlaceholderText="z. B. MON HED"
|
||||
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto,Auto" ColumnSpacing="12" RowSpacing="10">
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Titel" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding CoverTitle}" PlaceholderText="{Binding ExamTitle}"
|
||||
ToolTip.Tip="Vorbelegt mit dem Titel der Klausur. Änderungen gelten nur für diesen Druck; leer gelassen steht der Klausurtitel auf dem Deckblatt."/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Kürzel" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1" Text="{Binding TeacherAbbreviation}" PlaceholderText="z. B. MON HED"
|
||||
ToolTip.Tip="Vorbelegt mit dem eigenen Kürzel aus den Einstellungen. Änderungen gelten nur für diesen Druck."/>
|
||||
</Grid>
|
||||
<CheckBox Content="Punkte und Note eintragen" IsChecked="{Binding FillResults}"
|
||||
|
||||
@@ -4854,6 +4854,12 @@ beides vor dem ersten produktiven Zwei-Geräte-Einsatz empfehlenswert nachzuhole
|
||||
aus der Vorlage und ist im Dialog je Druck überschreibbar, ohne die Einstellung zu ändern —
|
||||
für gemeinsam unterrichtete Kurse mit zwei Kürzeln.
|
||||
|
||||
Nachgezogen (Nutzer-Wunsch): Der Dialog hat zusätzlich ein Feld "Titel", vorbelegt mit dem
|
||||
internen Klausurtitel und nur für diesen Druck änderbar (`CoverTitle` →
|
||||
`ExamCoverPlaceholderBuilder.Build(title:)` → `Exam.Title`) — der interne Titel passt nicht
|
||||
immer aufs Deckblatt. Die Klausur selbst und der vorgeschlagene Dateiname bleiben beim
|
||||
internen Titel; ein leer gelassenes Feld fällt auf ihn zurück.
|
||||
|
||||
**Punktetabelle ohne Verkleinern:** `ExamPointsTableDrawingBuilder` zeichnet feste
|
||||
Spaltenbreiten und bricht in weitere Blöcke um. Damit "Gesamtpunkte"/"Note" darunter
|
||||
mitwandern, bekam `FLOWDRAWBOX` das Opt-in-Attribut `fit=content` (belegt nur die
|
||||
|
||||
Reference in new issue
Block a user