feat: Package 4 Phase 2 — Frontend-Fixes und Backend-Endpoints vervollständigt
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 33s
CI / test-python-backend-compliance (push) Successful in 33s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 17s
All checks were successful
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Successful in 33s
CI / test-python-backend-compliance (push) Successful in 33s
CI / test-python-document-crawler (push) Successful in 21s
CI / test-python-dsms-gateway (push) Successful in 17s
- document-generator: STEP_EXPLANATIONS Key 'consent' → 'document-generator'
- Proxy: Content-Type nicht mehr hardcoded; forwarded vom Client (Fix für DOCX-Upload + multipart/arrayBuffer)
- Backend: GET /documents/{id}, DELETE /documents/{id}, GET /versions/{id} ergänzt
- Backend-Tests: 4 neue Tests für die neuen Endpoints
- consent/page.tsx: Create-Modal + handleCreateDocument() + DELETE-Handler verdrahtet
- einwilligungen/page.tsx: odentifier→identifier, ip_address, user_agent, history aus API gemappt; source nullable
- cookie-banner/page.tsx: handleExportCode() + Toast für 'Code exportieren' Button
- workflow/page.tsx: 'Neues Dokument' Button + createDocument() + Modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -86,6 +86,9 @@ export default function WorkflowPage() {
|
||||
const [showApprovalModal, setShowApprovalModal] = useState<'approve' | 'reject' | null>(null)
|
||||
const [showCompareView, setShowCompareView] = useState(false)
|
||||
const [uploading, setUploading] = useState(false)
|
||||
const [showNewDocModal, setShowNewDocModal] = useState(false)
|
||||
const [newDocForm, setNewDocForm] = useState({ type: 'privacy_policy', name: '', description: '' })
|
||||
const [creatingDoc, setCreatingDoc] = useState(false)
|
||||
|
||||
// Refs for synchronized scrolling
|
||||
const leftPanelRef = useRef<HTMLDivElement>(null)
|
||||
@@ -444,6 +447,31 @@ export default function WorkflowPage() {
|
||||
}
|
||||
}
|
||||
|
||||
const createDocument = async () => {
|
||||
if (!newDocForm.name.trim()) return
|
||||
setCreatingDoc(true)
|
||||
try {
|
||||
const res = await fetch('/api/admin/consent/documents', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(newDocForm),
|
||||
})
|
||||
if (res.ok) {
|
||||
const newDoc: Document = await res.json()
|
||||
setDocuments(prev => [newDoc, ...prev])
|
||||
setSelectedDocument(newDoc)
|
||||
setShowNewDocModal(false)
|
||||
setNewDocForm({ type: 'privacy_policy', name: '', description: '' })
|
||||
} else {
|
||||
setError('Fehler beim Erstellen des Dokuments')
|
||||
}
|
||||
} catch {
|
||||
setError('Verbindungsfehler beim Erstellen')
|
||||
} finally {
|
||||
setCreatingDoc(false)
|
||||
}
|
||||
}
|
||||
|
||||
const getNextVersionNumber = () => {
|
||||
if (versions.length === 0) return '1.0'
|
||||
const latest = versions[0]
|
||||
@@ -517,6 +545,13 @@ export default function WorkflowPage() {
|
||||
</span>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={() => setShowNewDocModal(true)}
|
||||
className="px-3 py-2 text-sm text-white bg-purple-600 hover:bg-purple-700 rounded-lg"
|
||||
>
|
||||
+ Neues Dokument
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowCompareView(true)}
|
||||
className="px-3 py-2 text-sm text-purple-600 hover:text-purple-800 border border-purple-300 rounded-lg hover:bg-purple-50"
|
||||
@@ -1026,6 +1061,68 @@ export default function WorkflowPage() {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* New Document Modal */}
|
||||
{showNewDocModal && (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
||||
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-md">
|
||||
<div className="px-6 py-4 border-b border-gray-200">
|
||||
<h2 className="text-lg font-bold text-gray-900">Neues Dokument erstellen</h2>
|
||||
</div>
|
||||
<div className="p-6 space-y-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Dokumenttyp</label>
|
||||
<select
|
||||
value={newDocForm.type}
|
||||
onChange={(e) => setNewDocForm({ ...newDocForm, type: e.target.value })}
|
||||
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500"
|
||||
>
|
||||
<option value="privacy_policy">Datenschutzerklärung</option>
|
||||
<option value="terms">AGB</option>
|
||||
<option value="cookie_policy">Cookie-Richtlinie</option>
|
||||
<option value="imprint">Impressum</option>
|
||||
<option value="dpa">AVV (Auftragsverarbeitung)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Name</label>
|
||||
<input
|
||||
type="text"
|
||||
value={newDocForm.name}
|
||||
onChange={(e) => setNewDocForm({ ...newDocForm, name: e.target.value })}
|
||||
placeholder="z.B. Datenschutzerklärung Website"
|
||||
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">Beschreibung (optional)</label>
|
||||
<textarea
|
||||
rows={2}
|
||||
value={newDocForm.description}
|
||||
onChange={(e) => setNewDocForm({ ...newDocForm, description: e.target.value })}
|
||||
placeholder="Kurze Beschreibung..."
|
||||
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-6 py-4 border-t border-gray-200 flex justify-end gap-3">
|
||||
<button
|
||||
onClick={() => setShowNewDocModal(false)}
|
||||
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg"
|
||||
>
|
||||
Abbrechen
|
||||
</button>
|
||||
<button
|
||||
onClick={createDocument}
|
||||
disabled={creatingDoc || !newDocForm.name.trim()}
|
||||
className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 disabled:opacity-50"
|
||||
>
|
||||
{creatingDoc ? 'Erstellen...' : 'Erstellen'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Approval Modal */}
|
||||
{showApprovalModal && (
|
||||
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50">
|
||||
|
||||
Reference in New Issue
Block a user