Skip to content

Commit

Permalink
[Security Solution] Integrate Vanilla Unified Data Table in Timeline (#…
Browse files Browse the repository at this point in the history
…176064)

## Fixes below issues

- elastic/security-team#8726
- elastic/security-team#7234

## Details

### Objective

The objective of this PR is to implement basic unified data table
replacing the current timeline table. It is intended to behave exactly
like discover table. Below are the functionalities of the timeline table
that are out of scope of this PR and will be included in the follow up
PR.

|Before|After|
|---|---|
|<video
src="https://github.com/elastic/kibana/assets/7485038/fd8e4a42-06ed-4705-96cf-3ed0a22caa46"
/>|<video
src="https://github.com/elastic/kibana/assets/7485038/d248856f-dcc0-4d5b-a710-b1218a4898f5"
/>|

This feature can be enabled with below feature flag:

```yaml
xpack.securitySolution.enableExperimental:
  - unifiedComponentsInTimelineEnabled

```

### Out of scope functionalities
- Row Renderers - elastic/security-team#8728
- Notes / Pinned Events / Analyzer / Session View Link -
elastic/security-team#8727
- Drag / Drop from table --> data providers.
- Telemetry

### Desk Testing Guide

Below are some areas which have changes and would warrant some desk
testing.

One pre-requisite is to enable feature flag
`unifiedComponentsInTimelineEnabled` which will replace traditional
timeline table with the new unified timeline table.

1. **Pagination**
- If total number of events are > sample size ( default 500 ), table
footer on last page should display the notification so that user can
`Load More` on-demand.
- Page changes should be instant, because it is just client-side
pagination where we download multiple pages ( 500 events ) at once.
3. **Flyouts**
    - Event Detail ( Open / Close ) - should be new Expandable flyout
    - Host / User / IP details flyout ( Open / Close) 
4. Unified List
    - Add column by dragging & by clicking ⨁ control.
- Remove columns by clicking on column header & by clicking on ❌ control
3. Full screen mode
6. Last updated date
7. Columns Order
    - Change columns order from table controls
8. Sort Order
    - timestamp
    - Any number column
    - Any string column
9. Column Actions
    - Move Right/Left
    - Sort Asc/Desc
    - Copy Column and Column Name
    - Edit Data View Field with custom label
8. Table Control - Display Options
- <img width="517" alt="image"
src="https://github.com/elastic/kibana/assets/7485038/efd4514a-20f1-4461-8686-78366bc9a611">
    - Try different row heights and Sample sizes.


## Current Observations of Unified table vis-a-vis discover UI + Issues
- [ ] Discover has custom UI on toolbar visibility when compared to
vanilla unified data table
- [x] Full screen behaviour of unified data table
- [x] column width calculation is not automatic.
    - [x] Unsaved Timeline
    - [x] Saved Timeline 
- [x] Host/Network Flyout is not opening when timeline is not saved
    - [x] Flyout is not closing after it has been opened
- [ ] Row highlighting for building block -> Will be covered with
Actions Column
- [x] Additional Controls 
   - [x] Row Renderer Selection
   - [x] Last updated Date
   - [x] Full Screen 
 - [ ] Table controls tab order
- [ ] Refactor singleton ActiveTimeline class ( Inform @PhilippeOberti )
 - [ ] Total Count not visible

### Checklist

Delete any items that are not applicable to this PR.

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [ ] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

---------

