feat: 6 Dokumentations-Module auf 100% — VVT Backend, Filter, PDF-Export
Phase 1 — VVT Backend (localStorage → API): - migrations/006_vvt.sql: Neue Tabellen (vvt_organization, vvt_activities, vvt_audit_log) - compliance/db/vvt_models.py: SQLAlchemy-Models für alle VVT-Tabellen - compliance/api/vvt_routes.py: Vollständiger CRUD-Router (10 Endpoints) - compliance/api/__init__.py: VVT-Router registriert - compliance/api/schemas.py: VVT Pydantic-Schemas ergänzt - app/(sdk)/sdk/vvt/page.tsx: API-Client + camelCase↔snake_case Mapping, localStorage durch persistente DB-Calls ersetzt (POST/PUT/DELETE/GET) - tests/test_vvt_routes.py: 18 Tests (alle grün) Phase 3 — Document Generator PDF-Export: - document-generator/page.tsx: "Als PDF exportieren"-Button funktioniert jetzt via window.print() + Print-Window mit korrektem HTML - Fallback-Banner wenn Template-Service (breakpilot-core) nicht erreichbar Phase 4 — Source Policy erweiterte Filter: - SourcesTab.tsx: source_type-Filter (Rechtlich / Leitlinien / Vorlagen / etc.) - PIIRulesTab.tsx: category-Filter (E-Mail / Telefon / IBAN / etc.) - source_policy_router.py: Backend-Endpoints unterstützen jetzt source_type und category als Query-Parameter - requirements.txt: reportlab==4.2.5 ergänzt (fehlende Audit-PDF-Dependency) Phase 2 — Training (Migration-Skripte): - scripts/apply_training_migrations.sh: SSH-Skript für Mac Mini - scripts/apply_vvt_migration.sh: Vollständiges Deploy-Skript für VVT Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -454,6 +454,13 @@ export default function DocumentGeneratorPage() {
|
||||
</button>
|
||||
</StepHeader>
|
||||
|
||||
{/* Service unreachable warning */}
|
||||
{!isLoading && !status && (
|
||||
<div className="bg-amber-50 border border-amber-200 rounded-xl p-4 text-sm text-amber-800">
|
||||
<strong>Template-Service nicht erreichbar.</strong> Stellen Sie sicher, dass breakpilot-core läuft (<code>curl -sf http://macmini:8099/health</code>). Das Suchen und Zusammenstellen von Vorlagen ist erst nach Verbindung möglich.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Status Overview */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-4">
|
||||
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
||||
@@ -737,6 +744,24 @@ export default function DocumentGeneratorPage() {
|
||||
Kopieren
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
const printWindow = window.open('', '_blank')
|
||||
if (!printWindow) return
|
||||
let content = combinedContent
|
||||
for (const [key, value] of Object.entries(placeholderValues)) {
|
||||
if (value) {
|
||||
content = content.replace(new RegExp(key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), value)
|
||||
}
|
||||
}
|
||||
const attributions = selectedTemplateObjects
|
||||
.filter(t => t.attributionRequired && t.attributionText)
|
||||
.map(t => `<li>${t.attributionText}</li>`)
|
||||
.join('')
|
||||
printWindow.document.write(`<!DOCTYPE html><html lang="de"><head><meta charset="UTF-8"><title>Datenschutzdokument</title><style>body{font-family:Arial,sans-serif;max-width:800px;margin:40px auto;padding:0 20px;line-height:1.6;color:#222}h2{border-bottom:1px solid #ccc;padding-bottom:8px;margin-top:32px}hr{border:none;border-top:1px solid #eee;margin:24px 0}.attribution{font-size:12px;color:#666;margin-top:48px;border-top:1px solid #ddd;padding-top:16px}@media print{body{margin:0}}</style></head><body><div style="white-space:pre-wrap">${content.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')}</div>${attributions ? `<div class="attribution"><strong>Quellenangaben:</strong><ul>${attributions}</ul></div>` : ''}</body></html>`)
|
||||
printWindow.document.close()
|
||||
printWindow.focus()
|
||||
setTimeout(() => printWindow.print(), 500)
|
||||
}}
|
||||
className="px-6 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
|
||||
>
|
||||
Als PDF exportieren
|
||||
|
||||
Reference in New Issue
Block a user