feat(iace): "Neu initialisieren" Button + DeleteHazard
- POST /initialize?force=true loescht bestehende Hazards + Mitigations und erstellt sie neu mit aktuellen Betriebszustaenden - Orange "Neu initialisieren" Button auf Interview-Seite (mit Confirm-Dialog) - DeleteHazard Store-Methode (kaskadiert Risk Assessments) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -236,6 +236,47 @@ export default function IACEInterviewPage() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
disabled={initStatus === 'running' || completionPct < 30}
|
||||||
|
onClick={async () => {
|
||||||
|
if (!confirm('Alle bestehenden Gefaehrdungen und Massnahmen loeschen und neu erstellen?')) return
|
||||||
|
if (saveTimerRef.current) {
|
||||||
|
clearTimeout(saveTimerRef.current)
|
||||||
|
await saveToBackend(latestFormRef.current)
|
||||||
|
}
|
||||||
|
setInitStatus('running')
|
||||||
|
setInitResult(null)
|
||||||
|
try {
|
||||||
|
const res = await fetch(`/api/sdk/v1/iace/projects/${projectId}/initialize?force=true`, { method: 'POST' })
|
||||||
|
if (!res.ok) {
|
||||||
|
const err = await res.json().catch(() => ({}))
|
||||||
|
alert(err.error || 'Neu-Initialisierung fehlgeschlagen')
|
||||||
|
setInitStatus('error')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const data = await res.json()
|
||||||
|
setInitResult(data)
|
||||||
|
setInitStatus('done')
|
||||||
|
} catch {
|
||||||
|
setInitStatus('error')
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
className="flex items-center gap-2 px-4 py-2 bg-orange-600 text-white rounded-lg hover:bg-orange-700 text-xs font-medium transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
{initStatus === 'running' ? (
|
||||||
|
<>
|
||||||
|
<span className="animate-spin inline-block w-3.5 h-3.5 border-2 border-white border-t-transparent rounded-full" />
|
||||||
|
Laeuft...
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<svg className="w-3.5 h-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||||
|
</svg>
|
||||||
|
Neu initialisieren
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (saveTimerRef.current) {
|
if (saveTimerRef.current) {
|
||||||
|
|||||||
@@ -42,8 +42,29 @@ func (h *IACEHandler) InitializeProject(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Support ?force=true to clear existing hazards + mitigations before re-init
|
||||||
|
forceReinit := c.Query("force") == "true"
|
||||||
|
|
||||||
steps := make([]InitStep, 0, 6)
|
steps := make([]InitStep, 0, 6)
|
||||||
|
|
||||||
|
// ── Step 0 (optional): Clear existing data for force re-init ──
|
||||||
|
if forceReinit {
|
||||||
|
cleared := 0
|
||||||
|
if mits, _ := h.store.ListMitigationsByProject(ctx, projectID); len(mits) > 0 {
|
||||||
|
for _, m := range mits {
|
||||||
|
_ = h.store.DeleteMitigation(ctx, m.ID)
|
||||||
|
cleared++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hazards, _ := h.store.ListHazards(ctx, projectID); len(hazards) > 0 {
|
||||||
|
for _, hz := range hazards {
|
||||||
|
_ = h.store.DeleteHazard(ctx, hz.ID)
|
||||||
|
cleared++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
steps = append(steps, InitStep{Name: "Alte Daten geloescht", Status: "done", Count: cleared})
|
||||||
|
}
|
||||||
|
|
||||||
// ── Step 1: Extract narrative from limits_form ──
|
// ── Step 1: Extract narrative from limits_form ──
|
||||||
narrativeText := extractNarrativeFromMetadata(project.Metadata)
|
narrativeText := extractNarrativeFromMetadata(project.Metadata)
|
||||||
if narrativeText == "" {
|
if narrativeText == "" {
|
||||||
|
|||||||
@@ -199,6 +199,19 @@ func (s *Store) UpdateHazard(ctx context.Context, id uuid.UUID, updates map[stri
|
|||||||
return s.GetHazard(ctx, id)
|
return s.GetHazard(ctx, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteHazard removes a hazard and its risk assessments.
|
||||||
|
func (s *Store) DeleteHazard(ctx context.Context, id uuid.UUID) error {
|
||||||
|
_, err := s.pool.Exec(ctx, `DELETE FROM iace_risk_assessments WHERE hazard_id = $1`, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("delete hazard assessments: %w", err)
|
||||||
|
}
|
||||||
|
_, err = s.pool.Exec(ctx, `DELETE FROM iace_hazards WHERE id = $1`, id)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("delete hazard: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Risk Assessment Operations
|
// Risk Assessment Operations
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user