The WYSIWYG authoring surface at /admin/templates (admin-gated page route):
- templates-authoring.tsx — page shell (upload form, template list,
workspace: palette / run-addressable preview / placed slots).
- client/templates-authoring.ts — hydrates it: lists templates, uploads a
.docx (multipart), renders the run-span preview, builds the variable
palette from the Go catalogue (GET /api/docforge/variables), and wires
the select-then-pick gesture: select text within one .docforge-run, click
a palette variable → POST the slot → re-render with the response. Reuses
the docforge-editor lib (escapeHtml, catalogue client). Cross-run
selections rejected with a hint (v1: single-run text slots).
- build.ts emits dist/templates-authoring.html + bundles the client.
- handleTemplatesAuthoringPage serves the shell; GET /admin/templates
registered under adminGate.
- 12 i18n keys (DE+EN) for the page; i18n-keys.ts regenerated (3079).
Verification: go build/vet/test green (13 pkgs); bun run build.ts clean
(i18n scan passes); bun test 274/274; gofmt-clean. The docx surgery + store
+ catalogue are unit/live-tested. VERIFICATION CEILING: the integrated live
flow (upload→render→select→inject→save in a browser) needs the app running
with DATABASE_URL + Supabase auth + Playwright — verified post-merge, not in
this env.
m/paliad#157
113 lines
5.4 KiB
TypeScript
113 lines
5.4 KiB
TypeScript
import { h } from "./jsx";
|
|
import { Sidebar } from "./components/Sidebar";
|
|
import { PaliadinWidget } from "./components/PaliadinWidget";
|
|
import { BottomNav } from "./components/BottomNav";
|
|
import { Footer } from "./components/Footer";
|
|
import { PWAHead } from "./components/PWAHead";
|
|
|
|
// t-paliad-349 docforge slice 6 — template authoring page at
|
|
// /admin/templates.
|
|
//
|
|
// Admin uploads a base .docx, sees it rendered as run-addressable text,
|
|
// selects a span + a variable from the palette to drop a {{slot}}, and the
|
|
// result saves as a reusable docforge template. Pure shell:
|
|
// client/templates-authoring.ts hydrates the list, upload form, preview,
|
|
// palette, and slot list after load. The palette labels come from the Go
|
|
// variable catalogue (GET /api/docforge/variables, the SSOT from slice 5).
|
|
//
|
|
// Design ref: docs/plans/prd-docforge-2026-05-29.md §2.1.
|
|
|
|
export function renderTemplatesAuthoring(): string {
|
|
return "<!DOCTYPE html>" + (
|
|
<html lang="de">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
|
<meta name="theme-color" content="#BFF355" />
|
|
<PWAHead />
|
|
<title data-i18n="templates.authoring.title">Vorlagen — Paliad</title>
|
|
<link rel="stylesheet" href="/assets/global.css" />
|
|
</head>
|
|
<body className="has-sidebar page-templates-authoring">
|
|
<Sidebar currentPath="/admin" />
|
|
<BottomNav currentPath="/admin" />
|
|
|
|
<main>
|
|
<section className="tool-page docforge-templates-page">
|
|
<div className="container">
|
|
<header className="docforge-templates-header">
|
|
<h1 data-i18n="templates.authoring.heading">Vorlagen</h1>
|
|
<p
|
|
className="docforge-templates-intro"
|
|
data-i18n="templates.authoring.intro">
|
|
Lade eine Word-Vorlage hoch, markiere Stellen und setze Variablen ein.
|
|
</p>
|
|
</header>
|
|
|
|
{/* Upload a new base .docx */}
|
|
<section className="docforge-upload" id="docforge-upload">
|
|
<h2 data-i18n="templates.authoring.upload.title">Neue Vorlage hochladen</h2>
|
|
<form id="docforge-upload-form" className="entity-form">
|
|
<label className="entity-form-row">
|
|
<span data-i18n="templates.authoring.upload.file">Word-Datei (.docx)</span>
|
|
<input type="file" name="file" accept=".docx,.dotx,.docm,.dotm" required />
|
|
</label>
|
|
<label className="entity-form-row">
|
|
<span data-i18n="templates.authoring.upload.name_de">Name (DE)</span>
|
|
<input type="text" name="name_de" className="entity-form-input" required />
|
|
</label>
|
|
<label className="entity-form-row">
|
|
<span data-i18n="templates.authoring.upload.name_en">Name (EN)</span>
|
|
<input type="text" name="name_en" className="entity-form-input" required />
|
|
</label>
|
|
<label className="entity-form-row">
|
|
<span data-i18n="templates.authoring.upload.firm">Kanzlei (optional)</span>
|
|
<input type="text" name="firm" className="entity-form-input" />
|
|
</label>
|
|
<button type="submit" className="btn-primary" data-i18n="templates.authoring.upload.submit">
|
|
Hochladen
|
|
</button>
|
|
<span className="docforge-upload-status" id="docforge-upload-status" />
|
|
</form>
|
|
</section>
|
|
|
|
{/* Existing templates */}
|
|
<section className="docforge-template-list-wrap">
|
|
<h2 data-i18n="templates.authoring.list.title">Vorhandene Vorlagen</h2>
|
|
<ul className="entity-table docforge-template-list" id="docforge-template-list" />
|
|
</section>
|
|
|
|
{/* Authoring workspace — hidden until a template is opened. */}
|
|
<section className="docforge-workspace" id="docforge-workspace" hidden>
|
|
<header className="docforge-workspace-header">
|
|
<h2 id="docforge-workspace-title" />
|
|
<span className="docforge-workspace-hint" data-i18n="templates.authoring.workspace.hint">
|
|
Text markieren, dann eine Variable wählen, um einen Platzhalter zu setzen.
|
|
</span>
|
|
<span className="docforge-workspace-status" id="docforge-workspace-status" />
|
|
</header>
|
|
<div className="docforge-workspace-grid">
|
|
{/* Variable palette (left) — populated from the catalogue. */}
|
|
<aside className="docforge-palette" id="docforge-palette" />
|
|
{/* Run-addressable preview (center) — selection target. */}
|
|
<div className="docforge-preview" id="docforge-preview" />
|
|
{/* Placed slots (right). */}
|
|
<aside className="docforge-slots">
|
|
<h3 data-i18n="templates.authoring.slots.title">Platzhalter</h3>
|
|
<ul className="docforge-slot-list" id="docforge-slot-list" />
|
|
</aside>
|
|
</div>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<Footer />
|
|
<PaliadinWidget />
|
|
|
|
<script src="/assets/templates-authoring.js"></script>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|