From caab20936ddc5af765703506adcd1c41aa237dcd Mon Sep 17 00:00:00 2001 From: Pablo Neves Machado Date: Wed, 14 Jun 2023 08:37:34 +0200 Subject: [PATCH 1/2] Bug fix ShowTopN cell action --- .../cell_action/show_top_n.test.tsx | 38 ++++++++++++++----- .../show_top_n/cell_action/show_top_n.tsx | 10 ++--- .../security_solution/public/actions/utils.ts | 11 ++++++ 3 files changed, 44 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx index bb64a2a2bdac6..87c920e787895 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx @@ -17,6 +17,7 @@ import { createStore } from '../../../common/store'; import { createShowTopNCellActionFactory } from './show_top_n'; import React from 'react'; import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; jest.mock('../../../common/lib/kibana'); @@ -45,7 +46,7 @@ describe('createShowTopNCellActionFactory', () => { value: 'the-value', field: { name: 'user.name', - type: 'keyword', + type: KBN_FIELD_TYPES.STRING, aggregatable: true, searchable: true, }, @@ -71,35 +72,54 @@ describe('createShowTopNCellActionFactory', () => { }); describe('isCompatible', () => { - it('should return true if everything is okay', async () => { - expect(await showTopNAction.isCompatible(context)).toEqual(true); - }); - - it('should return false if field esType does not support aggregations', async () => { + it('should return false if field is not aggregatable', async () => { expect( await showTopNAction.isCompatible({ ...context, data: [ { - field: { ...context.data[0].field, esTypes: ['text'] }, + field: { ...context.data[0].field, aggregatable: false }, }, ], }) ).toEqual(false); }); - it('should return false if field is not aggregatable', async () => { + it('should return false if field is nested', async () => { expect( await showTopNAction.isCompatible({ ...context, data: [ { - field: { ...context.data[0].field, aggregatable: false }, + field: { ...context.data[0].field, subType: { nested: { path: 'test_path' } } }, }, ], }) ).toEqual(false); }); + + describe.each([ + { type: KBN_FIELD_TYPES.STRING, expectedValue: true }, + { type: KBN_FIELD_TYPES.BOOLEAN, expectedValue: true }, + { type: KBN_FIELD_TYPES.NUMBER, expectedValue: true }, + { type: KBN_FIELD_TYPES.IP, expectedValue: true }, + { type: KBN_FIELD_TYPES.DATE, expectedValue: false }, + { type: KBN_FIELD_TYPES.GEO_SHAPE, expectedValue: false }, + { type: KBN_FIELD_TYPES.IP_RANGE, expectedValue: false }, + ])('lens supported KBN types', ({ type, expectedValue }) => { + it(`should return ${expectedValue} when type is ${type}`, async () => { + expect( + await showTopNAction.isCompatible({ + ...context, + data: [ + { + field: { ...context.data[0].field, type }, + }, + ], + }) + ).toEqual(expectedValue); + }); + }); }); describe('execute', () => { diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx index 0e1c419b0449e..db89adfa25e9b 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx @@ -12,11 +12,11 @@ import { Router } from '@kbn/shared-ux-router'; import { i18n } from '@kbn/i18n'; import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions'; import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; -import { ES_FIELD_TYPES } from '@kbn/field-types'; +import { isDataViewFieldSubtypeNested } from '@kbn/es-query'; import { KibanaContextProvider } from '../../../common/lib/kibana'; import { APP_NAME, DEFAULT_DARK_MODE } from '../../../../common/constants'; import type { SecurityAppStore } from '../../../common/store'; -import { fieldHasCellActions } from '../../utils'; +import { fieldHasCellActions, isLensSupportedType } from '../../utils'; import { TopNAction } from '../show_top_n_component'; import type { StartServices } from '../../../types'; import type { SecurityCellAction } from '../../types'; @@ -29,7 +29,6 @@ const SHOW_TOP = (fieldName: string) => }); const ICON = 'visBarVertical'; -const UNSUPPORTED_ES_FIELD_TYPES = [ES_FIELD_TYPES.DATE, ES_FIELD_TYPES.TEXT]; export const createShowTopNCellActionFactory = createCellActionFactory( ({ @@ -51,9 +50,8 @@ export const createShowTopNCellActionFactory = createCellActionFactory( return ( data.length === 1 && fieldHasCellActions(field.name) && - (field.esTypes ?? []).every( - (esType) => !UNSUPPORTED_ES_FIELD_TYPES.includes(esType as ES_FIELD_TYPES) - ) && + isLensSupportedType(field.type) && + !isDataViewFieldSubtypeNested(field) && !!field.aggregatable ); }, diff --git a/x-pack/plugins/security_solution/public/actions/utils.ts b/x-pack/plugins/security_solution/public/actions/utils.ts index 74b40334284cf..c6d25d9c634b1 100644 --- a/x-pack/plugins/security_solution/public/actions/utils.ts +++ b/x-pack/plugins/security_solution/public/actions/utils.ts @@ -7,6 +7,7 @@ import type { IEmbeddable } from '@kbn/embeddable-plugin/public'; import { LENS_EMBEDDABLE_TYPE, type Embeddable as LensEmbeddable } from '@kbn/lens-plugin/public'; import type { Serializable } from '@kbn/utility-types'; +import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { APP_UI_ID } from '../../common/constants'; // All cell actions are disabled for these fields in Security @@ -35,3 +36,13 @@ export const isCountField = ( ) => { return fieldType === 'number' && sourceParamType === 'value_count'; }; + +const SUPPORTED_LENS_TYPES = new Set([ + KBN_FIELD_TYPES.STRING, + KBN_FIELD_TYPES.BOOLEAN, + KBN_FIELD_TYPES.NUMBER, + KBN_FIELD_TYPES.IP, +]); + +export const isLensSupportedType = (fieldType: string | undefined) => + fieldType ? SUPPORTED_LENS_TYPES.has(fieldType as KBN_FIELD_TYPES) : false; From f6bc536aef78a94d418556207087e242675662b8 Mon Sep 17 00:00:00 2001 From: Pablo Neves Machado Date: Mon, 3 Jul 2023 14:22:12 +0200 Subject: [PATCH 2/2] Move isLensSupportedType to common/utils --- .../show_top_n/cell_action/show_top_n.tsx | 3 ++- .../security_solution/public/actions/utils.ts | 11 ----------- .../public/common/utils/lens.ts | 18 ++++++++++++++++++ .../components/alerts_kpis/common/hooks.ts | 6 +----- 4 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/common/utils/lens.ts diff --git a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx index db89adfa25e9b..3491f0ffcc620 100644 --- a/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx +++ b/x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx @@ -16,11 +16,12 @@ import { isDataViewFieldSubtypeNested } from '@kbn/es-query'; import { KibanaContextProvider } from '../../../common/lib/kibana'; import { APP_NAME, DEFAULT_DARK_MODE } from '../../../../common/constants'; import type { SecurityAppStore } from '../../../common/store'; -import { fieldHasCellActions, isLensSupportedType } from '../../utils'; +import { fieldHasCellActions } from '../../utils'; import { TopNAction } from '../show_top_n_component'; import type { StartServices } from '../../../types'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; +import { isLensSupportedType } from '../../../common/utils/lens'; const SHOW_TOP = (fieldName: string) => i18n.translate('xpack.securitySolution.actions.showTopTooltip', { diff --git a/x-pack/plugins/security_solution/public/actions/utils.ts b/x-pack/plugins/security_solution/public/actions/utils.ts index c6d25d9c634b1..74b40334284cf 100644 --- a/x-pack/plugins/security_solution/public/actions/utils.ts +++ b/x-pack/plugins/security_solution/public/actions/utils.ts @@ -7,7 +7,6 @@ import type { IEmbeddable } from '@kbn/embeddable-plugin/public'; import { LENS_EMBEDDABLE_TYPE, type Embeddable as LensEmbeddable } from '@kbn/lens-plugin/public'; import type { Serializable } from '@kbn/utility-types'; -import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { APP_UI_ID } from '../../common/constants'; // All cell actions are disabled for these fields in Security @@ -36,13 +35,3 @@ export const isCountField = ( ) => { return fieldType === 'number' && sourceParamType === 'value_count'; }; - -const SUPPORTED_LENS_TYPES = new Set([ - KBN_FIELD_TYPES.STRING, - KBN_FIELD_TYPES.BOOLEAN, - KBN_FIELD_TYPES.NUMBER, - KBN_FIELD_TYPES.IP, -]); - -export const isLensSupportedType = (fieldType: string | undefined) => - fieldType ? SUPPORTED_LENS_TYPES.has(fieldType as KBN_FIELD_TYPES) : false; diff --git a/x-pack/plugins/security_solution/public/common/utils/lens.ts b/x-pack/plugins/security_solution/public/common/utils/lens.ts new file mode 100644 index 0000000000000..047144ce55f6f --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/utils/lens.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KBN_FIELD_TYPES } from '@kbn/field-types'; + +const SUPPORTED_LENS_TYPES = new Set([ + KBN_FIELD_TYPES.STRING, + KBN_FIELD_TYPES.BOOLEAN, + KBN_FIELD_TYPES.NUMBER, + KBN_FIELD_TYPES.IP, +]); + +export const isLensSupportedType = (fieldType: string | undefined) => + fieldType ? SUPPORTED_LENS_TYPES.has(fieldType as KBN_FIELD_TYPES) : false; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts index 2658a0af00d6b..86c8719053c81 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/common/hooks.ts @@ -14,6 +14,7 @@ import type { BrowserField } from '@kbn/timelines-plugin/common'; import type { GlobalTimeArgs } from '../../../../common/containers/use_global_time'; import { getScopeFromPath, useSourcererDataView } from '../../../../common/containers/sourcerer'; import { getAllFieldsByName } from '../../../../common/containers/source'; +import { isLensSupportedType } from '../../../../common/utils/lens'; export interface UseInspectButtonParams extends Pick { response: string; @@ -65,11 +66,6 @@ export function isDataViewFieldSubtypeNested(field: Partial) { return !!subTypeNested?.nested?.path; } -export function isLensSupportedType(fieldType: string | undefined) { - const supportedTypes = new Set(['string', 'boolean', 'number', 'ip']); - return fieldType ? supportedTypes.has(fieldType) : false; -} - export interface GetAggregatableFields { [fieldName: string]: Partial; }