Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ import { HeaderSection } from '../../../../common/components/header_section';
import { StepAboutRule } from '../../../rule_creation_ui/components/step_about_rule';
import type { AboutStepRule } from '../../../common/types';
import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock';
import { usePrebuiltRuleBaseVersionContext } from '../../../rule_management/components/rule_details/base_version_diff/base_version_context';
import { useRuleCustomizationsContext } from '../../../rule_management/components/rule_details/rule_customizations_diff/rule_customizations_context';

jest.mock('../../../../common/lib/kibana');
jest.mock(
'../../../rule_management/components/rule_details/base_version_diff/base_version_context'
'../../../rule_management/components/rule_details/rule_customizations_diff/rule_customizations_context'
);

const usePrebuiltRuleBaseVersionContextMock = usePrebuiltRuleBaseVersionContext as jest.Mock;
const useRuleCustomizationsContextMock = useRuleCustomizationsContext as jest.Mock;

const mockTheme = getMockTheme({
eui: { euiSizeL: '10px', euiBreakpoints: { s: '450px' }, euiSizeM: '10px' },
Expand All @@ -37,7 +37,7 @@ describe('StepAboutRuleToggleDetails', () => {

beforeEach(() => {
stepDataMock = mockAboutStepRule();
usePrebuiltRuleBaseVersionContextMock.mockReturnValue({
useRuleCustomizationsContextMock.mockReturnValue({
actions: { openCustomizationsPreviewFlyout: jest.fn() },
state: { doesBaseVersionExist: true, modifiedFields: new Set() },
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import type { AboutStepRule, AboutStepRuleDetails } from '../../../common/types'
import * as i18n from './translations';
import { fullHeight } from './styles';
import type { RuleResponse } from '../../../../../common/api/detection_engine';
import { ModifiedFieldBadge } from '../../../rule_management/components/rule_details/modified_field_badge';
import { RuleFieldName } from '../../../rule_management/components/rule_details/rule_field_name';

const detailsOption: EuiButtonGroupOptionProps = {
Expand All @@ -47,7 +46,6 @@ const setupOption: EuiButtonGroupOptionProps = {
label: i18n.ABOUT_PANEL_SETUP_TAB,
'data-test-subj': 'stepAboutDetailsToggle-setup',
};

interface StepPanelProps {
stepData: AboutStepRule | null;
stepDataDetails: AboutStepRuleDetails | null;
Expand Down Expand Up @@ -79,7 +77,7 @@ const StepAboutRuleToggleDetailsComponent: React.FC<StepPanelProps> = ({
...(notesExist ? [notesOption] : []),
...(setupExists ? [setupOption] : []),
];
}, [stepDataDetails]);
}, [stepDataDetails?.note, stepDataDetails?.setup]);

return (
<EuiPanel
Expand Down Expand Up @@ -122,34 +120,22 @@ const StepAboutRuleToggleDetailsComponent: React.FC<StepPanelProps> = ({
</VerticalOverflowContent>
</VerticalOverflowContainer>
<EuiSpacer size="m" />
<RuleAboutSection rule={rule} hideName hideDescription showModifiedFields />
<RuleAboutSection rule={rule} hideName hideDescription />
</div>
)}
</EuiResizeObserver>
)}
{selectedToggleOption === 'notes' && (
<VerticalOverflowContainer
data-test-subj="stepAboutDetailsNoteContent"
maxHeight={aboutPanelHeight}
>
<VerticalOverflowContainer maxHeight={aboutPanelHeight}>
<VerticalOverflowContent maxHeight={aboutPanelHeight}>
<EuiFlexGroup gutterSize="xs" direction="column" alignItems="flexStart">
<ModifiedFieldBadge fieldName={'note'} />
<MarkdownRenderer>{stepDataDetails.note}</MarkdownRenderer>
</EuiFlexGroup>
<RuleInvestigationGuide note={stepDataDetails.note} />
</VerticalOverflowContent>
</VerticalOverflowContainer>
)}
{selectedToggleOption === 'setup' && (
<VerticalOverflowContainer
data-test-subj="stepAboutDetailsSetupContent"
maxHeight={aboutPanelHeight}
>
<VerticalOverflowContainer maxHeight={aboutPanelHeight}>
<VerticalOverflowContent maxHeight={aboutPanelHeight}>
<EuiFlexGroup gutterSize="xs" direction="column" alignItems="flexStart">
<ModifiedFieldBadge fieldName={'setup'} />
<MarkdownRenderer>{stepDataDetails.setup}</MarkdownRenderer>
</EuiFlexGroup>
<RuleSetupGuide setup={stepDataDetails.setup} />
</VerticalOverflowContent>
</VerticalOverflowContainer>
)}
Expand All @@ -164,12 +150,10 @@ export const StepAboutRuleToggleDetails = memo(StepAboutRuleToggleDetailsCompone

interface VerticalOverflowContainerProps {
maxHeight: number;
'data-test-subj'?: string;
}

function VerticalOverflowContainer({
maxHeight,
'data-test-subj': dataTestSubject,
children,
}: PropsWithChildren<VerticalOverflowContainerProps>): JSX.Element {
return (
Expand All @@ -179,7 +163,6 @@ function VerticalOverflowContainer({
overflow-y: hidden;
word-break: break-word;
`}
data-test-subj={dataTestSubject}
>
{children}
</div>
Expand Down Expand Up @@ -209,13 +192,7 @@ const RuleDescription = ({ description }: { description: string }) => (
<EuiDescriptionList
listItems={[
{
title: (
<RuleFieldName
label={i18n.ABOUT_PANEL_DESCRIPTION_LABEL}
fieldName="description"
showModifiedFields
/>
),
title: <RuleFieldName label={i18n.ABOUT_PANEL_DESCRIPTION_LABEL} fieldName="description" />,
description: (
<EuiText size="s" data-test-subj="stepAboutRuleDetailsToggleDescriptionText">
{description}
Expand All @@ -225,3 +202,27 @@ const RuleDescription = ({ description }: { description: string }) => (
]}
/>
);

const RuleInvestigationGuide = ({ note }: { note: string }) => (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these live within this file, now, or do you intend to reuse them?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think they are fine to live here for now, we don't display either of these fields this way anywhere else - they usually get split up into their own section or tab. I broke them out into the smaller fragment stubs for overall readability in the main component

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While these two components aren't explicitly reused they are actually reused, please check setup and note components from the Prebuilt Rule Upgrade Flyout.

Ideally we should reuse Investigation Guide and Setup Guide components. You may see some readonly components are defined in rule_definition_section.tsx. note component in the Prebuilt Rule Upgrade Flyout should be renamed to investigation_guide.

nit: IMHO functions have higher readability

interface MyComponentProps {
  propA: string;
}

function MyComponent(props: MyComponentProps): JSX.Element {
  // implementation...
}

vs

interface MyComponentProps {
  propA: string;
}

const MyComponent = (props: MyComponentProps) => {
  // implementation...
};

<EuiDescriptionList
listItems={[
{
title: <RuleFieldName fieldName="note" />,
description: <MarkdownRenderer>{note}</MarkdownRenderer>,
},
]}
descriptionProps={{ 'data-test-subj': 'stepAboutDetailsNoteContent' }}
/>
);

const RuleSetupGuide = ({ setup }: { setup: string }) => (
<EuiDescriptionList
listItems={[
{
title: <RuleFieldName fieldName="setup" />,
description: <MarkdownRenderer>{setup}</MarkdownRenderer>,
},
]}
descriptionProps={{ 'data-test-subj': 'stepAboutDetailsSetupContent' }}
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ import {
TableId,
} from '@kbn/securitysolution-data-table';
import {
PrebuiltRuleBaseVersionFlyoutContextProvider,
usePrebuiltRuleBaseVersionContext,
} from '../../../rule_management/components/rule_details/base_version_diff/base_version_context';
RuleCustomizationsContextProvider,
useRuleCustomizationsContext,
} from '../../../rule_management/components/rule_details/rule_customizations_diff/rule_customizations_context';
import { useGroupTakeActionsItems } from '../../../../detections/hooks/alerts_table/use_group_take_action_items';
import { useDataView } from '../../../../data_view_manager/hooks/use_data_view';
import {
Expand Down Expand Up @@ -337,16 +337,16 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
}, [navigateToApp, ruleId]);

const {
actions: { setBaseVersionRule },
} = usePrebuiltRuleBaseVersionContext();
actions: { setCustomizationsRule },
} = useRuleCustomizationsContext();

// persist rule until refresh is complete
useEffect(() => {
if (maybeRule != null) {
setRule(maybeRule);
setBaseVersionRule(maybeRule);
setCustomizationsRule(maybeRule);
}
}, [maybeRule, setBaseVersionRule]);
}, [maybeRule, setCustomizationsRule]);

useLegacyUrlRedirect({ rule, spacesApi });

Expand Down Expand Up @@ -756,15 +756,14 @@ const RuleDetailsPageComponent: React.FC<DetectionEngineComponentProps> = ({
rule={rule}
isInteractive
dataTestSubj="definitionRule"
showModifiedFields
/>
)}
</StepPanel>
</EuiFlexItem>
<EuiSpacer />
<EuiFlexItem data-test-subj="schedule" component="section" grow={1}>
<StepPanel loading={isLoading} title={ruleI18n.SCHEDULE}>
{rule != null && <RuleScheduleSection rule={rule} showModifiedFields />}
{rule != null && <RuleScheduleSection rule={rule} />}
</StepPanel>
</EuiFlexItem>
{hasActions && (
Expand Down Expand Up @@ -899,9 +898,9 @@ RuleDetailsPageComponent.displayName = 'RuleDetailsPageComponent';
const ConnectedRuleDetailsPage = connector(React.memo(RuleDetailsPageComponent));

export const RuleDetailsPage = () => (
<PrebuiltRuleBaseVersionFlyoutContextProvider>
<RuleCustomizationsContextProvider>
<ConnectedRuleDetailsPage />
</PrebuiltRuleBaseVersionFlyoutContextProvider>
</RuleCustomizationsContextProvider>
);

RuleDetailsPage.displayName = 'RuleDetailsPage';
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useBulkExport } from '../../../../rule_management/logic/bulk_actions/us
import { useExecuteBulkAction } from '../../../../rule_management/logic/bulk_actions/use_execute_bulk_action';
import { mockRule } from '../../../../rule_management_ui/components/rules_table/__mocks__/mock';
import type { ExternalRuleSource } from '../../../../../../common/api/detection_engine';
import { usePrebuiltRuleBaseVersionContext } from '../../../../rule_management/components/rule_details/base_version_diff/base_version_context';
import { useRuleCustomizationsContext } from '../../../../rule_management/components/rule_details/rule_customizations_diff/rule_customizations_context';

const showBulkDuplicateExceptionsConfirmation = () => Promise.resolve(null);
const showManualRuleRunConfirmation = () => Promise.resolve(null);
Expand All @@ -23,7 +23,7 @@ jest.mock('../../../../../common/hooks/use_experimental_features');
jest.mock('../../../../rule_management/logic/bulk_actions/use_execute_bulk_action');
jest.mock('../../../../rule_management/logic/bulk_actions/use_bulk_export');
jest.mock(
'../../../../rule_management/components/rule_details/base_version_diff/base_version_context'
'../../../../rule_management/components/rule_details/rule_customizations_diff/rule_customizations_context'
);

const mockReportEvent = jest.fn();
Expand Down Expand Up @@ -51,11 +51,11 @@ jest.mock('../../../../../common/lib/kibana', () => {

const useExecuteBulkActionMock = useExecuteBulkAction as jest.Mock;
const useBulkExportMock = useBulkExport as jest.Mock;
const usePrebuiltRuleBaseVersionContextMock = usePrebuiltRuleBaseVersionContext as jest.Mock;
const useRuleCustomizationsContextMock = useRuleCustomizationsContext as jest.Mock;

describe('RuleActionsOverflow', () => {
beforeEach(() => {
usePrebuiltRuleBaseVersionContextMock.mockReturnValue({
useRuleCustomizationsContextMock.mockReturnValue({
actions: { openCustomizationsRevertFlyout: jest.fn() },
state: { doesBaseVersionExist: true },
});
Expand Down Expand Up @@ -322,7 +322,7 @@ describe('RuleActionsOverflow', () => {
});

test('it disabled the revert action when isRevertBaseVersionDisabled is true', async () => {
usePrebuiltRuleBaseVersionContextMock.mockReturnValue({
useRuleCustomizationsContextMock.mockReturnValue({
actions: { openCustomizationsRevertFlyout: jest.fn() },
state: { doesBaseVersionExist: false },
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from '@elastic/eui';
import React, { useCallback, useMemo } from 'react';
import styled from 'styled-components';
import { usePrebuiltRuleBaseVersionContext } from '../../../../rule_management/components/rule_details/base_version_diff/base_version_context';
import { useRuleCustomizationsContext } from '../../../../rule_management/components/rule_details/rule_customizations_diff/rule_customizations_context';
import { isCustomizedPrebuiltRule } from '../../../../../../common/api/detection_engine';
import { useScheduleRuleRun } from '../../../../rule_gaps/logic/use_schedule_rule_run';
import type { TimeRange } from '../../../../rule_gaps/types';
Expand Down Expand Up @@ -91,7 +91,7 @@ const RuleActionsOverflowComponent = ({
const {
actions: { openCustomizationsRevertFlyout },
state: { doesBaseVersionExist },
} = usePrebuiltRuleBaseVersionContext();
} = useRuleCustomizationsContext();

const actions = useMemo(
() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
DiffLayout,
} from '../../../model/rule_details/rule_field_diff';
import { fieldToDisplayNameMap } from './translations';
import { convertFieldToDisplayName } from '../helpers';

const SubFieldComponent = ({
currentVersion,
Expand All @@ -33,7 +34,7 @@ const SubFieldComponent = ({
<EuiFlexGroup direction="column">
{shouldShowSubtitles ? (
<EuiTitle data-test-subj="ruleUpgradePerFieldDiffSubtitle" size="xxxs">
<h4>{fieldToDisplayNameMap[fieldName] ?? startCase(camelCase(fieldName))}</h4>
<h4>{convertFieldToDisplayName(fieldName)}</h4>
</EuiTitle>
) : null}
{diffLayout === DiffLayout.RightToLeft ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ export const getHumanizedFieldName = (fieldName: string) => {
return i18n.MAX_SIGNALS_FIELD_LABEL;
case 'tags':
return i18n.TAGS_FIELD_LABEL;
case 'setup':
return i18n.SETUP_GUIDE_SECTION_LABEL;
case 'note':
return i18n.INVESTIGATION_GUIDE_TAB_LABEL;

// Definition section fields
case 'type':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { isPlainObject } from 'lodash';
import { camelCase, isPlainObject, startCase } from 'lodash';
import type { Filter } from '@kbn/es-query';
import type {
DiffableAllFields,
Expand All @@ -22,6 +22,7 @@ import {
} from './constants';
import * as i18n from './translations';
import { assertUnreachable } from '../../../../../common/utility_types';
import { fieldToDisplayNameMap } from './diff_components/translations';

export const getSectionedFieldDiffs = (fields: FieldsGroupDiff[]) => {
const aboutFields = [];
Expand Down Expand Up @@ -115,3 +116,6 @@ export function getDataSourceProps(dataSource: DiffableAllFields['data_source'])

return assertUnreachable(dataSource);
}

export const convertFieldToDisplayName = (fieldName: string) =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we have one utility function to convert field names to huma/display names? There is already getHumanizedFieldName which maps field names to human field names.

fieldToDisplayNameMap[fieldName] ?? startCase(camelCase(fieldName));
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
*/

import React from 'react';
import { EuiToolTip } from '@elastic/eui';
import * as i18n from './translations';
import { usePrebuiltRuleBaseVersionContext } from './base_version_diff/base_version_context';
import { useRuleCustomizationsContext } from './rule_customizations_diff/rule_customizations_context';
import { PrebuiltRuleDiffBadge } from './prebuilt_rule_diff_badge';

interface ModifiedFieldBadgeProps {
Expand All @@ -17,16 +18,22 @@ interface ModifiedFieldBadgeProps {
export const ModifiedFieldBadge: React.FC<ModifiedFieldBadgeProps> = ({ fieldName }) => {
const {
state: { doesBaseVersionExist, modifiedFields },
} = usePrebuiltRuleBaseVersionContext();
} = useRuleCustomizationsContext();

if (!doesBaseVersionExist || !modifiedFields.has(fieldName)) {
return null;
}

return (
<PrebuiltRuleDiffBadge
label={i18n.MODIFIED_PREBUILT_RULE_PER_FIELD_LABEL}
dataTestSubj="modified-prebuilt-rule-per-field-badge"
/>
<EuiToolTip
position="right"
title={i18n.MODIFIED_PREBUILT_RULE_PER_FIELD_LABEL}
content={i18n.MODIFIED_FIELD_BADGE_TOOLTIP_CONTENT}
>
<PrebuiltRuleDiffBadge
label={i18n.MODIFIED_PREBUILT_RULE_PER_FIELD_LABEL}
dataTestSubj={`modified-prebuilt-rule-per-field-${fieldName}-badge`}
/>
</EuiToolTip>
);
};
Loading