Unterrichtsplanung: Einheiten, Verlaufsplan-Editor, Kürzel-Katalog (Kapitel 4.1/4.2)
Neuer Tab "Planung" in GroupDetailView ersetzt den Platzhalter: Einheiten anlegen/bearbeiten/ als Vorlage in andere Gruppe kopieren, Stunden je Einheit mit Verschieben (inkl. Nachrücken der Folgestunden). Stundeneditor als tabellarischer Verlaufsplan (Phase/Dauer/Tätigkeit/ Material/Kurzsymbol je Zeile, Uhrzeit aus optionalem Stundenbeginn abgeleitet) statt eines einzelnen Phase-Felds mit Methoden-/Materialien-Chips — Kurzsymbol als Freitext mit Vorschlägen aus neuem Kürzel-Katalog (Einstellungen) plus bisher verwendeten Werten. Schema-Migrationen v1-v3 überführen bestehende Daten verlustfrei. 4.2.5 bewusst offen gelassen (hängt an Stundenplan, Kapitel 4.3). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@ public class LiteDbContext : IDisposable
|
||||
/// Aktuelle Schema-Version. Migrationsschritte werden versioniert unter
|
||||
/// <see cref="RunVersionedMigrations"/> ergänzt, statt bei jedem Start erneut
|
||||
/// (idempotent, aber unnötig) über alle Daten zu laufen.
|
||||
private const int CurrentSchemaVersion = 1;
|
||||
private const int CurrentSchemaVersion = 3;
|
||||
|
||||
private readonly LiteDatabase _db;
|
||||
|
||||
@@ -55,6 +55,7 @@ public class LiteDbContext : IDisposable
|
||||
public ILiteCollection<ParticipationSection> ParticipationSections => _db.GetCollection<ParticipationSection>("participation_sections");
|
||||
public ILiteCollection<Subject> Subjects => _db.GetCollection<Subject>("subjects");
|
||||
public ILiteCollection<CompetencyDomain> CompetencyDomains => _db.GetCollection<CompetencyDomain>("competency_domains");
|
||||
public ILiteCollection<ShorthandCode> ShorthandCodes => _db.GetCollection<ShorthandCode>("shorthand_codes");
|
||||
|
||||
public void Checkpoint() => _db.Checkpoint();
|
||||
|
||||
@@ -83,6 +84,16 @@ public class LiteDbContext : IDisposable
|
||||
MigrateExistingData();
|
||||
version = 1;
|
||||
}
|
||||
if (version < 2)
|
||||
{
|
||||
MigrateLessonPhases();
|
||||
version = 2;
|
||||
}
|
||||
if (version < 3)
|
||||
{
|
||||
MigrateLessonShorthand();
|
||||
version = 3;
|
||||
}
|
||||
WriteSchemaVersion(version);
|
||||
}
|
||||
|
||||
@@ -174,6 +185,79 @@ public class LiteDbContext : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// Fasst die frühere flache Struktur einer Stunde (einzelnes Phase-Textfeld, Methoden-/
|
||||
/// Materialien-Listen) verlustfrei in eine einzige <see cref="LessonPhaseStep"/>-Zeile der
|
||||
/// neuen Verlaufsplan-Tabelle zusammen. Nur die alten Felder werden gelesen — die typisierte
|
||||
/// <see cref="Lesson"/>-Klasse kennt sie nicht mehr, ein Zugriff über die typisierte
|
||||
/// Lessons-Collection würde sie beim Deserialisieren bereits verwerfen.
|
||||
private void MigrateLessonPhases()
|
||||
{
|
||||
var lessons = _db.GetCollection<BsonDocument>("lessons");
|
||||
foreach (var lesson in lessons.FindAll().ToList())
|
||||
{
|
||||
if (lesson.ContainsKey(nameof(Lesson.Phases))) continue;
|
||||
|
||||
var phase = lesson.TryGetValue("Phase", out var p) && p.IsString ? p.AsString.Trim() : "";
|
||||
var methods = lesson.TryGetValue("Methods", out var m) && m.IsArray
|
||||
? string.Join("; ", m.AsArray.Select(x => x.AsString)) : "";
|
||||
var materials = lesson.TryGetValue("Materials", out var mat) && mat.IsArray
|
||||
? string.Join(", ", mat.AsArray.Select(x => x.AsString)) : "";
|
||||
|
||||
var phases = new BsonArray();
|
||||
if (phase.Length > 0 || methods.Length > 0 || materials.Length > 0)
|
||||
{
|
||||
phases.Add(new BsonDocument
|
||||
{
|
||||
[nameof(LessonPhaseStep.Id)] = Guid.NewGuid(),
|
||||
[nameof(LessonPhaseStep.Name)] = phase,
|
||||
[nameof(LessonPhaseStep.DurationMinutes)] = 0,
|
||||
[nameof(LessonPhaseStep.Activity)] = methods,
|
||||
[nameof(LessonPhaseStep.Material)] = materials,
|
||||
[nameof(LessonPhaseStep.Shorthand)] = "",
|
||||
});
|
||||
}
|
||||
lesson[nameof(Lesson.Phases)] = phases;
|
||||
lesson.Remove("Phase");
|
||||
lesson.Remove("Methods");
|
||||
lesson.Remove("Materials");
|
||||
lessons.Update(lesson);
|
||||
}
|
||||
}
|
||||
|
||||
/// Führt die anfangs erzwungene Von/Nach-Struktur des Kurzsymbols (<c>ShorthandFrom</c>/
|
||||
/// <c>ShorthandTo</c>) in ein einzelnes Freitextfeld zusammen — der Praxis nach ist ein
|
||||
/// Kurzsymbol nicht immer ein Materialfluss-Pfeil, manchmal nur eine Sozialform ("Plenum").
|
||||
/// Beide Felder gesetzt ergeben "Von->Nach", nur eines gesetzt bleibt als Einzelwert erhalten.
|
||||
private void MigrateLessonShorthand()
|
||||
{
|
||||
var lessons = _db.GetCollection<BsonDocument>("lessons");
|
||||
foreach (var lesson in lessons.FindAll().ToList())
|
||||
{
|
||||
if (!lesson.TryGetValue(nameof(Lesson.Phases), out var phasesValue) || !phasesValue.IsArray) continue;
|
||||
|
||||
var changed = false;
|
||||
foreach (var phaseValue in phasesValue.AsArray)
|
||||
{
|
||||
if (phaseValue is not BsonDocument phase) continue;
|
||||
if (phase.ContainsKey(nameof(LessonPhaseStep.Shorthand))) continue;
|
||||
|
||||
var from = phase.TryGetValue("ShorthandFrom", out var f) && f.IsString ? f.AsString : "";
|
||||
var to = phase.TryGetValue("ShorthandTo", out var t) && t.IsString ? t.AsString : "";
|
||||
phase[nameof(LessonPhaseStep.Shorthand)] = (from.Length > 0, to.Length > 0) switch
|
||||
{
|
||||
(true, true) => $"{from}->{to}",
|
||||
(true, false) => from,
|
||||
(false, true) => to,
|
||||
_ => "",
|
||||
};
|
||||
phase.Remove("ShorthandFrom");
|
||||
phase.Remove("ShorthandTo");
|
||||
changed = true;
|
||||
}
|
||||
if (changed) lessons.Update(lesson);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveRedundantLegacyFields()
|
||||
{
|
||||
RemoveFields("exams", "Subject");
|
||||
@@ -237,6 +321,7 @@ public class LiteDbContext : IDisposable
|
||||
Subjects.EnsureIndex("ux_subject_name", BsonExpression.Create("LOWER(TRIM($.Name))"), unique: true);
|
||||
CompetencyDomains.EnsureIndex(x => x.SubjectId);
|
||||
CompetencyDomains.EnsureIndex(x => x.GradeLevel);
|
||||
ShorthandCodes.EnsureIndex("ux_shorthand_code", BsonExpression.Create("LOWER(TRIM($.Code))"), unique: true);
|
||||
}
|
||||
|
||||
public void Dispose() => _db.Dispose();
|
||||
|
||||
Reference in New Issue
Block a user