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.
85 lines
3.7 KiB
TypeScript
85 lines
3.7 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-240 — global Schriftsätze drafts index. Top-level sidebar
|
|
// entry that lists every draft the caller owns across visible projects.
|
|
// Per-project editor stays at /projects/{id}/submissions/{code}/draft —
|
|
// this page only adds a discovery surface and click-through to it.
|
|
|
|
export function renderSubmissionsIndex(): 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.index.title">Schriftsätze — 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">
|
|
<div className="container">
|
|
<div className="tool-header">
|
|
<div className="submissions-index-headline">
|
|
<div>
|
|
<h1 data-i18n="submissions.index.heading">Schriftsätze</h1>
|
|
<p className="tool-subtitle" data-i18n="submissions.index.subtitle">
|
|
Ihre Schriftsatz-Entwürfe über alle sichtbaren Projekte.
|
|
</p>
|
|
</div>
|
|
<a href="/submissions/new" className="btn-primary btn-cta-lime"
|
|
data-i18n="submissions.index.action.new">+ Neuer Entwurf</a>
|
|
</div>
|
|
</div>
|
|
|
|
<p className="entity-events-empty" id="submissions-index-loading"
|
|
data-i18n="submissions.index.loading">Lädt…</p>
|
|
|
|
<div className="entity-empty" id="submissions-index-empty" style="display:none">
|
|
<p data-i18n="submissions.index.empty">
|
|
Noch keine Entwürfe. Beginnen Sie mit einem neuen Entwurf — mit oder ohne Projekt.
|
|
</p>
|
|
<a href="/submissions/new" className="btn-primary btn-cta-lime"
|
|
data-i18n="submissions.index.empty.cta">+ Neuer Entwurf</a>
|
|
</div>
|
|
|
|
<div className="entity-empty" id="submissions-index-error" style="display:none">
|
|
<p data-i18n="submissions.index.error">Schriftsätze konnten nicht geladen werden.</p>
|
|
</div>
|
|
|
|
<div className="entity-table-wrap" id="submissions-index-tablewrap" style="display:none">
|
|
<table className="entity-table">
|
|
<thead>
|
|
<tr>
|
|
<th data-i18n="submissions.index.col.project">Projekt</th>
|
|
<th data-i18n="submissions.index.col.submission">Schriftsatz</th>
|
|
<th data-i18n="submissions.index.col.draft">Entwurf</th>
|
|
<th data-i18n="submissions.index.col.updated">Zuletzt geändert</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="submissions-index-body" />
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<Footer />
|
|
<PaliadinWidget />
|
|
<script src="/assets/submissions-index.js"></script>
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|