From 164ef253938b31178da5a409c3f7efabdd37a871 Mon Sep 17 00:00:00 2001 From: kitos Date: Fri, 3 Jul 2026 17:25:15 +0200 Subject: [PATCH] fix(campaigns): complete ACTION_LABELS map and timeline cache invalidation Adds the 4 backend-logged campaign actions missing from ACTION_LABELS (delete_campaign, generate_campaign, schedule_campaign, recurring_campaign_run), and wires campaign-timeline invalidation into the remaining audit-logging mutations on the page (complete, schedule, approve/reject modification request) so the timeline panel updates live instead of only on next reload, consistent with submit/approve/ reject campaign. --- frontend/src/components/CampaignAuditTimeline.tsx | 4 ++++ frontend/src/pages/CampaignDetailPage.tsx | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/frontend/src/components/CampaignAuditTimeline.tsx b/frontend/src/components/CampaignAuditTimeline.tsx index 3faf17e..aa6a74f 100644 --- a/frontend/src/components/CampaignAuditTimeline.tsx +++ b/frontend/src/components/CampaignAuditTimeline.tsx @@ -17,6 +17,10 @@ const ACTION_LABELS: Record = { request_campaign_modification: "Modification requested", approve_campaign_modification: "Modification approved", reject_campaign_modification: "Modification rejected", + delete_campaign: "Campaign deleted", + generate_campaign: "Generated from threat actor", + schedule_campaign: "Schedule updated", + recurring_campaign_run: "Recurring run executed", }; export default function CampaignAuditTimeline({ entries, isLoading }: Props) { diff --git a/frontend/src/pages/CampaignDetailPage.tsx b/frontend/src/pages/CampaignDetailPage.tsx index 269f70b..5655507 100644 --- a/frontend/src/pages/CampaignDetailPage.tsx +++ b/frontend/src/pages/CampaignDetailPage.tsx @@ -140,6 +140,7 @@ export default function CampaignDetailPage() { mutationFn: () => completeCampaign(campaignId!), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["campaign", campaignId] }); + queryClient.invalidateQueries({ queryKey: ["campaign-timeline", campaignId] }); showToast("Campaign completed", "success"); }, onError: (err: Error) => showToast(err.message, "error"), @@ -159,6 +160,7 @@ export default function CampaignDetailPage() { scheduleCampaign(campaignId!, payload), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["campaign", campaignId] }); + queryClient.invalidateQueries({ queryKey: ["campaign-timeline", campaignId] }); showToast("Schedule updated", "success"); }, onError: (err: Error) => showToast(err.message, "error"), @@ -199,6 +201,7 @@ export default function CampaignDetailPage() { onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["campaign", campaignId] }); queryClient.invalidateQueries({ queryKey: ["campaign-modification-requests", campaignId] }); + queryClient.invalidateQueries({ queryKey: ["campaign-timeline", campaignId] }); showToast("Modification approved and applied", "success"); }, onError: (err: Error) => showToast(err.message, "error"), @@ -209,6 +212,7 @@ export default function CampaignDetailPage() { rejectModificationRequest(requestId, notes), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["campaign-modification-requests", campaignId] }); + queryClient.invalidateQueries({ queryKey: ["campaign-timeline", campaignId] }); showToast("Modification rejected", "success"); }, onError: (err: Error) => showToast(err.message, "error"),