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:
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user