feat(alerts): "Quittierte löschen" — Backlog war nur seitenweise raeumbar
Gemeldet als "Loeschen tut nichts". Das Loeschen hat funktioniert: der
Audit-Eintrag zeigt deleted=25 und die IDs waren danach weg. Nur war das
unsichtbar — die Kopf-Checkbox der Tabelle markiert ausschliesslich die
AKTUELLE Seite (25 Zeilen), und bei einem Backlog von ~950 optisch
identischen backend.down-Alarmen ruecken sofort die naechsten 25 nach.
Fuer den Operator sah es aus, als sei nichts passiert; um den Backlog
leerzubekommen waeren ~38 Klick-Runden noetig gewesen.
Neu: POST /alerts/events/delete-acknowledged loescht alle quittierten
Events auf einmal — Gegenstueck zum bereits vorhandenen "Alle
quittieren". Bewusst nur die quittierten: was noch niemand gesehen hat,
soll nicht per Sammelaktion verschwinden. Der Button zeigt die Anzahl
ueber den gesamten Datensatz, nicht nur die sichtbare Seite.
Ausserdem meldet das seitenweise Loeschen jetzt die Anzahl zurueck
("N Alarme geloescht") statt nur "Loeschen" und leert die Auswahl —
damit ist erkennbar, dass etwas passiert ist, auch wenn die Liste
optisch gleich aussieht.
Die automatische Aufraeumung (90 Tage) arbeitet uebrigens korrekt, sie
loescht taeglich die Eintraege die ueber die Grenze rutschen — der
Backlog stammt aus dem Zeitraum davor.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1558,7 +1558,10 @@
|
||||
"subject": "Betreff",
|
||||
"delivered": "Gesendet",
|
||||
"status": "Status"
|
||||
}
|
||||
},
|
||||
"deleteAcknowledged": "Quittierte löschen",
|
||||
"confirmDeleteAcked": "{{n}} quittierte Alarme endgültig löschen? Offene Alarme bleiben erhalten.",
|
||||
"eventsDeleted": "{{n}} Alarme gelöscht."
|
||||
},
|
||||
"remotes": {
|
||||
"scopeTitle": "Off-Site-Backup-Ziele",
|
||||
|
||||
@@ -1558,7 +1558,10 @@
|
||||
"subject": "Subject",
|
||||
"delivered": "Delivered",
|
||||
"status": "Status"
|
||||
}
|
||||
},
|
||||
"deleteAcknowledged": "Delete acknowledged",
|
||||
"confirmDeleteAcked": "Permanently delete {{n}} acknowledged alerts? Open alerts are kept.",
|
||||
"eventsDeleted": "{{n}} alerts deleted."
|
||||
},
|
||||
"remotes": {
|
||||
"scopeTitle": "Off-site backup targets",
|
||||
|
||||
@@ -120,9 +120,34 @@ export default function AlertsPage() {
|
||||
})
|
||||
const delEventsMut = useMutation({
|
||||
mutationFn: (ids: number[]) => apiClient.post('/alerts/events/delete', { ids }),
|
||||
onSuccess: () => { message.success(t('common.delete')); refreshEvents() },
|
||||
onSuccess: (_d, ids) => {
|
||||
// Anzahl mitsagen: die Kopf-Checkbox markiert nur die AKTUELLE Seite,
|
||||
// und bei einem groesseren Backlog ruecken sofort optisch identische
|
||||
// Eintraege nach. Ohne diese Rueckmeldung sieht es aus, als sei nichts
|
||||
// passiert (Befund 2026-09-11).
|
||||
message.success(t('alerts.eventsDeleted', { n: ids.length }))
|
||||
setSelectedIds([])
|
||||
refreshEvents()
|
||||
},
|
||||
onError: (e: Error) => message.error(e.message),
|
||||
})
|
||||
const delAckedMut = useMutation({
|
||||
mutationFn: () => apiClient.post('/alerts/events/delete-acknowledged'),
|
||||
onSuccess: (r) => {
|
||||
const n = (r?.data as { data?: { deleted?: number } })?.data?.deleted ?? 0
|
||||
message.success(t('alerts.eventsDeleted', { n }))
|
||||
setSelectedIds([])
|
||||
refreshEvents()
|
||||
},
|
||||
onError: (e: Error) => message.error(e.message),
|
||||
})
|
||||
|
||||
// Anzahl quittierter Events ueber den GESAMTEN Datensatz, nicht nur die
|
||||
// sichtbare Seite — der Button soll zeigen, was er wirklich raeumt.
|
||||
const ackedCount = useMemo(
|
||||
() => (events.data ?? []).filter(e => e.acknowledged_at).length,
|
||||
[events.data],
|
||||
)
|
||||
|
||||
const kindOptions = useMemo(() => {
|
||||
const kinds = [...new Set((events.data ?? []).map(e => e.kind))].sort()
|
||||
@@ -429,6 +454,18 @@ export default function AlertsPage() {
|
||||
{t('alerts.acknowledgeAll')}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{/* Gegenstueck zu "Alle quittieren": ohne das kommt man an
|
||||
einen groesseren Backlog nur seitenweise heran, weil die
|
||||
Kopf-Checkbox der Tabelle nur die aktuelle Seite markiert. */}
|
||||
<Popconfirm title={t('alerts.confirmDeleteAcked', { n: ackedCount })}
|
||||
onConfirm={() => delAckedMut.mutate()}
|
||||
disabled={isViewer || ackedCount === 0}>
|
||||
<Button size="small" danger ghost
|
||||
disabled={isViewer || ackedCount === 0}
|
||||
loading={delAckedMut.isPending}>
|
||||
{t('alerts.deleteAcknowledged')}{ackedCount > 0 ? ` (${ackedCount})` : ''}
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</Space>
|
||||
</div>
|
||||
<Table size="small" rowKey="id" loading={events.isFetching}
|
||||
|
||||
Reference in New Issue
Block a user