Co-authored-by: Jatin Kathuria <jatin.kathuria@elastic.co>
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
3 people authored Apr 2, 2024
1 parent 61b80ca commit 883beee
Show file tree
Hide file tree
Showing 93 changed files with 5,239 additions and 518 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,45 +161,49 @@ describe('useDataGridColumnsCellActions', () => {
cellAction1.getByTestId(`dataGridColumnCellAction-${action1.id}`).click();

await waitFor(() => {
expect(action1.execute).toHaveBeenCalledWith(
expect.objectContaining({
data: [
{
value: fieldValues[field1.name][1],
field: {
name: field1.name,
type: field1.type,
aggregatable: true,
searchable: true,
},
expect(action1.execute).toHaveBeenCalledWith({
data: [
{
value: fieldValues[field1.name][1],
field: {
name: field1.name,
type: field1.type,
aggregatable: true,
searchable: true,
},
],
trigger: { id: useDataGridColumnsCellActionsProps.triggerId },
})
);
},
],
metadata: {
some: 'value',
},
nodeRef: expect.any(Object),
trigger: { id: useDataGridColumnsCellActionsProps.triggerId },
});
});

const cellAction2 = renderCellAction(result.current[1][1], { rowIndex: 2 });

cellAction2.getByTestId(`dataGridColumnCellAction-${action2.id}`).click();

await waitFor(() => {
expect(action2.execute).toHaveBeenCalledWith(
expect.objectContaining({
data: [
{
value: fieldValues[field2.name][2],
field: {
name: field2.name,
type: field2.type,
aggregatable: true,
searchable: true,
},
expect(action2.execute).toHaveBeenCalledWith({
data: [
{
value: fieldValues[field2.name][2],
field: {
name: field2.name,
type: field2.type,
aggregatable: true,
searchable: true,
},
],
trigger: { id: useDataGridColumnsCellActionsProps.triggerId },
})
);
},
],
metadata: {
some: 'value',
},
nodeRef: expect.any(Object),
trigger: { id: useDataGridColumnsCellActionsProps.triggerId },
});
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,14 @@
font-family: $euiCodeFontFamily;
}

.unifiedDataTable__cell--expanded {
background-color: $euiColorHighlight;
}

.unifiedDataTable__cell--selected {
background-color: $euiColorHighlight;
}

.unifiedDataTable__cellPopover {
// Fixes https://github.com/elastic/kibana/issues/145216 in Chrome
.lines-content.monaco-editor-background {
Expand Down
43 changes: 26 additions & 17 deletions packages/kbn-unified-data-table/src/components/data_table.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ function getProps(): UnifiedDataTableProps {
data: services.data,
theme: services.theme,
},
cellActionsMetadata: {
someKey: 'someValue',
},
};
}

Expand Down Expand Up @@ -254,13 +257,16 @@ describe('UnifiedDataTable', () => {
columns: ['message'],
onFieldEdited: jest.fn(),
});
expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith(
expect.objectContaining({
triggerId: undefined,
getCellValue: expect.any(Function),
fields: undefined,
})
);
expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith({
triggerId: undefined,
getCellValue: expect.any(Function),
fields: undefined,
dataGridRef: expect.any(Object),
metadata: {
dataViewId: 'the-data-view-id',
someKey: 'someValue',
},
});
});

it('should call useDataGridColumnsCellActions properly when cellActionsTriggerId defined', async () => {
Expand All @@ -270,16 +276,19 @@ describe('UnifiedDataTable', () => {
onFieldEdited: jest.fn(),
cellActionsTriggerId: 'test',
});
expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith(
expect.objectContaining({
triggerId: 'test',
getCellValue: expect.any(Function),
fields: [
dataViewMock.getFieldByName('@timestamp')?.toSpec(),
dataViewMock.getFieldByName('message')?.toSpec(),
],
})
);
expect(mockUseDataGridColumnsCellActions).toHaveBeenCalledWith({
triggerId: 'test',
getCellValue: expect.any(Function),
fields: [
dataViewMock.getFieldByName('@timestamp')?.toSpec(),
dataViewMock.getFieldByName('message')?.toSpec(),
],
dataGridRef: expect.any(Object),
metadata: {
dataViewId: 'the-data-view-id',
someKey: 'someValue',
},
});
});
});

Expand Down
17 changes: 14 additions & 3 deletions packages/kbn-unified-data-table/src/components/data_table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,12 @@ export interface UnifiedDataTableProps {
* Optional row line height override. Default is 1.6em.
*/
rowLineHeightOverride?: string;
/**
* Custom set of properties used by some actions.
* An action might require a specific set of metadata properties to render.
* This data is sent directly to actions.
*/
cellActionsMetadata?: Record<string, unknown>;
}

export const EuiDataGridMemoized = React.memo(EuiDataGrid);
Expand Down Expand Up @@ -430,11 +436,13 @@ export const UnifiedDataTable = ({
componentsTourSteps,
gridStyleOverride,
rowLineHeightOverride,
cellActionsMetadata,
customGridColumnsConfiguration,
customControlColumnsConfiguration,
}: UnifiedDataTableProps) => {
const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings, storage, data } =
services;

const { darkMode } = useObservable(services.theme?.theme$ ?? of(themeDefault), themeDefault);
const dataGridRef = useRef<EuiDataGridRefProps>(null);
const [selectedDocs, setSelectedDocs] = useState<string[]>([]);
Expand Down Expand Up @@ -671,14 +679,17 @@ export const UnifiedDataTable = ({
: undefined,
[cellActionsTriggerId, isPlainRecord, visibleColumns, dataView]
);
const cellActionsMetadata = useMemo(() => ({ dataViewId: dataView.id }), [dataView]);
const allCellActionsMetadata = useMemo(
() => ({ dataViewId: dataView.id, ...(cellActionsMetadata ?? {}) }),
[dataView, cellActionsMetadata]
);

const columnsCellActions = useDataGridColumnsCellActions({
fields: cellActionsFields,
getCellValue,
triggerId: cellActionsTriggerId,
dataGridRef,
metadata: cellActionsMetadata,
metadata: allCellActionsMetadata,
});

const {
Expand Down Expand Up @@ -730,6 +741,7 @@ export const UnifiedDataTable = ({
customGridColumnsConfiguration,
}),
[
showColumnTokens,
columnsMeta,
columnsCellActions,
customGridColumnsConfiguration,
Expand All @@ -743,7 +755,6 @@ export const UnifiedDataTable = ({
isSortEnabled,
onFilter,
settings,
showColumnTokens,
toastNotifications,
uiSettings,
valueToStringConverter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
useEuiTheme,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { euiDarkVars as themeDark, euiLightVars as themeLight } from '@kbn/ui-theme';
import { i18n } from '@kbn/i18n';
import { css } from '@emotion/react';
import type { DataTableRecord } from '@kbn/discover-utils/types';
Expand All @@ -40,9 +39,7 @@ export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle
useEffect(() => {
if (expanded && doc && expanded.id === doc.id) {
setCellProps({
style: {
backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight,
},
className: 'unifiedDataTable__cell--selected',
});
} else {
setCellProps({ style: undefined });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import React, { useContext, useEffect, useRef, useState } from 'react';
import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui';
import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-theme';
import { i18n } from '@kbn/i18n';
import { UnifiedDataTableContext } from '../table_context';
import { DataTableRowControl } from './data_table_row_control';
Expand All @@ -27,13 +26,11 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle
useEffect(() => {
if (current.isAnchor) {
setCellProps({
className: 'dscDocsGrid__cell--highlight',
className: 'unifiedDataTable__cell--highlight',
});
} else if (expanded && current && expanded.id === current.id) {
setCellProps({
style: {
backgroundColor: isDarkMode ? themeDark.euiColorHighlight : themeLight.euiColorHighlight,
},
className: 'unifiedDataTable__cell--expanded',
});
} else {
setCellProps({ style: undefined });
Expand Down
31 changes: 12 additions & 19 deletions packages/kbn-unified-data-table/src/utils/get_render_cell_value.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

import React, { useContext, useEffect } from 'react';
import { i18n } from '@kbn/i18n';
import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-theme';
import type { DataView, DataViewField } from '@kbn/data-views-plugin/public';
import {
EuiDataGridCellValueElementProps,
Expand Down Expand Up @@ -62,22 +61,16 @@ export const getRenderCellValueFn = ({
const ctx = useContext(UnifiedDataTableContext);

useEffect(() => {
if (!externalCustomRenderers) {
if (row?.isAnchor) {
setCellProps({
className: 'dscDocsGrid__cell--highlight',
});
} else if (ctx.expanded && row && ctx.expanded.id === row.id) {
setCellProps({
style: {
backgroundColor: ctx.isDarkMode
? themeDark.euiColorHighlight
: themeLight.euiColorHighlight,
},
});
} else {
setCellProps({ style: undefined });
}
if (row?.isAnchor) {
setCellProps({
className: 'unifiedDataTable__cell--highlight',
});
} else if (ctx.expanded && row && ctx.expanded.id === row.id) {
setCellProps({
className: 'unifiedDataTable__cell--expanded',
});
} else {
setCellProps({ style: undefined });
}
}, [ctx, row, setCellProps]);

Expand All @@ -87,7 +80,7 @@ export const getRenderCellValueFn = ({

if (!!externalCustomRenderers && !!externalCustomRenderers[columnId]) {
return (
<>
<span className={CELL_CLASS}>
{externalCustomRenderers[columnId]({
rowIndex,
columnId,
Expand All @@ -101,7 +94,7 @@ export const getRenderCellValueFn = ({
fieldFormats,
closePopover,
})}
</>
</span>
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ export const UnifiedFieldListSidebarComponent: React.FC<UnifiedFieldListSidebarP
'data-test-subj':
stateService.creationOptions.dataTestSubj?.fieldListAddFieldButtonTestSubj ??
'unifiedFieldListAddField',
className: 'unifiedFieldListSidebar__addBtn',
};
const buttonAddFieldLabel = i18n.translate(
'unifiedFieldList.fieldListSidebar.addFieldButtonLabel',
Expand Down
Loading

0 comments on commit 883beee

Please sign in to comment.