diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx
index 0753c6f613cb81..161fc4db117de4 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.test.tsx
@@ -8,7 +8,11 @@
import React from 'react';
import { render } from '@testing-library/react';
-import { ASSIGNEES_ADD_BUTTON_TEST_ID, ASSIGNEES_TITLE_TEST_ID } from './test_ids';
+import {
+ ASSIGNEES_ADD_BUTTON_TEST_ID,
+ ASSIGNEES_TITLE_TEST_ID,
+ ASSIGNEES_HEADER_TEST_ID,
+} from './test_ids';
import { Assignees } from './assignees';
import { useGetCurrentUserProfile } from '../../../../common/components/user_profiles/use_get_current_user_profile';
@@ -44,7 +48,8 @@ const mockUserProfiles = [
const renderAssignees = (
eventId = 'event-1',
alertAssignees = ['user-id-1'],
- onAssigneesUpdated = jest.fn()
+ onAssigneesUpdated = jest.fn(),
+ isPreview = false
) => {
const assignedProfiles = mockUserProfiles.filter((user) => alertAssignees.includes(user.uid));
(useBulkGetUserProfiles as jest.Mock).mockReturnValue({
@@ -57,6 +62,7 @@ const renderAssignees = (
eventId={eventId}
assignedUserIds={alertAssignees}
onAssigneesUpdated={onAssigneesUpdated}
+ isPreview={isPreview}
/>
);
@@ -163,4 +169,17 @@ describe('', () => {
expect(getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)).toBeInTheDocument();
expect(getByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)).toBeDisabled();
});
+
+ it('should render empty tag in preview mode', () => {
+ const assignees = ['user-id-1', 'user-id-2'];
+ const { getByTestId, queryByTestId } = renderAssignees(
+ 'test-event',
+ assignees,
+ jest.fn(),
+ true
+ );
+
+ expect(queryByTestId(ASSIGNEES_ADD_BUTTON_TEST_ID)).not.toBeInTheDocument();
+ expect(getByTestId(ASSIGNEES_HEADER_TEST_ID)).toHaveTextContent('Assignees—');
+ });
});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx
index 7544388a62f966..39429c96b0534a 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/assignees.tsx
@@ -12,7 +12,7 @@ import React, { memo, useCallback, useMemo, useState } from 'react';
import { EuiButtonIcon, EuiFlexGroup, EuiFlexItem, EuiTitle, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
-
+import { getEmptyTagValue } from '../../../../common/components/empty_value';
import { useUpsellingMessage } from '../../../../common/hooks/use_upselling';
import { useLicense } from '../../../../common/hooks/use_license';
import { useAlertsPrivileges } from '../../../../detections/containers/detection_engine/alerts/use_alerts_privileges';
@@ -60,13 +60,18 @@ export interface AssigneesProps {
* Callback to handle the successful assignees update
*/
onAssigneesUpdated?: () => void;
+
+ /**
+ * Boolean to indicate whether it is a preview flyout
+ */
+ isPreview?: boolean;
}
/**
* Document assignees details displayed in flyout right section header
*/
export const Assignees: FC = memo(
- ({ eventId, assignedUserIds, onAssigneesUpdated }) => {
+ ({ eventId, assignedUserIds, onAssigneesUpdated, isPreview }) => {
const isPlatinumPlus = useLicense().isPlatinumPlus();
const upsellingMessage = useUpsellingMessage('alert_assignments');
@@ -108,9 +113,8 @@ export const Assignees: FC = memo(
return (
@@ -118,39 +122,45 @@ export const Assignees: FC = memo(
- {assignedUsers && (
-
-
-
- )}
-
-
+ {assignedUsers && (
+
+
+
+ )}
+
+
}
+ isPopoverOpen={isPopoverOpen}
+ closePopover={togglePopover}
+ onAssigneesApply={onAssigneesApply}
/>
- }
- isPopoverOpen={isPopoverOpen}
- closePopover={togglePopover}
- onAssigneesApply={onAssigneesApply}
- />
-
+
+ >
+ )}
);
}
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.test.tsx
index 75ddf6ed6dec48..95af8ecb3351be 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.test.tsx
@@ -13,6 +13,8 @@ import {
SEVERITY_VALUE_TEST_ID,
FLYOUT_HEADER_TITLE_TEST_ID,
STATUS_BUTTON_TEST_ID,
+ ASSIGNEES_HEADER_TEST_ID,
+ ALERT_SUMMARY_PANEL_TEST_ID,
} from './test_ids';
import { HeaderTitle } from './header_title';
import moment from 'moment-timezone';
@@ -51,9 +53,12 @@ describe('', () => {
const { getByTestId } = renderHeader(mockContextValue);
expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toBeInTheDocument();
- expect(getByTestId(RISK_SCORE_VALUE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(SEVERITY_VALUE_TEST_ID)).toBeInTheDocument();
+ expect(getByTestId(ALERT_SUMMARY_PANEL_TEST_ID)).toBeInTheDocument();
+
+ expect(getByTestId(RISK_SCORE_VALUE_TEST_ID)).toBeInTheDocument();
expect(getByTestId(STATUS_BUTTON_TEST_ID)).toBeInTheDocument();
+ expect(getByTestId(ASSIGNEES_HEADER_TEST_ID)).toBeInTheDocument();
});
it('should render rule name in the title if document is an alert', () => {
@@ -81,7 +86,7 @@ describe('', () => {
expect(getByTestId(FLYOUT_HEADER_TITLE_TEST_ID)).toHaveTextContent('Event details');
});
- it('should not render document status if document is not an alert', () => {
+ it('should not render alert summary kpis if document is not an alert', () => {
const contextValue = {
...mockContextValue,
dataFormattedForFieldBrowser: [
@@ -96,16 +101,9 @@ describe('', () => {
} as unknown as RightPanelContext;
const { queryByTestId } = renderHeader(contextValue);
+ expect(queryByTestId(ALERT_SUMMARY_PANEL_TEST_ID)).not.toBeInTheDocument();
expect(queryByTestId(STATUS_BUTTON_TEST_ID)).not.toBeInTheDocument();
- });
-
- it('should not render document status if flyout is open in preview', () => {
- const contextValue = {
- ...mockContextValue,
- isPreview: true,
- } as unknown as RightPanelContext;
-
- const { queryByTestId } = renderHeader(contextValue);
- expect(queryByTestId(STATUS_BUTTON_TEST_ID)).not.toBeInTheDocument();
+ expect(queryByTestId(RISK_SCORE_VALUE_TEST_ID)).not.toBeInTheDocument();
+ expect(queryByTestId(ASSIGNEES_HEADER_TEST_ID)).not.toBeInTheDocument();
});
});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx
index 0d8f581626736c..d4bbeb42d2e2fc 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/header_title.tsx
@@ -7,9 +7,17 @@
import type { FC } from 'react';
import React, { memo, useCallback, useMemo } from 'react';
-import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui';
+import {
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiSpacer,
+ EuiPanel,
+ EuiTitle,
+ useEuiTheme,
+} from '@elastic/eui';
import { isEmpty } from 'lodash';
import { FormattedMessage } from '@kbn/i18n-react';
+import { css } from '@emotion/css';
import { ALERT_WORKFLOW_ASSIGNEE_IDS } from '@kbn/rule-data-utils';
import { DocumentStatus } from './status';
import { DocumentSeverity } from './severity';
@@ -20,7 +28,7 @@ import { useRightPanelContext } from '../context';
import { PreferenceFormattedDate } from '../../../../common/components/formatted_date';
import { RenderRuleName } from '../../../../timelines/components/timeline/body/renderers/formatted_field_helpers';
import { SIGNAL_RULE_NAME_FIELD_NAME } from '../../../../timelines/components/timeline/body/renderers/constants';
-import { FLYOUT_HEADER_TITLE_TEST_ID } from './test_ids';
+import { FLYOUT_HEADER_TITLE_TEST_ID, ALERT_SUMMARY_PANEL_TEST_ID } from './test_ids';
import { Assignees } from './assignees';
import { FlyoutTitle } from '../../../shared/components/flyout_title';
@@ -39,6 +47,7 @@ export const HeaderTitle: FC = memo(() => {
const { isAlert, ruleName, timestamp, ruleId } = useBasicDataFromDetailsData(
dataFormattedForFieldBrowser
);
+ const { euiTheme } = useEuiTheme();
const ruleTitle = useMemo(
() =>
@@ -102,25 +111,41 @@ export const HeaderTitle: FC = memo(() => {
{isAlert && !isEmpty(ruleName) ? ruleTitle : eventTitle}
-
- {isAlert && !isPreview && (
-
-
-
- )}
-
-
-
- {isAlert && !isPreview && (
-
-
-
- )}
-
+ {isAlert && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
>
);
});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/risk_score.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/risk_score.tsx
index a603cd9563d288..6266b349f40782 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/risk_score.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/risk_score.tsx
@@ -34,13 +34,13 @@ export const RiskScore: FC = memo(() => {
}
return (
-
+
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.test.tsx
index 82ebab4f962de2..2d11e3dc24f487 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.test.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.test.tsx
@@ -56,7 +56,7 @@ describe('', () => {
expect(getByTestId('data-test-subj')).toBeInTheDocument();
});
- it('should render empty component', () => {
+ it('should render empty tag when status is not available', () => {
const contextValue = {
eventId: 'eventId',
browserFields: {},
@@ -66,6 +66,20 @@ describe('', () => {
const { container } = renderStatus(contextValue);
- expect(container).toBeEmptyDOMElement();
+ expect(container).toHaveTextContent('Status—');
+ });
+
+ it('should render empty tag in preview mode', () => {
+ const contextValue = {
+ eventId: 'eventId',
+ browserFields: {},
+ dataFormattedForFieldBrowser: mockDataFormattedForFieldBrowser,
+ scopeId: 'scopeId',
+ isPreview: true,
+ } as unknown as RightPanelContext;
+
+ const { container } = renderStatus(contextValue);
+
+ expect(container).toHaveTextContent('Status—');
});
});
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx
index cc1f7bc02f17dc..553dfd5834a0e9 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/status.tsx
@@ -8,10 +8,13 @@
import type { FC } from 'react';
import React, { useMemo } from 'react';
import { find } from 'lodash/fp';
+import { FormattedMessage } from '@kbn/i18n-react';
import { useExpandableFlyoutApi } from '@kbn/expandable-flyout';
import { CellActionsMode } from '@kbn/cell-actions';
+import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui';
import { getSourcererScopeId } from '../../../../helpers';
import { SecurityCellActions } from '../../../../common/components/cell_actions';
+import { getEmptyTagValue } from '../../../../common/components/empty_value';
import type {
EnrichedFieldInfo,
EnrichedFieldInfoWithValues,
@@ -21,6 +24,7 @@ import { StatusPopoverButton } from '../../../../common/components/event_details
import { useRightPanelContext } from '../context';
import { getEnrichedFieldInfo } from '../../../../common/components/event_details/helpers';
import { SecurityCellActionsTrigger } from '../../../../actions/constants';
+import { STATUS_TITLE_TEST_ID } from './test_ids';
/**
* Checks if the field info has data to convert EnrichedFieldInfo into EnrichedFieldInfoWithValues
@@ -34,7 +38,8 @@ function hasData(fieldInfo?: EnrichedFieldInfo): fieldInfo is EnrichedFieldInfoW
*/
export const DocumentStatus: FC = () => {
const { closeFlyout } = useExpandableFlyoutApi();
- const { eventId, browserFields, dataFormattedForFieldBrowser, scopeId } = useRightPanelContext();
+ const { eventId, browserFields, dataFormattedForFieldBrowser, scopeId, isPreview } =
+ useRightPanelContext();
const statusData = useMemo(() => {
const item = find(
@@ -53,28 +58,44 @@ export const DocumentStatus: FC = () => {
);
}, [browserFields, dataFormattedForFieldBrowser, eventId, scopeId]);
- if (!statusData || !hasData(statusData)) return null;
-
return (
-
-
-
+
+
+
+
+
+
+
+
+
+ {!statusData || !hasData(statusData) || isPreview ? (
+ getEmptyTagValue()
+ ) : (
+
+
+
+ )}
+
+
);
};
diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts
index 5b176a34014abf..2a218e9b28234d 100644
--- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts
+++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/test_ids.ts
@@ -12,6 +12,8 @@ import { CONTENT_TEST_ID, HEADER_TEST_ID } from './expandable_section';
const FLYOUT_HEADER_TEST_ID = `${PREFIX}Header` as const;
export const FLYOUT_HEADER_TITLE_TEST_ID = `${FLYOUT_HEADER_TEST_ID}Title` as const;
+export const ALERT_SUMMARY_PANEL_TEST_ID = `${FLYOUT_HEADER_TEST_ID}AlertSumaryPanel` as const;
+export const STATUS_TITLE_TEST_ID = `${FLYOUT_HEADER_TEST_ID}StatusTitle` as const;
export const STATUS_BUTTON_TEST_ID = 'rule-status-badge' as const;
export const SEVERITY_VALUE_TEST_ID = 'severity' as const;
export const RISK_SCORE_TITLE_TEST_ID = `${FLYOUT_HEADER_TEST_ID}RiskScoreTitle` as const;
diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts
index aaa8806362d066..357758aabf9c69 100644
--- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts
+++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/alerts/expandable_flyout/alert_details_right_panel.cy.ts
@@ -34,6 +34,7 @@ import {
DOCUMENT_DETAILS_FLYOUT_HEADER_LINK_ICON,
DOCUMENT_DETAILS_FLYOUT_HEADER_RISK_SCORE,
DOCUMENT_DETAILS_FLYOUT_HEADER_RISK_SCORE_VALUE,
+ DOCUMENT_DETAILS_FLYOUT_HEADER_ASSIGNEES,
DOCUMENT_DETAILS_FLYOUT_HEADER_SEVERITY_VALUE,
DOCUMENT_DETAILS_FLYOUT_HEADER_STATUS,
DOCUMENT_DETAILS_FLYOUT_HEADER_TITLE,
@@ -80,11 +81,13 @@ describe('Alert details expandable flyout right panel', { tags: ['@ess', '@serve
cy.get(DOCUMENT_DETAILS_FLYOUT_HEADER_STATUS).should('have.text', 'open');
- cy.get(DOCUMENT_DETAILS_FLYOUT_HEADER_RISK_SCORE).should('have.text', 'Risk score:');
+ cy.get(DOCUMENT_DETAILS_FLYOUT_HEADER_RISK_SCORE).should('have.text', 'Risk score');
cy.get(DOCUMENT_DETAILS_FLYOUT_HEADER_RISK_SCORE_VALUE)
.should('be.visible')
.and('have.text', rule.risk_score);
+ cy.get(DOCUMENT_DETAILS_FLYOUT_HEADER_ASSIGNEES).should('have.text', 'Assignees');
+
cy.get(DOCUMENT_DETAILS_FLYOUT_HEADER_SEVERITY_VALUE)
.should('be.visible')
.and('have.text', upperFirst(rule.severity));