Adds the dedicated Submissions/Schriftsätze editor at
/projects/{id}/submissions/{code}/draft (and …/draft/{draft_id}) per
docs/design-submission-page-2026-05-22.md.
Lawyer picks (or creates) a named draft, edits placeholder variables
in a sticky sidebar, sees a read-only HTML preview of the merged
document body, and exports a .docx with project state + lawyer
overrides resolved. Drafts persist in paliad.submission_drafts
keyed on (project_id, submission_code, user_id, name) with RLS via
can_see_project; updates and deletes additionally gated on owner-only
(Q-E4 owner-scoped pick, m-confirmed).
Resurrected from git history per the design's "no rewrite" plan:
SubmissionVarsService ← commit 1765d5e (Slice 2 with patent_number_upc)
SubmissionRenderer ← commit 8ea3509 (in-house merge engine — the
lukasjarosch/go-docx library refuses sibling
placeholders in one run, which patent submissions
use routinely)
ConvertDotmToDocx ← existing format-only convert (kept; reused as
pre-pass so .dotm inputs strip macros before
merge)
New code:
paliad.submission_drafts migration 119 (idempotent — DROP POLICY IF EXISTS
+ CREATE; CREATE OR REPLACE for the shared trigger
function). Applied to live DB.
SubmissionDraftService CRUD + autosave-friendly Update + Export/RenderPreview
entry points
RenderHTML method new on the renderer; walks the same merged
document.xml as Render but emits HTML for the
preview pane (Q-E3 server-side pick)
7 API handlers list / create / get / patch / delete / preview / export
2 page routes /draft and /draft/{draft_id}
submission-draft.tsx stand-alone editor page (header / sidebar /
preview / export button); served via
dist/submission-draft.html
submission-draft.ts client bundle — autosave (500ms debounce),
draft switcher, rename, delete, export with
blob download
Tab integration: existing /projects/{id}/#tab-submissions rows get
[Bearbeiten] alongside the existing [Generieren] one-click format-only
path — additive, no removal.
Slice A template: universal HL Patents Style .dotm (same path
t-paliad-230 uses). resolveSubmissionTemplate carries the
submission_code parameter so Slice B's TemplateRegistry wiring (per-
code .docx fallback chain) is a one-function swap.
Audit trail: paliad.system_audit_log row per export
(event_type='submission.exported') + paliad.project_events row
(event_type='submission_exported', timeline_kind='custom_milestone')
so the export surfaces on the project's Verlauf / SmartTimeline. No
paliad.documents write (Q-E2 inventor pick, head-ratified).
Tests: TestRender_* / TestPlaceholderRegex_* / TestRenderHTML_* +
TestLegalSourcePretty / TestOurSide* / TestPatentNumberUPC — all
green. go build / go vet / go test ./internal/... / bun run build all
clean.
Migration slot taken: 119.
144 lines
6.2 KiB
TypeScript
144 lines
6.2 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-238 Slice A — dedicated Submissions/Schriftsätze editor page.
|
|
//
|
|
// Lawyer picks (or creates) a draft for one (project, submission_code),
|
|
// edits placeholder variables in a sticky sidebar, sees a read-only
|
|
// HTML preview of the merged document, and exports the result as
|
|
// .docx. Drafts persist server-side per paliad.submission_drafts.
|
|
//
|
|
// Pure shell: client/submission-draft.ts hydrates draft list + variable
|
|
// form + preview pane after page load. The same dist/submission-draft.html
|
|
// serves every (project_id, submission_code, [draft_id]) URL.
|
|
//
|
|
// Design ref: docs/design-submission-page-2026-05-22.md §6.
|
|
|
|
export function renderSubmissionDraft(): 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" />
|
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
|
|
<PWAHead />
|
|
<title data-i18n="submissions.draft.title">Schriftsatz bearbeiten — Paliad</title>
|
|
<link rel="stylesheet" href="/assets/global.css" />
|
|
</head>
|
|
<body className="has-sidebar page-submission-draft">
|
|
<Sidebar currentPath="/projects" />
|
|
<BottomNav currentPath="/projects" />
|
|
|
|
<main>
|
|
<section className="tool-page submission-draft-page">
|
|
<div className="container">
|
|
<a
|
|
id="submission-draft-back-link"
|
|
href="/projects"
|
|
className="back-link"
|
|
data-i18n="submissions.draft.back">
|
|
← Zurück zum Projekt
|
|
</a>
|
|
|
|
<div id="submission-draft-loading" className="entity-loading">
|
|
<p data-i18n="submissions.draft.loading">Lädt…</p>
|
|
</div>
|
|
|
|
<div id="submission-draft-notfound" className="entity-empty" style="display:none">
|
|
<p data-i18n="submissions.draft.notfound">
|
|
Schriftsatz nicht gefunden oder keine Berechtigung.
|
|
</p>
|
|
</div>
|
|
|
|
<div id="submission-draft-error" className="entity-empty" style="display:none" />
|
|
|
|
<div id="submission-draft-body" style="display:none">
|
|
<header className="submission-draft-header">
|
|
<div className="submission-draft-header-text">
|
|
<h1 id="submission-draft-title" />
|
|
<p id="submission-draft-subtitle" className="tool-subtitle" />
|
|
</div>
|
|
<div className="submission-draft-header-actions">
|
|
<button
|
|
id="submission-draft-export-btn"
|
|
type="button"
|
|
className="btn-primary btn-cta-lime"
|
|
data-i18n="submissions.draft.action.export">
|
|
Als .docx exportieren
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<div className="submission-draft-grid">
|
|
{/* Sidebar — draft switcher + variable groups. */}
|
|
<aside className="submission-draft-sidebar" id="submission-draft-sidebar">
|
|
<div className="submission-draft-switcher">
|
|
<label htmlFor="submission-draft-pick" data-i18n="submissions.draft.switcher.label">
|
|
Entwurf
|
|
</label>
|
|
<select id="submission-draft-pick" />
|
|
<button
|
|
type="button"
|
|
id="submission-draft-new-btn"
|
|
className="btn-small btn-secondary"
|
|
data-i18n="submissions.draft.action.new">
|
|
+ Neuer Entwurf
|
|
</button>
|
|
</div>
|
|
|
|
<div className="submission-draft-name-row">
|
|
<input
|
|
type="text"
|
|
id="submission-draft-name"
|
|
className="entity-form-input"
|
|
data-i18n-placeholder="submissions.draft.name.placeholder"
|
|
placeholder="Name dieses Entwurfs"
|
|
/>
|
|
<button
|
|
type="button"
|
|
id="submission-draft-delete-btn"
|
|
className="btn-small btn-link-danger"
|
|
data-i18n="submissions.draft.action.delete">
|
|
Löschen
|
|
</button>
|
|
</div>
|
|
|
|
<p className="submission-draft-savestatus" id="submission-draft-savestatus" />
|
|
|
|
<div className="submission-draft-variables" id="submission-draft-variables" />
|
|
</aside>
|
|
|
|
{/* Preview pane — read-only HTML render of the merged
|
|
document body. Re-renders on autosave round-trip. */}
|
|
<section className="submission-draft-preview-wrap">
|
|
<header className="submission-draft-preview-header">
|
|
<h2 data-i18n="submissions.draft.preview.title">Vorschau</h2>
|
|
<span
|
|
className="submission-draft-preview-hint"
|
|
data-i18n="submissions.draft.preview.hint">
|
|
Read-only Vorschau — finale Bearbeitung in Word.
|
|
</span>
|
|
</header>
|
|
<div className="submission-draft-preview" id="submission-draft-preview" />
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<Footer />
|
|
<PaliadinWidget />
|
|
|
|
<script src="/assets/submission-draft.js"></script>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|