Edit Stammdaten Mitarbeitsessions
This commit is contained in:
@@ -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 ObservableCollection<CompetencyTagGroup> CompetencyTagGroups { get; } = [];
|
||||||
|
|
||||||
public Func<Task<ParticipationSession?>>? OnAddSession { get; set; }
|
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>? OnQuickInput { get; set; }
|
||||||
public Func<ParticipationTabViewModel, Task>? OnStatusQuickInput { get; set; }
|
public Func<ParticipationTabViewModel, Task>? OnStatusQuickInput { get; set; }
|
||||||
public Func<ParticipationTabViewModel, Task>? OnComputeGrade { get; set; }
|
public Func<ParticipationTabViewModel, Task>? OnComputeGrade { get; set; }
|
||||||
@@ -118,6 +119,7 @@ public partial class ParticipationTabViewModel : ObservableObject
|
|||||||
partial void OnSelectedSessionChanged(ParticipationSessionItem? value)
|
partial void OnSelectedSessionChanged(ParticipationSessionItem? value)
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(SelectedSessionDisplay));
|
OnPropertyChanged(nameof(SelectedSessionDisplay));
|
||||||
|
EditSessionCommand.NotifyCanExecuteChanged();
|
||||||
if (value is null)
|
if (value is null)
|
||||||
{
|
{
|
||||||
StudentRows.Clear();
|
StudentRows.Clear();
|
||||||
@@ -265,6 +267,23 @@ public partial class ParticipationTabViewModel : ObservableObject
|
|||||||
SelectedSession = Sessions.FirstOrDefault(s => s.Id == session.Id);
|
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))]
|
[RelayCommand(CanExecute = nameof(CanQuickInput))]
|
||||||
private async Task QuickInput()
|
private async Task QuickInput()
|
||||||
{
|
{
|
||||||
@@ -716,12 +735,26 @@ public class ParticipationSessionItem
|
|||||||
|
|
||||||
public partial class AddSessionDialogViewModel : ObservableObject
|
public partial class AddSessionDialogViewModel : ObservableObject
|
||||||
{
|
{
|
||||||
|
private readonly ParticipationSession? _editingSession;
|
||||||
|
|
||||||
[ObservableProperty] private DateOnly _date = DateOnly.FromDateTime(DateTime.Today);
|
[ObservableProperty] private DateOnly _date = DateOnly.FromDateTime(DateTime.Today);
|
||||||
[ObservableProperty] private string _comment = "";
|
[ObservableProperty] private string _comment = "";
|
||||||
[ObservableProperty] private string _dateText = DateOnly.FromDateTime(DateTime.Today).ToString("dd.MM.yyyy");
|
[ObservableProperty] private string _dateText = DateOnly.FromDateTime(DateTime.Today).ToString("dd.MM.yyyy");
|
||||||
[ObservableProperty] private string _dateTextError = "";
|
[ObservableProperty] private string _dateTextError = "";
|
||||||
|
|
||||||
public ParticipationSession? Result { get; private set; }
|
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]
|
[RelayCommand]
|
||||||
private void Save()
|
private void Save()
|
||||||
@@ -733,7 +766,10 @@ public partial class AddSessionDialogViewModel : ObservableObject
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DateTextError = "";
|
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"
|
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
|
||||||
x:Class="LehrerApp.Desktop.Views.Groups.AddSessionDialog"
|
x:Class="LehrerApp.Desktop.Views.Groups.AddSessionDialog"
|
||||||
x:DataType="vm:AddSessionDialogViewModel"
|
x:DataType="vm:AddSessionDialogViewModel"
|
||||||
Title="Bewertungszeitpunkt anlegen"
|
Title="{Binding DialogTitle}"
|
||||||
Width="380" SizeToContent="Height"
|
Width="380" SizeToContent="Height"
|
||||||
CanResize="False" WindowStartupLocation="CenterOwner">
|
CanResize="False" WindowStartupLocation="CenterOwner">
|
||||||
|
|
||||||
<Grid RowDefinitions="*,Auto" Margin="24">
|
<Grid RowDefinitions="*,Auto" Margin="24">
|
||||||
<StackPanel Grid.Row="0" Spacing="14">
|
<StackPanel Grid.Row="0" Spacing="14">
|
||||||
<TextBlock Text="Neuer Bewertungszeitpunkt" Classes="dialogtitle"/>
|
<TextBlock Text="{Binding DialogTitle}" Classes="dialogtitle"/>
|
||||||
|
|
||||||
<StackPanel Spacing="4">
|
<StackPanel Spacing="4">
|
||||||
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
|
<TextBlock Text="Datum *" FontSize="12" Opacity="0.7"/>
|
||||||
@@ -20,13 +20,14 @@
|
|||||||
|
|
||||||
<StackPanel Spacing="4">
|
<StackPanel Spacing="4">
|
||||||
<TextBlock Text="Kommentar (optional)" FontSize="12" Opacity="0.7"/>
|
<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>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
|
<Grid Grid.Row="1" ColumnDefinitions="*,8,*" Margin="0,20,0,0">
|
||||||
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
|
<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>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@@ -11,7 +11,16 @@ public partial class AddSessionDialog : Window
|
|||||||
protected override void OnOpened(EventArgs e)
|
protected override void OnOpened(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnOpened(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)
|
private void OnSave(object? s, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -53,13 +53,16 @@
|
|||||||
Text="{Binding SelectedSessionDisplay}"
|
Text="{Binding SelectedSessionDisplay}"
|
||||||
FontSize="13" FontWeight="SemiBold"
|
FontSize="13" FontWeight="SemiBold"
|
||||||
VerticalAlignment="Center"/>
|
VerticalAlignment="Center"/>
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
|
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6">
|
||||||
IsVisible="{Binding HasCompetencyCatalog}">
|
<Button Content="✎ Sitzung bearbeiten" Command="{Binding EditSessionCommand}"
|
||||||
|
IsVisible="{Binding !IsReadOnly}" FontSize="11" Padding="8,3"/>
|
||||||
<ToggleButton Content="◇ Kompetenzen"
|
<ToggleButton Content="◇ Kompetenzen"
|
||||||
IsChecked="{Binding CompetencyTagsVisible}"
|
IsChecked="{Binding CompetencyTagsVisible}"
|
||||||
|
IsVisible="{Binding HasCompetencyCatalog}"
|
||||||
FontSize="11" Padding="8,3"/>
|
FontSize="11" Padding="8,3"/>
|
||||||
<ToggleButton Content="◈ Schüler-Bewertungen"
|
<ToggleButton Content="◈ Schüler-Bewertungen"
|
||||||
IsChecked="{Binding StudentCompetencyRatingsVisible}"
|
IsChecked="{Binding StudentCompetencyRatingsVisible}"
|
||||||
|
IsVisible="{Binding HasCompetencyCatalog}"
|
||||||
FontSize="11" Padding="8,3"/>
|
FontSize="11" Padding="8,3"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ public partial class ParticipationTabView : UserControl
|
|||||||
{
|
{
|
||||||
_vm = vm;
|
_vm = vm;
|
||||||
vm.OnAddSession = ShowAddSessionDialog;
|
vm.OnAddSession = ShowAddSessionDialog;
|
||||||
|
vm.OnEditSession = ShowEditSessionDialog;
|
||||||
vm.OnQuickInput = ShowQuickInputDialog;
|
vm.OnQuickInput = ShowQuickInputDialog;
|
||||||
vm.OnStatusQuickInput = ShowStatusQuickInputDialog;
|
vm.OnStatusQuickInput = ShowStatusQuickInputDialog;
|
||||||
vm.OnComputeGrade = ShowComputeGradeDialog;
|
vm.OnComputeGrade = ShowComputeGradeDialog;
|
||||||
@@ -283,6 +284,17 @@ public partial class ParticipationTabView : UserControl
|
|||||||
return ok ? vm.Result : null;
|
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)
|
private async Task ShowQuickInputDialog(ParticipationTabViewModel tabVm)
|
||||||
{
|
{
|
||||||
if (tabVm.StudentRows.Count == 0) return;
|
if (tabVm.StudentRows.Count == 0) return;
|
||||||
|
|||||||
Reference in New Issue
Block a user