Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expandable flyout context #165662

Merged
merged 3 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -6,17 +6,11 @@
*/

import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
import { css } from '@emotion/react';
import React, { createContext, memo, useContext, useMemo } from 'react';
import { EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';

import { useTimelineEventsDetails } from '../../timelines/containers/details';
import { getAlertIndexAlias } from '../../timelines/components/side_panel/event_details/helpers';
import { useSpaceId } from '../../common/hooks/use_space_id';
import { useRouteSpy } from '../../common/utils/route/use_route_spy';
import { SecurityPageName } from '../../../common/constants';
import { SourcererScopeName } from '../../common/store/sourcerer/model';
import { useSourcererDataView } from '../../common/containers/sourcerer';
import { useEventDetails } from '../shared/hooks/use_event_details';
import { FlyoutError } from '../shared/components/flyout_error';
import { FlyoutLoading } from '../shared/components/flyout_loading';
import type { IsolateHostPanelProps } from '.';

export interface IsolateHostPanelContext {
Expand All @@ -35,7 +29,7 @@ export interface IsolateHostPanelContext {
/**
* An array of field objects with category and value
*/
dataFormattedForFieldBrowser: TimelineEventsDetailsItem[] | null;
dataFormattedForFieldBrowser: TimelineEventsDetailsItem[];
/**
* Isolate action, either 'isolateHost' or 'unisolateHost'
*/
Expand All @@ -55,26 +49,11 @@ export type IsolateHostPanelProviderProps = {

export const IsolateHostPanelProvider = memo(
({ id, indexName, scopeId, isolateAction, children }: IsolateHostPanelProviderProps) => {
const currentSpaceId = useSpaceId();
// TODO Replace getAlertIndexAlias way to retrieving the eventIndex with the GET /_alias
// https://github.com/elastic/kibana/issues/113063
const eventIndex = indexName ? getAlertIndexAlias(indexName, currentSpaceId) ?? indexName : '';
const [{ pageName }] = useRouteSpy();
const sourcererScope =
pageName === SecurityPageName.detections
? SourcererScopeName.detections
: SourcererScopeName.default;
const sourcererDataView = useSourcererDataView(sourcererScope);
const [loading, dataFormattedForFieldBrowser] = useTimelineEventsDetails({
indexName: eventIndex,
eventId: id ?? '',
runtimeMappings: sourcererDataView.runtimeMappings,
skip: !id,
});
const { dataFormattedForFieldBrowser, loading } = useEventDetails({ eventId: id, indexName });

const contextValue = useMemo(
() =>
id && indexName && scopeId && isolateAction
id && indexName && scopeId && isolateAction && dataFormattedForFieldBrowser
? {
eventId: id,
indexName,
Expand All @@ -87,16 +66,11 @@ export const IsolateHostPanelProvider = memo(
);

if (loading) {
return (
<EuiFlexItem
css={css`
align-items: center;
justify-content: center;
`}
>
<EuiLoadingSpinner size="xxl" />
</EuiFlexItem>
);
return <FlyoutLoading />;
}

if (!contextValue) {
return <FlyoutError />;
}

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import '@testing-library/jest-dom';
import { LeftPanelContext } from '../context';
import { TestProviders } from '../../../common/mock';
import { AnalyzeGraph } from './analyze_graph';
import { ANALYZE_GRAPH_ERROR_TEST_ID, ANALYZER_GRAPH_TEST_ID } from './test_ids';
import { ANALYZER_GRAPH_TEST_ID } from './test_ids';

jest.mock('react-router-dom', () => {
const actual = jest.requireActual('react-router-dom');
Expand Down Expand Up @@ -45,21 +45,4 @@ describe('<AnalyzeGraph />', () => {
);
expect(wrapper.getByTestId(ANALYZER_GRAPH_TEST_ID)).toBeInTheDocument();
});

it('should render error message on null eventId', () => {
const contextValue = {
eventId: null,
} as unknown as LeftPanelContext;

const wrapper = render(
<TestProviders>
<LeftPanelContext.Provider value={contextValue}>
<AnalyzeGraph />
</LeftPanelContext.Provider>
</TestProviders>
);
expect(wrapper.getByTestId(ANALYZE_GRAPH_ERROR_TEST_ID)).toBeInTheDocument();
expect(wrapper.getByText('Unable to display analyzer')).toBeInTheDocument();
expect(wrapper.getByText('There was an error displaying analyzer')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@

import type { FC } from 'react';
import React, { useMemo } from 'react';
import { EuiEmptyPrompt } from '@elastic/eui';

import { ANALYZER_ERROR_MESSAGE } from './translations';
import { useLeftPanelContext } from '../context';
import { ANALYZE_GRAPH_ERROR_TEST_ID, ANALYZER_GRAPH_TEST_ID } from './test_ids';
import { ANALYZER_GRAPH_TEST_ID } from './test_ids';
import { Resolver } from '../../../resolver/view';
import { useTimelineDataFilters } from '../../../timelines/containers/use_timeline_data_filters';
import { ERROR_TITLE, ERROR_MESSAGE } from '../../shared/translations';
import { isActiveTimeline } from '../../../helpers';

export const ANALYZE_GRAPH_ID = 'analyze_graph';
Expand All @@ -30,18 +27,6 @@ export const AnalyzeGraph: FC = () => {
);
const filters = useMemo(() => ({ from, to }), [from, to]);

if (!eventId) {
return (
<EuiEmptyPrompt
iconType="error"
color="danger"
title={<h2>{ERROR_TITLE(ANALYZER_ERROR_MESSAGE)}</h2>}
body={<p>{ERROR_MESSAGE(ANALYZER_ERROR_MESSAGE)}</p>}
data-test-subj={ANALYZE_GRAPH_ERROR_TEST_ID}
/>
);
}

return (
<div data-test-subj={ANALYZER_GRAPH_TEST_ID}>
<Resolver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,12 @@ describe('<InvestigationGuide />', () => {
expect(getByTestId(INVESTIGATION_GUIDE_NO_DATA_TEST_ID)).toBeInTheDocument();
});

it('should render null when dataFormattedForFieldBrowser is null', () => {
const mockContext = {
...mockContextValue,
dataFormattedForFieldBrowser: null,
};
(useInvestigationGuide as jest.Mock).mockReturnValue({
loading: false,
error: false,
});
const { container } = render(renderInvestigationGuide(mockContext));
expect(container).toBeEmptyDOMElement();
});

it('should render null useInvestigationGuide errors out', () => {
it('should render no data message when useInvestigationGuide errors out', () => {
(useInvestigationGuide as jest.Mock).mockReturnValue({
loading: false,
error: true,
});
const { container } = render(renderInvestigationGuide());
expect(container).toBeEmptyDOMElement();
const { getByTestId } = render(renderInvestigationGuide());
expect(getByTestId(INVESTIGATION_GUIDE_NO_DATA_TEST_ID)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ export const InvestigationGuide: React.FC = () => {
dataFormattedForFieldBrowser,
});

if (!dataFormattedForFieldBrowser || error) {
return null;
}

if (loading) {
return (
<EuiFlexGroup
Expand All @@ -45,7 +41,7 @@ export const InvestigationGuide: React.FC = () => {

return (
<>
{basicAlertData.ruleId && ruleNote ? (
{!error && basicAlertData.ruleId && ruleNote ? (
<InvestigationGuideView
basicData={basicAlertData}
ruleNote={ruleNote}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import {
PREVALENCE_DETAILS_LOADING_TEST_ID,
PREVALENCE_DETAILS_TABLE_ALERT_COUNT_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_DOC_COUNT_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID,
PREVALENCE_DETAILS_TABLE_FIELD_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_NO_DATA_TEST_ID,
PREVALENCE_DETAILS_TABLE_TEST_ID,
PREVALENCE_DETAILS_TABLE_USER_PREVALENCE_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID,
Expand Down Expand Up @@ -218,7 +218,7 @@ describe('PrevalenceDetails', () => {
expect(getByTestId(PREVALENCE_DETAILS_LOADING_TEST_ID)).toBeInTheDocument();
});

it('should render error if call errors out', () => {
it('should render no data message if call errors out', () => {
(usePrevalence as jest.Mock).mockReturnValue({
loading: false,
error: true,
Expand All @@ -231,66 +231,6 @@ describe('PrevalenceDetails', () => {
</LeftPanelContext.Provider>
);

expect(getByTestId(PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID)).toBeInTheDocument();
});

it('should render error if event is null', () => {
const contextValue = {
...panelContextValue,
eventId: null,
} as unknown as LeftPanelContext;
(usePrevalence as jest.Mock).mockReturnValue({
loading: false,
error: true,
data: [],
});

const { getByTestId } = render(
<LeftPanelContext.Provider value={contextValue}>
<PrevalenceDetails />
</LeftPanelContext.Provider>
);

expect(getByTestId(PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID)).toBeInTheDocument();
});

it('should render error if dataFormattedForFieldBrowser is null', () => {
const contextValue = {
...panelContextValue,
dataFormattedForFieldBrowser: null,
};
(usePrevalence as jest.Mock).mockReturnValue({
loading: false,
error: true,
data: [],
});

const { getByTestId } = render(
<LeftPanelContext.Provider value={contextValue}>
<PrevalenceDetails />
</LeftPanelContext.Provider>
);

expect(getByTestId(PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID)).toBeInTheDocument();
});

it('should render error if browserFields is null', () => {
const contextValue = {
...panelContextValue,
browserFields: null,
};
(usePrevalence as jest.Mock).mockReturnValue({
loading: false,
error: true,
data: [],
});

const { getByTestId } = render(
<LeftPanelContext.Provider value={contextValue}>
<PrevalenceDetails />
</LeftPanelContext.Provider>
);

expect(getByTestId(PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID)).toBeInTheDocument();
expect(getByTestId(`${PREVALENCE_DETAILS_TABLE_NO_DATA_TEST_ID}Error`)).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import React, { useMemo, useState } from 'react';
import type { EuiBasicTableColumn, OnTimeChangeProps } from '@elastic/eui';
import {
EuiCallOut,
EuiEmptyPrompt,
EuiFlexGroup,
EuiFlexItem,
EuiInMemoryTable,
Expand All @@ -28,10 +27,8 @@ import { useLicense } from '../../../common/hooks/use_license';
import { InvestigateInTimelineButton } from '../../../common/components/event_details/table/investigate_in_timeline_button';
import type { PrevalenceData } from '../../shared/hooks/use_prevalence';
import { usePrevalence } from '../../shared/hooks/use_prevalence';
import { ERROR_MESSAGE, ERROR_TITLE } from '../../shared/translations';
import {
HOST_TITLE,
PREVALENCE_ERROR_MESSAGE,
PREVALENCE_TABLE_ALERT_COUNT_COLUMN_TITLE,
PREVALENCE_TABLE_COUNT_COLUMN_TITLE,
PREVALENCE_TABLE_DOC_COUNT_COLUMN_TITLE,
Expand All @@ -49,7 +46,6 @@ import {
PREVALENCE_DETAILS_LOADING_TEST_ID,
PREVALENCE_DETAILS_TABLE_ALERT_COUNT_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_DOC_COUNT_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID,
PREVALENCE_DETAILS_TABLE_HOST_PREVALENCE_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_VALUE_CELL_TEST_ID,
PREVALENCE_DETAILS_TABLE_FIELD_CELL_TEST_ID,
Expand Down Expand Up @@ -208,8 +204,7 @@ const columns: Array<EuiBasicTableColumn<PrevalenceDetailsRow>> = [
* Prevalence table displayed in the document details expandable flyout left section under the Insights tab
*/
export const PrevalenceDetails: React.FC = () => {
const { browserFields, dataFormattedForFieldBrowser, eventId, investigationFields } =
useLeftPanelContext();
const { dataFormattedForFieldBrowser, investigationFields } = useLeftPanelContext();

const isPlatinumPlus = useLicense().isPlatinumPlus();

Expand Down Expand Up @@ -273,18 +268,6 @@ export const PrevalenceDetails: React.FC = () => {
);
}

if (!eventId || !dataFormattedForFieldBrowser || !browserFields || error) {
return (
<EuiEmptyPrompt
iconType="error"
color="danger"
title={<h2>{ERROR_TITLE(PREVALENCE_ERROR_MESSAGE)}</h2>}
body={<p>{ERROR_MESSAGE(PREVALENCE_ERROR_MESSAGE)}</p>}
data-test-subj={PREVALENCE_DETAILS_TABLE_ERROR_TEST_ID}
/>
);
}

const upsell = (
<>
<EuiCallOut data-test-subj={`${PREVALENCE_DETAILS_TABLE_TEST_ID}UpSell`}>
Expand All @@ -309,7 +292,7 @@ export const PrevalenceDetails: React.FC = () => {

return (
<>
{!isPlatinumPlus && upsell}
{!error && !isPlatinumPlus && upsell}
<EuiPanel>
<EuiSuperDatePicker
start={start}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface SuppressedAlertsProps {
/**
* An object with top level fields from the ECS object
*/
dataAsNestedObject: Ecs | null;
dataAsNestedObject: Ecs;
/**
* Value of the kibana.alert.suppression.doc_count field
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,6 @@ export const RELATED_USERS_TOOL_TIP = (hostName: string) =>
values: { hostName },
});

export const PREVALENCE_ERROR_MESSAGE = i18n.translate(
'xpack.securitySolution.flyout.prevalenceErrorMessage',
{
defaultMessage: 'prevalence',
}
);

export const PREVALENCE_NO_DATA_MESSAGE = i18n.translate(
'xpack.securitySolution.flyout.prevalenceNoDataMessage',
{
Expand Down
Loading
Loading