Skip to content

Commit adbe8ff

Browse files
authored
[Security Solution] [Timeline] Timeline manager tweaks (#69988) (#71016)
1 parent d15242b commit adbe8ff

File tree

10 files changed

+60
-78
lines changed

10 files changed

+60
-78
lines changed

x-pack/plugins/security_solution/public/alerts/components/alerts_table/default_config.tsx

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
SetEventsLoadingProps,
3737
UpdateTimelineLoading,
3838
} from './types';
39+
import { Ecs } from '../../../graphql/types';
3940

4041
export const buildAlertStatusFilter = (status: Status): Filter[] => [
4142
{
@@ -173,11 +174,28 @@ export const requiredFieldsForActions = [
173174
'signal.rule.id',
174175
];
175176

177+
interface AlertActionArgs {
178+
apolloClient?: ApolloClient<{}>;
179+
canUserCRUD: boolean;
180+
createTimeline: CreateTimeline;
181+
dispatch: Dispatch;
182+
ecsRowData: Ecs;
183+
hasIndexWrite: boolean;
184+
onAlertStatusUpdateFailure: (status: Status, error: Error) => void;
185+
onAlertStatusUpdateSuccess: (count: number, status: Status) => void;
186+
setEventsDeleted: ({ eventIds, isDeleted }: SetEventsDeletedProps) => void;
187+
setEventsLoading: ({ eventIds, isLoading }: SetEventsLoadingProps) => void;
188+
status: Status;
189+
timelineId: string;
190+
updateTimelineIsLoading: UpdateTimelineLoading;
191+
}
192+
176193
export const getAlertActions = ({
177194
apolloClient,
178195
canUserCRUD,
179196
createTimeline,
180197
dispatch,
198+
ecsRowData,
181199
hasIndexWrite,
182200
onAlertStatusUpdateFailure,
183201
onAlertStatusUpdateSuccess,
@@ -186,20 +204,7 @@ export const getAlertActions = ({
186204
status,
187205
timelineId,
188206
updateTimelineIsLoading,
189-
}: {
190-
apolloClient?: ApolloClient<{}>;
191-
canUserCRUD: boolean;
192-
createTimeline: CreateTimeline;
193-
dispatch: Dispatch;
194-
hasIndexWrite: boolean;
195-
onAlertStatusUpdateFailure: (status: Status, error: Error) => void;
196-
onAlertStatusUpdateSuccess: (count: number, status: Status) => void;
197-
setEventsDeleted: ({ eventIds, isDeleted }: SetEventsDeletedProps) => void;
198-
setEventsLoading: ({ eventIds, isLoading }: SetEventsLoadingProps) => void;
199-
status: Status;
200-
timelineId: string;
201-
updateTimelineIsLoading: UpdateTimelineLoading;
202-
}): TimelineRowAction[] => {
207+
}: AlertActionArgs): TimelineRowAction[] => {
203208
const openAlertActionComponent: TimelineRowAction = {
204209
ariaLabel: 'Open alert',
205210
content: <EuiText size="m">{i18n.ACTION_OPEN_ALERT}</EuiText>,

x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
import React from 'react';
88
import { shallow } from 'enzyme';
99

10-
import { TestProviders } from '../../../common/mock/test_providers';
1110
import { TimelineId } from '../../../../common/types/timeline';
11+
import { TestProviders } from '../../../common/mock';
1212
import { AlertsTableComponent } from './index';
1313

1414
describe('AlertsTableComponent', () => {

x-pack/plugins/security_solution/public/alerts/components/alerts_table/index.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
displaySuccessToast,
4949
displayErrorToast,
5050
} from '../../../common/components/toasters';
51+
import { Ecs } from '../../../graphql/types';
5152
import { getInvestigateInResolverAction } from '../../../timelines/components/timeline/body/helpers';
5253

5354
interface OwnProps {
@@ -290,20 +291,21 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
290291

291292
// Send to Timeline / Update Alert Status Actions for each table row
292293
const additionalActions = useMemo(
293-
() =>
294+
() => (ecsRowData: Ecs) =>
294295
getAlertActions({
295296
apolloClient,
296297
canUserCRUD,
298+
createTimeline: createTimelineCallback,
299+
ecsRowData,
297300
dispatch,
298301
hasIndexWrite,
299-
createTimeline: createTimelineCallback,
300-
setEventsLoading: setEventsLoadingCallback,
302+
onAlertStatusUpdateFailure,
303+
onAlertStatusUpdateSuccess,
301304
setEventsDeleted: setEventsDeletedCallback,
305+
setEventsLoading: setEventsLoadingCallback,
302306
status: filterGroup,
303307
timelineId,
304308
updateTimelineIsLoading,
305-
onAlertStatusUpdateSuccess,
306-
onAlertStatusUpdateFailure,
307309
}),
308310
[
309311
apolloClient,
@@ -328,17 +330,19 @@ export const AlertsTableComponent: React.FC<AlertsTableComponentProps> = ({
328330
return [...defaultFilters, ...buildAlertStatusFilter(filterGroup)];
329331
}
330332
}, [defaultFilters, filterGroup]);
333+
const { filterManager } = useKibana().services.data.query;
331334
const { initializeTimeline, setTimelineRowActions } = useManageTimeline();
332335

333336
useEffect(() => {
334337
initializeTimeline({
335338
defaultModel: alertsDefaultModel,
336339
documentType: i18n.ALERTS_DOCUMENT_TYPE,
340+
filterManager,
337341
footerText: i18n.TOTAL_COUNT_OF_ALERTS,
338342
id: timelineId,
339343
loadingText: i18n.LOADING_ALERTS,
340344
selectAll: canUserCRUD ? selectAll : false,
341-
timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId })],
345+
timelineRowActions: () => [getInvestigateInResolverAction({ dispatch, timelineId })],
342346
title: i18n.ALERTS_TABLE_TITLE,
343347
});
344348
// eslint-disable-next-line react-hooks/exhaustive-deps

x-pack/plugins/security_solution/public/common/components/alerts_viewer/alerts_table.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { alertsDefaultModel } from './default_headers';
1414
import { useManageTimeline } from '../../../timelines/components/manage_timeline';
1515
import { getInvestigateInResolverAction } from '../../../timelines/components/timeline/body/helpers';
1616
import * as i18n from './translations';
17+
import { useKibana } from '../../lib/kibana';
1718

1819
export interface OwnProps {
1920
end: number;
@@ -69,15 +70,17 @@ const AlertsTableComponent: React.FC<Props> = ({
6970
}) => {
7071
const dispatch = useDispatch();
7172
const alertsFilter = useMemo(() => [...defaultAlertsFilters, ...pageFilters], [pageFilters]);
73+
const { filterManager } = useKibana().services.data.query;
7274
const { initializeTimeline } = useManageTimeline();
7375

7476
useEffect(() => {
7577
initializeTimeline({
7678
id: timelineId,
7779
documentType: i18n.ALERTS_DOCUMENT_TYPE,
80+
filterManager,
7881
defaultModel: alertsDefaultModel,
7982
footerText: i18n.TOTAL_COUNT_OF_ALERTS,
80-
timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId })],
83+
timelineRowActions: () => [getInvestigateInResolverAction({ dispatch, timelineId })],
8184
title: i18n.ALERTS_TABLE_TITLE,
8285
unit: i18n.UNIT,
8386
});

x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -93,23 +93,14 @@ const EventsViewerComponent: React.FC<Props> = ({
9393
}) => {
9494
const columnsHeader = isEmpty(columns) ? defaultHeaders : columns;
9595
const kibana = useKibana();
96-
const { filterManager } = useKibana().services.data.query;
9796
const [isQueryLoading, setIsQueryLoading] = useState(false);
9897

99-
const {
100-
getManageTimelineById,
101-
setIsTimelineLoading,
102-
setTimelineFilterManager,
103-
} = useManageTimeline();
98+
const { getManageTimelineById, setIsTimelineLoading } = useManageTimeline();
10499

105100
useEffect(() => {
106101
setIsTimelineLoading({ id, isLoading: isQueryLoading });
107102
// eslint-disable-next-line react-hooks/exhaustive-deps
108103
}, [isQueryLoading]);
109-
useEffect(() => {
110-
setTimelineFilterManager({ id, filterManager });
111-
// eslint-disable-next-line react-hooks/exhaustive-deps
112-
}, [filterManager]);
113104

114105
const { queryFields, title, unit } = useMemo(() => getManageTimelineById(id), [
115106
getManageTimelineById,

x-pack/plugins/security_solution/public/hosts/pages/navigation/events_query_tab_body.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ export const EventsQueryTabBody = ({
6565
initializeTimeline({
6666
id: TimelineId.hostsPageEvents,
6767
defaultModel: eventsDefaultModel,
68-
timelineRowActions: [
68+
timelineRowActions: () => [
6969
getInvestigateInResolverAction({ dispatch, timelineId: TimelineId.hostsPageEvents }),
7070
],
7171
});

x-pack/plugins/security_solution/public/timelines/components/manage_timeline/index.tsx

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,18 @@ import { SubsetTimelineModel } from '../../store/timeline/model';
1414
import * as i18n from '../../../common/components/events_viewer/translations';
1515
import * as i18nF from '../timeline/footer/translations';
1616
import { timelineDefaults as timelineDefaultModel } from '../../store/timeline/defaults';
17+
import { Ecs } from '../../../graphql/types';
1718

1819
interface ManageTimelineInit {
1920
documentType?: string;
2021
defaultModel?: SubsetTimelineModel;
22+
filterManager?: FilterManager;
2123
footerText?: string;
2224
id: string;
2325
indexToAdd?: string[] | null;
2426
loadingText?: string;
2527
selectAll?: boolean;
26-
timelineRowActions: TimelineRowAction[];
28+
timelineRowActions: (ecsData: Ecs) => TimelineRowAction[];
2729
title?: string;
2830
unit?: (totalCount: number) => string;
2931
}
@@ -39,7 +41,7 @@ interface ManageTimeline {
3941
loadingText: string;
4042
queryFields: string[];
4143
selectAll: boolean;
42-
timelineRowActions: TimelineRowAction[];
44+
timelineRowActions: (ecsData: Ecs) => TimelineRowAction[];
4345
title: string;
4446
unit: (totalCount: number) => string;
4547
}
@@ -67,12 +69,10 @@ type ActionManageTimeline =
6769
| {
6870
type: 'SET_TIMELINE_ACTIONS';
6971
id: string;
70-
payload: { queryFields?: string[]; timelineRowActions: TimelineRowAction[] };
71-
}
72-
| {
73-
type: 'SET_TIMELINE_FILTER_MANAGER';
74-
id: string;
75-
payload: { filterManager: FilterManager };
72+
payload: {
73+
queryFields?: string[];
74+
timelineRowActions: (ecsData: Ecs) => TimelineRowAction[];
75+
};
7676
};
7777

7878
export const getTimelineDefaults = (id: string) => ({
@@ -85,7 +85,7 @@ export const getTimelineDefaults = (id: string) => ({
8585
id,
8686
isLoading: false,
8787
queryFields: [],
88-
timelineRowActions: [],
88+
timelineRowActions: () => [],
8989
title: i18n.EVENTS,
9090
unit: (n: number) => i18n.UNIT(n),
9191
});
@@ -112,7 +112,6 @@ const reducerManageTimeline = (
112112
},
113113
} as ManageTimelineById;
114114
case 'SET_TIMELINE_ACTIONS':
115-
case 'SET_TIMELINE_FILTER_MANAGER':
116115
return {
117116
...state,
118117
[action.id]: {
@@ -143,9 +142,8 @@ interface UseTimelineManager {
143142
setTimelineRowActions: (actionsArgs: {
144143
id: string;
145144
queryFields?: string[];
146-
timelineRowActions: TimelineRowAction[];
145+
timelineRowActions: (ecsData: Ecs) => TimelineRowAction[];
147146
}) => void;
148-
setTimelineFilterManager: (filterArgs: { id: string; filterManager: FilterManager }) => void;
149147
}
150148

151149
const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseTimelineManager => {
@@ -169,7 +167,7 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT
169167
}: {
170168
id: string;
171169
queryFields?: string[];
172-
timelineRowActions: TimelineRowAction[];
170+
timelineRowActions: (ecsData: Ecs) => TimelineRowAction[];
173171
}) => {
174172
dispatch({
175173
type: 'SET_TIMELINE_ACTIONS',
@@ -180,17 +178,6 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT
180178
[]
181179
);
182180

183-
const setTimelineFilterManager = useCallback(
184-
({ id, filterManager }: { id: string; filterManager: FilterManager }) => {
185-
dispatch({
186-
type: 'SET_TIMELINE_FILTER_MANAGER',
187-
id,
188-
payload: { filterManager },
189-
});
190-
},
191-
[]
192-
);
193-
194181
const setIsTimelineLoading = useCallback(
195182
({ id, isLoading }: { id: string; isLoading: boolean }) => {
196183
dispatch({
@@ -219,7 +206,7 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT
219206
if (state[id] != null) {
220207
return state[id];
221208
}
222-
initializeTimeline({ id, timelineRowActions: [] });
209+
initializeTimeline({ id, timelineRowActions: () => [] });
223210
return getTimelineDefaults(id);
224211
},
225212
[initializeTimeline, state]
@@ -234,7 +221,6 @@ const useTimelineManager = (manageTimelineForTesting?: ManageTimelineById): UseT
234221
setIndexToAdd,
235222
setIsTimelineLoading,
236223
setTimelineRowActions,
237-
setTimelineFilterManager,
238224
};
239225
};
240226

@@ -246,7 +232,6 @@ const init = {
246232
initializeTimeline: () => noop,
247233
setIsTimelineLoading: () => noop,
248234
setTimelineRowActions: () => noop,
249-
setTimelineFilterManager: () => noop,
250235
};
251236

252237
const ManageTimelineContext = createContext<UseTimelineManager>(init);

x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/event_column_view.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,10 @@ export const EventColumnView = React.memo<Props>(
8989
updateNote,
9090
}) => {
9191
const { getManageTimelineById } = useManageTimeline();
92-
const timelineActions = useMemo(() => getManageTimelineById(timelineId).timelineRowActions, [
93-
getManageTimelineById,
94-
timelineId,
95-
]);
92+
const timelineActions = useMemo(
93+
() => getManageTimelineById(timelineId).timelineRowActions(ecsData),
94+
[ecsData, getManageTimelineById, timelineId]
95+
);
9696
const [isPopoverOpen, setPopover] = useState(false);
9797

9898
const onButtonClick = useCallback(() => {
@@ -105,6 +105,7 @@ export const EventColumnView = React.memo<Props>(
105105

106106
const button = (
107107
<EuiButtonIcon
108+
aria-label="context menu"
108109
data-test-subj="timeline-context-menu-button"
109110
size="s"
110111
iconType="boxesHorizontal"

x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,10 @@ export const Body = React.memo<BodyProps>(
103103
}) => {
104104
const containerElementRef = useRef<HTMLDivElement>(null);
105105
const { getManageTimelineById } = useManageTimeline();
106-
const timelineActions = useMemo(() => getManageTimelineById(id).timelineRowActions, [
107-
getManageTimelineById,
108-
id,
109-
]);
106+
const timelineActions = useMemo(
107+
() => (data.length > 0 ? getManageTimelineById(id).timelineRowActions(data[0].ecs) : []),
108+
[data, getManageTimelineById, id]
109+
);
110110

111111
const additionalActionWidth = useMemo(() => {
112112
let hasContextMenu = false;

x-pack/plugins/security_solution/public/timelines/components/timeline/timeline.tsx

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -172,26 +172,19 @@ export const TimelineComponent: React.FC<Props> = ({
172172
[sort.columnId, sort.sortDirection]
173173
);
174174
const [isQueryLoading, setIsQueryLoading] = useState(false);
175-
const {
176-
initializeTimeline,
177-
setIndexToAdd,
178-
setIsTimelineLoading,
179-
setTimelineFilterManager,
180-
} = useManageTimeline();
175+
const { initializeTimeline, setIndexToAdd, setIsTimelineLoading } = useManageTimeline();
181176
useEffect(() => {
182177
initializeTimeline({
178+
filterManager,
183179
id,
184180
indexToAdd,
185-
timelineRowActions: [getInvestigateInResolverAction({ dispatch, timelineId: id })],
181+
timelineRowActions: () => [getInvestigateInResolverAction({ dispatch, timelineId: id })],
186182
});
187183
// eslint-disable-next-line react-hooks/exhaustive-deps
188184
}, []);
189185
useEffect(() => {
190186
setIsTimelineLoading({ id, isLoading: isQueryLoading || loadingIndexName });
191187
}, [loadingIndexName, id, isQueryLoading, setIsTimelineLoading]);
192-
useEffect(() => {
193-
setTimelineFilterManager({ id, filterManager });
194-
}, [filterManager, id, setTimelineFilterManager]);
195188

196189
useEffect(() => {
197190
setIndexToAdd({ id, indexToAdd });

0 commit comments

Comments
 (0)