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

[Security Solution] Event Renderer Virtualization #193316

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
697974b
fix: virt. working with height issue
logeekal Sep 11, 2024
0321968
fix: working list virt - react-virtualized
logeekal Sep 16, 2024
f35f347
react-window virtualization
logeekal Sep 18, 2024
5ca5a77
incremental changes
logeekal Sep 19, 2024
c1a79ea
Great pert with auto height.
logeekal Sep 25, 2024
cb98169
fix: working great + better performance
logeekal Sep 27, 2024
84de4ee
fix: fast and working RC
logeekal Sep 27, 2024
962d7ad
correct deps
logeekal Sep 27, 2024
9a7efb2
eui_rc
logeekal Sep 30, 2024
f080311
Upgrade EUI to v97.0.0
cee-chen Oct 9, 2024
5495557
i18n updates
cee-chen Oct 9, 2024
6f99866
[EuiDataGrid] Handle breaking `renderCustomGridBody` change for Alert…
cee-chen Oct 9, 2024
22d78d6
[EuiDataGrid] Handle breaking `renderCustomGridBody` change for Secur…
cee-chen Oct 9, 2024
657a043
[EuiLink] Update snapshots to account for new SR text copy
cee-chen Oct 9, 2024
fbf95d4
[EuiLink] Update text assertions/selectors to account for new SR text…
cee-chen Oct 9, 2024
3bf6b59
[EuiLink] Update test regex utils to account for new SR text copy
cee-chen Oct 9, 2024
a03923d
[EuiLink] Update test icon assertion to account for the fact the icon…
cee-chen Oct 9, 2024
d049f3b
[EuiButtonDisplay] Update snapshots
cee-chen Oct 9, 2024
924f71f
Merge remote-tracking branch 'cee/eui/v97.0.0' into feat/custom_grid_…
logeekal Oct 10, 2024
f87fbea
fix: more optims
logeekal Oct 11, 2024
7e65a87
remove unnecessary logic
logeekal Oct 11, 2024
72cc0d6
fix: jest tests
logeekal Oct 14, 2024
a43664d
Merge branch 'main' into feat/custom_grid_body_list_virtualization
logeekal Oct 15, 2024
7399da6
chore: remove unnecessary console statements
logeekal Oct 15, 2024
5c089b0
ci: 😊
logeekal Oct 15, 2024
2eb53a0
Merge branch 'main' into feat/custom_grid_body_list_virtualization
logeekal Oct 16, 2024
12f6032
fix: cypress test
logeekal Oct 16, 2024
a64ccc4
fix: remove focused test
logeekal Oct 16, 2024
fd9e1ef
fix: types
logeekal Oct 16, 2024
fcdbaf0
Merge branch 'main' into feat/custom_grid_body_list_virtualization
logeekal Oct 16, 2024
86e5d00
Merge branch 'main' into feat/custom_grid_body_list_virtualization
logeekal Oct 16, 2024
ecd7653
Merge branch 'main' into feat/custom_grid_body_list_virtualization
logeekal Oct 16, 2024
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1632,7 +1632,7 @@
"@types/react-router-dom": "^5.3.3",
"@types/react-syntax-highlighter": "^15.4.0",
"@types/react-test-renderer": "^17.0.2",
"@types/react-virtualized": "^9.21.22",
"@types/react-virtualized": "^9.21.30",
"@types/react-window": "^1.8.8",
"@types/react-window-infinite-loader": "^1.0.9",
"@types/redux-actions": "^2.6.1",
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/security_solution/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -513,3 +513,8 @@ export const CASE_ATTACHMENT_ENDPOINT_TYPE_ID = 'endpoint' as const;
*/
export const MAX_MANUAL_RULE_RUN_LOOKBACK_WINDOW_DAYS = 90;
export const MAX_MANUAL_RULE_RUN_BULK_SIZE = 100;

