@@ -2,53 +2,66 @@ import { Trash2 } from 'lucide-react'
22import { useTranslation } from 'react-i18next'
33import { Link } from 'react-router-dom'
44import { cn } from '@/shared/lib/utils'
5+ import { ConfirmDialog } from '@/shared/components/ui/confirm-dialog'
56import { sevKey } from '../lib/incident-meta'
67import { useIncidentAlertsTab } from '../hooks/use-incident-alerts-tab'
78import { TabEmpty , TabError , TabLoader } from './ui-primitives'
89
910export function IncidentAlertsTab ( { incidentId, onChanged } : { incidentId : number ; onChanged : ( ) => void } ) {
1011 const { t } = useTranslation ( )
11- const { rows, error, reload, remove } = useIncidentAlertsTab ( incidentId , onChanged )
12+ const { rows, error, reload, remove, pendingDelete , deleting , cancelDelete , confirmDelete } = useIncidentAlertsTab ( incidentId , onChanged )
1213
1314 if ( error ) return < TabError onRetry = { reload } />
1415 if ( rows === null ) return < TabLoader />
1516 if ( rows . length === 0 ) return < TabEmpty > { t ( 'incidents.alerts.empty' ) } </ TabEmpty >
1617 return (
17- < div className = "overflow-hidden rounded-lg border border-border bg-card" >
18- { rows . map ( ( a ) => (
19- < Link
20- to = "/threat-management/alerts"
21- state = { {
22- socaiFilters : [
23- { field : 'id' , operator : 'IS' , value : a . alertId } ,
24- { field : '@timestamp' , operator : 'IS_BETWEEN' , value : [ 'now-30d' , 'now' ] } ,
25- ] ,
26- socaiTime : 'now-30d' ,
27- } }
28- key = { a . id }
29- className = "group flex items-center gap-3 border-b border-border/60 px-4 py-2.5 text-xs last:border-b-0"
30- >
31- < span
32- className = { cn (
33- 'h-4 w-1 shrink-0 rounded-full' ,
34- a . alertSeverity === 3 ? 'bg-red-500' : a . alertSeverity === 2 ? 'bg-amber-500' : 'bg-sky-500'
35- ) }
36- />
37- < span className = "min-w-0 flex-1 truncate font-medium" title = { a . alertName } >
38- { a . alertName }
39- </ span >
40- < span className = "shrink-0 font-mono text-[10px] text-muted-foreground" >
41- { t ( `incidents.sev.${ sevKey ( a . alertSeverity ) } ` ) }
42- </ span >
43- < button
44- onClick = { ( ) => void remove ( a ) }
45- title = { t ( 'incidents.alerts.remove' ) }
46- className = "shrink-0 rounded p-1 text-muted-foreground opacity-0 transition hover:bg-muted hover:text-red-500 group-hover:opacity-100"
18+ < >
19+ < div className = "overflow-hidden rounded-lg border border-border bg-card" >
20+ { rows . map ( ( a ) => (
21+ < Link
22+ to = "/threat-management/alerts"
23+ state = { {
24+ socaiFilters : [
25+ { field : 'id' , operator : 'IS' , value : a . alertId } ,
26+ { field : '@timestamp' , operator : 'IS_BETWEEN' , value : [ 'now-30d' , 'now' ] } ,
27+ ] ,
28+ socaiTime : 'now-30d' ,
29+ } }
30+ key = { a . id }
31+ className = "group flex items-center gap-3 border-b border-border/60 px-4 py-2.5 text-xs last:border-b-0"
4732 >
48- < Trash2 size = { 13 } />
49- </ button >
50- </ Link >
51- ) ) }
52- </ div >
33+ < span
34+ className = { cn (
35+ 'h-4 w-1 shrink-0 rounded-full' ,
36+ a . alertSeverity === 3 ? 'bg-red-500' : a . alertSeverity === 2 ? 'bg-amber-500' : 'bg-sky-500'
37+ ) }
38+ />
39+ < span className = "min-w-0 flex-1 truncate font-medium" title = { a . alertName } >
40+ { a . alertName }
41+ </ span >
42+ < span className = "shrink-0 font-mono text-[10px] text-muted-foreground" >
43+ { t ( `incidents.sev.${ sevKey ( a . alertSeverity ) } ` ) }
44+ </ span >
45+ < button
46+ onClick = { ( ) => remove ( a ) }
47+ title = { t ( 'incidents.alerts.remove' ) }
48+ className = "shrink-0 rounded p-1 text-muted-foreground opacity-0 transition hover:bg-muted hover:text-red-500 group-hover:opacity-100"
49+ >
50+ < Trash2 size = { 13 } />
51+ </ button >
52+ </ Link >
53+ ) ) }
54+ </ div >
55+ < ConfirmDialog
56+ open = { pendingDelete != null }
57+ title = { t ( 'incidents.alerts.remove' ) ?? 'Remove alert' }
58+ body = { pendingDelete ? t ( 'incidents.alerts.removeConfirm' , { name : pendingDelete . alertName } ) : '' }
59+ confirmLabel = { t ( 'common.actions.remove' ) ?? t ( 'incidents.alerts.remove' ) ?? undefined }
60+ danger
61+ busy = { deleting }
62+ onClose = { ( ) => ! deleting && cancelDelete ( ) }
63+ onConfirm = { confirmDelete }
64+ />
65+ </ >
5366 )
5467}
0 commit comments