From cbba4d4d9fa2712bb65a8d170e27b943a1241ef6 Mon Sep 17 00:00:00 2001 From: Ryan Carroll Date: Fri, 21 Aug 2026 09:12:07 -0500 Subject: [PATCH] Event Definitions - Retain selected sharing info across navigation (#26990) * Reain selected sharing info across navigation * update cl * cleanup * fix linter issues * address PR feedback (cherry picked from commit 074aba3c85fd067abf295a61e668d6afad9410ab) --- changelog/unreleased/issue-14480.toml | 5 +++ .../event-definition-form/ShareForm.tsx | 1 + .../event-definitions-types.ts | 2 ++ .../EntityCreateShareFormGroup.test.tsx | 35 ++++++++++++++++++- .../EntityCreateShareFormGroup.tsx | 13 ++++--- 5 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 changelog/unreleased/issue-14480.toml diff --git a/changelog/unreleased/issue-14480.toml b/changelog/unreleased/issue-14480.toml new file mode 100644 index 000000000000..d675f701450d --- /dev/null +++ b/changelog/unreleased/issue-14480.toml @@ -0,0 +1,5 @@ +type = "fixed" +message = "Keep the share settings of an event definition populated when navigating between wizard steps." + +issues = ["Graylog2/graylog-plugin-enterprise#14480"] +pulls = ["26990"] diff --git a/graylog2-web-interface/src/components/event-definitions/event-definition-form/ShareForm.tsx b/graylog2-web-interface/src/components/event-definitions/event-definition-form/ShareForm.tsx index ba9d5a4bfb64..11cacf9d7eb5 100644 --- a/graylog2-web-interface/src/components/event-definitions/event-definition-form/ShareForm.tsx +++ b/graylog2-web-interface/src/components/event-definitions/event-definition-form/ShareForm.tsx @@ -49,6 +49,7 @@ const ShareForm = ({ onChange, eventDefinition }: Props) => { entityType="event_definition" entityTitle="" dependenciesGRN={[...streamDependenciesGRN, ...notificationDependenciesGRN]} + defaultSharePayload={eventDefinition.share_request} /> diff --git a/graylog2-web-interface/src/components/event-definitions/event-definitions-types.ts b/graylog2-web-interface/src/components/event-definitions/event-definitions-types.ts index 84bb24ee6d2b..9848cbf363ca 100644 --- a/graylog2-web-interface/src/components/event-definitions/event-definitions-types.ts +++ b/graylog2-web-interface/src/components/event-definitions/event-definitions-types.ts @@ -17,6 +17,7 @@ import type { SyntheticEvent } from 'react'; import type { StepsType } from 'components/common/Wizard'; +import type { EntitySharePayload } from 'actions/permissions/EntityShareActions'; import type { LookupTableParameterJson } from 'views/logic/parameters/LookupTableParameter'; import { SYSTEM_EVENT_DEFINITION_TYPE } from 'components/event-definitions/constants'; @@ -111,6 +112,7 @@ export type EventDefinition = { matched_at: string; scheduler: Scheduler; event_summary_template: string; + share_request?: EntitySharePayload; }; export type EventDefinitionFormControlsProps = { diff --git a/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.test.tsx b/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.test.tsx index d25a177f6019..921c4c966dd7 100644 --- a/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.test.tsx +++ b/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.test.tsx @@ -76,7 +76,40 @@ describe('EntityCreateShareFormGroup', () => { render(); await waitFor(() => { - expect(EntityShareActions.prepare).toHaveBeenCalledWith(mockEntity.entityType, '', mockEntity.entityId, {}); + expect(EntityShareActions.prepare).toHaveBeenCalledWith(mockEntity.entityType, '', mockEntity.entityId, { + prepare_request: null, + }); + }); + }); + + it('restores a previously made selection from the default share payload', async () => { + const selected_grantee_capabilities = createEntityShareState.selectedGranteeCapabilities.merge({ + [everyone.id]: viewer.id, + }); + + render(); + + await waitFor(() => { + expect(EntityShareActions.prepare).toHaveBeenCalledWith(mockEntity.entityType, '', mockEntity.entityId, { + selected_grantee_capabilities, + prepare_request: null, + }); + }); + }); + + it('re-runs the dependency check when restoring a selection', async () => { + const selected_grantee_capabilities = createEntityShareState.selectedGranteeCapabilities.merge({ + [everyone.id]: viewer.id, + }); + const dependenciesGRN = ['grn::::stream:stream-id']; + + render(); + + await waitFor(() => { + expect(EntityShareActions.prepare).toHaveBeenCalledWith(mockEntity.entityType, '', mockEntity.entityId, { + selected_grantee_capabilities, + prepare_request: dependenciesGRN, + }); }); }); diff --git a/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.tsx b/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.tsx index 11d3151b5dbb..69e1102125de 100644 --- a/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.tsx +++ b/graylog2-web-interface/src/components/permissions/EntityCreateShareFormGroup.tsx @@ -16,7 +16,6 @@ */ import * as React from 'react'; import { useEffect, useState } from 'react'; -import isEmpty from 'lodash/isEmpty'; import type SharedEntity from 'logic/permissions/SharedEntity'; import { useStore } from 'stores/connect'; @@ -88,9 +87,13 @@ const EntityCreateShareFormGroup = ({ useEffect(() => { const { selected_collections: _, ...rest } = defaultSharePayload ?? {}; + // Restoring a selection has to re-run the dependency check, or the missing dependency + // warnings shown before would silently disappear. + const hasSelection = (rest.selected_grantee_capabilities?.size ?? 0) > 0; + const prepare_request = hasSelection && dependenciesGRN?.length ? dependenciesGRN : null; - EntityShareDomain.prepare(entityType, entityTitle, entityGRN, rest); - }, [entityType, entityTitle, entityGRN, defaultSharePayload]); + EntityShareDomain.prepare(entityType, entityTitle, entityGRN, { ...rest, prepare_request }); + }, [entityType, entityTitle, entityGRN, defaultSharePayload, dependenciesGRN]); const resetSelection = () => { setDisableSubmit(false); @@ -122,7 +125,7 @@ const EntityCreateShareFormGroup = ({ setDisableSubmit(true); - const prepare_request = isEmpty(newSelectedCapabilities) ? null : dependenciesGRN; + const prepare_request = (newSelectedCapabilities?.size ?? 0) > 0 ? dependenciesGRN : null; const payload: EntitySharePayload = { selected_grantee_capabilities: newSelectedCapabilities, prepare_request, @@ -198,6 +201,8 @@ const EntityCreateShareFormGroup = ({ availableGrantees={entityShareState.availableGrantees} /> {PluggableEntityShareFormGroup && ( + /* Resolved from the plugin store at render time and cannot be hoisted. */ + /* eslint-disable-next-line react-hooks/static-components */