Skip to content

[RAC][Alert Triage][TGrid] Update the Alerts Table (TGrid) API to implement a subset of the EuiDataGridColumn API#98241

Merged
andrew-goldstein merged 6 commits intoelastic:masterfrom
andrew-goldstein:columns-api
Apr 28, 2021
Merged

[RAC][Alert Triage][TGrid] Update the Alerts Table (TGrid) API to implement a subset of the EuiDataGridColumn API#98241
andrew-goldstein merged 6 commits intoelastic:masterfrom
andrew-goldstein:columns-api

Conversation

@andrew-goldstein
Copy link
Contributor

[RAC][Alert Triage][TGrid] Update the Alerts Table (TGrid) API to implement a subset of the EuiDataGridColumn API

This PR implements the following subset of the EuiDataGridColumn API from EuiDataGrid in the TGrid (Timeline grid):

Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'>

The above properties are documented in EuiDataGrid's data_grid_types.ts, and summarized in the table below:

Property Description
display?: ReactNode A ReactNode used when rendering the column header
displayAsText?: string Displays the column name as text (in lieu of using display). If not used, id will be shown as the column name.
id: string The unique identifier for this column, e.g. user.name
initialWidth?: number Initial width (in pixels) of the column

The following screenshot shows the TGrid rendering (from left-to-right):

  • An (example) RAC-flavored Observability alerts table
  • An (example) RAC-flavored Security Solution alerts table
  • The production alerts table in the Security Solutions Detections page, which remains the default

three_table_configurations

Above, three table configurations, rendered via the updated API

The public/detections/configurations directory contains the configurations for the three tables shown in the screenshot above

This change works in concert with another recent change to the TGrid that added support for the renderCellValue API.

Example configurations

(example) RAC-flavored Observability alerts table

observability_alerts_example

The column specification for the (example) RAC-flavored Observability alerts table, shown in the screenshot above is defined in x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts:

export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.STATUS,
    id: 'kibana.rac.alert.status',
    initialWidth: 74,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.TRIGGERED,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERT_DURATION,
    id: 'kibana.rac.alert.duration.us',
    initialWidth: 116,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    id: 'signal.rule.severity',
    initialWidth: 102,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    id: 'signal.reason',
    initialWidth: 644,
  },
];

The example implementation of EuiDataGrid's renderCellValue API used to render the RAC-flavored Observability alerts table shown in the screenshot above is located in x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx:

/**
 * This implementation of `EuiDataGrid`'s `renderCellValue`
 * accepts `EuiDataGridCellValueElementProps`, plus `data`
 * from the TGrid
 */
export const renderCellValue: React.FC<
  EuiDataGridCellValueElementProps & CellValueElementProps
> = ({
  columnId,
  data,
  eventId,
  header,
  isDetails,
  isExpandable,
  isExpanded,
  linkValues,
  rowIndex,
  setCellProps,
  timelineId,
}) => {
  const value =
    getMappedNonEcsValue({
      data,
      fieldName: columnId,
    })?.reduce((x) => x[0]) ?? '';

  switch (columnId) {
    case 'kibana.rac.alert.status':
      return <Status status={random(0, 1) ? 'recovered' : 'active'} />;
    case 'kibana.rac.alert.duration.us':
      return <span>{moment(value).fromNow(true)}</span>;
    case 'signal.rule.severity':
      return <Severity severity={value} />;
    case 'signal.reason':
      return (
        <EuiLink>
          <TruncatableText>{reason}</TruncatableText>
        </EuiLink>
      );
    default:
      // NOTE: we're using `DefaultCellRenderer` in this example configuration as a fallback, but
      // using `DefaultCellRenderer` here is entirely optional
      return (
        <DefaultCellRenderer
          columnId={columnId}
          data={data}
          eventId={eventId}
          header={header}
          isDetails={isDetails}
          isExpandable={isExpandable}
          isExpanded={isExpanded}
          linkValues={linkValues}
          rowIndex={rowIndex}
          setCellProps={setCellProps}
          timelineId={timelineId}
        />
      );
  }
};

(example) RAC-flavored Security Solution alerts table

secuirty_solution_rac_example

The column specification for the (example) RAC-flavored Security Solution alerts table, shown in the screenshot above is defined in x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts:

