From 3ba1888a3539bb27efb0bb95885c2c22350bc5e9 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 9 May 2025 12:20:49 -0400 Subject: [PATCH 1/9] Impelement design changes for rule create form details update. --- .../src/rule_details/rule_details.tsx | 112 ++++++++---------- .../rule_form/src/translations.ts | 11 -- 2 files changed, 50 insertions(+), 73 deletions(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx index acc5bf72d0e72..5f9ad1f4fbc4d 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx @@ -8,22 +8,15 @@ */ import React, { useCallback, useMemo } from 'react'; -import { css } from '@emotion/react'; import { - EuiDescribedFormGroup, EuiFormRow, EuiFieldText, EuiComboBox, EuiComboBoxOptionOption, - EuiText, + EuiFlexGroup, + EuiFlexItem, } from '@elastic/eui'; -import { - RULE_DETAILS_TITLE, - RULE_DETAILS_DESCRIPTION, - RULE_NAME_INPUT_TITLE, - RULE_TAG_INPUT_TITLE, - RULE_TAG_PLACEHOLDER, -} from '../translations'; +import { RULE_NAME_INPUT_TITLE, RULE_TAG_INPUT_TITLE, RULE_TAG_PLACEHOLDER } from '../translations'; import { useRuleFormState, useRuleFormDispatch } from '../hooks'; import { OptionalFieldLabel } from '../optional_field_label'; @@ -34,16 +27,16 @@ export const RuleDetails = () => { const { tags = [], name } = formData; - const ruleDetailsContainerCss = css` - @container (max-width: 767px) { - &.euiDescribedFormGroup { - flex-direction: column; - } - &.euiDescribedFormGroup > .euiFlexItem { - width: 100%; - } - } - `; + // const ruleDetailsContainerCss = css` + // @container (max-width: 767px) { + // &.euiDescribedFormGroup { + // flex-direction: column; + // } + // &.euiDescribedFormGroup > .euiFlexItem { + // width: 100%; + // } + // } + // `; const tagsOptions = useMemo(() => { return tags.map((tag: string) => ({ label: tag })); @@ -89,49 +82,44 @@ export const RuleDetails = () => { }, [dispatch, tags]); return ( - {RULE_DETAILS_TITLE}} - description={ - -

{RULE_DETAILS_DESCRIPTION}

-
- } - data-test-subj="ruleDetails" - > - - + + - - - + + + + + - -
+ label={RULE_TAG_INPUT_TITLE} + labelAppend={OptionalFieldLabel} + isInvalid={!!baseErrors?.tags?.length} + error={baseErrors?.tags} + > + + + + ); }; diff --git a/src/platform/packages/shared/response-ops/rule_form/src/translations.ts b/src/platform/packages/shared/response-ops/rule_form/src/translations.ts index b3ce7e655e9b9..a204ff175d808 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/translations.ts +++ b/src/platform/packages/shared/response-ops/rule_form/src/translations.ts @@ -255,17 +255,6 @@ export const ADD_ACTION_DESCRIPTION_TEXT = i18n.translate( } ); -export const RULE_DETAILS_TITLE = i18n.translate('responseOpsRuleForm.ruleForm.ruleDetails.title', { - defaultMessage: 'Rule name and tags', -}); - -export const RULE_DETAILS_DESCRIPTION = i18n.translate( - 'responseOpsRuleForm.ruleForm.ruleDetails.description', - { - defaultMessage: 'Define a name and tags for your rule.', - } -); - export const RULE_NAME_INPUT_TITLE = i18n.translate( 'responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputTitle', { From 07f071bf931670a275a539b0d2573c7b8f078243 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 9 May 2025 13:15:25 -0400 Subject: [PATCH 2/9] Make row/column direction responsive. --- .../src/rule_details/rule_details.tsx | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx index 5f9ad1f4fbc4d..6743650ff2c66 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useCallback, useMemo } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { EuiFormRow, EuiFieldText, @@ -20,6 +20,8 @@ import { RULE_NAME_INPUT_TITLE, RULE_TAG_INPUT_TITLE, RULE_TAG_PLACEHOLDER } fro import { useRuleFormState, useRuleFormDispatch } from '../hooks'; import { OptionalFieldLabel } from '../optional_field_label'; +export const RULE_DETAIL_MIN_ROW_WIDTH = 600; + export const RuleDetails = () => { const { formData, baseErrors } = useRuleFormState(); @@ -81,8 +83,13 @@ export const RuleDetails = () => { } }, [dispatch, tags]); + const { + ref, + size: { width }, + } = useContainerRef(); + return ( - + RULE_DETAIL_MIN_ROW_WIDTH ? 'row' : 'column'}> { ); }; + +function useContainerRef() { + const ref = useRef(null); + const [size, setSize] = useState({ width: 0, height: 0 }); + + useEffect(() => { + if (!ref.current) return; + + const observer = new ResizeObserver(([entry]) => { + const { width, height } = entry.contentRect; + setSize({ width, height }); + }); + + observer.observe(ref.current); + + return () => observer.disconnect(); + }, []); + + return { ref, size }; +} From 5b589f7f3650c87943a2883e80603361856a8239 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 9 May 2025 14:32:29 -0400 Subject: [PATCH 3/9] i18n fixup. --- .../plugins/private/translations/translations/fr-FR.json | 2 -- .../plugins/private/translations/translations/ja-JP.json | 2 -- .../plugins/private/translations/translations/zh-CN.json | 2 -- 3 files changed, 6 deletions(-) diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 1921e7a0ec437..fda9f88464682 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -6660,12 +6660,10 @@ "responseOpsRuleForm.ruleForm.ruleDefinition.scopeTitle": "Portée de la règle", "responseOpsRuleForm.ruleForm.ruleDefinitionTitle": "Définition de la règle", "responseOpsRuleForm.ruleForm.ruleDefinitionTitleShort": "Définition", - "responseOpsRuleForm.ruleForm.ruleDetails.description": "Définissez un nom et des balises pour votre règle.", "responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputButtonAriaLabel": "Enregistrer le nom de la règle", "responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputTitle": "Nom de règle", "responseOpsRuleForm.ruleForm.ruleDetails.ruleTagsInputTitle": "Balises", "responseOpsRuleForm.ruleForm.ruleDetails.ruleTagsPlaceholder": "Ajouter des balises", - "responseOpsRuleForm.ruleForm.ruleDetails.title": "Nom et balises de la règle", "responseOpsRuleForm.ruleForm.ruleDetailsTitle": "Détails de la règle", "responseOpsRuleForm.ruleForm.ruleDetailsTitleShort": "Détails", "responseOpsRuleForm.ruleForm.ruleFlyoutFooter.backText": "Retour", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index c8669c6919b1c..630d11b22eccc 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -6654,12 +6654,10 @@ "responseOpsRuleForm.ruleForm.ruleDefinition.scopeTitle": "ルール範囲", "responseOpsRuleForm.ruleForm.ruleDefinitionTitle": "ルール検知", "responseOpsRuleForm.ruleForm.ruleDefinitionTitleShort": "定義", - "responseOpsRuleForm.ruleForm.ruleDetails.description": "ルールの名前とタグを定義します。", "responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputButtonAriaLabel": "ルール名を保存", "responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputTitle": "ルール名", "responseOpsRuleForm.ruleForm.ruleDetails.ruleTagsInputTitle": "タグ", "responseOpsRuleForm.ruleForm.ruleDetails.ruleTagsPlaceholder": "タグを追加", - "responseOpsRuleForm.ruleForm.ruleDetails.title": "ルールの名前とタグ", "responseOpsRuleForm.ruleForm.ruleDetailsTitle": "ルール詳細", "responseOpsRuleForm.ruleForm.ruleDetailsTitleShort": "詳細", "responseOpsRuleForm.ruleForm.ruleFlyoutFooter.backText": "戻る", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index 355c180b80d24..e13f4ea7006be 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -6664,12 +6664,10 @@ "responseOpsRuleForm.ruleForm.ruleDefinition.scopeTitle": "规则范围", "responseOpsRuleForm.ruleForm.ruleDefinitionTitle": "规则定义", "responseOpsRuleForm.ruleForm.ruleDefinitionTitleShort": "定义", - "responseOpsRuleForm.ruleForm.ruleDetails.description": "为您的规则定义名称和标签。", "responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputButtonAriaLabel": "保存规则名称", "responseOpsRuleForm.ruleForm.ruleDetails.ruleNameInputTitle": "规则名称", "responseOpsRuleForm.ruleForm.ruleDetails.ruleTagsInputTitle": "标签", "responseOpsRuleForm.ruleForm.ruleDetails.ruleTagsPlaceholder": "添加标签", - "responseOpsRuleForm.ruleForm.ruleDetails.title": "规则名称和标签", "responseOpsRuleForm.ruleForm.ruleDetailsTitle": "规则详情", "responseOpsRuleForm.ruleForm.ruleDetailsTitleShort": "详情", "responseOpsRuleForm.ruleForm.ruleFlyoutFooter.backText": "返回", From abdfaf28de6499c4f44b66f2c5d857ebad9bbcba Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Fri, 9 May 2025 14:32:34 -0400 Subject: [PATCH 4/9] Simplify. --- .../response-ops/rule_form/src/rule_details/rule_details.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx index 6743650ff2c66..c159ba6e81ded 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx @@ -145,7 +145,7 @@ function useContainerRef() { observer.observe(ref.current); - return () => observer.disconnect(); + return observer.disconnect; }, []); return { ref, size }; From 00dca54b4b6a228fcbe6b8f6f6e00e7e708b2260 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 19 May 2025 11:51:36 -0400 Subject: [PATCH 5/9] Remove obsolete code. --- .../rule_form/src/rule_details/rule_details.tsx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx index c159ba6e81ded..9f6c33bad87e8 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx @@ -29,17 +29,6 @@ export const RuleDetails = () => { const { tags = [], name } = formData; - // const ruleDetailsContainerCss = css` - // @container (max-width: 767px) { - // &.euiDescribedFormGroup { - // flex-direction: column; - // } - // &.euiDescribedFormGroup > .euiFlexItem { - // width: 100%; - // } - // } - // `; - const tagsOptions = useMemo(() => { return tags.map((tag: string) => ({ label: tag })); }, [tags]); From 3dc4013d0dcfe68a108ed58ba9b49189cb3fb0f2 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 19 May 2025 12:24:38 -0400 Subject: [PATCH 6/9] Fix unit tests file. --- .../src/rule_details/rule_details.test.tsx | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx index 78d35d066059c..6f03844fef29e 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx @@ -8,7 +8,7 @@ */ import React from 'react'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { fireEvent, render, screen, configure } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { RuleDetails } from './rule_details'; @@ -21,7 +21,20 @@ jest.mock('../hooks', () => ({ const { useRuleFormState, useRuleFormDispatch } = jest.requireMock('../hooks'); +configure({ testIdAttribute: 'data-test-subj' }); + describe('RuleDetails', () => { + beforeAll(() => { + class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} + } + + // Only override it for this test file + globalThis.ResizeObserver = ResizeObserver; + }); + beforeEach(() => { useRuleFormState.mockReturnValue({ formData: { @@ -36,6 +49,12 @@ describe('RuleDetails', () => { jest.resetAllMocks(); }); + afterAll(() => { + if ('ResizeObserver' in globalThis) { + delete (globalThis as any).ResizeObserver; + } + }); + test('Renders correctly', () => { render(); From be94853ddad2e9f831960647bd211f511aa911af Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 19 May 2025 12:33:03 -0400 Subject: [PATCH 7/9] Delete unneeded code. --- .../rule_form/src/rule_details/rule_details.test.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx index 6f03844fef29e..7af16ffc46310 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx @@ -8,7 +8,7 @@ */ import React from 'react'; -import { fireEvent, render, screen, configure } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { RuleDetails } from './rule_details'; @@ -21,8 +21,6 @@ jest.mock('../hooks', () => ({ const { useRuleFormState, useRuleFormDispatch } = jest.requireMock('../hooks'); -configure({ testIdAttribute: 'data-test-subj' }); - describe('RuleDetails', () => { beforeAll(() => { class ResizeObserver { @@ -31,7 +29,8 @@ describe('RuleDetails', () => { disconnect() {} } - // Only override it for this test file + // this only sets the mock polyfill for this test file's env + // we delete it in `afterAll` as well globalThis.ResizeObserver = ResizeObserver; }); From 2a4570adfbf6efa12a575ddc0049c87c16aee610 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Mon, 19 May 2025 13:22:30 -0400 Subject: [PATCH 8/9] Simplify. --- .../src/rule_details/rule_details.test.tsx | 18 ----------- .../src/rule_details/rule_details.tsx | 31 ++----------------- 2 files changed, 2 insertions(+), 47 deletions(-) diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx index 7af16ffc46310..78d35d066059c 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.test.tsx @@ -22,18 +22,6 @@ jest.mock('../hooks', () => ({ const { useRuleFormState, useRuleFormDispatch } = jest.requireMock('../hooks'); describe('RuleDetails', () => { - beforeAll(() => { - class ResizeObserver { - observe() {} - unobserve() {} - disconnect() {} - } - - // this only sets the mock polyfill for this test file's env - // we delete it in `afterAll` as well - globalThis.ResizeObserver = ResizeObserver; - }); - beforeEach(() => { useRuleFormState.mockReturnValue({ formData: { @@ -48,12 +36,6 @@ describe('RuleDetails', () => { jest.resetAllMocks(); }); - afterAll(() => { - if ('ResizeObserver' in globalThis) { - delete (globalThis as any).ResizeObserver; - } - }); - test('Renders correctly', () => { render(); diff --git a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx index 9f6c33bad87e8..dcfa1c75a331f 100644 --- a/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx +++ b/src/platform/packages/shared/response-ops/rule_form/src/rule_details/rule_details.tsx @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { EuiFormRow, EuiFieldText, @@ -20,8 +20,6 @@ import { RULE_NAME_INPUT_TITLE, RULE_TAG_INPUT_TITLE, RULE_TAG_PLACEHOLDER } fro import { useRuleFormState, useRuleFormDispatch } from '../hooks'; import { OptionalFieldLabel } from '../optional_field_label'; -export const RULE_DETAIL_MIN_ROW_WIDTH = 600; - export const RuleDetails = () => { const { formData, baseErrors } = useRuleFormState(); @@ -72,13 +70,8 @@ export const RuleDetails = () => { } }, [dispatch, tags]); - const { - ref, - size: { width }, - } = useContainerRef(); - return ( - RULE_DETAIL_MIN_ROW_WIDTH ? 'row' : 'column'}> + { ); }; - -function useContainerRef() { - const ref = useRef(null); - const [size, setSize] = useState({ width: 0, height: 0 }); - - useEffect(() => { - if (!ref.current) return; - - const observer = new ResizeObserver(([entry]) => { - const { width, height } = entry.contentRect; - setSize({ width, height }); - }); - - observer.observe(ref.current); - - return observer.disconnect; - }, []); - - return { ref, size }; -} From 468195156003702ed5c65cf489218d0a61b4b912 Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 20 May 2025 14:11:03 -0400 Subject: [PATCH 9/9] Fix weird FTR failure. --- .../alert_create_flyout.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts index c4a780957e605..e9e35657e242e 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alert_create_flyout.ts @@ -236,7 +236,24 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // add webhook connector 2 await testSubjects.click('ruleActionsAddActionButton'); await testSubjects.existOrFail('ruleActionsConnectorsModal'); - await find.clickByButtonText(webhookConnectorName); + + /* + * there is a naming overload between the card button text on the modal, and the button text on the + * action accordion rendered behind the modal. We select the cards and filter for the one we want, + * and then pick up the button by role. + */ + const modalCards = await find.allByCssSelector( + '[data-test-subj="ruleActionsConnectorsModalCard"]' + ); + const webhookCard = modalCards.find(async (card) => { + return (await card.getAttribute('innerText'))?.indexOf(webhookConnectorName) !== -1; + }); + if (!webhookCard) { + throw new Error('Webhook connector card not found'); + } + const cardButton = await webhookCard.findByCssSelector('button'); + await cardButton.click(); + await find.setValueByClass('kibanaCodeEditor', 'myUniqueKey1'); await find.clickByCssSelector(