Skip to content

Commit a2771a3

Browse files
[Security Solution] Refactor Timeline Notes to use EuiCommentList (#85256) (#85716)
* [Security Solution] Refactor Timeline Notes to use EuiCommentList * notes * fix types * unit tests * selector * uncomment Pinned tab * note event details * cleanup * cleanup * transparent background * don't display elastic as an owner when note is created * review + bugs fixed found Co-authored-by: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Co-authored-by: Patryk Kopyciński <patryk.kopycinski@elastic.co>
1 parent 6e8ca9c commit a2771a3

File tree

71 files changed

+648
-1929
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+648
-1929
lines changed

x-pack/plugins/security_solution/public/cases/components/timeline_actions/add_to_case_action.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ const AddToCaseActionComponent: React.FC<AddToCaseActionProps> = ({ ecsRowData,
134134

135135
return (
136136
<>
137-
<ActionIconItem id="attachAlertToCase">
137+
<ActionIconItem>
138138
<EuiPopover
139139
id="attachAlertToCasePanel"
140140
button={button}

x-pack/plugins/security_solution/public/common/components/charts/barchart.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { getOr, get, isNumber } from 'lodash/fp';
1111
import deepmerge from 'deepmerge';
1212
import uuid from 'uuid';
1313
import styled from 'styled-components';
14+
import deepEqual from 'fast-deep-equal';
1415

1516
import { escapeDataProviderId } from '../drag_and_drop/helpers';
1617
import { useTimeZone } from '../../lib/kibana';
@@ -193,4 +194,11 @@ export const BarChartComponent: React.FC<BarChartComponentProps> = ({
193194
);
194195
};
195196

196-
export const BarChart = React.memo(BarChartComponent);
197+
export const BarChart = React.memo(
198+
BarChartComponent,
199+
(prevProps, nextProps) =>
200+
prevProps.stackByField === nextProps.stackByField &&
201+
prevProps.timelineId === nextProps.timelineId &&
202+
deepEqual(prevProps.configs, nextProps.configs) &&
203+
deepEqual(prevProps.barChart, nextProps.barChart)
204+
);

x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/json_view.test.tsx.snap

Lines changed: 14 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

x-pack/plugins/security_solution/public/common/components/event_details/event_fields_browser.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export const EventFieldsBrowser = React.memo<Props>(
9898
}
9999
const linkFieldData = (data ?? []).find((d) => d.field === linkField);
100100
const linkFieldValue = getOr(null, 'originalValue', linkFieldData);
101-
return linkFieldValue;
101+
return Array.isArray(linkFieldValue) ? linkFieldValue[0] : linkFieldValue;
102102
},
103103
[data, columnHeaders]
104104
);

x-pack/plugins/security_solution/public/common/components/event_details/json_view.tsx

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ interface Props {
1616
data: TimelineEventsDetailsItem[];
1717
}
1818

19-
const StyledEuiCodeEditor = styled(EuiCodeEditor)`
20-
flex: 1;
19+
const EuiCodeEditorContainer = styled.div`
20+
.euiCodeEditorWrapper {
21+
position: absolute;
22+
}
2123
`;
2224

2325
const EDITOR_SET_OPTIONS = { fontSize: '12px' };
@@ -34,19 +36,29 @@ export const JsonView = React.memo<Props>(({ data }) => {
3436
);
3537

3638
return (
37-
<StyledEuiCodeEditor
38-
data-test-subj="jsonView"
39-
isReadOnly
40-
mode="javascript"
41-
setOptions={EDITOR_SET_OPTIONS}
42-
value={value}
43-
width="100%"
44-
height="100%"
45-
/>
39+
<EuiCodeEditorContainer>
40+
<EuiCodeEditor
41+
data-test-subj="jsonView"
42+
isReadOnly
43+
mode="javascript"
44+
setOptions={EDITOR_SET_OPTIONS}
45+
value={value}
46+
width="100%"
47+
height="100%"
48+
/>
49+
</EuiCodeEditorContainer>
4650
);
4751
});
4852

4953
JsonView.displayName = 'JsonView';
5054

5155
export const buildJsonView = (data: TimelineEventsDetailsItem[]) =>
52-
data.reduce((accumulator, item) => set(item.field, item.originalValue, accumulator), {});
56+
data.reduce(
57+
(accumulator, item) =>
58+
set(
59+
item.field,
60+
Array.isArray(item.originalValue) ? item.originalValue.join() : item.originalValue,
61+
accumulator
62+
),
63+
{}
64+
);

x-pack/plugins/security_solution/public/common/components/event_details/summary_view.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -167,15 +167,12 @@ export const SummaryViewComponent: React.FC<{
167167
eventId: string;
168168
timelineId: string;
169169
}> = ({ data, eventId, timelineId, browserFields }) => {
170-
const ruleId = useMemo(
171-
() =>
172-
getOr(
173-
null,
174-
'originalValue',
175-
data.find((d) => d.field === 'signal.rule.id')
176-
),
177-
[data]
178-
);
170+
const ruleId = useMemo(() => {
171+
const item = data.find((d) => d.field === 'signal.rule.id');
172+
return Array.isArray(item?.originalValue)
173+
? item?.originalValue[0]
174+
: item?.originalValue ?? null;
175+
}, [data]);
179176
const { rule: maybeRule } = useRuleAsync(ruleId);
180177
const summaryList = useMemo(() => getSummary({ browserFields, data, eventId, timelineId }), [
181178
browserFields,

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const EventDetailsFlyoutComponent: React.FC<EventDetailsFlyoutProps> = ({
3939
const dispatch = useDispatch();
4040
const getTimeline = useMemo(() => timelineSelectors.getTimelineByIdSelector(), []);
4141
const expandedEvent = useDeepEqualSelector(
42-
(state) => (getTimeline(state, timelineId) ?? timelineDefaults).expandedEvent
42+
(state) => (getTimeline(state, timelineId) ?? timelineDefaults)?.expandedEvent ?? {}
4343
);
4444

4545
const handleClearSelection = useCallback(() => {
@@ -48,8 +48,8 @@ const EventDetailsFlyoutComponent: React.FC<EventDetailsFlyoutProps> = ({
4848

4949
const [loading, detailsData] = useTimelineEventsDetails({
5050
docValueFields,
51-
indexName: expandedEvent.indexName!,
52-
eventId: expandedEvent.eventId!,
51+
indexName: expandedEvent?.indexName ?? '',
52+
eventId: expandedEvent?.eventId ?? '',
5353
skip: !expandedEvent.eventId,
5454
});
5555

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
*/
66

77
import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui';
8-
import { isEmpty, some } from 'lodash/fp';
9-
import React, { useEffect, useMemo, useState } from 'react';
8+
import { isEmpty } from 'lodash/fp';
9+
import React, { useEffect, useMemo, useState, useRef } from 'react';
1010
import styled from 'styled-components';
1111
import deepEqual from 'fast-deep-equal';
1212
import { useDispatch } from 'react-redux';
@@ -180,6 +180,9 @@ const EventsViewerComponent: React.FC<Props> = ({
180180
[justTitle]
181181
);
182182

183+
const prevCombinedQueries = useRef<{
184+
filterQuery: string;
185+
} | null>(null);
183186
const combinedQueries = combineQueries({
184187
config: esQuery.getEsQueryConfig(kibana.services.uiSettings),
185188
dataProviders,
@@ -232,10 +235,11 @@ const EventsViewerComponent: React.FC<Props> = ({
232235
});
233236

234237
useEffect(() => {
235-
if (!events || (expandedEvent.eventId && !some(['_id', expandedEvent.eventId], events))) {
238+
if (!deepEqual(prevCombinedQueries.current, combinedQueries)) {
239+
prevCombinedQueries.current = combinedQueries;
236240
dispatch(timelineActions.toggleExpandedEvent({ timelineId: id }));
237241
}
238-
}, [dispatch, events, expandedEvent, id]);
242+
}, [combinedQueries, dispatch, id]);
239243

240244
const totalCountMinusDeleted = useMemo(
241245
() => (totalCount > 0 ? totalCount - deletedEventIds.length : 0),

x-pack/plugins/security_solution/public/common/components/links/index.tsx

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,20 @@ const ReputationLinkComponent: React.FC<{
327327
[ipReputationLinksSetting, domain, defaultNameMapping, allItemsLimit]
328328
);
329329

330+
const renderCallback = useCallback(
331+
(rowItem) =>
332+
isReputationLink(rowItem) && (
333+
<ExternalLink
334+
url={rowItem.url_template}
335+
overflowIndexStart={overflowIndexStart}
336+
allItemsLimit={allItemsLimit}
337+
>
338+
<>{rowItem.name ?? domain}</>
339+
</ExternalLink>
340+
),
341+
[allItemsLimit, domain, overflowIndexStart]
342+
);
343+
330344
return ipReputationLinks?.length > 0 ? (
331345
<section>
332346
<EuiFlexGroup
@@ -357,19 +371,7 @@ const ReputationLinkComponent: React.FC<{
357371
<DefaultFieldRendererOverflow
358372
rowItems={ipReputationLinks}
359373
idPrefix="moreReputationLink"
360-
render={(rowItem) => {
361-
return (
362-
isReputationLink(rowItem) && (
363-
<ExternalLink
364-
url={rowItem.url_template}
365-
overflowIndexStart={overflowIndexStart}
366-
allItemsLimit={allItemsLimit}
367-
>
368-
<>{rowItem.name ?? domain}</>
369-
</ExternalLink>
370-
)
371-
);
372-
}}
374+
render={renderCallback}
373375
moreMaxHeight={DEFAULT_MORE_MAX_HEIGHT}
374376
overflowIndexStart={overflowIndexStart}
375377
/>

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

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,17 @@ export interface Props extends Pick<GlobalTimeArgs, 'from' | 'to' | 'deleteQuery
5858
value?: string[] | string | null;
5959
}
6060

61-
const NO_FILTERS: Filter[] = [];
62-
const DEFAULT_QUERY: Query = { query: '', language: 'kuery' };
63-
6461
const TopNComponent: React.FC<Props> = ({
6562
combinedQueries,
6663
defaultView,
6764
deleteQuery,
68-
filters = NO_FILTERS,
65+
filters,
6966
field,
7067
from,
7168
indexPattern,
7269
indexNames,
7370
options,
74-
query = DEFAULT_QUERY,
71+
query,
7572
setAbsoluteRangeDatePickerTarget,
7673
setQuery,
7774
timelineId,
@@ -132,7 +129,6 @@ const TopNComponent: React.FC<Props> = ({
132129
filters={filters}
133130
from={from}
134131
headerChildren={headerChildren}
135-
indexPattern={indexPattern}
136132
onlyField={field}
137133
query={query}
138134
setAbsoluteRangeDatePickerTarget={setAbsoluteRangeDatePickerTarget}

0 commit comments

Comments
 (0)