feat: 7 Vorbereitungs-Module auf 100% — Frontend, Proxy-Routen, Backend-Fixes
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 35s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s
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 35s
CI / test-python-backend-compliance (push) Successful in 30s
CI / test-python-document-crawler (push) Successful in 22s
CI / test-python-dsms-gateway (push) Successful in 19s
Profil: machineBuilder-Felder im POST-Body, PATCH-Handler Scope: API-Route (GET/POST), ScopeDecisionTab Props + Buttons, Export-Druckansicht HTML Anwendung: PUT-Handler, Bearbeiten-Button, Pagination/Search Import: Verlauf laden, DELETE-Route, Offline-Badge, ObjectURL Memory-Leak fix Screening: Security-Backlog Button verdrahtet, Scan-Verlauf Module: Detail-Seite, GET-Proxy, Konfigurieren-Button, Modul-erstellen-Modal, Error-Toast Quellen: 10 Proxy-Routen, Tab-Komponenten umgestellt, Dashboard-Tab, blocked_today Bug fix, Datum-Filter Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -15,15 +15,8 @@ import { OperationsMatrixTab } from '@/components/sdk/source-policy/OperationsMa
|
||||
import { PIIRulesTab } from '@/components/sdk/source-policy/PIIRulesTab'
|
||||
import { AuditTab } from '@/components/sdk/source-policy/AuditTab'
|
||||
|
||||
// API base URL for backend-compliance
|
||||
const getApiBase = () => {
|
||||
if (typeof window === 'undefined') return 'http://localhost:8002/api'
|
||||
const hostname = window.location.hostname
|
||||
if (hostname === 'localhost' || hostname === '127.0.0.1') {
|
||||
return 'http://localhost:8002/api'
|
||||
}
|
||||
return `https://${hostname}:8002/api`
|
||||
}
|
||||
// API base URL — now uses Next.js proxy routes
|
||||
const API_BASE = '/api/sdk/v1/source-policy'
|
||||
|
||||
interface PolicyStats {
|
||||
active_policies: number
|
||||
@@ -41,23 +34,15 @@ export default function SourcePolicyPage() {
|
||||
const [stats, setStats] = useState<PolicyStats | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState<string | null>(null)
|
||||
const [apiBase, setApiBase] = useState<string | null>(null)
|
||||
|
||||
useEffect(() => {
|
||||
const base = getApiBase()
|
||||
setApiBase(base)
|
||||
fetchStats()
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (apiBase !== null) {
|
||||
fetchStats()
|
||||
}
|
||||
}, [apiBase])
|
||||
|
||||
const fetchStats = async () => {
|
||||
try {
|
||||
setLoading(true)
|
||||
const res = await fetch(`${apiBase}/v1/admin/policy-stats`)
|
||||
const res = await fetch(`${API_BASE}/policy-stats`)
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error('Fehler beim Laden der Statistiken')
|
||||
@@ -182,21 +167,82 @@ export default function SourcePolicyPage() {
|
||||
</div>
|
||||
|
||||
{/* Tab Content */}
|
||||
{apiBase === null ? (
|
||||
<div className="text-center py-12 text-slate-500">Initialisiere...</div>
|
||||
) : (
|
||||
<>
|
||||
{activeTab === 'dashboard' && (
|
||||
<div className="text-center py-12 text-slate-500">
|
||||
{loading ? 'Lade Dashboard...' : 'Dashboard-Ansicht - Wechseln Sie zu einem Tab fuer Details.'}
|
||||
<>
|
||||
{activeTab === 'dashboard' && stats && (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Quellen-Uebersicht</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">Zugelassene Quellen</span>
|
||||
<span className="text-2xl font-bold text-green-600">{stats.allowed_sources}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">Aktive Policies</span>
|
||||
<span className="text-2xl font-bold text-purple-600">{stats.active_policies}</span>
|
||||
</div>
|
||||
<div className="h-2 bg-gray-100 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-green-500 rounded-full"
|
||||
style={{ width: `${stats.allowed_sources > 0 ? Math.min((stats.active_policies / stats.allowed_sources) * 100, 100) : 0}%` }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 'sources' && <SourcesTab apiBase={apiBase} onUpdate={fetchStats} />}
|
||||
{activeTab === 'operations' && <OperationsMatrixTab apiBase={apiBase} />}
|
||||
{activeTab === 'pii' && <PIIRulesTab apiBase={apiBase} onUpdate={fetchStats} />}
|
||||
{activeTab === 'audit' && <AuditTab apiBase={apiBase} />}
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="bg-white rounded-xl border border-gray-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Datenschutz-Regeln</h3>
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">PII-Regeln aktiv</span>
|
||||
<span className="text-2xl font-bold text-blue-600">{stats.pii_rules}</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">Blockiert (heute)</span>
|
||||
<span className={`text-2xl font-bold ${stats.blocked_today > 0 ? 'text-red-600' : 'text-green-600'}`}>
|
||||
{stats.blocked_today}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-sm text-gray-600">Blockiert (gesamt)</span>
|
||||
<span className="text-lg font-semibold text-gray-500">{stats.blocked_total}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="md:col-span-2 bg-white rounded-xl border border-gray-200 p-6">
|
||||
<h3 className="text-lg font-semibold text-gray-900 mb-4">Compliance-Status</h3>
|
||||
<div className="flex items-center gap-6">
|
||||
<div className="flex-1 text-center p-4 bg-green-50 rounded-lg">
|
||||
<div className="text-sm text-green-700 font-medium">Quellen konfiguriert</div>
|
||||
<div className="text-3xl font-bold text-green-600 mt-1">
|
||||
{stats.allowed_sources > 0 ? 'Ja' : 'Nein'}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 text-center p-4 bg-blue-50 rounded-lg">
|
||||
<div className="text-sm text-blue-700 font-medium">PII-Schutz aktiv</div>
|
||||
<div className="text-3xl font-bold text-blue-600 mt-1">
|
||||
{stats.pii_rules > 0 ? 'Ja' : 'Nein'}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 text-center p-4 bg-purple-50 rounded-lg">
|
||||
<div className="text-sm text-purple-700 font-medium">Policies definiert</div>
|
||||
<div className="text-3xl font-bold text-purple-600 mt-1">
|
||||
{stats.active_policies > 0 ? 'Ja' : 'Nein'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{activeTab === 'dashboard' && !stats && loading && (
|
||||
<div className="text-center py-12 text-slate-500">Lade Dashboard...</div>
|
||||
)}
|
||||
{activeTab === 'sources' && <SourcesTab apiBase={API_BASE} onUpdate={fetchStats} />}
|
||||
{activeTab === 'operations' && <OperationsMatrixTab apiBase={API_BASE} />}
|
||||
{activeTab === 'pii' && <PIIRulesTab apiBase={API_BASE} onUpdate={fetchStats} />}
|
||||
{activeTab === 'audit' && <AuditTab apiBase={API_BASE} />}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user