/*
* Whether it is a Jest environment
*/
export const JEST_ENVIRONMENT = typeof jest !== 'undefined';
Original file line number Diff line number Diff line change
Expand Up @@ -40,69 +40,67 @@ import { useStatefulRowRenderer } from './use_stateful_row_renderer';
* which focuses the current or next row, respectively.
* - A screen-reader-only message provides additional context and instruction
*/
export const StatefulRowRenderer = ({
ariaRowindex,
containerRef,
event,
lastFocusedAriaColindex,
rowRenderers,
timelineId,
}: {
ariaRowindex: number;
containerRef: React.MutableRefObject<HTMLDivElement | null>;
event: TimelineItem;
lastFocusedAriaColindex: number;
rowRenderers: RowRenderer[];
timelineId: string;
}) => {
const { focusOwnership, onFocus, onKeyDown, onOutsideClick } = useStatefulEventFocus({
export const StatefulRowRenderer = React.memo(
({
ariaRowindex,
colindexAttribute: ARIA_COLINDEX_ATTRIBUTE,
containerRef,
event,
lastFocusedAriaColindex,
onColumnFocused: noop,
rowindexAttribute: ARIA_ROWINDEX_ATTRIBUTE,
});

const { rowRenderer } = useStatefulRowRenderer({
data: event.ecs,
rowRenderers,
});

const content = useMemo(
() =>
rowRenderer && (
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
<div className={getRowRendererClassName(ariaRowindex)} role="dialog" onFocus={onFocus}>
<EuiOutsideClickDetector onOutsideClick={onOutsideClick}>
<EuiFocusTrap clickOutsideDisables={true} disabled={focusOwnership !== 'owned'}>
<EuiScreenReaderOnly data-test-subj="eventRendererScreenReaderOnly">
<p>{i18n.YOU_ARE_IN_AN_EVENT_RENDERER(ariaRowindex)}</p>
</EuiScreenReaderOnly>
<EuiFlexGroup direction="column" onKeyDown={onKeyDown}>
<EuiFlexItem grow={true}>
{rowRenderer.renderRow({
data: event.ecs,
isDraggable: true,
scopeId: timelineId,
})}
</EuiFlexItem>
</EuiFlexGroup>
</EuiFocusTrap>
</EuiOutsideClickDetector>
</div>
),
[
timelineId,
}: {
ariaRowindex: number;
containerRef: React.MutableRefObject<HTMLDivElement | null>;
event: TimelineItem;
lastFocusedAriaColindex: number;
rowRenderers: RowRenderer[];
timelineId: string;
}) => {
const { focusOwnership, onFocus, onKeyDown, onOutsideClick } = useStatefulEventFocus({
ariaRowindex,
event.ecs,
focusOwnership,
onFocus,
onKeyDown,
onOutsideClick,
rowRenderer,
timelineId,
]
);
colindexAttribute: ARIA_COLINDEX_ATTRIBUTE,
containerRef,
lastFocusedAriaColindex,
onColumnFocused: noop,
rowindexAttribute: ARIA_ROWINDEX_ATTRIBUTE,
});

const { rowRenderer } = useStatefulRowRenderer({
data: event.ecs,
rowRenderers,
});

const row = useMemo(() => {
const result = rowRenderer?.renderRow({
data: event.ecs,
isDraggable: false,
scopeId: timelineId,
});
return result;
}, [rowRenderer, event.ecs, timelineId]);

const content = useMemo(
() =>
rowRenderer && (
// eslint-disable-next-line jsx-a11y/no-noninteractive-element-interactions
<div className={getRowRendererClassName(ariaRowindex)} role="dialog" onFocus={onFocus}>
<EuiOutsideClickDetector onOutsideClick={onOutsideClick}>
<EuiFocusTrap clickOutsideDisables={true} disabled={focusOwnership !== 'owned'}>
<EuiScreenReaderOnly data-test-subj="eventRendererScreenReaderOnly">
<p>{i18n.YOU_ARE_IN_AN_EVENT_RENDERER(ariaRowindex)}</p>
</EuiScreenReaderOnly>
<EuiFlexGroup direction="column" onKeyDown={onKeyDown}>
<EuiFlexItem grow={true}>{row}</EuiFlexItem>
</EuiFlexGroup>
</EuiFocusTrap>
</EuiOutsideClickDetector>
</div>
),
[ariaRowindex, focusOwnership, onFocus, onKeyDown, onOutsideClick, rowRenderer, row]
);

return content;
}
);

return content;
};
StatefulRowRenderer.displayName = 'StatefulRowRenderer';
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface UseStatefulRowRendererArgs {

export function useStatefulRowRenderer(args: UseStatefulRowRendererArgs) {
const { data, rowRenderers } = args;

const rowRenderer = useMemo(() => getRowRenderer({ data, rowRenderers }), [data, rowRenderers]);

const result = useMemo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
* 2.0.
*/

import React, { useMemo } from 'react';
import React, { useMemo, useEffect } from 'react';
import type { EuiDataGridCellValueElementProps } from '@elastic/eui';
import type { SortColumnTable } from '@kbn/securitysolution-data-table';
import type { TimelineItem } from '@kbn/timelines-plugin/common';
import { JEST_ENVIRONMENT } from '../../../../../../common/constants';
import { useLicense } from '../../../../../common/hooks/use_license';
import { SourcererScopeName } from '../../../../../sourcerer/store/model';
import { useSourcererDataView } from '../../../../../sourcerer/containers';
Expand All @@ -21,6 +22,7 @@ import { TimelineControlColumnCellRender } from '../../unified_components/data_t
import type { ColumnHeaderOptions } from '../../../../../../common/types';
import { useTimelineColumns } from './use_timeline_columns';
import type { UnifiedTimelineDataGridCellContext } from '../../types';
import { useTimelineUnifiedDataTableContext } from '../../unified_components/data_table/use_timeline_unified_data_table_context';

interface UseTimelineControlColumnArgs {
columns: ColumnHeaderOptions[];
Expand Down Expand Up @@ -59,6 +61,58 @@ export const useTimelineControlColumn = ({
const ACTION_BUTTON_COUNT = isEnterprisePlus ? 6 : 5;
const { localColumns } = useTimelineColumns(columns);

const RowCellRender = useMemo(
() =>
function TimelineControlColumnCellRenderer(
props: EuiDataGridCellValueElementProps & UnifiedTimelineDataGridCellContext
) {
const ctx = useTimelineUnifiedDataTableContext();

useEffect(() => {
props.setCellProps({
className:
ctx.expanded?.id === events[props.rowIndex]?._id
? 'unifiedDataTable__cell--expanded'
: '',
});
});

/*
* In some cases, when number of events is updated
* but new table is not yet rendered it can result
* in the mismatch between the number of events v/s
* the number of rows in the table currently rendered.
*
* */
if ('rowIndex' in props && props.rowIndex >= events.length) return <></>;
return (
<TimelineControlColumnCellRender
rowIndex={props.rowIndex}
columnId={props.columnId}
timelineId={timelineId}
ariaRowindex={props.rowIndex}
checked={false}
columnValues=""
data={events[props.rowIndex].data}
ecsData={events[props.rowIndex].ecs}
loadingEventIds={EMPTY_STRING_ARRAY}
eventId={events[props.rowIndex]?._id}
index={props.rowIndex}
onEventDetailsPanelOpened={noOp}
onRowSelected={noOp}
refetch={refetch}
showCheckboxes={false}
setEventsLoading={noOp}
setEventsDeleted={noOp}
pinnedEventIds={pinnedEventIds}
eventIdToNoteIds={eventIdToNoteIds}
toggleShowNotes={onToggleShowNotes}
/>
);
},
[events, timelineId, refetch, pinnedEventIds, eventIdToNoteIds, onToggleShowNotes]
);

// We need one less when the unified components are enabled because the document expand is provided by the unified data table
const UNIFIED_COMPONENTS_ACTION_BUTTON_COUNT = ACTION_BUTTON_COUNT - 1;
return useMemo(() => {
Expand All @@ -84,49 +138,7 @@ export const useTimelineControlColumn = ({
/>
);
},
rowCellRender: (
props: EuiDataGridCellValueElementProps & UnifiedTimelineDataGridCellContext
) => {
/*
* In some cases, when number of events is updated
* but new table is not yet rendered it can result
* in the mismatch between the number of events v/s
* the number of rows in the table currently rendered.
*
* */
if ('rowIndex' in props && props.rowIndex >= events.length) return <></>;
props.setCellProps({
className:
props.expandedEventId === events[props.rowIndex]?._id
? 'unifiedDataTable__cell--expanded'
: '',
});

return (
<TimelineControlColumnCellRender
rowIndex={props.rowIndex}
columnId={props.columnId}
timelineId={timelineId}
ariaRowindex={props.rowIndex}
checked={false}
columnValues=""
data={events[props.rowIndex].data}
ecsData={events[props.rowIndex].ecs}
loadingEventIds={EMPTY_STRING_ARRAY}
eventId={events[props.rowIndex]?._id}
index={props.rowIndex}
onEventDetailsPanelOpened={noOp}
onRowSelected={noOp}
refetch={refetch}
showCheckboxes={false}
setEventsLoading={noOp}
setEventsDeleted={noOp}
pinnedEventIds={pinnedEventIds}
eventIdToNoteIds={eventIdToNoteIds}
toggleShowNotes={onToggleShowNotes}
/>
);
},
rowCellRender: JEST_ENVIRONMENT ? RowCellRender : React.memo(RowCellRender),
logeekal marked this conversation as resolved.
Show resolved Hide resolved
}));
} else {
return getDefaultControlColumn(ACTION_BUTTON_COUNT).map((x) => ({
Expand All @@ -142,11 +154,7 @@ export const useTimelineControlColumn = ({
sort,
activeTab,
timelineId,
refetch,
events,
pinnedEventIds,
eventIdToNoteIds,
onToggleShowNotes,
ACTION_BUTTON_COUNT,
RowCellRender,
]);
};
Loading