Dunkelmodus über neuen Einstellungen-Tab "Darstellung" (Systemvorgabe/Hell/Dunkel), Fenstergröße/Maximiert-Status wird über Sitzungen hinweg gemerkt (bewusst ohne Fensterposition), und ein generischer Snapshot-basierter Papierkorb (30 Tage) für Sitzpläne, Noten, Notenschlüssel-Vorlagen, Aufgaben und Zeiteinträge. Details und bewusste Scope-Entscheidungen (Spaltenbreiten zurückgestellt, Farb-Audit für Dunkelmodus offen, welche Entitäten der Papierkorb abdeckt) in TODO.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
101 lines
3.8 KiB
C#
101 lines
3.8 KiB
C#
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using LehrerApp.Core.Interfaces;
|
|
using LehrerApp.Core.Models;
|
|
using System.Collections.ObjectModel;
|
|
|
|
namespace LehrerApp.Desktop.ViewModels.Settings;
|
|
|
|
/// <summary>
|
|
/// Papierkorb (14.3): zeigt gelöschte Datensätze der abgedeckten Modelle (siehe
|
|
/// TODO.md 14.3 für die vollständige Liste und die bewusst ausgeschlossenen, kaskadierenden
|
|
/// Löschvorgänge wie eine ganze Lerngruppe) und erlaubt das Wiederherstellen. Rein lokal — der
|
|
/// Papierkorb selbst wird nicht synchronisiert (siehe TrashRepository-Klassenkommentar);
|
|
/// wiederhergestellte Einträge synchronisieren sich danach ganz normal wie jede andere Änderung.
|
|
/// </summary>
|
|
public partial class TrashViewModel : ObservableObject
|
|
{
|
|
private readonly ITrashRepository _trash;
|
|
private readonly IGradeRepository _grades;
|
|
private readonly IWorkTaskRepository _tasks;
|
|
private readonly ITimeEntryRepository _timeEntries;
|
|
private readonly ISeatingPlanRepository _seatingPlans;
|
|
private readonly IGradingKeyTemplateRepository _gradingKeyTemplates;
|
|
|
|
[ObservableProperty] private string _status = "";
|
|
|
|
public ObservableCollection<TrashItemViewModel> Items { get; } = [];
|
|
public bool HasItems => Items.Count > 0;
|
|
|
|
public TrashViewModel(ITrashRepository trash, IGradeRepository grades, IWorkTaskRepository tasks,
|
|
ITimeEntryRepository timeEntries, ISeatingPlanRepository seatingPlans,
|
|
IGradingKeyTemplateRepository gradingKeyTemplates)
|
|
{
|
|
_trash = trash;
|
|
_grades = grades;
|
|
_tasks = tasks;
|
|
_timeEntries = timeEntries;
|
|
_seatingPlans = seatingPlans;
|
|
_gradingKeyTemplates = gradingKeyTemplates;
|
|
Load();
|
|
}
|
|
|
|
public void Load()
|
|
{
|
|
Items.Clear();
|
|
foreach (var item in _trash.GetAll())
|
|
Items.Add(new TrashItemViewModel(item, TypeLabel(item.EntityType)));
|
|
OnPropertyChanged(nameof(HasItems));
|
|
}
|
|
|
|
[RelayCommand]
|
|
private void Restore(TrashItemViewModel? item)
|
|
{
|
|
if (item is null) return;
|
|
switch (item.EntityType)
|
|
{
|
|
case nameof(Grade): _grades.Restore(item.Id); break;
|
|
case nameof(WorkTask): _tasks.Restore(item.Id); break;
|
|
case nameof(TimeEntry): _timeEntries.Restore(item.Id); break;
|
|
case nameof(SeatingPlan): _seatingPlans.Restore(item.Id); break;
|
|
case nameof(GradingKeyTemplate): _gradingKeyTemplates.Restore(item.Id); break;
|
|
default: return; // Unbekannter Typ (sollte nicht vorkommen) - Eintrag unverändert lassen.
|
|
}
|
|
Status = $"„{item.Summary}“ wiederhergestellt.";
|
|
Load();
|
|
}
|
|
|
|
private static string TypeLabel(string entityType) => entityType switch
|
|
{
|
|
nameof(Grade) => "Note",
|
|
nameof(WorkTask) => "Aufgabe",
|
|
nameof(TimeEntry) => "Zeiteintrag",
|
|
nameof(SeatingPlan) => "Sitzplan",
|
|
nameof(GradingKeyTemplate) => "Notenschlüssel-Vorlage",
|
|
_ => entityType,
|
|
};
|
|
}
|
|
|
|
public class TrashItemViewModel
|
|
{
|
|
private const int RetentionDays = 30;
|
|
|
|
public Guid Id { get; }
|
|
public string EntityType { get; }
|
|
public string TypeLabel { get; }
|
|
public string Summary { get; }
|
|
public string DeletedAtDisplay { get; }
|
|
public string ExpiresInDisplay { get; }
|
|
|
|
public TrashItemViewModel(TrashedItem item, string typeLabel)
|
|
{
|
|
Id = item.Id;
|
|
EntityType = item.EntityType;
|
|
TypeLabel = typeLabel;
|
|
Summary = item.Summary;
|
|
DeletedAtDisplay = item.DeletedAt.ToLocalTime().ToString("dd.MM.yyyy HH:mm");
|
|
var daysLeft = RetentionDays - (DateTime.UtcNow - item.DeletedAt).Days;
|
|
ExpiresInDisplay = daysLeft <= 0 ? "läuft heute ab" : $"noch {daysLeft} Tag(e)";
|
|
}
|
|
}
|