fix(import+screening): GET-Alias, DELETE-Endpoint, ehrlicher Scan-Status
Some checks failed
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 37s
CI / test-python-backend-compliance (push) Successful in 32s
CI / test-python-dsms-gateway (push) Has been cancelled
CI / test-python-document-crawler (push) Has been cancelled

Import-Backend:
- GET /v1/import (Root-Alias) → list_documents; behebt URL-Mismatch im Proxy
- DELETE /v1/import/{document_id} → löscht Dokument + Gap-Analyse (mit Tenant-Isolierung)
- 6 neue Tests (65 total, alle grün)

Screening-Frontend:
- Simulierten Fortschrittsbalken (Math.random) entfernt — war inhaltlich falsch
- Ersetzt durch indeterminate Spinner + rotierende ehrliche Status-Texte
  (z.B. "OSV.dev Datenbank wird abgefragt...") im 2-Sek.-Takt
- Kein scanProgress-State mehr benötigt

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-05 12:07:01 +01:00
parent 3707ffe799
commit ef17151a41
3 changed files with 175 additions and 50 deletions

View File

@@ -8,38 +8,18 @@ import { useSDK, ScreeningResult, SecurityIssue, SBOMComponent, BacklogItem } fr
// COMPONENTS
// =============================================================================
function ScanProgress({ progress, status }: { progress: number; status: string }) {
function ScanProgress({ status }: { status: string }) {
return (
<div className="bg-white rounded-xl border border-gray-200 p-6">
<div className="flex items-center gap-4">
<div className="relative w-16 h-16">
<svg className="w-16 h-16 transform -rotate-90">
<circle cx="32" cy="32" r="28" stroke="#e5e7eb" strokeWidth="4" fill="none" />
<circle
cx="32"
cy="32"
r="28"
stroke="#9333ea"
strokeWidth="4"
fill="none"
strokeDasharray={`${progress * 1.76} 176`}
strokeLinecap="round"
/>
</svg>
<span className="absolute inset-0 flex items-center justify-center text-sm font-bold text-gray-900">
{progress}%
</span>
</div>
<div className="w-10 h-10 border-4 border-gray-200 border-t-purple-600 rounded-full animate-spin flex-shrink-0" />
<div>
<h3 className="font-semibold text-gray-900">Scanning...</h3>
<h3 className="font-semibold text-gray-900">Scan läuft...</h3>
<p className="text-sm text-gray-500">{status}</p>
</div>
</div>
<div className="mt-4 h-2 bg-gray-100 rounded-full overflow-hidden">
<div
className="h-full bg-purple-600 rounded-full transition-all duration-500"
style={{ width: `${progress}%` }}
/>
<div className="mt-4 h-1.5 bg-gray-100 rounded-full overflow-hidden">
<div className="h-full bg-purple-600 rounded-full animate-pulse w-full" />
</div>
</div>
)
@@ -166,7 +146,6 @@ 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[]>([])
@@ -214,27 +193,22 @@ export default function ScreeningPage() {
const startScan = async (file: File) => {
setIsScanning(true)
setScanProgress(0)
setScanStatus('Initialisierung...')
setScanStatus('Abhängigkeiten werden analysiert...')
setScanError(null)
// Show progress steps while API processes
const progressInterval = setInterval(() => {
setScanProgress(prev => {
if (prev >= 90) return prev
const step = Math.random() * 15 + 5
const next = Math.min(prev + step, 90)
const statuses = [
'Abhaengigkeiten werden analysiert...',
'SBOM wird generiert...',
'Schwachstellenscan laeuft...',
'OSV.dev Datenbank wird abgefragt...',
'Lizenzpruefung...',
]
setScanStatus(statuses[Math.min(Math.floor(next / 20), statuses.length - 1)])
return next
})
}, 600)
// Rotate through honest status messages while backend processes
const statusMessages = [
'Abhängigkeiten werden analysiert...',
'SBOM wird generiert...',
'Schwachstellenscan läuft...',
'OSV.dev Datenbank wird abgefragt...',
'Lizenzprüfung...',
]
let statusIdx = 0
const statusInterval = setInterval(() => {
statusIdx = (statusIdx + 1) % statusMessages.length
setScanStatus(statusMessages[statusIdx])
}, 2000)
try {
const formData = new FormData()
@@ -246,7 +220,7 @@ export default function ScreeningPage() {
body: formData,
})
clearInterval(progressInterval)
clearInterval(statusInterval)
if (!response.ok) {
const err = await response.json().catch(() => ({ error: 'Unknown error' }))
@@ -255,7 +229,6 @@ export default function ScreeningPage() {
const data = await response.json()
setScanProgress(100)
setScanStatus('Abgeschlossen!')
// Map backend response to ScreeningResult
@@ -308,10 +281,9 @@ export default function ScreeningPage() {
dispatch({ type: 'ADD_SECURITY_ISSUE', payload: issue })
})
} catch (error: any) {
clearInterval(progressInterval)
clearInterval(statusInterval)
console.error('Screening scan failed:', error)
setScanError(error.message || 'Scan fehlgeschlagen')
setScanProgress(0)
setScanStatus('')
} finally {
setIsScanning(false)
@@ -369,7 +341,7 @@ export default function ScreeningPage() {
)}
{/* Scan Progress */}
{isScanning && <ScanProgress progress={scanProgress} status={scanStatus} />}
{isScanning && <ScanProgress status={scanStatus} />}
{/* Results */}
{state.screening && state.screening.status === 'COMPLETED' && (