'use client' import { useState, useEffect } from 'react' interface OperationPermission { id: string source_id: string operation: string allowed: boolean conditions?: string } interface SourceWithOperations { id: string domain: string name: string license?: string active: boolean operations: OperationPermission[] } interface OperationsMatrixTabProps { apiBase: string } const OPERATIONS = [ { id: 'lookup', name: 'Lookup', description: 'Inhalt anzeigen/durchsuchen', icon: '🔍' }, { id: 'rag', name: 'RAG', description: 'Retrieval Augmented Generation', icon: '🤖' }, { id: 'training', name: 'Training', description: 'KI-Training (VERBOTEN)', icon: '🚫' }, { id: 'export', name: 'Export', description: 'Daten exportieren', icon: '📤' }, ] export function OperationsMatrixTab({ apiBase }: OperationsMatrixTabProps) { const [sources, setSources] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) const [updating, setUpdating] = useState(null) useEffect(() => { fetchMatrix() }, []) const fetchMatrix = async () => { try { setLoading(true) const [sourcesRes, opsRes] = await Promise.all([ fetch(`${apiBase}/sources`), fetch(`${apiBase}/operations-matrix`), ]) if (!sourcesRes.ok || !opsRes.ok) throw new Error('Fehler beim Laden') const sourcesData = await sourcesRes.json() const opsData = await opsRes.json() // Join: group operations by source_id const opsBySource = new Map() for (const op of opsData.operations || []) { const list = opsBySource.get(op.source_id) || [] list.push(op) opsBySource.set(op.source_id, list) } const joined: SourceWithOperations[] = (sourcesData.sources || []).map((s: any) => ({ id: s.id, domain: s.domain, name: s.name, license: s.license, active: s.active, operations: opsBySource.get(s.id) || [], })) setSources(joined) } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } finally { setLoading(false) } } const togglePermission = async ( source: SourceWithOperations, operationId: string ) => { // Find the permission const permission = source.operations.find((op) => op.operation === operationId) if (!permission) return // Block enabling training if (operationId === 'training' && !permission.allowed) { setError('Training mit externen Daten ist VERBOTEN und kann nicht aktiviert werden.') return } const updateId = `${permission.id}-allowed` setUpdating(updateId) try { const res = await fetch(`${apiBase}/operations/${permission.id}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ allowed: !permission.allowed }), }) if (!res.ok) { const errData = await res.json() throw new Error(errData.message || errData.error || 'Fehler beim Aktualisieren') } fetchMatrix() } catch (err) { setError(err instanceof Error ? err.message : 'Unbekannter Fehler') } finally { setUpdating(null) } } if (loading) { return
Lade Operations-Matrix...
} return (
{/* Error Display */} {error && (
{error}
)} {/* Legend */}

Legende

Erlaubt
Verboten
Cite Zitation erforderlich
System-gesperrt (Training)
{/* Matrix Table */}
{OPERATIONS.map((op) => ( ))} {sources.length === 0 ? ( ) : ( sources.map((source) => ( {OPERATIONS.map((op) => { const permission = source.operations.find((p) => p.operation === op.id) const isTraining = op.id === 'training' const isAllowed = permission?.allowed ?? false const hasConditions = !!permission?.conditions const isUpdating = updating === `${permission?.id}-allowed` return ( ) })} )) )}
Quelle
{op.icon} {op.name} {op.description}
Keine Quellen vorhanden
{source.name}
{source.domain}
{/* Allowed Toggle */} {/* Conditions indicator (read-only) */} {isAllowed && !isTraining && hasConditions && ( Bedingung )}
{/* Training Warning */}

Training-Operation: System-gesperrt

Das Training von KI-Modellen mit gecrawlten externen Daten ist aufgrund von Urheberrechts- und Datenschutzbestimmungen grundsaetzlich verboten. Diese Einschraenkung ist im System hart kodiert und kann nicht ueber diese Oberflaeche geaendert werden.

Ausnahmen erfordern eine schriftliche Genehmigung des DSB und eine rechtliche Pruefung.

) }