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