Adds an end-to-end project-optional path for Schriftsatz drafts:
- Migration 120 drops NOT NULL on paliad.submission_drafts.project_id
and rewrites the four RLS policies to gate purely on user_id when
project_id IS NULL, otherwise on paliad.can_see_project. Down
refuses to run if project-less rows exist (safer than silent
data corruption).
- SubmissionDraft.ProjectID becomes *uuid.UUID end-to-end. Service
layer skips project/parties/deadline lookups when nil and exposes
DraftPatch.ProjectID for the "Projekt zuweisen" affordance.
ListAllForUser LEFT JOINs paliad.projects so project-less drafts
surface in the global index next to project-scoped ones.
- New HTTP surface:
GET /submissions/new (picker page)
GET /submissions/draft/{draft_id} (editor for any draft)
GET /api/submissions/catalog (catalog without project)
POST /api/submission-drafts (project-less or attached)
GET/PATCH/DELETE /api/submission-drafts/{draft_id}
POST /api/submission-drafts/{draft_id}/export
Existing /api/projects/{id}/submissions/... routes remain bit-
identical so the project-scoped flow keeps working unchanged.
- Frontend: /submissions/new lists the full cross-proceeding catalog
grouped by proceeding, filterable by text + chip. Each row offers
"Ohne Projekt" (instant draft) or "Mit Projekt…" (modal picker
with autocomplete over visible projects). /submissions index gains
a prominent "Neuer Entwurf" CTA and an empty-state CTA pointing at
the picker. The editor renders a banner + "Projekt zuweisen"
action when project_id is null; assigning persists project_id and
redirects to the project-scoped URL.
Audit + project-event writes detect d.ProjectID == nil; the audit
row's scope flips to 'user' (scope_root = user_id) and the
project_events row is skipped entirely.
119 lines
5.5 KiB
TypeScript
119 lines
5.5 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-243 — global Schriftsatz picker. Lists the full
|
|
// cross-proceeding submission catalog (grouped by proceeding,
|
|
// filterable) and lets the lawyer start a draft with or without
|
|
// binding a project. Picking "Ohne Projekt" jumps straight to
|
|
// /submissions/draft/{id}; picking "Mit Projekt verknüpfen" opens an
|
|
// autocomplete project picker, then redirects to the project-scoped
|
|
// editor.
|
|
|
|
export function renderSubmissionsNew(): 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.new.title">Neuer Schriftsatz — Paliad</title>
|
|
<link rel="stylesheet" href="/assets/global.css" />
|
|
</head>
|
|
<body className="has-sidebar">
|
|
<Sidebar currentPath="/submissions" />
|
|
<BottomNav currentPath="/submissions" />
|
|
|
|
<main>
|
|
<section className="tool-page submissions-new-page">
|
|
<div className="container">
|
|
<a href="/submissions" className="back-link"
|
|
data-i18n="submissions.new.back">← Zurück zur Übersicht</a>
|
|
|
|
<div className="tool-header">
|
|
<h1 data-i18n="submissions.new.heading">Neuer Schriftsatz</h1>
|
|
<p className="tool-subtitle" data-i18n="submissions.new.subtitle">
|
|
Wählen Sie eine Vorlage. Optional verknüpfen Sie den
|
|
Entwurf mit einem Projekt — sonst füllen Sie alle
|
|
Variablen manuell.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="submissions-new-toolbar">
|
|
<input
|
|
type="search"
|
|
id="submissions-new-search"
|
|
className="entity-form-input"
|
|
data-i18n-placeholder="submissions.new.search.placeholder"
|
|
placeholder="Suche nach Schriftsatz, Code oder Norm…" />
|
|
<div id="submissions-new-proceeding-chips" className="submissions-new-chips" />
|
|
</div>
|
|
|
|
<p className="entity-events-empty" id="submissions-new-loading"
|
|
data-i18n="submissions.new.loading">Lädt…</p>
|
|
|
|
<div className="entity-empty" id="submissions-new-error" style="display:none">
|
|
<p data-i18n="submissions.new.error">Katalog konnte nicht geladen werden.</p>
|
|
</div>
|
|
|
|
<div className="entity-table-wrap" id="submissions-new-tablewrap" style="display:none">
|
|
<table className="entity-table entity-table--readonly">
|
|
<thead>
|
|
<tr>
|
|
<th data-i18n="submissions.new.col.name">Schriftsatz</th>
|
|
<th data-i18n="submissions.new.col.party">Partei</th>
|
|
<th data-i18n="submissions.new.col.source">Rechtsgrundlage</th>
|
|
<th data-i18n="submissions.new.col.actions">Entwurf starten</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="submissions-new-body" />
|
|
</table>
|
|
</div>
|
|
|
|
<p className="entity-empty" id="submissions-new-empty" style="display:none">
|
|
<span data-i18n="submissions.new.empty.filtered">
|
|
Keine passenden Schriftsätze. Filter zurücksetzen.
|
|
</span>
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Project picker modal — opened by "Mit Projekt verknüpfen". */}
|
|
<div id="submissions-new-project-modal" className="modal-overlay" style="display:none" role="dialog" aria-modal="true">
|
|
<div className="modal-card">
|
|
<header className="modal-header">
|
|
<h2 data-i18n="submissions.new.picker.title">Projekt wählen</h2>
|
|
<button type="button" id="submissions-new-project-modal-close"
|
|
className="modal-close" aria-label="Close">×</button>
|
|
</header>
|
|
<div className="modal-body">
|
|
<input
|
|
type="search"
|
|
id="submissions-new-project-search"
|
|
className="entity-form-input"
|
|
data-i18n-placeholder="submissions.new.picker.placeholder"
|
|
placeholder="Projekt suchen (Titel oder Aktenzeichen)…" />
|
|
<ul id="submissions-new-project-list" className="submissions-new-project-list" />
|
|
<p id="submissions-new-project-loading" className="entity-events-empty" style="display:none"
|
|
data-i18n="submissions.new.picker.loading">Lädt Projekte…</p>
|
|
<p id="submissions-new-project-empty" className="entity-empty" style="display:none"
|
|
data-i18n="submissions.new.picker.empty">Keine sichtbaren Projekte.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<Footer />
|
|
<PaliadinWidget />
|
|
<script src="/assets/submissions-new.js"></script>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|