Kompetenzen fast fertig

This commit is contained in:
2026-08-16 02:32:12 +02:00
parent 7c7fe6dfcb
commit 4437f951d9
22 changed files with 979 additions and 29 deletions
@@ -0,0 +1,68 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
x:Class="LehrerApp.Desktop.Views.Groups.CompetencyOverviewTabView"
x:DataType="vm:CompetencyOverviewTabViewModel">
<Grid RowDefinitions="Auto,*" Margin="20">
<StackPanel Grid.Row="0" Spacing="10" Margin="0,0,0,12">
<Grid ColumnDefinitions="*,Auto">
<StackPanel Grid.Column="0" Spacing="3">
<TextBlock Text="Kompetenzübersicht" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="{Binding Summary}" FontSize="12" Opacity="0.65"/>
</StackPanel>
<Button Grid.Column="1" Content="Aktualisieren" Command="{Binding RefreshCommand}"/>
</Grid>
<Grid ColumnDefinitions="*,16,210" IsVisible="{Binding HasRows}">
<StackPanel Grid.Column="0" Spacing="4">
<TextBlock Text="Schülerprofil" FontSize="12" Opacity="0.7"/>
<ComboBox ItemsSource="{Binding StudentOptions}" SelectedItem="{Binding SelectedStudent}"
PlaceholderText="Keine Schüler vorhanden" IsEnabled="{Binding HasStudents}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="vm:CompetencyStudentOption">
<TextBlock Text="{Binding DisplayName}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
<StackPanel Grid.Column="2" Spacing="4">
<TextBlock Text="{Binding ThresholdLabel}" FontSize="12" Opacity="0.7"/>
<NumericUpDown Value="{Binding ReviewThreshold}" Minimum="0" Maximum="100"
Increment="5" FormatString="0"/>
</StackPanel>
</Grid>
<TextBlock Text="Prozentwerte beruhen auf bewerteten Klausuraufgaben. Eine Aufgabe mit mehreren Kompetenzcodes zählt für jede dieser Kompetenzen."
TextWrapping="Wrap" FontSize="11" Opacity="0.55" IsVisible="{Binding HasRows}"/>
</StackPanel>
<Grid Grid.Row="1">
<TextBlock Text="{Binding EmptyMessage}" Classes="emptyhint"
HorizontalAlignment="Center" VerticalAlignment="Center"
TextWrapping="Wrap" MaxWidth="520"
IsVisible="{Binding !HasRows}"/>
<DataGrid ItemsSource="{Binding Rows}" AutoGenerateColumns="False" IsReadOnly="True"
GridLinesVisibility="Horizontal" CanUserReorderColumns="False"
CanUserResizeColumns="True" IsVisible="{Binding HasRows}">
<DataGrid.Columns>
<DataGridTextColumn Header="Bereich" Binding="{Binding Domain}" Width="170"/>
<DataGridTextColumn Header="Code" Binding="{Binding Code}" Width="75"/>
<DataGridTextColumn Header="Kompetenz" Binding="{Binding Description}" Width="2*"/>
<DataGridTextColumn Header="Unterricht" Binding="{Binding InstructionCoverage}" Width="145"/>
<DataGridTextColumn Header="Klausuren" Binding="{Binding ExamCoverage}" Width="135"/>
<DataGridTextColumn Header="Gruppenmittel" Binding="{Binding GroupResult}" Width="210"/>
<DataGridTextColumn Header="Ausgewählter Schüler" Binding="{Binding StudentResult}" Width="160"/>
<DataGridTemplateColumn Header="Hinweis" Width="155">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate x:DataType="vm:CompetencyOverviewRow">
<TextBlock Text="{Binding Recommendation}" Foreground="{Binding RecommendationColor}"
FontWeight="SemiBold" VerticalAlignment="Center"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Grid>
</UserControl>
@@ -0,0 +1,8 @@
using Avalonia.Controls;
namespace LehrerApp.Desktop.Views.Groups;
public partial class CompetencyOverviewTabView : UserControl
{
public CompetencyOverviewTabView() => InitializeComponent();
}
@@ -191,6 +191,11 @@
<views:PlanningTabView DataContext="{Binding PlanningTab}"/>
</ContentPage>
<!-- Tab: Kompetenzen -->
<ContentPage Header="Kompetenzen">
<views:CompetencyOverviewTabView DataContext="{Binding CompetencyOverviewTab}"/>
</ContentPage>
<!-- Tab: Dokumentation -->
<ContentPage Header="Dokumentation">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
@@ -132,11 +132,16 @@
Padding="12,9"
Command="{Binding NavigateToSectionCommand}"
CommandParameter="5"/>
<Button Content="📋 Dokumentation"
<Button Content="🎯 Kompetenzübersicht"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Padding="12,9"
Command="{Binding NavigateToSectionCommand}"
CommandParameter="6"/>
<Button Content="📋 Dokumentation"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Left"
Padding="12,9"
Command="{Binding NavigateToSectionCommand}"
CommandParameter="7"/>
</StackPanel>
</StackPanel>
@@ -0,0 +1,29 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Settings"
x:Class="LehrerApp.Desktop.Views.Settings.CompetencyCatalogCopyTargetDialog"
x:DataType="vm:CompetencyCatalogCopyTargetViewModel"
Title="Kompetenzkatalog kopieren"
Width="460" Height="280" CanResize="False"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*,Auto" Margin="24,20">
<StackPanel Grid.Row="0" Spacing="8">
<TextBlock Text="Katalog kopieren" Classes="dialogtitle"/>
<TextBlock Text="{Binding SourceLabel}" FontWeight="SemiBold"/>
<TextBlock Text="Wähle die Zielklassenstufe. Anschließend kannst du vorhandene Einträge und Konflikte in einer Vorschau prüfen."
TextWrapping="Wrap" FontSize="12" Opacity="0.7"/>
</StackPanel>
<StackPanel Grid.Row="1" Spacing="5" Margin="0,16,0,0">
<TextBlock Text="Zielklassenstufe" FontSize="12" Opacity="0.7"/>
<NumericUpDown Value="{Binding TargetGradeLevel}" Minimum="1" Maximum="13" FormatString="0"/>
<TextBlock Text="{Binding Error}" Foreground="Red" FontSize="12"
IsVisible="{Binding Error, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
</StackPanel>
<Grid Grid.Row="2" ColumnDefinitions="*,10,*" Margin="0,16,0,0">
<Button Grid.Column="0" Content="Abbrechen" HorizontalAlignment="Stretch" Click="OnCancel"/>
<Button Grid.Column="2" Content="Weiter zur Vorschau" HorizontalAlignment="Stretch" Click="OnContinue"/>
</Grid>
</Grid>
</Window>
@@ -0,0 +1,18 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using LehrerApp.Desktop.ViewModels.Settings;
namespace LehrerApp.Desktop.Views.Settings;
public partial class CompetencyCatalogCopyTargetDialog : Window
{
public CompetencyCatalogCopyTargetDialog() => InitializeComponent();
private void OnContinue(object? sender, RoutedEventArgs e)
{
if (DataContext is CompetencyCatalogCopyTargetViewModel vm && vm.Validate())
Close((int?)vm.TargetGradeLevel);
}
private void OnCancel(object? sender, RoutedEventArgs e) => Close(null);
}
@@ -3,12 +3,12 @@
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels.Settings"
x:Class="LehrerApp.Desktop.Views.Settings.CompetencyCatalogImportDialog"
x:DataType="vm:CompetencyCatalogImportViewModel"
Title="Kompetenzkatalog importieren"
Title="{Binding Heading}"
Width="760" Height="720" MinWidth="620" MinHeight="560"
CanResize="True" WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,*,Auto" Margin="24,20">
<StackPanel Grid.Row="0" Spacing="10">
<TextBlock Text="Import prüfen" Classes="dialogtitle"/>
<TextBlock Text="{Binding Heading}" Classes="dialogtitle"/>
<TextBlock Text="{Binding Target}" FontWeight="SemiBold"/>
<TextBlock Text="{Binding Summary}" FontSize="12" Opacity="0.7"/>
@@ -111,7 +111,7 @@
<StackPanel Margin="32,20,32,28" Spacing="14" MaxWidth="640">
<!-- Fach + Klassenstufe Auswahl + Import/Export -->
<Grid ColumnDefinitions="*,12,120,12,Auto,8,Auto">
<Grid ColumnDefinitions="*,12,100,12,Auto,8,Auto,8,Auto">
<ComboBox Grid.Column="0"
ItemsSource="{Binding Subjects}"
SelectedItem="{Binding CatalogSubject}"
@@ -130,6 +130,9 @@
IsEnabled="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<Button Grid.Column="6" Content="JSON exportieren" Click="OnExportClick"
IsEnabled="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}"/>
<Button Grid.Column="8" Content="Kopieren…" Click="OnCopyCatalogClick"
IsEnabled="{Binding CatalogSubject, Converter={x:Static ObjectConverters.IsNotNull}}"
ToolTip.Tip="Katalog in eine andere Klassenstufe kopieren"/>
</Grid>
<!-- Katalog-Validierungsmeldung -->
@@ -150,10 +153,14 @@
<StackPanel Spacing="8">
<!-- Bereichs-Header -->
<Grid ColumnDefinitions="*,Auto">
<Grid ColumnDefinitions="*,Auto,4,Auto,8,Auto">
<TextBlock Grid.Column="0" Text="{Binding DisplayName}"
FontWeight="SemiBold" FontSize="14" VerticalAlignment="Center"/>
<Button Grid.Column="1" Content="Bereich löschen" FontSize="12" Padding="10,4"
<Button Grid.Column="1" Content="" FontSize="13" Padding="8,3"
Command="{Binding MoveUpCommand}" ToolTip.Tip="Bereich nach oben"/>
<Button Grid.Column="3" Content="↓" FontSize="13" Padding="8,3"
Command="{Binding MoveDownCommand}" ToolTip.Tip="Bereich nach unten"/>
<Button Grid.Column="5" Content="Bereich löschen" FontSize="12" Padding="10,4"
Command="{Binding $parent[ItemsControl].((vm:SettingsViewModel)DataContext).DeleteDomainCommand}"
CommandParameter="{Binding}"/>
</Grid>
@@ -162,11 +169,15 @@
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="vm:CompetencyItemVm">
<Grid ColumnDefinitions="*,Auto" Margin="0,3">
<Grid ColumnDefinitions="*,Auto,4,Auto,6,Auto" Margin="0,3">
<TextBlock Grid.Column="0" Text="{Binding Display}"
TextWrapping="Wrap" VerticalAlignment="Center"
FontSize="13"/>
<Button Grid.Column="1" Content="×" Padding="7,2" FontSize="13"
<Button Grid.Column="1" Content="" Padding="7,2" FontSize="12"
Command="{Binding MoveUpCommand}" ToolTip.Tip="Kompetenz nach oben"/>
<Button Grid.Column="3" Content="↓" Padding="7,2" FontSize="12"
Command="{Binding MoveDownCommand}" ToolTip.Tip="Kompetenz nach unten"/>
<Button Grid.Column="5" Content="×" Padding="7,2" FontSize="13"
Command="{Binding DeleteCommand}"/>
</Grid>
</DataTemplate>
@@ -93,6 +93,30 @@ public partial class SettingsView : UserControl
await File.WriteAllTextAsync(file.Path.LocalPath, json);
}
private async void OnCopyCatalogClick(object? sender, RoutedEventArgs e)
{
if (DataContext is not SettingsViewModel { CatalogSubject: not null } vm) return;
var owner = TopLevel.GetTopLevel(this) as Window;
if (owner is null) return;
var targetDialog = new CompetencyCatalogCopyTargetDialog
{
DataContext = new CompetencyCatalogCopyTargetViewModel(
vm.CatalogSubject.Name, vm.CatalogGradeLevel),
};
var targetGradeLevel = await targetDialog.ShowDialog<int?>(owner);
if (targetGradeLevel is null) return;
var preview = vm.PrepareCatalogCopy(targetGradeLevel.Value);
if (preview is null) return;
var previewDialog = new CompetencyCatalogImportDialog
{
DataContext = new CompetencyCatalogImportViewModel(vm, preview, "Kopie prüfen"),
};
if (await previewDialog.ShowDialog<bool>(owner))
vm.SetCatalogCopyStatus(targetGradeLevel.Value);
}
private async void OnEditGradingKeyTemplateClick(object? sender, RoutedEventArgs e)
{
if (sender is not Button { Tag: GradingKeyTemplateEditItem item }) return;