Nutzer-Feedback: Klassenlehrer ist eine Rolle für die ganze Klasse, unabhängig vom eigenen Unterricht - die Anbindung an ein LearningGroup.IsClassTeacher-Flag mit Tab in der Gruppendetailansicht war deshalb der falsche Ort. Ersetzt durch: - Klassenauswahl in den WebUntis-Einstellungen (WebUntisSettingsService.HomeroomClassName), über den bestehenden WebUntis-Klassenpicker. - Eigener Sidebar-Bereich "Klassenlehrer" statt Gruppen-Tab. - Zwei Ebenen: kompakte Roster-Übersicht mit Ampel-Symbolen (Fehlzeiten heute, Klassenbuch-Badge) und Details (die bisherigen Rohdaten-Listen, jetzt gefiltert auf einzelne Schüler*innen anspringbar). Noch nicht mit echtem WebUntis-Zugang gegengeprüft (siehe TODO.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
312 lines
16 KiB
XML
312 lines
16 KiB
XML
<Window xmlns="https://github.com/avaloniaui"
|
||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||
xmlns:vm="clr-namespace:LehrerApp.Desktop.ViewModels"
|
||
xmlns:vmg="clr-namespace:LehrerApp.Desktop.ViewModels.Groups"
|
||
xmlns:vms="clr-namespace:LehrerApp.Desktop.ViewModels.Students"
|
||
xmlns:views="clr-namespace:LehrerApp.Desktop.Views"
|
||
xmlns:vd="clr-namespace:LehrerApp.Desktop.Views.Dashboard"
|
||
xmlns:vg="clr-namespace:LehrerApp.Desktop.Views.Groups"
|
||
xmlns:vs="clr-namespace:LehrerApp.Desktop.Views.Students"
|
||
xmlns:vset="clr-namespace:LehrerApp.Desktop.Views.Settings"
|
||
xmlns:vmset="clr-namespace:LehrerApp.Desktop.ViewModels.Settings"
|
||
xmlns:vp="clr-namespace:LehrerApp.Desktop.Views.Planning"
|
||
xmlns:vmp="clr-namespace:LehrerApp.Desktop.ViewModels.Planning"
|
||
xmlns:vw="clr-namespace:LehrerApp.Desktop.Views.Workload"
|
||
xmlns:vmw="clr-namespace:LehrerApp.Desktop.ViewModels.Workload"
|
||
xmlns:vct="clr-namespace:LehrerApp.Desktop.Views.ClassTeacher"
|
||
xmlns:vmct="clr-namespace:LehrerApp.Desktop.ViewModels.ClassTeacher"
|
||
xmlns:svc="clr-namespace:LehrerApp.Desktop.Services"
|
||
x:Class="LehrerApp.Desktop.Views.MainWindow"
|
||
x:DataType="vm:MainWindowViewModel"
|
||
Title="LehrerApp"
|
||
Width="1280" Height="800"
|
||
MinWidth="900" MinHeight="600">
|
||
|
||
<Panel>
|
||
<!--
|
||
Avalonia 12: DrawerPage ersetzt die selbstgebaute Sidebar.
|
||
DrawerBreakpointWidth="900" → Sidebar ab 900px dauerhaft sichtbar,
|
||
darunter als Overlay-Drawer mit Hamburger-Button (automatisch).
|
||
Kein eigener Code nötig.
|
||
-->
|
||
<DrawerPage x:Name="RootDrawer"
|
||
DrawerLength="220"
|
||
DrawerBehavior="Auto"
|
||
DrawerLayoutBehavior="CompactInline"
|
||
Content="{Binding CurrentPage}">
|
||
|
||
<DrawerPage.DataTemplates>
|
||
<DataTemplate DataType="vm:DashboardViewModel">
|
||
<vd:DashboardView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vmg:GroupListViewModel">
|
||
<vg:GroupListView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vmg:GroupDetailViewModel">
|
||
<vg:GroupDetailView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vms:StudentListViewModel">
|
||
<vs:StudentListView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vms:StudentDetailViewModel">
|
||
<vs:StudentDetailView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vmset:SettingsViewModel">
|
||
<vset:SettingsView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vmp:TimetableViewModel">
|
||
<vp:TimetableView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vmw:WorkloadViewModel">
|
||
<vw:WorkloadView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vmct:ClassTeacherOverviewViewModel">
|
||
<vct:ClassTeacherOverviewView/>
|
||
</DataTemplate>
|
||
<DataTemplate DataType="vm:PlaceholderViewModel">
|
||
<views:PlaceholderView/>
|
||
</DataTemplate>
|
||
</DrawerPage.DataTemplates>
|
||
|
||
<DrawerPage.Drawer>
|
||
<DockPanel Classes.compact="{Binding !#RootDrawer.IsOpen}">
|
||
<DockPanel.Styles>
|
||
<!-- Basisgröße der Icons als Style (nicht lokal), damit der Compact-Selector sie
|
||
überschreiben kann – lokale Werte hätten immer Vorrang vor Style-Settern.
|
||
FontFamily explizit auf die farbige Emoji-Schrift gepinnt: Windows kann für
|
||
Emoji-Codepoints je nach Fallback-Auflösung sonst auf "Segoe UI Symbol"
|
||
(einfarbig/schwarz) statt "Segoe UI Emoji" (farbig) ausweichen. -->
|
||
<Style Selector="TextBlock.navicon">
|
||
<Setter Property="FontSize" Value="15"/>
|
||
<Setter Property="Width" Value="24"/>
|
||
<Setter Property="FontFamily" Value="Segoe UI Emoji,Segoe UI Symbol,Segoe UI"/>
|
||
</Style>
|
||
<Style Selector="Button.navitem">
|
||
<Setter Property="Background" Value="Transparent"/>
|
||
<Setter Property="Padding" Value="10,8"/>
|
||
</Style>
|
||
<Style Selector="Button.navitem.active">
|
||
<Setter Property="Background" Value="{DynamicResource SystemControlBackgroundAccentBrush}"/>
|
||
<Setter Property="Foreground" Value="White"/>
|
||
</Style>
|
||
<!-- Minimierter Zustand: Icons größer & zentriert, Beschriftungen ausgeblendet -->
|
||
<Style Selector="DockPanel.compact TextBlock.navlabel">
|
||
<Setter Property="IsVisible" Value="False"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact TextBlock.navicon">
|
||
<Setter Property="FontSize" Value="20"/>
|
||
<Setter Property="Width" Value="28"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact Button.navitem">
|
||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||
<Setter Property="Padding" Value="2,8"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact StackPanel.navitems">
|
||
<Setter Property="Margin" Value="2,12,2,0"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact StackPanel.navcontent">
|
||
<Setter Property="Spacing" Value="0"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact Border.drawerheader">
|
||
<Setter Property="Padding" Value="8,20,8,14"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact TextBlock.navsection">
|
||
<Setter Property="IsVisible" Value="False"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact TextBlock.appsubtitle">
|
||
<Setter Property="IsVisible" Value="False"/>
|
||
</Style>
|
||
<Style Selector="DockPanel.compact Border.appheader">
|
||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||
</Style>
|
||
</DockPanel.Styles>
|
||
|
||
<Border Classes="drawerheader" DockPanel.Dock="Top" Padding="16,20,16,14"
|
||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||
BorderThickness="0,0,0,1">
|
||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||
<Border Classes="appheader" Width="32" Height="32" CornerRadius="8"
|
||
Background="{DynamicResource SystemControlBackgroundAccentBrush}">
|
||
<TextBlock Text="L" FontSize="16" FontWeight="Bold" Foreground="White"
|
||
HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||
</Border>
|
||
<StackPanel Classes="appsubtitle" VerticalAlignment="Center">
|
||
<TextBlock Text="LehrerApp" FontSize="15" FontWeight="SemiBold"/>
|
||
<TextBlock Text="{Binding CurrentSchoolYear}"
|
||
FontSize="11" Opacity="0.55"/>
|
||
</StackPanel>
|
||
</StackPanel>
|
||
</Border>
|
||
|
||
<Border DockPanel.Dock="Bottom" Padding="12,8"
|
||
BorderBrush="{DynamicResource SystemControlForegroundBaseLowBrush}"
|
||
BorderThickness="0,1,0,0">
|
||
<views:SyncStatusBar DataContext="{Binding SyncStatus}"/>
|
||
</Border>
|
||
|
||
<ScrollViewer>
|
||
<StackPanel Classes="navitems" Margin="8,12,8,0" Spacing="2">
|
||
<Button Classes="navitem" Classes.active="{Binding IsDashboardActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Dashboard}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="📊" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Dashboard"/>
|
||
</StackPanel>
|
||
</Button>
|
||
|
||
<TextBlock Classes="navsection" Text="UNTERRICHT" FontSize="10" FontWeight="Bold"
|
||
Opacity="0.4" Margin="10,14,0,4"/>
|
||
|
||
<Button Classes="navitem" Classes.active="{Binding IsGroupsActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Groups}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="🏫" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Lerngruppen"/>
|
||
</StackPanel>
|
||
</Button>
|
||
<Button Classes="navitem" Classes.active="{Binding IsStudentsActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Students}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="👤" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Schüler"/>
|
||
</StackPanel>
|
||
</Button>
|
||
<Button Classes="navitem" Classes.active="{Binding IsExamsActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Exams}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="📝" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Klausuren"/>
|
||
</StackPanel>
|
||
</Button>
|
||
<Button Classes="navitem" Classes.active="{Binding IsPlannerActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Planner}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="📅" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Planung"/>
|
||
</StackPanel>
|
||
</Button>
|
||
|
||
<TextBlock Classes="navsection" Text="VERWALTUNG" FontSize="10" FontWeight="Bold"
|
||
Opacity="0.4" Margin="10,14,0,4"/>
|
||
|
||
<Button Classes="navitem" Classes.active="{Binding IsWorkloadActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Workload}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="⏱" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Arbeitszeit"/>
|
||
</StackPanel>
|
||
</Button>
|
||
<Button Classes="navitem" Classes.active="{Binding IsClassTeacherActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.ClassTeacher}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="🎓" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Klassenlehrer"/>
|
||
</StackPanel>
|
||
</Button>
|
||
<Button Classes="navitem" Classes.active="{Binding IsSettingsActive}" HorizontalAlignment="Stretch"
|
||
HorizontalContentAlignment="Left"
|
||
CornerRadius="6"
|
||
Command="{Binding NavigateToCommand}"
|
||
CommandParameter="{x:Static vm:NavItem.Settings}">
|
||
<StackPanel Classes="navcontent" Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Classes="navicon" Text="⚙️" TextAlignment="Center"/>
|
||
<TextBlock Classes="navlabel" Text="Einstellungen"/>
|
||
</StackPanel>
|
||
</Button>
|
||
</StackPanel>
|
||
</ScrollViewer>
|
||
</DockPanel>
|
||
</DrawerPage.Drawer>
|
||
|
||
</DrawerPage>
|
||
|
||
<!-- Dauerhafte Meldung bei einer echten Protokoll-Inkompatibilität. Als Overlay außerhalb
|
||
von DrawerPage.Content bleibt der DataContext das MainWindowViewModel; innerhalb des
|
||
ContentPresenters würde eine fehlgeschlagene Bindung IsVisible auf true stehen lassen. -->
|
||
<Border IsVisible="{Binding SyncStatus.IsIncompatibleVersion}"
|
||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
||
MaxWidth="760" Margin="0,12,12,0"
|
||
Background="#B3261E" CornerRadius="8" Padding="16,12">
|
||
<StackPanel Orientation="Horizontal" Spacing="10">
|
||
<TextBlock Text="⚠" FontSize="18" Foreground="White"
|
||
VerticalAlignment="Center"/>
|
||
<StackPanel>
|
||
<TextBlock Text="Software-Update erforderlich"
|
||
Foreground="White" FontWeight="SemiBold"/>
|
||
<TextBlock Text="{x:Static vm:SyncStatusViewModel.IncompatibleVersionMessage}"
|
||
Foreground="White" Opacity="0.92" TextWrapping="Wrap"/>
|
||
</StackPanel>
|
||
</StackPanel>
|
||
</Border>
|
||
|
||
<!-- Toast-Benachrichtigungen (13.2.3): schweben über der aktuellen Seite, unten rechts. -->
|
||
<ItemsControl ItemsSource="{Binding Toasts}"
|
||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||
Margin="0,0,20,20" IsHitTestVisible="False">
|
||
<ItemsControl.ItemsPanel>
|
||
<ItemsPanelTemplate>
|
||
<StackPanel Spacing="8"/>
|
||
</ItemsPanelTemplate>
|
||
</ItemsControl.ItemsPanel>
|
||
<ItemsControl.Styles>
|
||
<Style Selector="Border.toast">
|
||
<Setter Property="Background" Value="#323232"/>
|
||
</Style>
|
||
<Style Selector="Border.toast.error">
|
||
<Setter Property="Background" Value="#B3261E"/>
|
||
</Style>
|
||
</ItemsControl.Styles>
|
||
<ItemsControl.ItemTemplate>
|
||
<DataTemplate x:DataType="svc:ToastItem">
|
||
<Border Classes="toast" Classes.error="{Binding IsError}"
|
||
CornerRadius="8" Padding="14,10" MaxWidth="360">
|
||
<TextBlock Text="{Binding Message}" Foreground="White" FontSize="13" TextWrapping="Wrap"/>
|
||
</Border>
|
||
</DataTemplate>
|
||
</ItemsControl.ItemTemplate>
|
||
</ItemsControl>
|
||
|
||
<!-- App-Sperre nach Inaktivität (13.3.5): blockiert die gesamte Oberfläche. -->
|
||
<Border Background="#E6101014" IsVisible="{Binding AppLock.IsLocked}">
|
||
<Border Width="320" Padding="24" CornerRadius="10"
|
||
Background="{DynamicResource SystemControlBackgroundAltHighBrush}"
|
||
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||
<StackPanel Spacing="12">
|
||
<TextBlock Text="🔒" FontSize="28" HorizontalAlignment="Center"/>
|
||
<TextBlock Text="LehrerApp gesperrt" FontSize="16" FontWeight="SemiBold"
|
||
HorizontalAlignment="Center"/>
|
||
<TextBox PlaceholderText="Passwort" PasswordChar="●"
|
||
Text="{Binding AppLock.PasswordAttempt}"
|
||
KeyDown="OnLockScreenKeyDown"/>
|
||
<TextBlock Text="{Binding AppLock.UnlockError}" Foreground="Red" FontSize="12"
|
||
HorizontalAlignment="Center"
|
||
IsVisible="{Binding AppLock.UnlockError, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||
<Button Content="Entsperren" Command="{Binding AppLock.UnlockCommand}"
|
||
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"/>
|
||
</StackPanel>
|
||
</Border>
|
||
</Border>
|
||
</Panel>
|
||
</Window>
|