feat(fp): WP-25 — server-rendered letter HTML preview
Adds LetterHtml.Render, a pure composer mirroring the FE letter canvas'
class vocabulary, behind two ExcludeFromDescription()'d endpoints
(GET /brief/preview, GET /admin/org-template/{subOrgId}/preview).
Auto-resolvable placeholders pull from seed/case data; unresolved
manual ones render as "[NOG IN TE VULLEN: label]". A sent brief
archives its composed HTML (BriefEntity.ArchivedHtml) so a later
org-template republish never changes it. FE gets a hand-written fetch
adapter (text/html, not JSON) and a "Voorbeeld" button that opens the
preview in a new tab.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -346,6 +346,31 @@ api.MapPost("/brief/send", (HttpContext ctx) =>
|
||||
.Produces<BriefViewDto>()
|
||||
.ProducesProblem(StatusCodes.Status409Conflict);
|
||||
|
||||
// Server-rendered HTML preview (WP-25): "what you compose is what is sent" — the
|
||||
// same LetterHtml.Render a sent brief archived. Hand-written on the FE (fetch →
|
||||
// blob → new tab), so excluded from the OpenAPI doc, same seam as uploads. Sent
|
||||
// letters serve their frozen archive; anything else renders live with a watermark.
|
||||
api.MapGet("/brief/preview", (HttpContext ctx) =>
|
||||
{
|
||||
var e = BriefStore.GetOrCreate(DocumentStore.DemoOwner);
|
||||
if (e.Status.Tag == "sent" && e.ArchivedHtml is { } archived)
|
||||
return Results.Content(archived, "text/html");
|
||||
var template = OrgTemplateStore.TemplateForBrief(e.SubOrgId, null);
|
||||
return Results.Content(LetterHtml.Render(e, template, Now(), watermark: true), "text/html");
|
||||
})
|
||||
.ExcludeFromDescription();
|
||||
|
||||
// Proefbrief: the admin's unpublished draft template rendered over a fixture
|
||||
// brief, so the appearance can be checked before publishing touches real letters.
|
||||
api.MapGet("/admin/org-template/{subOrgId}/preview", (string subOrgId, HttpContext ctx) => OrgAdmin(ctx, () =>
|
||||
{
|
||||
var view = OrgTemplateStore.AdminView(subOrgId);
|
||||
if (view is null) return Results.NotFound();
|
||||
var fixture = BriefSeed.NewBrief("proefbrief");
|
||||
return Results.Content(LetterHtml.Render(fixture, view.Draft, Now(), watermark: true), "text/html");
|
||||
}))
|
||||
.ExcludeFromDescription();
|
||||
|
||||
api.MapPost("/brief/reset", (HttpContext ctx) =>
|
||||
{
|
||||
// Demo "start over": recreate a fresh draft. No guards — showcase affordance only.
|
||||
|
||||
Reference in New Issue
Block a user