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

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:
Benjamin Admin
2026-03-02 15:08:13 +01:00
parent fc83ebfd82
commit d079886819
32 changed files with 1734 additions and 76 deletions

View File

@@ -1,7 +1,8 @@
'use client'
import React, { useState, useRef } from 'react'
import { useSDK, ScreeningResult, SecurityIssue, SBOMComponent } from '@/lib/sdk'
import React, { useState, useRef, useEffect } from 'react'
import { useRouter } from 'next/navigation'
import { useSDK, ScreeningResult, SecurityIssue, SBOMComponent, BacklogItem } from '@/lib/sdk'
// =============================================================================
// COMPONENTS
@@ -163,12 +164,54 @@ function SecurityIssueCard({ issue }: { issue: SecurityIssue }) {
export default function ScreeningPage() {
const { state, dispatch } = useSDK()
const router = useRouter()
const [isScanning, setIsScanning] = useState(false)
const [scanProgress, setScanProgress] = useState(0)
const [scanStatus, setScanStatus] = useState('')
const [scanError, setScanError] = useState<string | null>(null)
const [scanHistory, setScanHistory] = useState<any[]>([])
const [historyLoading, setHistoryLoading] = useState(false)
const fileInputRef = useRef<HTMLInputElement>(null)
// 5.2: Load scan history
useEffect(() => {
const loadHistory = async () => {
setHistoryLoading(true)
try {
const response = await fetch('/api/sdk/v1/screening?tenant_id=default')
if (response.ok) {
const data = await response.json()
setScanHistory(Array.isArray(data) ? data : data.items || [])
}
} catch (err) {
console.error('Failed to load scan history:', err)
} finally {
setHistoryLoading(false)
}
}
loadHistory()
}, [state.screening])
// 5.1: Add issues to security backlog
const addToSecurityBacklog = () => {
const issues = state.screening?.securityScan?.issues || []
issues.forEach(issue => {
const backlogItem: BacklogItem = {
id: `backlog-${issue.id}`,
title: issue.title,
description: `${issue.description}\n\nBetroffene Komponente: ${issue.affectedComponent}\nEmpfehlung: ${issue.remediation}`,
severity: issue.severity,
securityIssueId: issue.id,
status: 'OPEN',
assignee: null,
dueDate: null,
createdAt: new Date(),
}
dispatch({ type: 'ADD_BACKLOG_ITEM', payload: backlogItem })
})
router.push('/sdk/security-backlog')
}
const startScan = async (file: File) => {
setIsScanning(true)
setScanProgress(0)
@@ -380,12 +423,54 @@ export default function ScreeningPage() {
>
Neuen Scan starten
</button>
<button className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors">
Zum Security Backlog hinzufügen
<button
onClick={addToSecurityBacklog}
className="px-4 py-2 bg-purple-600 text-white rounded-lg hover:bg-purple-700 transition-colors"
>
Zum Security Backlog hinzufuegen
</button>
</div>
</>
)}
{/* Scan-Verlauf */}
{scanHistory.length > 0 && (
<div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
<div className="px-6 py-4 border-b border-gray-200 bg-gray-50">
<h3 className="font-semibold text-gray-900">Scan-Verlauf</h3>
<p className="text-sm text-gray-500">{scanHistory.length} fruehere Scans</p>
</div>
<div className="divide-y divide-gray-100">
{scanHistory.map((scan: any, idx: number) => (
<div key={scan.id || idx} className="px-6 py-4 flex items-center justify-between hover:bg-gray-50">
<div>
<p className="text-sm font-medium text-gray-900">
Scan #{scan.id?.slice(0, 8) || idx + 1}
</p>
<p className="text-xs text-gray-500">
{scan.completed_at ? new Date(scan.completed_at).toLocaleString('de-DE') : 'Unbekannt'}
</p>
</div>
<div className="flex items-center gap-3">
<span className="text-xs text-gray-500">
{scan.total_issues || 0} Issues
</span>
<span className={`px-2 py-1 text-xs rounded-full ${
(scan.critical_issues || 0) > 0
? 'bg-red-100 text-red-700'
: 'bg-green-100 text-green-700'
}`}>
{(scan.critical_issues || 0) > 0 ? `${scan.critical_issues} Kritisch` : 'Keine kritischen'}
</span>
</div>
</div>
))}
</div>
</div>
)}
{historyLoading && (
<div className="text-center py-4 text-sm text-gray-500">Scan-Verlauf wird geladen...</div>
)}
</div>
)
}