This commit is contained in:
@@ -35,7 +35,9 @@ public partial class CreateLetterDialogViewModel : ObservableObject
|
||||
public ObservableCollection<LetterContactChoice> Contacts { get; } = [];
|
||||
public ObservableCollection<LetterGroupChoice> Groups { get; } = [];
|
||||
public ObservableCollection<LetterGenerationIssue> Issues { get; } = [];
|
||||
public ObservableCollection<LetterPlaceholderInput> CustomPlaceholders { get; } = [];
|
||||
public bool HasIssues => Issues.Count > 0;
|
||||
public bool HasCustomPlaceholders => CustomPlaceholders.Count > 0;
|
||||
public bool HasNoTemplates => Templates.Count == 0;
|
||||
public bool HasNoContacts => Contacts.Count == 0;
|
||||
public bool UsesAttendanceAdvancedContent => UsesAttendanceCalendar || UsesAbsenceDayList;
|
||||
@@ -68,6 +70,7 @@ public partial class CreateLetterDialogViewModel : ObservableObject
|
||||
OnPropertyChanged(nameof(UsesAttendanceAdvancedContent));
|
||||
AttendanceCalendarConfigured = false;
|
||||
ResetAttendanceCalendarOptions();
|
||||
RebuildCustomPlaceholders(value);
|
||||
RefreshValidation();
|
||||
}
|
||||
partial void OnSelectedContactChanged(LetterContactChoice? value) => RefreshValidation();
|
||||
@@ -117,11 +120,49 @@ public partial class CreateLetterDialogViewModel : ObservableObject
|
||||
OnPropertyChanged(nameof(HasIssues));
|
||||
}
|
||||
|
||||
private IReadOnlyDictionary<string, PlaceholderValue> BuildValues() => LetterPlaceholderBuilder.BuildStandardValues(
|
||||
_student, SelectedContact?.Model, SelectedGroup?.Model,
|
||||
DateOnly.FromDateTime((LetterDate ?? DateTimeOffset.Now).LocalDateTime), LetterText, TeacherName,
|
||||
UsesAttendanceCalendar ? _attendanceCalendarFactory?.Invoke(_attendanceCalendarOptions) : null,
|
||||
UsesAbsenceDayList ? _absenceDayListFactory?.Invoke(_attendanceCalendarOptions) : null);
|
||||
private IReadOnlyDictionary<string, PlaceholderValue> BuildValues()
|
||||
{
|
||||
var values = LetterPlaceholderBuilder.BuildStandardValues(
|
||||
_student, SelectedContact?.Model, SelectedGroup?.Model,
|
||||
DateOnly.FromDateTime((LetterDate ?? DateTimeOffset.Now).LocalDateTime), LetterText, TeacherName,
|
||||
UsesAttendanceCalendar ? _attendanceCalendarFactory?.Invoke(_attendanceCalendarOptions) : null,
|
||||
UsesAbsenceDayList ? _absenceDayListFactory?.Invoke(_attendanceCalendarOptions) : null);
|
||||
foreach (var custom in CustomPlaceholders) values[custom.Name] = custom.ToPlaceholderValue();
|
||||
return values;
|
||||
}
|
||||
|
||||
private void RebuildCustomPlaceholders(LetterTemplateChoice? choice)
|
||||
{
|
||||
foreach (var existing in CustomPlaceholders) existing.PropertyChanged -= OnCustomPlaceholderChanged;
|
||||
CustomPlaceholders.Clear();
|
||||
if (choice is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var loaded = _templates.Load(choice.Model);
|
||||
foreach (var placeholder in loaded.Manifest.Placeholders.Where(p => !p.IsConstant
|
||||
&& !StandardPlaceholderNames.Contains(p.Name) && p.Type is PlaceholderType.Text
|
||||
or PlaceholderType.Multiline or PlaceholderType.Date or PlaceholderType.Number))
|
||||
{
|
||||
var input = new LetterPlaceholderInput(placeholder.Name, placeholder.Type);
|
||||
input.PropertyChanged += OnCustomPlaceholderChanged;
|
||||
CustomPlaceholders.Add(input);
|
||||
}
|
||||
}
|
||||
catch (Exception ex) when (ex is IOException or InvalidDataException or TemplateValidationException) { }
|
||||
}
|
||||
OnPropertyChanged(nameof(HasCustomPlaceholders));
|
||||
}
|
||||
|
||||
private void OnCustomPlaceholderChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) => RefreshValidation();
|
||||
|
||||
private static readonly HashSet<string> StandardPlaceholderNames = new(StringComparer.Ordinal)
|
||||
{
|
||||
"Datum", "CurrentDate", "Empfaenger", "Anrede", "Brieftext", "LehrerName",
|
||||
"Student.FirstName", "Student.LastName", "Contact.Name", "Contact.Address", "Contact.Street",
|
||||
"Contact.PostalCode", "Contact.City", "Letter.Salutation", "Group.Name", "SchoolYear",
|
||||
StudentAttendanceCalendarDrawingBuilder.PlaceholderName, StudentAbsenceDayListDrawingBuilder.PlaceholderName,
|
||||
};
|
||||
|
||||
public AttendanceCalendarOptions GetAttendanceCalendarOptions() => _attendanceCalendarOptions;
|
||||
|
||||
@@ -187,3 +228,33 @@ public sealed class LetterContactChoice(Contact model) { public Contact Model {
|
||||
public sealed class LetterGroupChoice(LearningGroup model) { public LearningGroup Model { get; } = model; public string Display => $"{Model.Name} · {Model.SchoolYear}"; }
|
||||
public sealed class LetterGenerationIssue(string message, bool isStrong)
|
||||
{ public string Icon { get; } = isStrong ? "⚠" : "ⓘ"; public string Message { get; } = message; public string Color { get; } = isStrong ? "#D97706" : "#6B7280"; }
|
||||
|
||||
public sealed partial class LetterPlaceholderInput : ObservableObject
|
||||
{
|
||||
public string Name { get; }
|
||||
public PlaceholderType Type { get; }
|
||||
public string Label => Type switch
|
||||
{
|
||||
PlaceholderType.Date => $"{Name} (Datum)",
|
||||
PlaceholderType.Number => $"{Name} (Zahl)",
|
||||
_ => Name,
|
||||
};
|
||||
public bool IsTextType => Type == PlaceholderType.Text;
|
||||
public bool IsMultilineType => Type == PlaceholderType.Multiline;
|
||||
public bool IsDateType => Type == PlaceholderType.Date;
|
||||
public bool IsNumberType => Type == PlaceholderType.Number;
|
||||
|
||||
[ObservableProperty] private string _textValue = "";
|
||||
[ObservableProperty] private DateTimeOffset? _dateValue;
|
||||
[ObservableProperty] private decimal? _numberValue;
|
||||
|
||||
public LetterPlaceholderInput(string name, PlaceholderType type) { Name = name; Type = type; }
|
||||
|
||||
public PlaceholderValue ToPlaceholderValue() => Type switch
|
||||
{
|
||||
PlaceholderType.Multiline => new MultilineValue(TextValue),
|
||||
PlaceholderType.Date => new DateValue(DateValue.HasValue ? DateOnly.FromDateTime(DateValue.Value.LocalDateTime) : default),
|
||||
PlaceholderType.Number => new NumberValue(NumberValue ?? 0),
|
||||
_ => new TextValue(TextValue),
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user