From ea50214a97cc3075b9593511bfaeed300772bde3 Mon Sep 17 00:00:00 2001 From: Ryan Carroll Date: Mon, 6 Apr 2026 14:09:15 -0500 Subject: [PATCH] Handle events overview when event definition is missing (#25548) * Handle case where event definition is missing * add cl entry (cherry picked from commit c53ffbaa35c210c7249490cd1c060f378187e6bb) --- changelog/unreleased/pr-25548.toml | 5 +++++ .../events/events/hooks/useEventDefinition.tsx | 7 +++---- .../events/EventsList/EventDetails.test.tsx | 3 ++- .../events/filters/EventDefinitionName.tsx | 18 +++++++----------- 4 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 changelog/unreleased/pr-25548.toml diff --git a/changelog/unreleased/pr-25548.toml b/changelog/unreleased/pr-25548.toml new file mode 100644 index 000000000000..88970122bc3e --- /dev/null +++ b/changelog/unreleased/pr-25548.toml @@ -0,0 +1,5 @@ +type = "fixed" +message = "Show event definition ID instead of throwing errors in the Events Overview widget when the event definition has been deleted" + +pulls = ["25548"] +issues = ["graylog-plugin-enterprise#13756"] diff --git a/graylog2-web-interface/src/components/events/events/hooks/useEventDefinition.tsx b/graylog2-web-interface/src/components/events/events/hooks/useEventDefinition.tsx index 798701f616d6..d3793c7edb94 100644 --- a/graylog2-web-interface/src/components/events/events/hooks/useEventDefinition.tsx +++ b/graylog2-web-interface/src/components/events/events/hooks/useEventDefinition.tsx @@ -19,21 +19,20 @@ import { useQuery } from '@tanstack/react-query'; import fetch from 'logic/rest/FetchProvider'; import { qualifyUrl } from 'util/URLUtils'; import type { EventDefinition } from 'components/event-definitions/event-definitions-types'; -import { defaultOnError } from 'util/conditional/onError'; export const fetchEventDefinitionDetails = async (eventDefinitionId: string): Promise => fetch('GET', qualifyUrl(`/events/definitions/${eventDefinitionId}`)); const useEventDefinition = (eventDefId: string, enabled = true) => { - const { data, isFetching, isInitialLoading } = useQuery({ + const { data, isFetching, isInitialLoading, isError } = useQuery({ queryKey: ['get-event-definition-details', eventDefId], - queryFn: () => defaultOnError(fetchEventDefinitionDetails(eventDefId), 'Loading archives failed with status'), + queryFn: () => fetchEventDefinitionDetails(eventDefId), retry: 0, keepPreviousData: true, enabled: !!eventDefId && enabled, }); - return { data, isFetching, isInitialLoading }; + return { data, isFetching, isInitialLoading, isError }; }; export default useEventDefinition; diff --git a/graylog2-web-interface/src/views/components/widgets/events/EventsList/EventDetails.test.tsx b/graylog2-web-interface/src/views/components/widgets/events/EventsList/EventDetails.test.tsx index 9fc07a5ef1a9..73229c80824d 100644 --- a/graylog2-web-interface/src/views/components/widgets/events/EventsList/EventDetails.test.tsx +++ b/graylog2-web-interface/src/views/components/widgets/events/EventsList/EventDetails.test.tsx @@ -55,7 +55,7 @@ describe('EventDetails', () => { ); asMock(useCurrentUser).mockReturnValue(adminUser); - asMock(useEventDefinition).mockReturnValue({ data: undefined, isFetching: false, isInitialLoading: false }); + asMock(useEventDefinition).mockReturnValue({ data: undefined, isFetching: false, isInitialLoading: false, isError: false }); asMock(useEventById).mockImplementation(() => ({ data: mockEventData.event, @@ -90,6 +90,7 @@ describe('EventDetails', () => { data: mockEventDefinitionTwoAggregations, isFetching: false, isInitialLoading: false, + isError: false, }); renderEventDetails(); diff --git a/graylog2-web-interface/src/views/components/widgets/events/filters/EventDefinitionName.tsx b/graylog2-web-interface/src/views/components/widgets/events/filters/EventDefinitionName.tsx index db5bb369e27f..2d31aa6184ed 100644 --- a/graylog2-web-interface/src/views/components/widgets/events/filters/EventDefinitionName.tsx +++ b/graylog2-web-interface/src/views/components/widgets/events/filters/EventDefinitionName.tsx @@ -31,26 +31,22 @@ type Props = { const EventDefinitionName = ({ eventDefinitionId, displayAsLink = true }: Props) => { const currentUser = useCurrentUser(); const canViewDefinition = isPermitted(currentUser.permissions, `eventdefinitions:read:${eventDefinitionId}`); - const { data: eventDefinition, isFetching } = useEventDefinition(eventDefinitionId, canViewDefinition); + const { data: eventDefinition, isFetching, isError } = useEventDefinition(eventDefinitionId, canViewDefinition); const title = eventDefinition?.title ?? eventDefinitionId; if (isFetching) { return ; } - if (!displayAsLink || !canViewDefinition) { + if (!displayAsLink || !canViewDefinition || !eventDefinition || isError) { return <>{title}; } - if (eventDefinition) { - return ( - - {title} - - ); - } - - return null; + return ( + + {title} + + ); }; export default EventDefinitionName;