111 lines
5.1 KiB
C#
111 lines
5.1 KiB
C#
using System.Text.Json.Serialization;
|
|
|
|
namespace LehrerApp.Templating;
|
|
|
|
public enum PlaceholderType { Text, Multiline, Date, Number, Image, Table, Chart }
|
|
|
|
public abstract record PlaceholderValue(PlaceholderType Type);
|
|
public sealed record TextValue(string Value) : PlaceholderValue(PlaceholderType.Text);
|
|
public sealed record MultilineValue(string Value) : PlaceholderValue(PlaceholderType.Multiline);
|
|
public sealed record DateValue(DateOnly Value) : PlaceholderValue(PlaceholderType.Date);
|
|
public sealed record NumberValue(decimal Value) : PlaceholderValue(PlaceholderType.Number);
|
|
public sealed record ImageValue(byte[] Data, string MimeType) : PlaceholderValue(PlaceholderType.Image);
|
|
public sealed record ImageMetadata(int Width, int Height);
|
|
public sealed record TableValue(IReadOnlyList<string> Columns, IReadOnlyList<IReadOnlyList<string>> Rows)
|
|
: PlaceholderValue(PlaceholderType.Table);
|
|
public sealed record ChartPoint(string X, decimal Y);
|
|
public sealed record ChartSeries(string Label, IReadOnlyList<ChartPoint> Points);
|
|
public sealed record ChartValue(IReadOnlyList<ChartSeries> Series) : PlaceholderValue(PlaceholderType.Chart);
|
|
|
|
public interface ITemplateDataProvider
|
|
{
|
|
IReadOnlyDictionary<string, PlaceholderValue> GetValues();
|
|
}
|
|
|
|
public sealed record PageSizeDefinition(float Width, float Height, string Unit = "mm");
|
|
public sealed record PlaceholderDefinition(string Name, PlaceholderType Type, bool Required = false);
|
|
|
|
public sealed class TemplateManifest
|
|
{
|
|
public int SchemaVersion { get; set; } = 1;
|
|
public string Id { get; set; } = "neue-vorlage";
|
|
public string Name { get; set; } = "Neue Vorlage";
|
|
public string Description { get; set; } = "";
|
|
public PageSizeDefinition PageSize { get; set; } = new(210, 297);
|
|
public string LayoutFile { get; set; } = "layout.tpl";
|
|
public string MetadataFile { get; set; } = TemplateMetadataText.FileName;
|
|
[JsonIgnore]
|
|
public Dictionary<string, string> Metadata { get; set; } = new(StringComparer.OrdinalIgnoreCase);
|
|
public List<PlaceholderDefinition> Placeholders { get; set; } = [];
|
|
}
|
|
|
|
public abstract record TemplateElement(int Line, float X, float Y, float Width, float Height,
|
|
IReadOnlyDictionary<string, string> Attributes);
|
|
public sealed record BackgroundElement(int Line, string Path)
|
|
: TemplateElement(Line, 0, 0, 0, 0, EmptyAttributes.Value);
|
|
public sealed record ImageElement(int Line, string Path, float X, float Y, float Width, float Height,
|
|
IReadOnlyDictionary<string, string> Attributes)
|
|
: TemplateElement(Line, X, Y, Width, Height, Attributes);
|
|
public sealed record TextElement(int Line, float X, float Y, string Content, string? Placeholder,
|
|
string? Format, IReadOnlyDictionary<string, string> Attributes)
|
|
: TemplateElement(Line, X, Y, 0, 0, Attributes);
|
|
public sealed record TextBoxElement(int Line, float X, float Y, float Width, float Height,
|
|
string Content, string? Placeholder, string? Format, IReadOnlyDictionary<string, string> Attributes)
|
|
: TemplateElement(Line, X, Y, Width, Height, Attributes);
|
|
public sealed record TableElement(int Line, float X, float Y, float Width, float Height,
|
|
string Placeholder, IReadOnlyDictionary<string, string> Attributes)
|
|
: TemplateElement(Line, X, Y, Width, Height, Attributes);
|
|
public sealed record ChartElement(int Line, float X, float Y, float Width, float Height,
|
|
string Placeholder, string ChartType, IReadOnlyDictionary<string, string> Attributes)
|
|
: TemplateElement(Line, X, Y, Width, Height, Attributes);
|
|
|
|
internal static class EmptyAttributes
|
|
{
|
|
public static readonly IReadOnlyDictionary<string, string> Value =
|
|
new Dictionary<string, string>();
|
|
}
|
|
|
|
public sealed record TemplateLayout(float Width, float Height, string Unit,
|
|
IReadOnlyList<TemplateElement> Elements);
|
|
|
|
public sealed record LoadedTemplate(TemplateManifest Manifest, TemplateLayout Layout,
|
|
IReadOnlyDictionary<string, byte[]> Assets, string SourceName = "");
|
|
|
|
public enum ValidationSeverity { Warning, Error }
|
|
public sealed record ValidationIssue(ValidationSeverity Severity, string Message, int? Line = null);
|
|
public sealed record ValidationResult(IReadOnlyList<ValidationIssue> Issues)
|
|
{
|
|
public bool IsValid => Issues.All(x => x.Severity != ValidationSeverity.Error);
|
|
public static ValidationResult Success { get; } = new([]);
|
|
}
|
|
|
|
public sealed class TemplateValidationException(ValidationResult result)
|
|
: Exception(string.Join(Environment.NewLine, result.Issues.Select(x => x.Message)))
|
|
{
|
|
public ValidationResult Result { get; } = result;
|
|
}
|
|
|
|
public interface ITemplateRenderer
|
|
{
|
|
byte[] RenderToPdf(LoadedTemplate template, ITemplateDataProvider data);
|
|
}
|
|
|
|
public interface ITemplatePreviewRenderer
|
|
{
|
|
byte[] RenderFirstPageToPng(LoadedTemplate template, ITemplateDataProvider data, int dpi = 120);
|
|
}
|
|
|
|
public interface ITemplateLoader
|
|
{
|
|
LoadedTemplate LoadFromPackage(string packagePath);
|
|
LoadedTemplate LoadFromPackage(Stream package, string sourceName = "");
|
|
ValidationResult Validate(LoadedTemplate template,
|
|
IReadOnlyDictionary<string, PlaceholderType> providedTypes);
|
|
}
|
|
|
|
public interface ITemplateMigrator
|
|
{
|
|
int SourceVersion { get; }
|
|
TemplateManifest Migrate(TemplateManifest manifest);
|
|
}
|