[Security Solution] Analyze event moved outside of overflow popover (#115478)
This commit is contained in:
parent
0e5f2524b4
commit
340271fba2
6 changed files with 90 additions and 19 deletions
|
@ -34,7 +34,6 @@ import { useExceptionActions } from './use_add_exception_actions';
|
|||
import { useEventFilterModal } from './use_event_filter_modal';
|
||||
import { Status } from '../../../../../common/detection_engine/schemas/common/schemas';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { useInvestigateInResolverContextItem } from './investigate_in_resolver';
|
||||
import { ATTACH_ALERT_TO_CASE_FOR_ROW } from '../../../../timelines/components/timeline/body/translations';
|
||||
import { useEventFilterAction } from './use_event_filter_action';
|
||||
import { useAddToCaseActions } from './use_add_to_case_actions';
|
||||
|
@ -163,30 +162,19 @@ const AlertContextMenuComponent: React.FC<AlertContextMenuProps & PropsFromRedux
|
|||
isEndpointAlert: isAlertFromEndpointAlert({ ecsData: ecsRowData }),
|
||||
onAddExceptionTypeClick: handleOnAddExceptionTypeClick,
|
||||
});
|
||||
const investigateInResolverActionItems = useInvestigateInResolverContextItem({
|
||||
timelineId,
|
||||
ecsData: ecsRowData,
|
||||
onClose: afterItemSelection,
|
||||
});
|
||||
const { eventFilterActionItems } = useEventFilterAction({
|
||||
onAddEventFilterClick: handleOnAddEventFilterClick,
|
||||
});
|
||||
const items: React.ReactElement[] = useMemo(
|
||||
() =>
|
||||
!isEvent && ruleId
|
||||
? [
|
||||
...investigateInResolverActionItems,
|
||||
...addToCaseActionItems,
|
||||
...statusActionItems,
|
||||
...exceptionActionItems,
|
||||
]
|
||||
: [...investigateInResolverActionItems, ...addToCaseActionItems, ...eventFilterActionItems],
|
||||
? [...addToCaseActionItems, ...statusActionItems, ...exceptionActionItems]
|
||||
: [...addToCaseActionItems, ...eventFilterActionItems],
|
||||
[
|
||||
statusActionItems,
|
||||
addToCaseActionItems,
|
||||
eventFilterActionItems,
|
||||
exceptionActionItems,
|
||||
investigateInResolverActionItems,
|
||||
isEvent,
|
||||
ruleId,
|
||||
]
|
||||
|
|
|
@ -185,5 +185,34 @@ describe('Actions', () => {
|
|||
wrapper.find('[data-test-subj="timeline-context-menu-button"]').first().prop('isDisabled')
|
||||
).toBe(false);
|
||||
});
|
||||
test('it shows the analyze event button when the event is from an endpoint', () => {
|
||||
const ecsData = {
|
||||
...mockTimelineData[0].ecs,
|
||||
event: { kind: ['alert'] },
|
||||
agent: { type: ['endpoint'] },
|
||||
process: { entity_id: ['1'] },
|
||||
};
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<Actions {...defaultProps} ecsData={ecsData} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(wrapper.find('[data-test-subj="view-in-analyzer"]').exists()).toBe(true);
|
||||
});
|
||||
test('it does not render the analyze event button when the event is from an unsupported source', () => {
|
||||
const ecsData = {
|
||||
...mockTimelineData[0].ecs,
|
||||
event: { kind: ['alert'] },
|
||||
agent: { type: ['notendpoint'] },
|
||||
};
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<Actions {...defaultProps} ecsData={ecsData} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(wrapper.find('[data-test-subj="view-in-analyzer"]').exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -21,9 +21,23 @@ import { EventsTdContent } from '../../styles';
|
|||
import * as i18n from '../translations';
|
||||
import { DEFAULT_ICON_BUTTON_WIDTH } from '../../helpers';
|
||||
import { useShallowEqualSelector } from '../../../../../common/hooks/use_selector';
|
||||
import { TimelineId, ActionProps, OnPinEvent } from '../../../../../../common/types/timeline';
|
||||
import {
|
||||
setActiveTabTimeline,
|
||||
updateTimelineGraphEventId,
|
||||
} from '../../../../store/timeline/actions';
|
||||
import {
|
||||
useGlobalFullScreen,
|
||||
useTimelineFullScreen,
|
||||
} from '../../../../../common/containers/use_full_screen';
|
||||
import {
|
||||
TimelineId,
|
||||
ActionProps,
|
||||
OnPinEvent,
|
||||
TimelineTabs,
|
||||
} from '../../../../../../common/types/timeline';
|
||||
import { timelineActions, timelineSelectors } from '../../../../store/timeline';
|
||||
import { timelineDefaults } from '../../../../store/timeline/defaults';
|
||||
import { isInvestigateInResolverActionEnabled } from '../../../../../detections/components/alerts_table/timeline_actions/investigate_in_resolver';
|
||||
|
||||
const ActionsContainer = styled.div`
|
||||
align-items: center;
|
||||
|
@ -100,6 +114,24 @@ const ActionsComponent: React.FC<ActionProps> = ({
|
|||
[eventType, ecsData.event?.kind, ecsData.agent?.type]
|
||||
);
|
||||
|
||||
const isDisabled = useMemo(() => !isInvestigateInResolverActionEnabled(ecsData), [ecsData]);
|
||||
const { setGlobalFullScreen } = useGlobalFullScreen();
|
||||
const { setTimelineFullScreen } = useTimelineFullScreen();
|
||||
const handleClick = useCallback(() => {
|
||||
const dataGridIsFullScreen = document.querySelector('.euiDataGrid--fullScreen');
|
||||
dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: ecsData._id }));
|
||||
if (timelineId === TimelineId.active) {
|
||||
if (dataGridIsFullScreen) {
|
||||
setTimelineFullScreen(true);
|
||||
}
|
||||
dispatch(setActiveTabTimeline({ id: timelineId, activeTab: TimelineTabs.graph }));
|
||||
} else {
|
||||
if (dataGridIsFullScreen) {
|
||||
setGlobalFullScreen(true);
|
||||
}
|
||||
}
|
||||
}, [dispatch, ecsData._id, timelineId, setGlobalFullScreen, setTimelineFullScreen]);
|
||||
|
||||
return (
|
||||
<ActionsContainer>
|
||||
{showCheckboxes && !tGridEnabled && (
|
||||
|
@ -171,6 +203,26 @@ const ActionsComponent: React.FC<ActionProps> = ({
|
|||
refetch={refetch ?? noop}
|
||||
onRuleChange={onRuleChange}
|
||||
/>
|
||||
{isDisabled === false ? (
|
||||
<div>
|
||||
<EventsTdContent textAlign="center" width={36}>
|
||||
<EuiToolTip
|
||||
data-test-subj="view-in-analyzer-tool-tip"
|
||||
content={i18n.ACTION_INVESTIGATE_IN_RESOLVER}
|
||||
>
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.ACTION_INVESTIGATE_IN_RESOLVER_FOR_ROW({
|
||||
ariaRowindex,
|
||||
columnValues,
|
||||
})}
|
||||
data-test-subj="view-in-analyzer"
|
||||
iconType="analyzeEvent"
|
||||
onClick={handleClick}
|
||||
/>
|
||||
</EuiToolTip>
|
||||
</EventsTdContent>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
</ActionsContainer>
|
||||
);
|
||||
|
|
|
@ -521,7 +521,7 @@ exports[`ColumnHeaders rendering renders correctly against snapshot 1`] = `
|
|||
"compare": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"width": 108,
|
||||
"width": 140,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { ControlColumnProps } from '../../../../../../common/types/timeline';
|
|||
import { Actions } from '../actions';
|
||||
import { HeaderActions } from '../actions/header_actions';
|
||||
|
||||
const DEFAULT_CONTROL_COLUMN_WIDTH = 108;
|
||||
const DEFAULT_CONTROL_COLUMN_WIDTH = 140;
|
||||
|
||||
export const defaultControlColumn: ControlColumnProps = {
|
||||
id: 'default-timeline-control-column',
|
||||
|
|
|
@ -17,8 +17,10 @@ import {
|
|||
import { OnPinEvent, OnUnPinEvent } from '../events';
|
||||
import * as i18n from './translations';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
export const omitTypenameAndEmpty = (k: string, v: any): any | undefined =>
|
||||
export const omitTypenameAndEmpty = (
|
||||
k: string,
|
||||
v: string | object | Array<string | object>
|
||||
): string | object | Array<string | object> | undefined =>
|
||||
k !== '__typename' && v != null ? v : undefined;
|
||||
|
||||
export const stringifyEvent = (ecs: Ecs): string => JSON.stringify(ecs, omitTypenameAndEmpty, 2);
|
||||
|
|
Loading…
Reference in a new issue