Edit Stammdaten Mitarbeitsessions

This commit is contained in:
2026-08-19 12:47:09 +02:00
parent b2c1b15167
commit 9106b4b0e1
6 changed files with 131 additions and 8 deletions
@@ -0,0 +1,62 @@
using LehrerApp.Core.Models;
using LehrerApp.Desktop.ViewModels.Groups;
using Xunit;
namespace LehrerApp.Desktop.Tests;
public sealed class ParticipationSessionEditingTests
{
[Fact]
public void Bearbeitungsdialog_AendertBestehendeSessionOhneVerknuepfungenZuErsetzen()
{
var session = new ParticipationSession
{
GroupId = Guid.NewGuid(),
Date = new DateOnly(2026, 8, 19),
Comment = "Sitzplan",
LessonId = Guid.NewGuid(),
CompetencyCodes = ["K1"],
};
var vm = new AddSessionDialogViewModel(session)
{
DateText = "20.08.2026",
Comment = "Elektrische Stromkreise",
};
vm.SaveCommand.Execute(null);
Assert.Same(session, vm.Result);
Assert.Equal(new DateOnly(2026, 8, 20), session.Date);
Assert.Equal("Elektrische Stromkreise", session.Comment);
Assert.NotNull(session.LessonId);
Assert.Equal(["K1"], session.CompetencyCodes);
}
[Fact]
public async Task BearbeitenBefehl_SpeichertSessionUndAktualisiertAnzeige()
{
var group = new LearningGroup { Name = "8a", SchoolYear = "2026/27" };
var session = new ParticipationSession
{
GroupId = group.Id,
Date = new DateOnly(2026, 8, 19),
Comment = "Sitzplan",
};
var sessions = new FakeSessions([session]);
var vm = new ParticipationTabViewModel(
sessions, new FakeEntries(), new FakeAspects(), new FakeStudents([]),
new FakeMemberships([]), new FakeGroups([group]), new FakeCompetencyDomains());
vm.OnEditSession = existing =>
{
existing.Comment = "Nachbesprechung Elektrizität";
return Task.FromResult<ParticipationSession?>(existing);
};
vm.Initialize(group.Id, group.SchoolYear);
await vm.EditSessionCommand.ExecuteAsync(null);
Assert.Equal(session.Id, vm.SelectedSession?.Id);
Assert.Equal("Nachbesprechung Elektrizität", sessions.GetById(session.Id)?.Comment);
Assert.Contains("Nachbesprechung Elektrizität", vm.SelectedSessionDisplay);
}
}
@@ -48,6 +48,7 @@ public partial class ParticipationTabViewModel : ObservableObject
public ObservableCollection<CompetencyTagGroup> CompetencyTagGroups { get; } = [];
public Func<Task<ParticipationSession?>>? OnAddSession { get; set; }
public Func<ParticipationSession, Task<ParticipationSession?>>? OnEditSession { get; set; }
public Func<ParticipationTabViewModel, Task>? OnQuickInput { get; set; }
public Func<ParticipationTabViewModel, Task>? OnStatusQuickInput { get; set; }
public Func<ParticipationTabViewModel, Task>? OnComputeGrade { get; set; }
@@ -118,6 +119,7 @@ public partial class ParticipationTabViewModel : ObservableObject
partial void OnSelectedSessionChanged(ParticipationSessionItem? value)
{
OnPropertyChanged(nameof(SelectedSessionDisplay));
EditSessionCommand.NotifyCanExecuteChanged();
if (value is null)
{
StudentRows.Clear();
@@ -265,6 +267,23 @@ public partial class ParticipationTabViewModel : ObservableObject
SelectedSession = Sessions.FirstOrDefault(s => s.Id == session.Id);
}
[RelayCommand(CanExecute = nameof(CanEditSession))]
private async Task EditSession()
{
if (SelectedSession is null || OnEditSession is null) return;
var session = _sessions.GetById(SelectedSession.Id);
if (session is null) return;
var edited = await OnEditSession(session);
if (edited is null) return;
edited.GroupId = _groupId;
_sessions.Save(edited);
LoadSessions();
}
private bool CanEditSession() => !IsReadOnly && SelectedSession is not null;
partial void OnIsReadOnlyChanged(bool value) => EditSessionCommand.NotifyCanExecuteChanged();
[RelayCommand(CanExecute = nameof(CanQuickInput))]
private async Task QuickInput()
{
@@ -716,12 +735,26 @@ public class ParticipationSessionItem
public partial class AddSessionDialogViewModel : ObservableObject
{
private readonly ParticipationSession? _editingSession;
[ObservableProperty] private DateOnly _date = DateOnly.FromDateTime(DateTime.Today);
[ObservableProperty] private string _comment = "";
[ObservableProperty] private string _dateText = DateOnly.FromDateTime(DateTime.Today).ToString("dd.MM.yyyy");
[ObservableProperty] private string _dateTextError = "";
public ParticipationSession? Result { get; private set; }
public bool IsEditing => _editingSession is not null;
public string DialogTitle => IsEditing ? "Bewertungszeitpunkt bearbeiten" : "Bewertungszeitpunkt anlegen";
public string SaveButtonText => IsEditing ? "Speichern" : "Anlegen";
public AddSessionDialogViewModel(ParticipationSession? editingSession = null)
{
_editingSession = editingSession;
if (editingSession is null) return;
Date = editingSession.Date;
DateText = editingSession.Date.ToString("dd.MM.yyyy");
Comment = editingSession.Comment ?? "";
}
[RelayCommand]
private void Save()
@@ -733,7 +766,10 @@ public partial class AddSessionDialogViewModel : ObservableObject
return;
}
DateTextError = "";
Result = new ParticipationSession { Date = date, Comment = Comment.Trim() };
var session = _editingSession ?? new ParticipationSession();
session.Date = date;
session.Comment = Comment.Trim();
Result = session;
}
}
@@ -3,13 +3,13 @@
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
x:Class="LehrerApp.Desktop.Views.Groups.AddSessionDialog"
x:DataType="vm:AddSessionDialogViewModel"
Title="Bewertungszeitpunkt anlegen"
Title="{Binding DialogTitle}"
Width="380" SizeToContent="Height"
CanResize="False" WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="*,Auto" Margin="24">
<StackPanel Grid.Row="0" Spacing="14">
<TextBlock Text="Neuer Bewertungszeitpunkt" Classes="dialogtitle"/>
<TextBlock Text="{Binding DialogTitle}" Classes="dialogtitle"/>
<StackPanel Spacing="4">
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
@@ -20,13 +20,14 @@
<StackPanel Spacing="4">
<TextBlock Text="Kommentar (optional)" FontSize="12" Opacity="0.7"/>
<TextBox Text="{Binding Comment}" PlaceholderText="z. B. Stunde 12 Säure-Base-Reaktion"/>
<TextBox Text="{Binding Comment}" PlaceholderText="z. B. Stunde 12 Säure-Base-Reaktion"
x:Name="CommentBox"/>
</StackPanel>
</StackPanel>
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
<Button Grid.Column="2" Content="Anlegen" HorizontalAlignment="Stretch" Click="OnSave"/>
<Button Grid.Column="2" Content="{Binding SaveButtonText}" HorizontalAlignment="Stretch" Click="OnSave"/>
</Grid>
</Grid>
</Window>
@@ -11,7 +11,16 @@ public partial class AddSessionDialog : Window
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
this.FindControl<TextBox>("DateBox")?.Focus();
if (DataContext is AddSessionDialogViewModel { IsEditing: true })
{
var commentBox = this.FindControl<TextBox>("CommentBox");
commentBox?.Focus();
commentBox?.SelectAll();
}
else
{
this.FindControl<TextBox>("DateBox")?.Focus();
}
}
private void OnSave(object? s, RoutedEventArgs e)
@@ -53,13 +53,16 @@
Text="{Binding SelectedSessionDisplay}"
FontSize="13" FontWeight="SemiBold"
VerticalAlignment="Center"/>
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
IsVisible="{Binding HasCompetencyCatalog}">
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6">
<Button Content="✎ Sitzung bearbeiten" Command="{Binding EditSessionCommand}"
IsVisible="{Binding !IsReadOnly}" FontSize="11" Padding="8,3"/>
<ToggleButton Content="◇ Kompetenzen"
IsChecked="{Binding CompetencyTagsVisible}"
IsVisible="{Binding HasCompetencyCatalog}"
FontSize="11" Padding="8,3"/>
<ToggleButton Content="◈ Schüler-Bewertungen"
IsChecked="{Binding StudentCompetencyRatingsVisible}"
IsVisible="{Binding HasCompetencyCatalog}"
FontSize="11" Padding="8,3"/>
</StackPanel>
</Grid>
@@ -23,6 +23,7 @@ public partial class ParticipationTabView : UserControl
{
_vm = vm;
vm.OnAddSession = ShowAddSessionDialog;
vm.OnEditSession = ShowEditSessionDialog;
vm.OnQuickInput = ShowQuickInputDialog;
vm.OnStatusQuickInput = ShowStatusQuickInputDialog;
vm.OnComputeGrade = ShowComputeGradeDialog;
@@ -283,6 +284,17 @@ public partial class ParticipationTabView : UserControl
return ok ? vm.Result : null;
}
private async Task<LehrerApp.Core.Models.ParticipationSession?> ShowEditSessionDialog(
LehrerApp.Core.Models.ParticipationSession session)
{
var vm = new AddSessionDialogViewModel(session);
var dialog = new AddSessionDialog { DataContext = vm };
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner is null) return null;
var ok = await dialog.ShowDialog<bool>(owner);
return ok ? vm.Result : null;
}
private async Task ShowQuickInputDialog(ParticipationTabViewModel tabVm)
{
if (tabVm.StudentRows.Count == 0) return;