- Dashboard: Fehlzeiten-Warnung lädt Mitarbeitssitzungen einmal vorab statt pro Schüler/Eintrag einzeln nachzuschlagen (N+1 vermieden); neues IParticipationSessionRepository.GetAll() dafür. - CI: .gitea/workflows/ci.yml baut und testet bei jedem Push/PR. Dabei fehlende Release|Any CPU-Konfiguration für 6 Projekte in der .sln behoben (LehrerApp.Data.Tests wurde bei Release-Builds der Solution bislang stillschweigend übersprungen). TreatWarningsAsErrors jetzt aktiv. - SettingsViewModel (1986 Zeilen) als partial class auf 20 Themen- dateien aufgeteilt, Verhalten unverändert. - Backup: optionaler zweiter Sicherungsordner (USB-Stick/Netzlaufwerk, best-effort) und Integritätsprüfung nach jedem Backup (DatabaseEncryptionService.CanOpenAndRead). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
69 lines
2.4 KiB
C#
69 lines
2.4 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using LehrerApp.Core.Interfaces;
|
|
using LehrerApp.Core.Models;
|
|
using LehrerApp.Core.Services;
|
|
using LehrerApp.Data;
|
|
using LehrerApp.Desktop.Services;
|
|
using LehrerApp.Desktop.ViewModels.Planning;
|
|
using LehrerApp.Sync;
|
|
using LehrerApp.Sync.Crypto;
|
|
using System.Collections.ObjectModel;
|
|
using System.Globalization;
|
|
using System.Security.Cryptography;
|
|
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
|
|
namespace LehrerApp.Desktop.ViewModels.Settings;
|
|
|
|
public partial class SettingsViewModel
|
|
{
|
|
// ── Datenschutz: Löschfristen (5.4.2) ────────────────────────────────────
|
|
|
|
[ObservableProperty] private int _retentionYears = 3;
|
|
[ObservableProperty] private string _retentionStatus = "";
|
|
|
|
public ObservableCollection<ExpiredDocumentItem> ExpiredDocuments { get; } = [];
|
|
|
|
/// Vom Code-Behind gesetzt: zeigt einen Bestätigungsdialog vor dem endgültigen Löschen.
|
|
public Func<ExpiredDocumentItem, Task<bool>>? OnConfirmHardDelete { get; set; }
|
|
|
|
// ── Datenschutz: Löschfristen ─────────────────────────────────────────────
|
|
|
|
private void LoadExpiredDocuments()
|
|
{
|
|
ExpiredDocuments.Clear();
|
|
var cutoff = _privacy.RetentionCutoff();
|
|
foreach (var d in _documentation.GetAll().Where(d => d.CreatedAt < cutoff))
|
|
{
|
|
var student = _students.GetById(d.StudentId);
|
|
ExpiredDocuments.Add(new ExpiredDocumentItem(d, student?.FullName ?? "?"));
|
|
}
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void SaveRetentionYears()
|
|
{
|
|
_privacy.SetRetentionYears(RetentionYears);
|
|
LoadExpiredDocuments();
|
|
RetentionStatus = "Gespeichert.";
|
|
}
|
|
|
|
[RelayCommand]
|
|
private async Task HardDeleteDocument(ExpiredDocumentItem? item)
|
|
{
|
|
if (item is null) return;
|
|
if (OnConfirmHardDelete is not null && !await OnConfirmHardDelete(item)) return;
|
|
_documentation.HardDelete(item.Id);
|
|
ExpiredDocuments.Remove(item);
|
|
}
|
|
}
|
|
|
|
public class ExpiredDocumentItem(Documentation d, string studentName)
|
|
{
|
|
public Guid Id { get; } = d.Id;
|
|
public string StudentName { get; } = studentName;
|
|
public string Title { get; } = d.Title;
|
|
public string CreatedAtDisplay { get; } = d.CreatedAt.ToLocalTime().ToString("dd.MM.yyyy");
|
|
}
|