feat: unbenutzte Sitzplätze ausblenden können
Manche Räume sind unregelmäßig bestückt (z.B. eine Klasse mit 3 Reihen, in zwei davon fehlt ein Einzeltisch) - das feste Rows x Columns-Raster kennt aber keine per-Reihe abweichende Spaltenzahl. Neues Feld SeatingPlan.HiddenSeats für Plätze ohne physischen Tisch. Ein ausgeblendeter Platz bleibt Teil des Rasters (für die Spalten-/Reihenausrichtung von SeatingPlanPanel), wird im Ansichtsmodus aber nicht gerendert; im Bearbeitungsmodus bleibt er sichtbar (abgeblendet) mit einem Umschalt-Button direkt auf dem Platz. Nur leere Plätze lassen sich ausblenden; Zuweisen/ Verschieben eines Schülers auf einen ausgeblendeten Platz wird sowohl im ViewModel als auch im Drag&Drop-Ziel-Check verhindert. SeatingPlanRepository.Save filtert HiddenSeats zusätzlich auf das gültige Raster und blendet einen Platz automatisch wieder ein, falls er trotzdem belegt wird. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -115,6 +115,159 @@ public sealed class SeatingPlanViewModelTests
|
||||
Assert.Equal(2, plans.GetById(plan.Id)!.Assignments.Count);
|
||||
}
|
||||
|
||||
// ── Ausgeblendete Plätze (fehlender Tisch in einer Reihe) ─────────────────────────────
|
||||
|
||||
[Fact]
|
||||
public void LoadPlan_LaedtAusgeblendetePlaetzeAusDemPlan()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var plan = new SeatingPlan
|
||||
{
|
||||
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
||||
HiddenSeats = [new HiddenSeat { Row = 0, Column = 1 }],
|
||||
};
|
||||
var vm = new SeatingPlanTabViewModel(
|
||||
new FakeSeatingPlans([plan]), new FakeStudents([]), new FakeMemberships([]),
|
||||
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
||||
|
||||
vm.Initialize(groupId, isReadOnly: false);
|
||||
|
||||
Assert.False(vm.Seats[0].IsHidden);
|
||||
Assert.True(vm.Seats[1].IsHidden);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToggleSeatHidden_LeererPlatz_BlendetAusUndSpeichertUndKannWiederEingeblendetWerden()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var plan = new SeatingPlan { GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2 };
|
||||
var plans = new FakeSeatingPlans([plan]);
|
||||
var vm = new SeatingPlanTabViewModel(plans, new FakeStudents([]), new FakeMemberships([]),
|
||||
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
||||
vm.Initialize(groupId, isReadOnly: false);
|
||||
vm.IsEditMode = true;
|
||||
|
||||
vm.ToggleSeatHidden(vm.Seats[1]);
|
||||
|
||||
Assert.True(vm.Seats[1].IsHidden);
|
||||
var hidden = Assert.Single(plans.GetById(plan.Id)!.HiddenSeats);
|
||||
Assert.Equal((0, 1), (hidden.Row, hidden.Column));
|
||||
|
||||
vm.ToggleSeatHidden(vm.Seats[1]);
|
||||
|
||||
Assert.False(vm.Seats[1].IsHidden);
|
||||
Assert.Empty(plans.GetById(plan.Id)!.HiddenSeats);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToggleSeatHidden_BelegterPlatz_TutNichts()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var student = new Student { FirstName = "Anna", LastName = "A" };
|
||||
var memberships = new FakeMemberships([
|
||||
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
||||
]);
|
||||
var plan = new SeatingPlan
|
||||
{
|
||||
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
||||
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
||||
};
|
||||
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
||||
memberships, new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
||||
vm.Initialize(groupId, isReadOnly: false);
|
||||
vm.IsEditMode = true;
|
||||
|
||||
vm.ToggleSeatHidden(vm.Seats[0]);
|
||||
|
||||
Assert.False(vm.Seats[0].IsHidden);
|
||||
}
|
||||
|
||||
/// Ein ausgeblendeter Platz darf nie ein Ziel für Drag&Drop/Zuordnung sein - sonst hätte man
|
||||
/// gleichzeitig "kein Tisch hier" und einen dort sitzenden Schüler.
|
||||
[Fact]
|
||||
public void AssignStudent_AufAusgeblendetenPlatz_WirdIgnoriert()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var student = new Student { FirstName = "Anna", LastName = "A" };
|
||||
var memberships = new FakeMemberships([
|
||||
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
||||
]);
|
||||
var plan = new SeatingPlan
|
||||
{
|
||||
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 1,
|
||||
HiddenSeats = [new HiddenSeat { Row = 0, Column = 0 }],
|
||||
};
|
||||
var plans = new FakeSeatingPlans([plan]);
|
||||
var vm = new SeatingPlanTabViewModel(plans, new FakeStudents([student]), memberships,
|
||||
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
||||
vm.Initialize(groupId, isReadOnly: false);
|
||||
vm.IsEditMode = true;
|
||||
|
||||
vm.AssignStudent(vm.StudentOptions.Single(o => o.StudentId == student.Id), vm.Seats[0]);
|
||||
|
||||
Assert.False(vm.Seats[0].IsOccupied);
|
||||
Assert.Empty(plans.GetById(plan.Id)!.Assignments);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MoveSeat_AufAusgeblendetenPlatz_WirdIgnoriert()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var student = new Student { FirstName = "Anna", LastName = "A" };
|
||||
var memberships = new FakeMemberships([
|
||||
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
||||
]);
|
||||
var plan = new SeatingPlan
|
||||
{
|
||||
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
||||
HiddenSeats = [new HiddenSeat { Row = 0, Column = 1 }],
|
||||
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
||||
};
|
||||
var plans = new FakeSeatingPlans([plan]);
|
||||
var vm = new SeatingPlanTabViewModel(plans, new FakeStudents([student]), memberships,
|
||||
new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
||||
vm.Initialize(groupId, isReadOnly: false);
|
||||
vm.IsEditMode = true;
|
||||
|
||||
vm.MoveSeat(vm.Seats[0], vm.Seats[1]);
|
||||
|
||||
Assert.Equal(student.Id, vm.Seats[0].SelectedOption.StudentId);
|
||||
Assert.False(vm.Seats[1].IsOccupied);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShowSeatUndCanToggleHidden_HaengenVonBearbeitungsmodusUndBelegungAb()
|
||||
{
|
||||
var groupId = Guid.NewGuid();
|
||||
var student = new Student { FirstName = "Anna", LastName = "A" };
|
||||
var memberships = new FakeMemberships([
|
||||
new GroupMembership { GroupId = groupId, StudentId = student.Id },
|
||||
]);
|
||||
var plan = new SeatingPlan
|
||||
{
|
||||
GroupId = groupId, Name = "Standard", Rows = 1, Columns = 2,
|
||||
HiddenSeats = [new HiddenSeat { Row = 0, Column = 1 }],
|
||||
Assignments = [new SeatAssignment { Row = 0, Column = 0, StudentId = student.Id }],
|
||||
};
|
||||
var vm = new SeatingPlanTabViewModel(new FakeSeatingPlans([plan]), new FakeStudents([student]),
|
||||
memberships, new FakeSessions([]), new FakeEntries(), new FakeAspects());
|
||||
vm.Initialize(groupId, isReadOnly: false);
|
||||
|
||||
// Ansichtsmodus: der ausgeblendete Platz wird nicht gerendert, belegte Plätze können
|
||||
// ohnehin nicht ausgeblendet werden.
|
||||
Assert.False(vm.Seats[1].ShowSeat);
|
||||
Assert.False(vm.Seats[0].CanToggleHidden);
|
||||
Assert.False(vm.Seats[1].CanToggleHidden);
|
||||
|
||||
vm.IsEditMode = true;
|
||||
|
||||
// Bearbeitungsmodus: der ausgeblendete Platz bleibt sichtbar (abgeblendet), um ihn wieder
|
||||
// einblenden zu können - der belegte Platz kann weiterhin nicht ausgeblendet werden.
|
||||
Assert.True(vm.Seats[1].ShowSeat);
|
||||
Assert.False(vm.Seats[0].CanToggleHidden);
|
||||
Assert.True(vm.Seats[1].CanToggleHidden);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ansichtsmodus_VerhindertVerschiebenUndBlendetBearbeitungsbefehleAus()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user