/**
 * columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
 * plus additional TGrid column properties
 */
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.name',
    displayAsText: i18n.ALERTS_HEADERS_RULE_NAME,
    linkField: 'signal.rule.id',
    initialWidth: 212,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.severity',
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    initialWidth: 104,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.reason',
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    initialWidth: 644,
  },
];

Testing the example configurations locally

For now, the alerts table in the Security Solution's Detections page is configured to use the existing (7.13) column configuration.

To test the Alerts table in the Security Solution Detections page with the example configurations provided in this PR:

  1. Edit x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx and change the following line:
import { columns, RenderCellValue } from '../../configurations/security_solution_detections';

from the above to

import { columns, RenderCellValue } from '../../configurations/examples/observablity_alerts';

for the (example) RAC-flavored Observability alerts table, or change it to

import { columns, RenderCellValue } from '../../configurations/examples/security_solution_rac';

for the (example) RAC-flavored Security solution alerts table.

  1. Navigate to your local instance of the Security Solution Detections page (Note: you may need to enable detection rules to populate the alerts table.)

  2. Click the customize_columns button shown in the screenshot below:

customize_columns

  1. In the Customize Columns popover, click the Reset Fields button, shown in the screenshot below:

reset-fields

After clicking Reset Fields, the new default columns will be displayed.

Backwards compatibility

The width property of Timeline's model was changed to initialWidth as part of this PR.

  • This change has no effect on Timelines persisted as saved objects
  • This change has no effect on Timeline's Export and Import Timelines feature
  • When a TGrid's column configuration containing the legacy width and label ColumnHeaderOptions is read from localstorage, these properties are migrated to initialWidth and displayAsText respectively.
    • Backwards compatibility was desk tested by persisting a custom column configuration while running off master, and then re-visiting the page after running this PR branch. As expected, the previously persisted column configuration was rendered correctly after running the PR branch.
    • Unit tests were added to x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts to test the migration of the width and label properties

Other changes

  • The minium width of a resized column is now 70px. The new minium is no longer data-type specific.

…implement a subset of the `EuiDataGridColumn` API

