diff --git a/x-pack/plugins/security_solution/public/common/components/wrapper_page/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/wrapper_page/__snapshots__/index.test.tsx.snap
index 5ade447994a1e..89ed2f45a6bf1 100644
--- a/x-pack/plugins/security_solution/public/common/components/wrapper_page/__snapshots__/index.test.tsx.snap
+++ b/x-pack/plugins/security_solution/public/common/components/wrapper_page/__snapshots__/index.test.tsx.snap
@@ -7,33 +7,3 @@ exports[`WrapperPage it renders 1`] = `
`;
-
-exports[`WrapperPage restrict width custom max width when restrictWidth is number 1`] = `
-
-
- Test page
-
-
-`;
-
-exports[`WrapperPage restrict width custom max width when restrictWidth is string 1`] = `
-
-
- Test page
-
-
-`;
-
-exports[`WrapperPage restrict width default max width when restrictWidth is true 1`] = `
-
-
- Test page
-
-
-`;
diff --git a/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.test.tsx
index 23cae15004e39..e87faf1b5c82c 100644
--- a/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.test.tsx
@@ -22,42 +22,4 @@ describe('WrapperPage', () => {
expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot();
});
-
- describe('restrict width', () => {
- test('default max width when restrictWidth is true', () => {
- const wrapper = shallow(
-
-
- {'Test page'}
-
-
- );
-
- expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot();
- });
-
- test('custom max width when restrictWidth is number', () => {
- const wrapper = shallow(
-
-
- {'Test page'}
-
-
- );
-
- expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot();
- });
-
- test('custom max width when restrictWidth is string', () => {
- const wrapper = shallow(
-
-
- {'Test page'}
-
-
- );
-
- expect(wrapper.find('Memo(WrapperPageComponent)')).toMatchSnapshot();
- });
- });
});
diff --git a/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx b/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx
index 0908c887d25f6..8eff52dae89f3 100644
--- a/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/wrapper_page/index.tsx
@@ -16,16 +16,6 @@ import { AppGlobalStyle } from '../page/index';
const Wrapper = styled.div`
padding: ${(props) => `${props.theme.eui.paddingSizes.l}`};
- &.siemWrapperPage--restrictWidthDefault,
- &.siemWrapperPage--restrictWidthCustom {
- box-sizing: content-box;
- margin: 0 auto;
- }
-
- &.siemWrapperPage--restrictWidthDefault {
- max-width: 1000px;
- }
-
&.siemWrapperPage--fullHeight {
height: 100%;
display: flex;
@@ -58,7 +48,6 @@ interface WrapperPageProps {
const WrapperPageComponent: React.FC = ({
children,
className,
- restrictWidth,
style,
noPadding,
noTimeline,
@@ -74,20 +63,10 @@ const WrapperPageComponent: React.FC = ({
'siemWrapperPage--noPadding': noPadding,
'siemWrapperPage--withTimeline': !noTimeline,
'siemWrapperPage--fullHeight': globalFullScreen,
- 'siemWrapperPage--restrictWidthDefault':
- restrictWidth && typeof restrictWidth === 'boolean' && restrictWidth === true,
- 'siemWrapperPage--restrictWidthCustom': restrictWidth && typeof restrictWidth !== 'boolean',
});
- let customStyle: WrapperPageProps['style'];
-
- if (restrictWidth && typeof restrictWidth !== 'boolean') {
- const value = typeof restrictWidth === 'number' ? `${restrictWidth}px` : restrictWidth;
- customStyle = { ...style, maxWidth: value };
- }
-
return (
-
+
{children}
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx
index 87401408c3cc1..b2c22af3a75f9 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.test.tsx
@@ -5,21 +5,235 @@
*/
import React from 'react';
-import { shallow } from 'enzyme';
+import { mount, shallow } from 'enzyme';
import { SelectRuleType } from './index';
-import { useFormFieldMock } from '../../../../common/mock';
+import { TestProviders, useFormFieldMock } from '../../../../common/mock';
jest.mock('../../../../common/lib/kibana');
describe('SelectRuleType', () => {
+ // I do this to avoid the messy warning from happening
+ // Warning: React does not recognize the `isVisible` prop on a DOM element.
+ beforeEach(() => {
+ jest.spyOn(console, 'error').mockImplementation(jest.fn());
+ });
+
+ afterEach(() => {
+ jest.spyOn(console, 'error').mockRestore();
+ });
+
it('renders correctly', () => {
const Component = () => {
const field = useFormFieldMock();
- return ;
+ return (
+
+ );
};
const wrapper = shallow();
expect(wrapper.dive().find('[data-test-subj="selectRuleType"]')).toHaveLength(1);
});
+
+ describe('update mode vs. non-update mode', () => {
+ it('renders all the cards when not in update mode', () => {
+ const field = useFormFieldMock({ value: 'query' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeTruthy();
+ });
+
+ it('renders only the card selected when in update mode of "eql"', () => {
+ const field = useFormFieldMock({ value: 'eql' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeFalsy();
+ });
+
+ it('renders only the card selected when in update mode of "machine_learning', () => {
+ const field = useFormFieldMock({ value: 'machine_learning' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeFalsy();
+ });
+
+ it('renders only the card selected when in update mode of "query', () => {
+ const field = useFormFieldMock({ value: 'query' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeFalsy();
+ });
+
+ it('renders only the card selected when in update mode of "threshold"', () => {
+ const field = useFormFieldMock({ value: 'threshold' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeTruthy();
+ expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeFalsy();
+ });
+
+ it('renders only the card selected when in update mode of "threat_match', () => {
+ const field = useFormFieldMock({ value: 'threat_match' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeFalsy();
+ expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeTruthy();
+ });
+ });
+
+ describe('permissions', () => {
+ it('renders machine learning as disabled if "hasValidLicense" is false and it is not selected', () => {
+ const field = useFormFieldMock({ value: 'query' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(
+ wrapper.find('[data-test-subj="machineLearningRuleType"]').first().prop('isDisabled')
+ ).toEqual(true);
+ });
+
+ it('renders machine learning as not disabled if "hasValidLicense" is false and it is selected', () => {
+ const field = useFormFieldMock({ value: 'machine_learning' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(
+ wrapper.find('[data-test-subj="machineLearningRuleType"]').first().prop('isDisabled')
+ ).toEqual(false);
+ });
+
+ it('renders machine learning as disabled if "isMlAdmin" is false and it is not selected', () => {
+ const field = useFormFieldMock({ value: 'query' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(
+ wrapper.find('[data-test-subj="machineLearningRuleType"]').first().prop('isDisabled')
+ ).toEqual(true);
+ });
+
+ it('renders machine learning as not disabled if "isMlAdmin" is false and it is selected', () => {
+ const field = useFormFieldMock({ value: 'machine_learning' });
+ const wrapper = mount(
+
+
+
+ );
+ expect(
+ wrapper.find('[data-test-subj="machineLearningRuleType"]').first().prop('isDisabled')
+ ).toEqual(false);
+ });
+ });
});
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx
index 4b96b8a0ad7bd..c365982db9cd8 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/select_rule_type/index.tsx
@@ -22,19 +22,19 @@ import { MlCardDescription } from './ml_card_description';
import EqlSearchIcon from './eql_search_icon.svg';
interface SelectRuleTypeProps {
- describedByIds?: string[];
+ describedByIds: string[];
field: FieldHook;
- hasValidLicense?: boolean;
- isMlAdmin?: boolean;
- isReadOnly?: boolean;
+ hasValidLicense: boolean;
+ isMlAdmin: boolean;
+ isUpdateView: boolean;
}
export const SelectRuleType: React.FC = ({
describedByIds = [],
field,
- isReadOnly = false,
- hasValidLicense = false,
- isMlAdmin = false,
+ isUpdateView,
+ hasValidLicense,
+ isMlAdmin,
}) => {
const ruleType = field.value as Type;
const setType = useCallback(
@@ -48,54 +48,54 @@ export const SelectRuleType: React.FC = ({
const setQuery = useCallback(() => setType('query'), [setType]);
const setThreshold = useCallback(() => setType('threshold'), [setType]);
const setThreatMatch = useCallback(() => setType('threat_match'), [setType]);
- const mlCardDisabled = isReadOnly || !hasValidLicense || !isMlAdmin;
const licensingUrl = useKibana().services.application.getUrlForApp('kibana', {
path: '#/management/stack/license_management',
});
const eqlSelectableConfig = useMemo(
() => ({
- isDisabled: isReadOnly,
onClick: setEql,
isSelected: isEqlRule(ruleType),
+ isVisible: !isUpdateView || isEqlRule(ruleType),
}),
- [isReadOnly, ruleType, setEql]
+ [ruleType, setEql, isUpdateView]
);
const querySelectableConfig = useMemo(
() => ({
- isDisabled: isReadOnly,
onClick: setQuery,
isSelected: isQueryRule(ruleType),
+ isVisible: !isUpdateView || isQueryRule(ruleType),
}),
- [isReadOnly, ruleType, setQuery]
+ [ruleType, setQuery, isUpdateView]
);
const mlSelectableConfig = useMemo(
() => ({
- isDisabled: mlCardDisabled,
+ isDisabled: !hasValidLicense || !isMlAdmin,
onClick: setMl,
isSelected: isMlRule(ruleType),
+ isVisible: !isUpdateView || isMlRule(ruleType),
}),
- [mlCardDisabled, ruleType, setMl]
+ [ruleType, setMl, isUpdateView, hasValidLicense, isMlAdmin]
);
const thresholdSelectableConfig = useMemo(
() => ({
- isDisabled: isReadOnly,
onClick: setThreshold,
isSelected: isThresholdRule(ruleType),
+ isVisible: !isUpdateView || isThresholdRule(ruleType),
}),
- [isReadOnly, ruleType, setThreshold]
+ [ruleType, setThreshold, isUpdateView]
);
const threatMatchSelectableConfig = useMemo(
() => ({
- isDisabled: isReadOnly,
onClick: setThreatMatch,
isSelected: isThreatMatchRule(ruleType),
+ isVisible: !isUpdateView || isThreatMatchRule(ruleType),
}),
- [isReadOnly, ruleType, setThreatMatch]
+ [ruleType, setThreatMatch, isUpdateView]
);
return (
@@ -105,63 +105,83 @@ export const SelectRuleType: React.FC = ({
describedByIds={describedByIds}
label={field.label}
>
-
-
- }
- isDisabled={querySelectableConfig.isDisabled && !querySelectableConfig.isSelected}
- selectable={querySelectableConfig}
- />
-
-
-
- }
- icon={}
- isDisabled={mlSelectableConfig.isDisabled && !mlSelectableConfig.isSelected}
- selectable={mlSelectableConfig}
- />
-
-
- }
- isDisabled={
- thresholdSelectableConfig.isDisabled && !thresholdSelectableConfig.isSelected
- }
- selectable={thresholdSelectableConfig}
- />
-
-
- }
- isDisabled={eqlSelectableConfig.isDisabled && !eqlSelectableConfig.isSelected}
- selectable={eqlSelectableConfig}
- />
-
-
- }
- isDisabled={
- threatMatchSelectableConfig.isDisabled && !threatMatchSelectableConfig.isSelected
- }
- selectable={threatMatchSelectableConfig}
- />
-
+
+ {querySelectableConfig.isVisible && (
+
+ }
+ selectable={querySelectableConfig}
+ layout="horizontal"
+ textAlign="left"
+ />
+
+ )}
+ {mlSelectableConfig.isVisible && (
+
+
+ }
+ icon={}
+ isDisabled={mlSelectableConfig.isDisabled && !mlSelectableConfig.isSelected}
+ selectable={mlSelectableConfig}
+ layout="horizontal"
+ textAlign="left"
+ />
+
+ )}
+ {thresholdSelectableConfig.isVisible && (
+
+ }
+ selectable={thresholdSelectableConfig}
+ layout="horizontal"
+ textAlign="left"
+ />
+
+ )}
+ {eqlSelectableConfig.isVisible && (
+
+ }
+ selectable={eqlSelectableConfig}
+ layout="horizontal"
+ textAlign="left"
+ />
+
+ )}
+ {threatMatchSelectableConfig.isVisible && (
+
+ }
+ selectable={threatMatchSelectableConfig}
+ layout="horizontal"
+ textAlign="left"
+ />
+
+ )}
);
diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx
index 9bd0e4fb4da5d..d13635bfd1b50 100644
--- a/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/rules/step_define_rule/index.tsx
@@ -236,7 +236,7 @@ const StepDefineRuleComponent: FC = ({
component={SelectRuleType}
componentProps={{
describedByIds: ['detectionEngineStepDefineRuleType'],
- isReadOnly: isUpdateView,
+ isUpdateView,
hasValidLicense: hasMlLicense(mlCapabilities),
isMlAdmin: hasMlAdminPermissions(mlCapabilities),
}}
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/index.tsx
index 542b7b1b84c3c..9d54879ee7495 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/create/index.tsx
@@ -4,7 +4,14 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { EuiButtonEmpty, EuiAccordion, EuiHorizontalRule, EuiPanel, EuiSpacer } from '@elastic/eui';
+import {
+ EuiButtonEmpty,
+ EuiAccordion,
+ EuiHorizontalRule,
+ EuiPanel,
+ EuiSpacer,
+ EuiFlexGroup,
+} from '@elastic/eui';
import React, { useCallback, useRef, useState, useMemo } from 'react';
import { useHistory } from 'react-router-dom';
import styled, { StyledComponent } from 'styled-components';
@@ -28,7 +35,12 @@ import { StepScheduleRule } from '../../../../components/rules/step_schedule_rul
import { StepRuleActions } from '../../../../components/rules/step_rule_actions';
import { DetectionEngineHeaderPage } from '../../../../components/detection_engine_header_page';
import * as RuleI18n from '../translations';
-import { redirectToDetections, getActionMessageParams, userHasNoPermissions } from '../helpers';
+import {
+ redirectToDetections,
+ getActionMessageParams,
+ userHasNoPermissions,
+ MaxWidthEuiFlexItem,
+} from '../helpers';
import { RuleStep, RuleStepsFormData, RuleStepsFormHooks } from '../types';
import { formatRule, stepIsValid } from './helpers';
import * as i18n from './translations';
@@ -273,151 +285,155 @@ const CreateRulePageComponent: React.FC = () => {
return (
<>
-
-
-
- editStep(RuleStep.defineRule)}
- >
- {i18n.EDIT_RULE}
-
- )
- }
- >
-
- submitStep(RuleStep.defineRule)}
- descriptionColumns="singleSplit"
- />
-
-
-
-
- editStep(RuleStep.aboutRule)}
- >
- {i18n.EDIT_RULE}
-
- )
- }
- >
-
- submitStep(RuleStep.aboutRule)}
- />
-
-
-
-
- editStep(RuleStep.scheduleRule)}
- >
- {i18n.EDIT_RULE}
-
- )
- }
- >
-
- submitStep(RuleStep.scheduleRule)}
- />
-
-
-
-
- editStep(RuleStep.ruleActions)}
- >
- {i18n.EDIT_RULE}
-
- )
- }
- >
-
-
+
+
+ submitStep(RuleStep.ruleActions)}
- actionMessageParams={actionMessageParams}
+ title={i18n.PAGE_TITLE}
/>
-
-
+
+ editStep(RuleStep.defineRule)}
+ >
+ {i18n.EDIT_RULE}
+
+ )
+ }
+ >
+
+ submitStep(RuleStep.defineRule)}
+ descriptionColumns="singleSplit"
+ />
+
+
+
+
+ editStep(RuleStep.aboutRule)}
+ >
+ {i18n.EDIT_RULE}
+
+ )
+ }
+ >
+
+ submitStep(RuleStep.aboutRule)}
+ />
+
+
+
+
+ editStep(RuleStep.scheduleRule)}
+ >
+ {i18n.EDIT_RULE}
+
+ )
+ }
+ >
+
+ submitStep(RuleStep.scheduleRule)}
+ />
+
+
+
+
+ editStep(RuleStep.ruleActions)}
+ >
+ {i18n.EDIT_RULE}
+
+ )
+ }
+ >
+
+ submitStep(RuleStep.ruleActions)}
+ actionMessageParams={actionMessageParams}
+ />
+
+
+
+
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx
index e2772af72da06..fa74565be660f 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/edit/index.tsx
@@ -47,6 +47,7 @@ import {
redirectToDetections,
getActionMessageParams,
userHasNoPermissions,
+ MaxWidthEuiFlexItem,
} from '../helpers';
import * as ruleI18n from '../translations';
import { RuleStep, RuleStepsFormHooks, RuleStepsFormData, RuleStepsData } from '../types';
@@ -332,75 +333,79 @@ const EditRulePageComponent: FC = () => {
return (
<>
-
-
- {invalidSteps.length > 0 && (
-
- {
- if (t === RuleStep.aboutRule) {
- return ruleI18n.ABOUT;
- } else if (t === RuleStep.defineRule) {
- return ruleI18n.DEFINITION;
- } else if (t === RuleStep.scheduleRule) {
- return ruleI18n.SCHEDULE;
- } else if (t === RuleStep.ruleActions) {
- return ruleI18n.RULE_ACTIONS;
- }
- return t;
- })
- .join(', '),
+
+
+
+
-
- )}
-
- t.id === activeStep)}
- onTabClick={onTabClick}
- tabs={tabs}
- />
+ {invalidSteps.length > 0 && (
+
+ {
+ if (t === RuleStep.aboutRule) {
+ return ruleI18n.ABOUT;
+ } else if (t === RuleStep.defineRule) {
+ return ruleI18n.DEFINITION;
+ } else if (t === RuleStep.scheduleRule) {
+ return ruleI18n.SCHEDULE;
+ } else if (t === RuleStep.ruleActions) {
+ return ruleI18n.RULE_ACTIONS;
+ }
+ return t;
+ })
+ .join(', '),
+ }}
+ />
+
+ )}
-
+ t.id === activeStep)}
+ onTabClick={onTabClick}
+ tabs={tabs}
+ />
-
-
-
- {i18n.CANCEL}
-
-
+
-
-
- {i18n.SAVE_CHANGES}
-
-
+
+
+ {i18n.CANCEL}
+
+
+
+
+
+ {i18n.SAVE_CHANGES}
+
+
+
+
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx
index 456bf8419a1f7..4dbcffbc807ec 100644
--- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx
@@ -9,6 +9,8 @@ import moment from 'moment';
import memoizeOne from 'memoize-one';
import { useLocation } from 'react-router-dom';
+import styled from 'styled-components';
+import { EuiFlexItem } from '@elastic/eui';
import { ActionVariable } from '../../../../../../triggers_actions_ui/public';
import { RuleAlertAction } from '../../../../../common/detection_engine/types';
import { assertUnreachable } from '../../../../../common/utility_types';
@@ -377,3 +379,8 @@ export const getActionMessageParams = memoizeOne((ruleType: Type | undefined): A
// typed as null not undefined as the initial state for this value is null.
export const userHasNoPermissions = (canUserCRUD: boolean | null): boolean =>
canUserCRUD != null ? !canUserCRUD : false;
+
+export const MaxWidthEuiFlexItem = styled(EuiFlexItem)`
+ max-width: 1000px;
+ overflow: hidden;
+`;