diff --git a/admin-compliance/app/sdk/agent/_components/ChecklistView.tsx b/admin-compliance/app/sdk/agent/_components/ChecklistView.tsx index ae8387d..2279a29 100644 --- a/admin-compliance/app/sdk/agent/_components/ChecklistView.tsx +++ b/admin-compliance/app/sdk/agent/_components/ChecklistView.tsx @@ -64,7 +64,11 @@ export function ChecklistView({ results }: { results: DocResult[] }) {
{r.label}
-
{r.url}
+
+ {r.checks.length > 0 + ? `${r.checks.filter(c => c.passed).length} von ${r.checks.length} Pruefpunkten bestanden` + : r.url} +
diff --git a/admin-compliance/app/sdk/agent/_components/DocCheckTab.tsx b/admin-compliance/app/sdk/agent/_components/DocCheckTab.tsx index b8ecbaa..f4e7897 100644 --- a/admin-compliance/app/sdk/agent/_components/DocCheckTab.tsx +++ b/admin-compliance/app/sdk/agent/_components/DocCheckTab.tsx @@ -24,12 +24,25 @@ function newEntry(): DocEntry { } export function DocCheckTab() { - const [entries, setEntries] = useState([newEntry()]) + const [entries, setEntries] = useState(() => { + if (typeof window === 'undefined') return [newEntry()] + try { const s = localStorage.getItem('doc-check-entries'); return s ? JSON.parse(s) : [newEntry()] } catch { return [newEntry()] } + }) const [checkCookieBanner, setCheckCookieBanner] = useState(false) const [loading, setLoading] = useState(false) const [progress, setProgress] = useState('') - const [results, setResults] = useState(null) + const [results, setResults] = useState(() => { + if (typeof window === 'undefined') return null + try { const s = localStorage.getItem('doc-check-results'); return s ? JSON.parse(s) : null } catch { return null } + }) const [error, setError] = useState(null) + const [history, setHistory] = useState<{ date: string; urls: number; findings: number }[]>(() => { + if (typeof window === 'undefined') return [] + try { return JSON.parse(localStorage.getItem('doc-check-history') || '[]') } catch { return [] } + }) + + // Persist entries + React.useEffect(() => { localStorage.setItem('doc-check-entries', JSON.stringify(entries)) }, [entries]) const updateEntry = (id: string, field: keyof DocEntry, value: string) => { setEntries(prev => prev.map(e => e.id === id ? { ...e, [field]: value } : e)) @@ -94,6 +107,11 @@ export function DocCheckTab() { if (pollData.status === 'completed' && pollData.result) { setResults(pollData.result) setProgress('') + localStorage.setItem('doc-check-results', JSON.stringify(pollData.result)) + const entry = { date: new Date().toISOString(), urls: validEntries.length, findings: pollData.result.total_findings || 0 } + const updated = [entry, ...history].slice(0, 30) + setHistory(updated) + localStorage.setItem('doc-check-history', JSON.stringify(updated)) break } if (pollData.status === 'failed') { @@ -128,7 +146,7 @@ export function DocCheckTab() { type="text" value={entry.label} onChange={e => updateEntry(entry.id, 'label', e.target.value)} - placeholder="Bezeichnung (optional)" + placeholder={entry.type === 'other' ? 'Dokumentname' : 'Version / Stand (optional)'} className="w-40 px-3 py-2.5 border border-gray-300 rounded-lg text-sm shrink-0" /> )} + + {/* History */} + {history.length > 0 && ( +
+

Letzte Pruefungen

+
+ {history.map((h, i) => ( +
+ + {new Date(h.date).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' })} + +
+ {h.urls} Dok. + 0 ? 'text-amber-600' : 'text-green-600'}`}> + {h.findings} Findings + +
+
+ ))} +
+
+ )}
) } diff --git a/backend-compliance/compliance/services/dsi_document_checker.py b/backend-compliance/compliance/services/dsi_document_checker.py index c7cd6d2..524cd6f 100644 --- a/backend-compliance/compliance/services/dsi_document_checker.py +++ b/backend-compliance/compliance/services/dsi_document_checker.py @@ -184,7 +184,10 @@ COOKIE_CHECKLIST = [ {"id": "cookie_types", "label": "Arten der Cookies", "patterns": [r"(?:notwendig|essentiell|funktional|statistik|marketing|tracking)", r"cookie.*(?:art|typ|kategori)"]}, {"id": "purposes", "label": "Zwecke der Cookies", - "patterns": [r"zweck.*cookie", r"cookie.*zweck", r"(?:wofuer|wozu|warum).*cookie"]}, + "patterns": [r"zweck.*cookie", r"cookie.*zweck", r"(?:wofuer|wozu|warum).*cookie", + r"cookies?\s+(?:ein|ver)?\s*,?\s*um\s+", r"(?:setzen|verwenden|nutzen)\s+.*cookies?\s+.*(?:um|fuer|für)", + r"(?:analyse|marketing|tracking|funktional)\w*\s*cookies?\s*\.?\s*(?:um|damit|diese|sie)", + r"cookies?\s+(?:dienen|helfen|ermöglichen|ermoeglichen)"]}, {"id": "retention", "label": "Speicherdauer der Cookies", "patterns": [r"(?:speicherdauer|laufzeit|gueltigk|ablauf).*cookie", r"cookie.*(?:\d+\s+(?:tag|monat|jahr)|session)"]}, {"id": "third_party", "label": "Drittanbieter-Cookies", @@ -232,6 +235,7 @@ def check_document_completeness( "doc_title": doc_title, "doc_url": doc_url, "doc_type": doc_type, + "all_checks": [], # No checks run for short documents }) return findings