This PR implements the following subset of the `EuiDataGridColumn` API from [EuiDataGrid](https://elastic.github.io/eui/#/tabular-content/data-grid) in the `TGrid` (Timeline grid):

```ts
Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'>
```

The above properties are [documented in EuiDataGrid's data_grid_types.ts](https://github.com/elastic/eui/blob/master/src/components/datagrid/data_grid_types.ts), and summarized in the table below:

| Property                   | Description                                                                                                                                                                                                                        |
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `display?:  ReactNode`    | A `ReactNode` used when rendering the column header                                                                                                                                                                                |
| `displayAsText?:  string` | Displays the column name as text (in lieu of using `display`). If not used, `id` will be shown as the column name. |
| `id:  string`             | The unique identifier for this column, e.g. `user.name`                                                                                                                                                                            |
| `initialWidth?:  number`   | Initial width (in pixels) of the column                                                                                                                                                                                            |

The following screenshot shows the `TGrid` rendering (from left-to-right):

- An (example) RAC-flavored Observability alerts table
- An (example) RAC-flavored Security Solution alerts table
- The production alerts table in the Security Solutions `Detections` page, which remains the default

![three_table_configurations](https://user-images.githubusercontent.com/4459398/115944491-5a69a780-a473-11eb-85b6-36120c3092d6.png)

_Above, three table configurations, rendered via the updated API_

The `public/detections/configurations` directory contains the configurations for the three tables shown in the screenshot above

This change works in concert with another recent change to the `TGrid` that [added support for the `renderCellValue` API](elastic#96098).

### Example configurations

#### (example) RAC-flavored Observability alerts table

![observability_alerts_example](https://user-images.githubusercontent.com/4459398/115944556-b3d1d680-a473-11eb-8338-6097731f2d48.png)

The column specification for the (example) RAC-flavored Observability alerts table, shown in the screenshot above is defined in `x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts`:

```ts
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.STATUS,
    id: 'kibana.rac.alert.status',
    initialWidth: 74,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.TRIGGERED,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERT_DURATION,
    id: 'kibana.rac.alert.duration.us',
    initialWidth: 116,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    id: 'signal.rule.severity',
    initialWidth: 102,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    id: 'signal.reason',
    initialWidth: 644,
  },
];
```

The example implementation of `EuiDataGrid`'s [`renderCellValue` API](elastic#96098) used to render the RAC-flavored Observability alerts table shown in the screenshot above is located in `x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx`:

```ts
/**
 * This implementation of `EuiDataGrid`'s `renderCellValue`
 * accepts `EuiDataGridCellValueElementProps`, plus `data`
 * from the TGrid
 */
export const renderCellValue: React.FC<
  EuiDataGridCellValueElementProps & CellValueElementProps
> = ({
  columnId,
  data,
  eventId,
  header,
  isDetails,
  isExpandable,
  isExpanded,
  linkValues,
  rowIndex,
  setCellProps,
  timelineId,
}) => {
  const value =
    getMappedNonEcsValue({
      data,
      fieldName: columnId,
    })?.reduce((x) => x[0]) ?? '';

  switch (columnId) {
    case 'kibana.rac.alert.status':
      return <Status status={random(0, 1) ? 'recovered' : 'active'} />;
    case 'kibana.rac.alert.duration.us':
      return <span>{moment(value).fromNow(true)}</span>;
    case 'signal.rule.severity':
      return <Severity severity={value} />;
    case 'signal.reason':
      return (
        <EuiLink>
          <TruncatableText>{reason}</TruncatableText>
        </EuiLink>
      );
    default:
      // NOTE: we're using `DefaultCellRenderer` in this example configuration as a fallback, but
      // using `DefaultCellRenderer` here is entirely optional
      return (
        <DefaultCellRenderer
          columnId={columnId}
          data={data}
          eventId={eventId}
          header={header}
          isDetails={isDetails}
          isExpandable={isExpandable}
          isExpanded={isExpanded}
          linkValues={linkValues}
          rowIndex={rowIndex}
          setCellProps={setCellProps}
          timelineId={timelineId}
        />
      );
  }
};
```

#### (example) RAC-flavored Security Solution alerts table

![secuirty_solution_rac_example](https://user-images.githubusercontent.com/4459398/115944592-e8459280-a473-11eb-9e0f-cef8519102d4.png)

The column specification for the (example) RAC-flavored Security Solution alerts table, shown in the screenshot above is defined in `x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts`:

```ts
/**
 * columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
 * plus additional TGrid column properties
 */
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.name',
    displayAsText: i18n.ALERTS_HEADERS_RULE_NAME,
    linkField: 'signal.rule.id',
    initialWidth: 212,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.severity',
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    initialWidth: 104,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.reason',
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    initialWidth: 644,
  },
];
```

### Testing the example configurations locally

For now, the alerts table in the Security Solution's `Detections` page is configured to use the existing (`7.13`) column configuration.

To test the Alerts table in the Security Solution `Detections` page with the example configurations provided in this PR:

1. Edit `x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx` and change the following line:

```ts
import { columns, RenderCellValue } from '../../configurations/security_solution_detections';
```

from the above to

```ts
import { columns, RenderCellValue } from '../../configurations/examples/observablity_alerts';
```

for the (example) RAC-flavored Observability alerts table, or change it to

```ts
import { columns, RenderCellValue } from '../../configurations/examples/security_solution_rac';
```

for the (example) RAC-flavored Security solution alerts table.

2. Navigate to your local instance of the Security Solution [Detections page](http://localhost:5601/xyx/app/security/detections) (Note: you may need to enable detection rules to populate the alerts table.)

3. Click the `customize_columns` button shown in the screenshot below:

![customize_columns](https://user-images.githubusercontent.com/4459398/115796322-e3f37980-a38e-11eb-930b-5b21dfcb5e65.png)

4. In the `Customize Columns` popover, click the `Reset Fields` button, shown in the screenshot below:

![reset-fields](https://user-images.githubusercontent.com/4459398/115797081-49943580-a390-11eb-9485-7e6cae2f2a6f.png)

After clicking `Reset Fields`, the new default columns will be displayed.

### Backwards compatibility

The `width` property of Timeline's model was changed to `initialWidth` as part of this PR.

- This change has no effect on Timelines persisted as saved objects
- This change has no effect on Timeline's [Export and Import Timelines](https://www.elastic.co/guide/en/security/current/timelines-ui.html#import-export-timelines) feature
- When a TGrid's column configuration containing the legacy `width` and `label` `ColumnHeaderOptions` is read from `localstorage`, these properties are migrated to `initialWidth` and `displayAsText` respectively.
  - Backwards compatibility was desk tested by persisting a custom column configuration while running off `master`, and then re-visiting the page after running this PR branch. As expected, the previously persisted column configuration was rendered correctly after running the PR branch.
  - Unit tests were added to `x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts` to test the migration of the `width` and `label` properties

### Other changes

- The minium width of a resized column is now `70px`. The new minium is no longer data-type specific.
@andrew-goldstein andrew-goldstein added v8.0.0 release_note:skip Skip the PR/issue when compiling release notes Team:Threat Hunting Security Solution Threat Hunting Team Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Feature:Timeline Security Solution Timeline feature Feature:Detection Alerts Security Solution Detection Alerts Feature v7.14.0 Theme: rac label obsolete Feature:RAC label obsolete labels Apr 24, 2021
@andrew-goldstein andrew-goldstein requested a review from a team as a code owner April 24, 2021 03:57
@andrew-goldstein andrew-goldstein self-assigned this Apr 24, 2021
@elasticmachine
Copy link
Contributor

Pinging @elastic/security-solution (Team: SecuritySolution)

@elasticmachine
Copy link
Contributor

Pinging @elastic/security-threat-hunting (Team:Threat Hunting)

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
securitySolution 2172 2175 +3

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
securitySolution 7.0MB 7.0MB +5.9KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

cc @andrew-goldstein

Copy link
Contributor

@kqualters-elastic kqualters-elastic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested both the new examples and the existing functionality locally, no visible regressions or bugs. everything lgtm 👍

@andrew-goldstein andrew-goldstein merged commit 78ae331 into elastic:master Apr 28, 2021
@andrew-goldstein andrew-goldstein deleted the columns-api branch April 28, 2021 18:26
andrew-goldstein added a commit to andrew-goldstein/kibana that referenced this pull request Apr 28, 2021
…lement a subset of the `EuiDataGridColumn` API (elastic#98241)

## [RAC][Alert Triage][TGrid] Update the Alerts Table (TGrid) API to implement a subset of the `EuiDataGridColumn` API

This PR implements the following subset of the `EuiDataGridColumn` API from [EuiDataGrid](https://elastic.github.io/eui/#/tabular-content/data-grid) in the `TGrid` (Timeline grid):

```ts
Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'>
```

The above properties are [documented in EuiDataGrid's data_grid_types.ts](https://github.com/elastic/eui/blob/master/src/components/datagrid/data_grid_types.ts), and summarized in the table below:

| Property                   | Description                                                                                                                                                                                                                        |
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `display?:  ReactNode`    | A `ReactNode` used when rendering the column header                                                                                                                                                                                |
| `displayAsText?:  string` | Displays the column name as text (in lieu of using `display`). If not used, `id` will be shown as the column name. |
| `id:  string`             | The unique identifier for this column, e.g. `user.name`                                                                                                                                                                            |
| `initialWidth?:  number`   | Initial width (in pixels) of the column                                                                                                                                                                                            |

The following screenshot shows the `TGrid` rendering (from left-to-right):

- An (example) RAC-flavored Observability alerts table
- An (example) RAC-flavored Security Solution alerts table
- The production alerts table in the Security Solutions `Detections` page, which remains the default

![three_table_configurations](https://user-images.githubusercontent.com/4459398/115944491-5a69a780-a473-11eb-85b6-36120c3092d6.png)

_Above, three table configurations, rendered via the updated API_

The `public/detections/configurations` directory contains the configurations for the three tables shown in the screenshot above

This change works in concert with another recent change to the `TGrid` that [added support for the `renderCellValue` API](elastic#96098).

### Example configurations

#### (example) RAC-flavored Observability alerts table

![observability_alerts_example](https://user-images.githubusercontent.com/4459398/115944556-b3d1d680-a473-11eb-8338-6097731f2d48.png)

The column specification for the (example) RAC-flavored Observability alerts table, shown in the screenshot above is defined in `x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts`:

```ts
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.STATUS,
    id: 'kibana.rac.alert.status',
    initialWidth: 74,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.TRIGGERED,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERT_DURATION,
    id: 'kibana.rac.alert.duration.us',
    initialWidth: 116,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    id: 'signal.rule.severity',
    initialWidth: 102,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    id: 'signal.reason',
    initialWidth: 644,
  },
];
```

The example implementation of `EuiDataGrid`'s [`renderCellValue` API](elastic#96098) used to render the RAC-flavored Observability alerts table shown in the screenshot above is located in `x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx`:

```ts
/**
 * This implementation of `EuiDataGrid`'s `renderCellValue`
 * accepts `EuiDataGridCellValueElementProps`, plus `data`
 * from the TGrid
 */
export const renderCellValue: React.FC<
  EuiDataGridCellValueElementProps & CellValueElementProps
> = ({
  columnId,
  data,
  eventId,
  header,
  isDetails,
  isExpandable,
  isExpanded,
  linkValues,
  rowIndex,
  setCellProps,
  timelineId,
}) => {
  const value =
    getMappedNonEcsValue({
      data,
      fieldName: columnId,
    })?.reduce((x) => x[0]) ?? '';

  switch (columnId) {
    case 'kibana.rac.alert.status':
      return <Status status={random(0, 1) ? 'recovered' : 'active'} />;
    case 'kibana.rac.alert.duration.us':
      return <span>{moment(value).fromNow(true)}</span>;
    case 'signal.rule.severity':
      return <Severity severity={value} />;
    case 'signal.reason':
      return (
        <EuiLink>
          <TruncatableText>{reason}</TruncatableText>
        </EuiLink>
      );
    default:
      // NOTE: we're using `DefaultCellRenderer` in this example configuration as a fallback, but
      // using `DefaultCellRenderer` here is entirely optional
      return (
        <DefaultCellRenderer
          columnId={columnId}
          data={data}
          eventId={eventId}
          header={header}
          isDetails={isDetails}
          isExpandable={isExpandable}
          isExpanded={isExpanded}
          linkValues={linkValues}
          rowIndex={rowIndex}
          setCellProps={setCellProps}
          timelineId={timelineId}
        />
      );
  }
};
```

#### (example) RAC-flavored Security Solution alerts table

![secuirty_solution_rac_example](https://user-images.githubusercontent.com/4459398/115944592-e8459280-a473-11eb-9e0f-cef8519102d4.png)

The column specification for the (example) RAC-flavored Security Solution alerts table, shown in the screenshot above is defined in `x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts`:

```ts
/**
 * columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
 * plus additional TGrid column properties
 */
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.name',
    displayAsText: i18n.ALERTS_HEADERS_RULE_NAME,
    linkField: 'signal.rule.id',
    initialWidth: 212,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.severity',
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    initialWidth: 104,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.reason',
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    initialWidth: 644,
  },
];
```

### Testing the example configurations locally

For now, the alerts table in the Security Solution's `Detections` page is configured to use the existing (`7.13`) column configuration.

To test the Alerts table in the Security Solution `Detections` page with the example configurations provided in this PR:

1. Edit `x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx` and change the following line:

```ts
import { columns, RenderCellValue } from '../../configurations/security_solution_detections';
```

from the above to

```ts
import { columns, RenderCellValue } from '../../configurations/examples/observablity_alerts';
```

for the (example) RAC-flavored Observability alerts table, or change it to

```ts
import { columns, RenderCellValue } from '../../configurations/examples/security_solution_rac';
```

for the (example) RAC-flavored Security solution alerts table.

2. Navigate to your local instance of the Security Solution [Detections page](http://localhost:5601/xyx/app/security/detections) (Note: you may need to enable detection rules to populate the alerts table.)

3. Click the `customize_columns` button shown in the screenshot below:

![customize_columns](https://user-images.githubusercontent.com/4459398/115796322-e3f37980-a38e-11eb-930b-5b21dfcb5e65.png)

4. In the `Customize Columns` popover, click the `Reset Fields` button, shown in the screenshot below:

![reset-fields](https://user-images.githubusercontent.com/4459398/115797081-49943580-a390-11eb-9485-7e6cae2f2a6f.png)

After clicking `Reset Fields`, the new default columns will be displayed.

### Backwards compatibility

The `width` property of Timeline's model was changed to `initialWidth` as part of this PR.

- This change has no effect on Timelines persisted as saved objects
- This change has no effect on Timeline's [Export and Import Timelines](https://www.elastic.co/guide/en/security/current/timelines-ui.html#import-export-timelines) feature
- When a TGrid's column configuration containing the legacy `width` and `label` `ColumnHeaderOptions` is read from `localstorage`, these properties are migrated to `initialWidth` and `displayAsText` respectively.
  - Backwards compatibility was desk tested by persisting a custom column configuration while running off `master`, and then re-visiting the page after running this PR branch. As expected, the previously persisted column configuration was rendered correctly after running the PR branch.
  - Unit tests were added to `x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts` to test the migration of the `width` and `label` properties

### Other changes

- The minium width of a resized column is now `70px`. The new minium is no longer data-type specific.
andrew-goldstein added a commit that referenced this pull request Apr 28, 2021
…lement a subset of the `EuiDataGridColumn` API (#98241) (#98665)

## [RAC][Alert Triage][TGrid] Update the Alerts Table (TGrid) API to implement a subset of the `EuiDataGridColumn` API

This PR implements the following subset of the `EuiDataGridColumn` API from [EuiDataGrid](https://elastic.github.io/eui/#/tabular-content/data-grid) in the `TGrid` (Timeline grid):

```ts
Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'>
```

The above properties are [documented in EuiDataGrid's data_grid_types.ts](https://github.com/elastic/eui/blob/master/src/components/datagrid/data_grid_types.ts), and summarized in the table below:

| Property                   | Description                                                                                                                                                                                                                        |
|----------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `display?:  ReactNode`    | A `ReactNode` used when rendering the column header                                                                                                                                                                                |
| `displayAsText?:  string` | Displays the column name as text (in lieu of using `display`). If not used, `id` will be shown as the column name. |
| `id:  string`             | The unique identifier for this column, e.g. `user.name`                                                                                                                                                                            |
| `initialWidth?:  number`   | Initial width (in pixels) of the column                                                                                                                                                                                            |

The following screenshot shows the `TGrid` rendering (from left-to-right):

- An (example) RAC-flavored Observability alerts table
- An (example) RAC-flavored Security Solution alerts table
- The production alerts table in the Security Solutions `Detections` page, which remains the default

![three_table_configurations](https://user-images.githubusercontent.com/4459398/115944491-5a69a780-a473-11eb-85b6-36120c3092d6.png)

_Above, three table configurations, rendered via the updated API_

The `public/detections/configurations` directory contains the configurations for the three tables shown in the screenshot above

This change works in concert with another recent change to the `TGrid` that [added support for the `renderCellValue` API](#96098).

### Example configurations

#### (example) RAC-flavored Observability alerts table

![observability_alerts_example](https://user-images.githubusercontent.com/4459398/115944556-b3d1d680-a473-11eb-8338-6097731f2d48.png)

The column specification for the (example) RAC-flavored Observability alerts table, shown in the screenshot above is defined in `x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/columns.ts`:

```ts
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.STATUS,
    id: 'kibana.rac.alert.status',
    initialWidth: 74,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.TRIGGERED,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERT_DURATION,
    id: 'kibana.rac.alert.duration.us',
    initialWidth: 116,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    id: 'signal.rule.severity',
    initialWidth: 102,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    id: 'signal.reason',
    initialWidth: 644,
  },
];
```

The example implementation of `EuiDataGrid`'s [`renderCellValue` API](#96098) used to render the RAC-flavored Observability alerts table shown in the screenshot above is located in `x-pack/plugins/security_solution/public/detections/configurations/examples/observablity_alerts/render_cell_value.tsx`:

```ts
/**
 * This implementation of `EuiDataGrid`'s `renderCellValue`
 * accepts `EuiDataGridCellValueElementProps`, plus `data`
 * from the TGrid
 */
export const renderCellValue: React.FC<
  EuiDataGridCellValueElementProps & CellValueElementProps
> = ({
  columnId,
  data,
  eventId,
  header,
  isDetails,
  isExpandable,
  isExpanded,
  linkValues,
  rowIndex,
  setCellProps,
  timelineId,
}) => {
  const value =
    getMappedNonEcsValue({
      data,
      fieldName: columnId,
    })?.reduce((x) => x[0]) ?? '';

  switch (columnId) {
    case 'kibana.rac.alert.status':
      return <Status status={random(0, 1) ? 'recovered' : 'active'} />;
    case 'kibana.rac.alert.duration.us':
      return <span>{moment(value).fromNow(true)}</span>;
    case 'signal.rule.severity':
      return <Severity severity={value} />;
    case 'signal.reason':
      return (
        <EuiLink>
          <TruncatableText>{reason}</TruncatableText>
        </EuiLink>
      );
    default:
      // NOTE: we're using `DefaultCellRenderer` in this example configuration as a fallback, but
      // using `DefaultCellRenderer` here is entirely optional
      return (
        <DefaultCellRenderer
          columnId={columnId}
          data={data}
          eventId={eventId}
          header={header}
          isDetails={isDetails}
          isExpandable={isExpandable}
          isExpanded={isExpanded}
          linkValues={linkValues}
          rowIndex={rowIndex}
          setCellProps={setCellProps}
          timelineId={timelineId}
        />
      );
  }
};
```

#### (example) RAC-flavored Security Solution alerts table

![secuirty_solution_rac_example](https://user-images.githubusercontent.com/4459398/115944592-e8459280-a473-11eb-9e0f-cef8519102d4.png)

The column specification for the (example) RAC-flavored Security Solution alerts table, shown in the screenshot above is defined in `x-pack/plugins/security_solution/public/detections/configurations/examples/security_solution_rac/columns.ts`:

```ts
/**
 * columns implements a subset of `EuiDataGrid`'s `EuiDataGridColumn` interface,
 * plus additional TGrid column properties
 */
export const columns: Array<
  Pick<EuiDataGridColumn, 'display' | 'displayAsText' | 'id' | 'initialWidth'> & ColumnHeaderOptions
> = [
  {
    columnHeaderType: defaultColumnHeaderType,
    id: '@timestamp',
    initialWidth: DEFAULT_DATE_COLUMN_MIN_WIDTH + 5,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.name',
    displayAsText: i18n.ALERTS_HEADERS_RULE_NAME,
    linkField: 'signal.rule.id',
    initialWidth: 212,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.rule.severity',
    displayAsText: i18n.ALERTS_HEADERS_SEVERITY,
    initialWidth: 104,
  },
  {
    columnHeaderType: defaultColumnHeaderType,
    id: 'signal.reason',
    displayAsText: i18n.ALERTS_HEADERS_REASON,
    initialWidth: 644,
  },
];
```

### Testing the example configurations locally

For now, the alerts table in the Security Solution's `Detections` page is configured to use the existing (`7.13`) column configuration.

To test the Alerts table in the Security Solution `Detections` page with the example configurations provided in this PR:

1. Edit `x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx` and change the following line:

```ts
import { columns, RenderCellValue } from '../../configurations/security_solution_detections';
```

from the above to

```ts
import { columns, RenderCellValue } from '../../configurations/examples/observablity_alerts';
```

for the (example) RAC-flavored Observability alerts table, or change it to

```ts
import { columns, RenderCellValue } from '../../configurations/examples/security_solution_rac';
```

for the (example) RAC-flavored Security solution alerts table.

2. Navigate to your local instance of the Security Solution [Detections page](http://localhost:5601/xyx/app/security/detections) (Note: you may need to enable detection rules to populate the alerts table.)

3. Click the `customize_columns` button shown in the screenshot below:

![customize_columns](https://user-images.githubusercontent.com/4459398/115796322-e3f37980-a38e-11eb-930b-5b21dfcb5e65.png)

4. In the `Customize Columns` popover, click the `Reset Fields` button, shown in the screenshot below:

![reset-fields](https://user-images.githubusercontent.com/4459398/115797081-49943580-a390-11eb-9485-7e6cae2f2a6f.png)

After clicking `Reset Fields`, the new default columns will be displayed.

### Backwards compatibility

The `width` property of Timeline's model was changed to `initialWidth` as part of this PR.

- This change has no effect on Timelines persisted as saved objects
- This change has no effect on Timeline's [Export and Import Timelines](https://www.elastic.co/guide/en/security/current/timelines-ui.html#import-export-timelines) feature
- When a TGrid's column configuration containing the legacy `width` and `label` `ColumnHeaderOptions` is read from `localstorage`, these properties are migrated to `initialWidth` and `displayAsText` respectively.
  - Backwards compatibility was desk tested by persisting a custom column configuration while running off `master`, and then re-visiting the page after running this PR branch. As expected, the previously persisted column configuration was rendered correctly after running the PR branch.
  - Unit tests were added to `x-pack/plugins/security_solution/public/timelines/containers/local_storage/index.test.ts` to test the migration of the `width` and `label` properties

### Other changes

- The minium width of a resized column is now `70px`. The new minium is no longer data-type specific.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature:Detection Alerts Security Solution Detection Alerts Feature Feature:RAC label obsolete Feature:Timeline Security Solution Timeline feature release_note:skip Skip the PR/issue when compiling release notes Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:Threat Hunting Security Solution Threat Hunting Team Theme: rac label obsolete v7.14.0 v8.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants