From a3de2d4141e4a1b5766d755501c73e16c34295ac Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Thu, 9 May 2024 16:30:13 +0200 Subject: [PATCH 1/2] [Security Solution] Timeline cell actions migration (#182092) ## Summary issue: https://github.com/elastic/kibana/issues/181849 This PR finishes the migration from the old hover actions components to the new cell-actions package in the Security Solution application, the latest parts still using the legacy hover actions were the Timeline draggable and the field renderer components. Besides the migration and cleaning, this PR refactors the cell-actions package exports and the Security Solution actions registration, to improve the bundling size. ### Changes: #### Refactoring - `packages/kbn-cell-actions/` -> Refactored to separate the "UI" exports (components, hooks, context) which are used by multiple components, from the "actions" export which is only used to register the cell actions' execution logic on the plugin start. This change reduced bundle size. - `x-pack/plugins/security_solution/public/actions/` -> Moved under `public/app/actions`. This directory contains the custom actions implementation and registration logic, the directory has been relocated for consistency since it was at the sub-plugin (app sections) directory level, the `/app` directory fits much better it's purpose. All the logic inside remains unchanged. #### Migration - `x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_cell_actions.tsx` -> New `DraggableCellActions` component implemented using the new cell-actions, replaces the usages of the old `WithHoverActions` component in the `DraggableWrapper`. - `x-pack/plugins/security_solution/public/common/components/hover_popover/index.tsx` -> New `HoverPopover` generic component that replaces "unconventional" usages of the old `WithHoverActions` component, it is decoupled from cell-actions. - `x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx` -> Implementation updated to use the new cell-actions (via `DraggableCellActions`) instead of the legacy hover_actions. - `x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx` -> Implementation updated using the new cell-actions instead of the legacy hover_actions. The `scopeId` prop has been added to the component it needs to be provided to the new cell-actions. The `sourcererScopeId` prop has been removed since it can be derived from the new `scopeId` prop. The UX should be the same, there's only one small change, for consistency, in the "Add to timeline" action title: | Old | New | |-|-| |![old](https://github.com/elastic/kibana/assets/17747913/8298e6a0-0621-4d5f-ae43-19e9ce7ce0bc)|![new](https://github.com/elastic/kibana/assets/17747913/8e4fe2a1-92e9-4c77-8e51-253d822f7a2c)| |![old_filter_in](https://github.com/elastic/kibana/assets/17747913/84ad85c1-81be-4789-89c7-9140b6de8977)|![new_filter_in](https://github.com/elastic/kibana/assets/17747913/22dead4b-0014-42f2-a243-2ce78e10d934)| |![old_filter_out](https://github.com/elastic/kibana/assets/17747913/0aeccc04-b497-4ec4-9a6d-90e22e592e13)|![new_filter_out](https://github.com/elastic/kibana/assets/17747913/d0dc7b2c-cf30-4e1d-9818-69e12c529df0)| |![old_add_timeline](https://github.com/elastic/kibana/assets/17747913/78616912-d7d2-4aaa-8260-cc8aa0038d78)|![new_add_timeline](https://github.com/elastic/kibana/assets/17747913/ec5d5bcb-5575-4aaa-a0ad-c987ed7b27a5)| |![old_top_n](https://github.com/elastic/kibana/assets/17747913/362af9ef-deca-44b5-9057-59d03876d5be)|![new_top_n](https://github.com/elastic/kibana/assets/17747913/d191c9ba-b605-4b2c-b298-092db94c4b07)| |![old_copy](https://github.com/elastic/kibana/assets/17747913/4c785535-35cf-4f1d-bd17-f2ae99858797)|![new_copy](https://github.com/elastic/kibana/assets/17747913/ce8db1a9-a73a-4515-91c9-4f0fc1429f73)| #### Replacement - `x-pack/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx` -> Unconventional usage of `WithHoverActions` has been replaced by the new `HoverPopover` component. Host risk level field hover: ![risk_score](https://github.com/elastic/kibana/assets/17747913/21049777-659f-486c-b515-f7e29448e540) - `x-pack/plugins/security_solution/public/overview/components/recent_timelines/recent_timelines.tsx` -> Unconventional usage of `WithHoverActions` has been replaced by the new `HoverPopover` component. Recent timelines hover: ![recent_timelines](https://github.com/elastic/kibana/assets/17747913/bc91dbe9-99c3-4138-a2cc-6d8d58b8c035) #### Cleaning Deprecated hover_actions directories removed: - `x-pack/plugins/security_solution/public/common/components/with_hover_actions/*` - `x-pack/plugins/security_solution/public/common/components/hover_actions/*` --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- .github/CODEOWNERS | 1 + packages/kbn-cell-actions/actions/index.ts | 9 + packages/kbn-cell-actions/actions/utils.ts | 9 + packages/kbn-cell-actions/index.ts | 6 +- .../kbn-cell-actions/src/actions/index.ts | 20 + .../kbn-cell-actions/src/actions/types.ts | 22 +- .../components/hover_actions_popover.test.tsx | 10 +- .../src/components/hover_actions_popover.tsx | 2 +- packages/kbn-cell-actions/src/index.ts | 41 - packages/kbn-cell-actions/src/types.ts | 19 +- .../public/actions/jest.config.js | 24 - .../cell_action/add_to_timeline.test.ts | 10 +- .../cell_action/add_to_timeline.ts | 13 +- .../investigate_in_new_timeline.test.ts | 12 +- .../investigate_in_new_timeline.ts | 18 +- .../actions/add_to_timeline/constants.ts | 0 .../actions/add_to_timeline/data_provider.ts | 16 +- .../discover/add_to_timeline.test.ts | 12 +- .../discover/add_to_timeline.ts | 4 +- .../actions/add_to_timeline/index.ts | 0 .../lens/add_to_timeline.test.ts | 14 +- .../add_to_timeline/lens/add_to_timeline.ts | 10 +- .../public/{ => app}/actions/constants.ts | 0 .../cell_action/copy_to_clipboard.test.ts | 2 +- .../cell_action/copy_to_clipboard.ts | 4 +- .../actions/copy_to_clipboard/constants.ts | 0 .../discover/copy_to_clipboard.test.ts | 4 +- .../discover/copy_to_clipboard.ts | 2 +- .../actions/copy_to_clipboard/index.ts | 0 .../lens/copy_to_clipboard.test.ts | 6 +- .../lens/copy_to_clipboard.ts | 2 +- .../filter/cell_action/filter_in.test.ts | 6 +- .../actions/filter/cell_action/filter_in.ts | 12 +- .../filter/cell_action/filter_out.test.ts | 6 +- .../actions/filter/cell_action/filter_out.ts | 12 +- .../actions/filter/discover/filter_in.test.ts | 6 +- .../actions/filter/discover/filter_in.ts | 4 +- .../filter/discover/filter_out.test.ts | 6 +- .../actions/filter/discover/filter_out.ts | 4 +- .../public/{ => app}/actions/filter/index.ts | 0 .../actions/filter/lens/create_action.test.ts | 6 +- .../actions/filter/lens/create_action.ts | 14 +- .../actions/filter/lens/filter_in.ts | 4 +- .../actions/filter/lens/filter_out.ts | 4 +- .../public/{ => app}/actions/index.ts | 0 .../public/{ => app}/actions/register.ts | 4 +- .../register_discover_histogram_actions.ts | 4 +- .../cell_action/show_top_n.test.tsx | 6 +- .../show_top_n/cell_action/show_top_n.tsx | 6 +- .../{ => app}/actions/show_top_n/index.ts | 0 .../{ => app}/actions/telemetry.test.ts | 2 +- .../public/{ => app}/actions/telemetry.ts | 2 +- .../cell_action/toggle_asset_column.test.ts | 8 +- .../cell_action/toggle_asset_column.ts | 8 +- .../actions/toggle_asset_column/index.tsx | 0 .../cell_action/toggle_column.test.ts | 6 +- .../cell_action/toggle_column.ts | 16 +- .../{ => app}/actions/toggle_column/index.tsx | 0 .../public/{ => app}/actions/types.ts | 6 +- .../public/{ => app}/actions/utils.ts | 2 +- .../legend/get_flattened_legend_items.test.ts | 5 +- .../alerts_treemap/lib/legend/index.test.ts | 14 +- .../alerts_treemap/lib/legend/index.ts | 3 + .../components/cell_actions/index.test.tsx | 2 +- .../common/components/cell_actions/index.tsx | 10 +- .../cell_actions_wrapper.test.tsx | 97 + .../drag_and_drop/cell_actions_wrapper.tsx | 76 + .../drag_and_drop/draggable_wrapper.test.tsx | 61 +- .../drag_and_drop/draggable_wrapper.tsx | 461 +-- .../hover_actions/actions/show_top_n.test.tsx | 193 - .../hover_actions/actions/show_top_n.tsx | 194 - .../common/components/hover_actions/index.tsx | 295 -- .../use_hover_action_items.test.tsx | 318 -- .../hover_actions/use_hover_action_items.tsx | 347 -- .../hover_actions/use_hover_actions.tsx | 207 -- .../components/hover_actions/utils.test.ts | 65 - .../common/components/hover_actions/utils.ts | 39 - .../hover_popover/hover_popover.test.tsx | 94 + .../hover_popover.tsx} | 100 +- .../index.ts} | 2 +- .../public/common/lib/telemetry/types.ts | 4 +- .../alerts_by_type_panel/columns.tsx | 7 +- .../alerts_count_panel/columns.tsx | 4 + .../alerts_progress_bar.tsx | 2 + .../severity_level_panel/columns.tsx | 2 + .../use_cell_actions.tsx | 2 +- .../index.test.tsx | 2 - .../components/severity/common/index.tsx | 67 +- .../left/components/cell_actions.tsx | 2 +- .../left/components/host_details.tsx | 3 +- .../left/components/user_details.tsx | 3 +- .../components/alert_reason_preview.test.tsx | 28 +- .../right/components/cell_actions.tsx | 2 +- .../right/components/event_renderer.test.tsx | 16 +- .../components/entity_table/columns.tsx | 2 - .../security_solution/public/lazy_actions.ts | 8 + .../host_alerts_table/host_alerts_table.tsx | 2 +- .../rule_alerts_table/rule_alerts_table.tsx | 5 +- .../user_alerts_table/user_alerts_table.tsx | 5 +- .../host_overview/endpoint_overview/index.tsx | 9 +- .../components/host_overview/index.tsx | 19 +- .../recent_timelines/recent_timelines.tsx | 89 +- .../components/user_overview/index.tsx | 13 +- .../security_solution/public/plugin.tsx | 4 +- .../field_renderers.test.tsx.snap | 204 +- .../field_renderers/field_renderers.test.tsx | 10 +- .../field_renderers/field_renderers.tsx | 46 +- .../netflow/__snapshots__/index.test.tsx.snap | 2290 ++++++------ .../host_details/expandable_host.tsx | 3 +- .../side_panel/new_user_detail/columns.tsx | 2 - .../user_details/expandable_user.tsx | 3 +- .../netflow_row_renderer.test.tsx.snap | 3136 ++++++++--------- .../use_histogram_customizations.tsx | 2 +- .../timeline/tabs/esql/mocks/index.ts | 2 +- .../unified_components/data_table/index.tsx | 2 +- x-pack/plugins/timelines/public/types.ts | 3 + .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../investigations/timelines/filters.cy.ts | 7 +- .../cypress/screens/alerts.ts | 2 +- .../cypress/screens/timeline.ts | 14 +- .../cypress/tasks/search_bar.ts | 26 +- 123 files changed, 3441 insertions(+), 5646 deletions(-) create mode 100644 packages/kbn-cell-actions/actions/index.ts create mode 100644 packages/kbn-cell-actions/actions/utils.ts create mode 100644 packages/kbn-cell-actions/src/actions/index.ts delete mode 100644 packages/kbn-cell-actions/src/index.ts delete mode 100644 x-pack/plugins/security_solution/public/actions/jest.config.js rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/cell_action/add_to_timeline.test.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/cell_action/add_to_timeline.ts (89%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts (93%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts (88%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/constants.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/data_provider.ts (88%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/discover/add_to_timeline.test.ts (88%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/discover/add_to_timeline.ts (89%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/index.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/lens/add_to_timeline.test.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/add_to_timeline/lens/add_to_timeline.ts (91%) rename x-pack/plugins/security_solution/public/{ => app}/actions/constants.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts (89%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/constants.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts (94%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/discover/copy_to_clipboard.ts (94%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/index.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts (97%) rename x-pack/plugins/security_solution/public/{ => app}/actions/copy_to_clipboard/lens/copy_to_clipboard.ts (97%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/cell_action/filter_in.test.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/cell_action/filter_in.ts (90%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/cell_action/filter_out.test.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/cell_action/filter_out.ts (90%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/discover/filter_in.test.ts (92%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/discover/filter_in.ts (89%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/discover/filter_out.test.ts (92%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/discover/filter_out.ts (89%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/index.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/lens/create_action.test.ts (97%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/lens/create_action.ts (92%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/lens/filter_in.ts (83%) rename x-pack/plugins/security_solution/public/{ => app}/actions/filter/lens/filter_out.ts (83%) rename x-pack/plugins/security_solution/public/{ => app}/actions/index.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/register.ts (98%) rename x-pack/plugins/security_solution/public/{ => app}/actions/register_discover_histogram_actions.ts (93%) rename x-pack/plugins/security_solution/public/{ => app}/actions/show_top_n/cell_action/show_top_n.test.tsx (94%) rename x-pack/plugins/security_solution/public/{ => app}/actions/show_top_n/cell_action/show_top_n.tsx (92%) rename x-pack/plugins/security_solution/public/{ => app}/actions/show_top_n/index.ts (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/telemetry.test.ts (96%) rename x-pack/plugins/security_solution/public/{ => app}/actions/telemetry.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts (93%) rename x-pack/plugins/security_solution/public/{ => app}/actions/toggle_asset_column/cell_action/toggle_asset_column.ts (89%) rename x-pack/plugins/security_solution/public/{ => app}/actions/toggle_asset_column/index.tsx (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/toggle_column/cell_action/toggle_column.test.ts (95%) rename x-pack/plugins/security_solution/public/{ => app}/actions/toggle_column/cell_action/toggle_column.ts (86%) rename x-pack/plugins/security_solution/public/{ => app}/actions/toggle_column/index.tsx (100%) rename x-pack/plugins/security_solution/public/{ => app}/actions/types.ts (93%) rename x-pack/plugins/security_solution/public/{ => app}/actions/utils.ts (95%) create mode 100644 x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx create mode 100644 x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_actions.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/utils.test.ts delete mode 100644 x-pack/plugins/security_solution/public/common/components/hover_actions/utils.ts create mode 100644 x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.test.tsx rename x-pack/plugins/security_solution/public/common/components/{with_hover_actions/index.tsx => hover_popover/hover_popover.tsx} (53%) rename x-pack/plugins/security_solution/public/common/components/{hover_actions/keyboard_shortcut_constants.ts => hover_popover/index.ts} (83%) create mode 100644 x-pack/plugins/security_solution/public/lazy_actions.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index de091b2a82ede..96226444859a8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1432,6 +1432,7 @@ x-pack/test/security_solution_cypress/cypress/tasks/expandable_flyout @elastic/ /x-pack/test/security_solution_cypress/cypress/tasks/hosts @elastic/security-threat-hunting-explore /x-pack/test/security_solution_cypress/cypress/tasks/network @elastic/security-threat-hunting-explore +/x-pack/plugins/security_solution/public/app/actions @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/public/common/components/guided_onboarding_tour @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/public/common/components/charts @elastic/security-threat-hunting-explore /x-pack/plugins/security_solution/public/detections/components/alerts_table/grouping_settings @elastic/security-threat-hunting-explore diff --git a/packages/kbn-cell-actions/actions/index.ts b/packages/kbn-cell-actions/actions/index.ts new file mode 100644 index 0000000000000..ca38510c84aaa --- /dev/null +++ b/packages/kbn-cell-actions/actions/index.ts @@ -0,0 +1,9 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from '../src/actions'; diff --git a/packages/kbn-cell-actions/actions/utils.ts b/packages/kbn-cell-actions/actions/utils.ts new file mode 100644 index 0000000000000..ede7ac90577db --- /dev/null +++ b/packages/kbn-cell-actions/actions/utils.ts @@ -0,0 +1,9 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from '../src/actions/utils'; diff --git a/packages/kbn-cell-actions/index.ts b/packages/kbn-cell-actions/index.ts index de0577ee3ed83..9829b99a0572b 100644 --- a/packages/kbn-cell-actions/index.ts +++ b/packages/kbn-cell-actions/index.ts @@ -6,4 +6,8 @@ * Side Public License, v 1. */ -export * from './src'; +export * from './src/types'; + +export * from './src/context'; +export * from './src/components'; +export * from './src/hooks'; diff --git a/packages/kbn-cell-actions/src/actions/index.ts b/packages/kbn-cell-actions/src/actions/index.ts new file mode 100644 index 0000000000000..955b10f067c44 --- /dev/null +++ b/packages/kbn-cell-actions/src/actions/index.ts @@ -0,0 +1,20 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export * from './types'; + +export { createCellActionFactory } from './factory'; + +export { createCopyToClipboardActionFactory } from './copy_to_clipboard'; +export { + createFilterInActionFactory, + createFilterOutActionFactory, + addFilterIn, + addFilterOut, + addExistsFilter, +} from './filter'; diff --git a/packages/kbn-cell-actions/src/actions/types.ts b/packages/kbn-cell-actions/src/actions/types.ts index f7700e3c5edaf..842b196e9cad2 100644 --- a/packages/kbn-cell-actions/src/actions/types.ts +++ b/packages/kbn-cell-actions/src/actions/types.ts @@ -6,8 +6,9 @@ * Side Public License, v 1. */ -import { SerializableRecord } from '@kbn/utility-types'; -import { SerializableArray } from '@kbn/utility-types/src/serializable'; +import type { SerializableRecord } from '@kbn/utility-types'; +import type { SerializableArray } from '@kbn/utility-types/src/serializable'; +import type { CellAction } from '../types'; export type DefaultActionsSupportedValue = string[] | number[] | boolean[]; @@ -17,3 +18,20 @@ export type NonNullableSerializable = | boolean | SerializableArray | SerializableRecord; + +/** + * Cell action factory template with optional `id`. + * The id override is required when using the action factory so it + * can be omitted in the original action creator + */ +export type CellActionTemplate = Omit; +/** + * Action factory extend parameter type, + */ +export type CellActionExtend = Partial & { id: string }; +export interface CellActionFactory { + (extend: CellActionExtend): A; + combine: ( + partialActionTemplate: Partial> + ) => CellActionFactory; +} diff --git a/packages/kbn-cell-actions/src/components/hover_actions_popover.test.tsx b/packages/kbn-cell-actions/src/components/hover_actions_popover.test.tsx index de524edfac9fe..d6dab633fec71 100644 --- a/packages/kbn-cell-actions/src/components/hover_actions_popover.test.tsx +++ b/packages/kbn-cell-actions/src/components/hover_actions_popover.test.tsx @@ -31,14 +31,16 @@ describe('HoverActionsPopover', () => { const TestComponent = () => ; jest.useFakeTimers(); - it('renders', () => { + it('renders the children', () => { const getActions = () => Promise.resolve([]); - const { queryByTestId } = render( + const { getByTestId } = render( - + + + ); - expect(queryByTestId('hoverActionsPopover')).toBeInTheDocument(); + expect(getByTestId('test-component')).toBeInTheDocument(); }); it('renders actions when hovered', async () => { diff --git a/packages/kbn-cell-actions/src/components/hover_actions_popover.tsx b/packages/kbn-cell-actions/src/components/hover_actions_popover.tsx index 8ba273f98c6a1..8cced2665fd89 100644 --- a/packages/kbn-cell-actions/src/components/hover_actions_popover.tsx +++ b/packages/kbn-cell-actions/src/components/hover_actions_popover.tsx @@ -135,7 +135,7 @@ export const HoverActionsPopover: React.FC = ({ panelPaddingSize="none" repositionOnScroll ownFocus={false} - data-test-subj={'hoverActionsPopover'} + panelProps={{ ['data-test-subj']: 'hoverActionsPopover' }} aria-label={ACTIONS_AREA_LABEL} > {showHoverContent && ( diff --git a/packages/kbn-cell-actions/src/index.ts b/packages/kbn-cell-actions/src/index.ts deleted file mode 100644 index 4b7dde4cdcaf1..0000000000000 --- a/packages/kbn-cell-actions/src/index.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// Types and enums -export type { - CellAction, - CellActionFieldValue, - CellActionsProps, - CellActionExecutionContext, - CellActionCompatibilityContext, - CellActionTemplate, - CellActionFactory, - CellActionExtend, -} from './types'; -export type { UseDataGridColumnsCellActions, UseDataGridColumnsCellActionsProps } from './hooks'; - -// Constants -export { CellActionsMode } from './constants'; - -// Components and hooks -export { CellActionsProvider } from './context'; -export { CellActions } from './components'; -export { useDataGridColumnsCellActions } from './hooks'; - -// Generic actions -export { createCopyToClipboardActionFactory } from './actions/copy_to_clipboard'; -export { - createFilterInActionFactory, - createFilterOutActionFactory, - addFilterIn, - addFilterOut, - addExistsFilter, -} from './actions/filter'; - -// Action factory -export { createCellActionFactory } from './actions/factory'; diff --git a/packages/kbn-cell-actions/src/types.ts b/packages/kbn-cell-actions/src/types.ts index 301997618b6f3..17679c2a2c14e 100644 --- a/packages/kbn-cell-actions/src/types.ts +++ b/packages/kbn-cell-actions/src/types.ts @@ -16,6 +16,8 @@ import type { FieldSpec } from '@kbn/data-views-plugin/common'; import { Serializable } from '@kbn/utility-types'; import type { CellActionsMode } from './constants'; +export * from './actions/types'; + export type CellActionsProviderProps = PropsWithChildren<{ /** * Please assign `uiActions.getTriggerCompatibleActions` function. @@ -133,20 +135,3 @@ export interface PartitionedActions { extraActions: CellAction[]; visibleActions: CellAction[]; } - -/** - * Cell action factory template with optional `id`. - * The id override is required when using the action factory so it - * can be omitted in the original action creator - */ -export type CellActionTemplate = Omit; -/** - * Action factory extend parameter type, - */ -export type CellActionExtend = Partial & { id: string }; -export interface CellActionFactory { - (extend: CellActionExtend): A; - combine: ( - partialActionTemplate: Partial> - ) => CellActionFactory; -} diff --git a/x-pack/plugins/security_solution/public/actions/jest.config.js b/x-pack/plugins/security_solution/public/actions/jest.config.js deleted file mode 100644 index 0c09f187ec983..0000000000000 --- a/x-pack/plugins/security_solution/public/actions/jest.config.js +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../../../..', - roots: ['/x-pack/plugins/security_solution/public/actions'], - coverageDirectory: - '/target/kibana-coverage/jest/x-pack/plugins/security_solution/public/actions', - coverageReporters: ['text', 'html'], - collectCoverageFrom: ['/x-pack/plugins/security_solution/public/actions/**/*.{ts,tsx}'], - // See: https://github.com/elastic/kibana/issues/117255, the moduleNameMapper creates mocks to avoid memory leaks from kibana core. - moduleNameMapper: { - 'core/server$': '/x-pack/plugins/security_solution/server/__mocks__/core.mock.ts', - 'task_manager/server$': - '/x-pack/plugins/security_solution/server/__mocks__/task_manager.mock.ts', - 'alerting/server$': '/x-pack/plugins/security_solution/server/__mocks__/alert.mock.ts', - 'actions/server$': '/x-pack/plugins/security_solution/server/__mocks__/action.mock.ts', - }, -}; diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/add_to_timeline.test.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/add_to_timeline.test.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts index 3a47134531d37..dfdc2a5ede83f 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/add_to_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.test.ts @@ -5,13 +5,13 @@ * 2.0. */ -import type { SecurityAppStore } from '../../../common/store/types'; -import { TimelineId } from '../../../../common/types'; -import { addProvider } from '../../../timelines/store/actions'; +import type { SecurityAppStore } from '../../../../common/store/types'; +import { TimelineId } from '../../../../../common/types'; +import { addProvider } from '../../../../timelines/store/actions'; import { createAddToTimelineCellActionFactory } from './add_to_timeline'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; -import { GEO_FIELD_TYPE } from '../../../timelines/components/timeline/body/renderers/constants'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { GEO_FIELD_TYPE } from '../../../../timelines/components/timeline/body/renderers/constants'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; import { set } from 'lodash/fp'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/add_to_timeline.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts similarity index 89% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/add_to_timeline.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts index 1b40784dcec4d..695569e98ee97 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/add_to_timeline.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/add_to_timeline.ts @@ -5,19 +5,18 @@ * 2.0. */ -import { createCellActionFactory } from '@kbn/cell-actions'; -import type { CellActionTemplate } from '@kbn/cell-actions'; +import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions/actions'; import { isTypeSupportedByDefaultActions, isValueSupportedByDefaultActions, filterOutNullableValues, valueToArray, -} from '@kbn/cell-actions/src/actions/utils'; +} from '@kbn/cell-actions/actions/utils'; import { ACTION_INCOMPATIBLE_VALUE_WARNING } from '@kbn/cell-actions/src/actions/translations'; import type { KBN_FIELD_TYPES } from '@kbn/field-types'; -import { addProvider } from '../../../timelines/store/actions'; -import { TimelineId } from '../../../../common/types'; -import type { SecurityAppStore } from '../../../common/store'; +import { addProvider } from '../../../../timelines/store/actions'; +import { TimelineId } from '../../../../../common/types'; +import type { SecurityAppStore } from '../../../../common/store'; import { fieldHasCellActions } from '../../utils'; import { ADD_TO_TIMELINE, @@ -28,7 +27,7 @@ import { } from '../constants'; import { createDataProviders, isValidDataProviderField } from '../data_provider'; import { SecurityCellActionType } from '../../constants'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import type { SecurityCellAction } from '../../types'; export const createAddToTimelineCellActionFactory = createCellActionFactory( diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts similarity index 93% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts index ee1d1ec579f12..d7750dd1cd4cd 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import type { SecurityAppStore } from '../../../common/store/types'; -import { TimelineId } from '../../../../common/types'; -import { addProvider, showTimeline } from '../../../timelines/store/actions'; +import type { SecurityAppStore } from '../../../../common/store/types'; +import { TimelineId } from '../../../../../common/types'; +import { addProvider, showTimeline } from '../../../../timelines/store/actions'; import { createInvestigateInNewTimelineCellActionFactory } from './investigate_in_new_timeline'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; -import { GEO_FIELD_TYPE } from '../../../timelines/components/timeline/body/renderers/constants'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; -import { timelineActions } from '../../../timelines/store'; +import { GEO_FIELD_TYPE } from '../../../../timelines/components/timeline/body/renderers/constants'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; +import { timelineActions } from '../../../../timelines/store'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; const services = createStartServicesMock(); diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts similarity index 88% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts index 2c9dd401d415a..ac0be8ea9eb15 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/cell_action/investigate_in_new_timeline.ts @@ -5,19 +5,19 @@ * 2.0. */ -import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions'; import type { KBN_FIELD_TYPES } from '@kbn/field-types'; +import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions/actions'; import { isTypeSupportedByDefaultActions, isValueSupportedByDefaultActions, - valueToArray, filterOutNullableValues, -} from '@kbn/cell-actions/src/actions/utils'; + valueToArray, +} from '@kbn/cell-actions/actions/utils'; import { ACTION_INCOMPATIBLE_VALUE_WARNING } from '@kbn/cell-actions/src/actions/translations'; -import { timelineActions } from '../../../timelines/store'; -import { addProvider, showTimeline } from '../../../timelines/store/actions'; -import { TimelineId } from '../../../../common/types'; -import type { SecurityAppStore } from '../../../common/store'; +import { timelineActions } from '../../../../timelines/store'; +import { addProvider, showTimeline } from '../../../../timelines/store/actions'; +import { TimelineId } from '../../../../../common/types'; +import type { SecurityAppStore } from '../../../../common/store'; import { fieldHasCellActions } from '../../utils'; import { ADD_TO_TIMELINE_FAILED_TEXT, @@ -27,9 +27,9 @@ import { } from '../constants'; import { createDataProviders, isValidDataProviderField } from '../data_provider'; import { SecurityCellActionType } from '../../constants'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import type { SecurityCellAction } from '../../types'; -import { timelineDefaults } from '../../../timelines/store/defaults'; +import { timelineDefaults } from '../../../../timelines/store/defaults'; export const createInvestigateInNewTimelineCellActionFactory = createCellActionFactory( ({ diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/constants.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/constants.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/constants.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/constants.ts diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/data_provider.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/data_provider.ts similarity index 88% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/data_provider.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/data_provider.ts index ac50c5de28ef5..ee1d32bd4b6f6 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/data_provider.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/data_provider.ts @@ -9,13 +9,13 @@ import { escapeDataProviderId } from '@kbn/securitysolution-t-grid'; import type { Serializable } from '@kbn/utility-types'; import { isArray, isString, isEmpty } from 'lodash/fp'; -import { INDICATOR_REFERENCE } from '../../../common/cti/constants'; -import type { DataProvider, QueryOperator } from '../../../common/types'; -import { EXISTS_OPERATOR, IS_OPERATOR } from '../../../common/types'; -import { IP_FIELD_TYPE } from '../../explore/network/components/ip'; -import { PORT_NAMES } from '../../explore/network/components/port/helpers'; -import { EVENT_DURATION_FIELD_NAME } from '../../timelines/components/duration'; -import { BYTES_FORMAT } from '../../timelines/components/timeline/body/renderers/bytes'; +import { INDICATOR_REFERENCE } from '../../../../common/cti/constants'; +import type { DataProvider, QueryOperator } from '../../../../common/types'; +import { EXISTS_OPERATOR, IS_OPERATOR } from '../../../../common/types'; +import { IP_FIELD_TYPE } from '../../../explore/network/components/ip'; +import { PORT_NAMES } from '../../../explore/network/components/port/helpers'; +import { EVENT_DURATION_FIELD_NAME } from '../../../timelines/components/duration'; +import { BYTES_FORMAT } from '../../../timelines/components/timeline/body/renderers/bytes'; import { GEO_FIELD_TYPE, MESSAGE_FIELD_NAME, @@ -25,7 +25,7 @@ import { RULE_REFERENCE_FIELD_NAME, REFERENCE_URL_FIELD_NAME, EVENT_URL_FIELD_NAME, -} from '../../timelines/components/timeline/body/renderers/constants'; +} from '../../../timelines/components/timeline/body/renderers/constants'; import { isCountField } from '../utils'; export const getDataProvider = ({ diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/discover/add_to_timeline.test.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts similarity index 88% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/discover/add_to_timeline.test.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts index 4374bf70b19bc..b79017aa322bb 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/discover/add_to_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import type { SecurityAppStore } from '../../../common/store/types'; -import { TimelineId } from '../../../../common/types'; -import { addProvider } from '../../../timelines/store/actions'; +import type { SecurityAppStore } from '../../../../common/store/types'; +import { TimelineId } from '../../../../../common/types'; +import { addProvider } from '../../../../timelines/store/actions'; import { createAddToTimelineDiscoverCellActionFactory } from './add_to_timeline'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; -import { GEO_FIELD_TYPE } from '../../../timelines/components/timeline/body/renderers/constants'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; -import { APP_UI_ID } from '../../../../common'; +import { GEO_FIELD_TYPE } from '../../../../timelines/components/timeline/body/renderers/constants'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; +import { APP_UI_ID } from '../../../../../common'; import { BehaviorSubject } from 'rxjs'; const services = createStartServicesMock(); diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/discover/add_to_timeline.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts similarity index 89% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/discover/add_to_timeline.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts index 859f14652810b..429d1e1f9db2a 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/discover/add_to_timeline.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/discover/add_to_timeline.ts @@ -6,9 +6,9 @@ */ import type { CellAction, CellActionFactory } from '@kbn/cell-actions'; -import type { SecurityAppStore } from '../../../common/store'; +import type { SecurityAppStore } from '../../../../common/store'; import { isInSecurityApp } from '../../utils'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import { createAddToTimelineCellActionFactory } from '../cell_action/add_to_timeline'; export const createAddToTimelineDiscoverCellActionFactory = ({ diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/index.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/index.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/index.ts diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/lens/add_to_timeline.test.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/lens/add_to_timeline.test.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts index 976d0f13efab0..b1a272de4d37e 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/lens/add_to_timeline.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.test.ts @@ -8,16 +8,16 @@ import { Subject } from 'rxjs'; import type { CellValueContext, EmbeddableInput, IEmbeddable } from '@kbn/embeddable-plugin/public'; import { ErrorEmbeddable } from '@kbn/embeddable-plugin/public'; import { LENS_EMBEDDABLE_TYPE } from '@kbn/lens-plugin/public'; -import type { SecurityAppStore } from '../../../common/store/types'; +import type { SecurityAppStore } from '../../../../common/store/types'; import { createAddToTimelineLensAction, getInvestigatedValue } from './add_to_timeline'; -import { KibanaServices } from '../../../common/lib/kibana'; -import { APP_UI_ID } from '../../../../common/constants'; -import type { DataProvider } from '../../../../common/types'; -import { TimelineId, EXISTS_OPERATOR } from '../../../../common/types'; -import { addProvider } from '../../../timelines/store/actions'; +import { KibanaServices } from '../../../../common/lib/kibana'; +import { APP_UI_ID } from '../../../../../common/constants'; +import type { DataProvider } from '../../../../../common/types'; +import { TimelineId, EXISTS_OPERATOR } from '../../../../../common/types'; +import { addProvider } from '../../../../timelines/store/actions'; import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -jest.mock('../../../common/lib/kibana'); +jest.mock('../../../../common/lib/kibana'); const currentAppId$ = new Subject(); KibanaServices.get().application.currentAppId$ = currentAppId$.asObservable(); const mockWarningToast = jest.fn(); diff --git a/x-pack/plugins/security_solution/public/actions/add_to_timeline/lens/add_to_timeline.ts b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts similarity index 91% rename from x-pack/plugins/security_solution/public/actions/add_to_timeline/lens/add_to_timeline.ts rename to x-pack/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts index 7646b3fba6814..84c95fd659fba 100644 --- a/x-pack/plugins/security_solution/public/actions/add_to_timeline/lens/add_to_timeline.ts +++ b/x-pack/plugins/security_solution/public/app/actions/add_to_timeline/lens/add_to_timeline.ts @@ -8,11 +8,11 @@ import type { CellValueContext, IEmbeddable } from '@kbn/embeddable-plugin/public'; import { isErrorEmbeddable, isFilterableEmbeddable } from '@kbn/embeddable-plugin/public'; import { createAction } from '@kbn/ui-actions-plugin/public'; -import { KibanaServices } from '../../../common/lib/kibana'; -import type { SecurityAppStore } from '../../../common/store/types'; -import { addProvider } from '../../../timelines/store/actions'; -import type { DataProvider } from '../../../../common/types'; -import { EXISTS_OPERATOR, TimelineId } from '../../../../common/types'; +import { KibanaServices } from '../../../../common/lib/kibana'; +import type { SecurityAppStore } from '../../../../common/store/types'; +import { addProvider } from '../../../../timelines/store/actions'; +import type { DataProvider } from '../../../../../common/types'; +import { EXISTS_OPERATOR, TimelineId } from '../../../../../common/types'; import { fieldHasCellActions, isInSecurityApp, isLensEmbeddable } from '../../utils'; import { ADD_TO_TIMELINE, diff --git a/x-pack/plugins/security_solution/public/actions/constants.ts b/x-pack/plugins/security_solution/public/app/actions/constants.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/constants.ts rename to x-pack/plugins/security_solution/public/app/actions/constants.ts diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts index ce4655bd6afe2..a7a72fdd967ee 100644 --- a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/cell_action/copy_to_clipboard.test.ts @@ -6,7 +6,7 @@ */ import { createCopyToClipboardCellActionFactory } from './copy_to_clipboard'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; const services = createStartServicesMock(); diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts similarity index 89% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts index e4e30a0576cbb..6b766d735f8dd 100644 --- a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts +++ b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/cell_action/copy_to_clipboard.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { createCopyToClipboardActionFactory as genericCreateCopyToClipboardActionFactory } from '@kbn/cell-actions'; +import { createCopyToClipboardActionFactory as genericCreateCopyToClipboardActionFactory } from '@kbn/cell-actions/actions'; import { fieldHasCellActions } from '../../utils'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/constants.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/constants.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/constants.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/constants.ts diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts similarity index 94% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts index 0a4032e9b0136..6e939c8fff5f4 100644 --- a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/discover/copy_to_clipboard.test.ts @@ -6,10 +6,10 @@ */ import { createCopyToClipboardDiscoverCellActionFactory } from './copy_to_clipboard'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; import { BehaviorSubject } from 'rxjs'; -import { APP_UI_ID } from '../../../../common'; +import { APP_UI_ID } from '../../../../../common'; const services = createStartServicesMock(); const mockSuccessToast = services.notifications.toasts.addSuccess; diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/discover/copy_to_clipboard.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/discover/copy_to_clipboard.ts similarity index 94% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/discover/copy_to_clipboard.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/discover/copy_to_clipboard.ts index ac3e077597afd..7a2c39717b342 100644 --- a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/discover/copy_to_clipboard.ts +++ b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/discover/copy_to_clipboard.ts @@ -7,7 +7,7 @@ import type { CellAction, CellActionFactory } from '@kbn/cell-actions'; import { isInSecurityApp } from '../../utils'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import { createCopyToClipboardCellActionFactory } from '../cell_action/copy_to_clipboard'; export const createCopyToClipboardDiscoverCellActionFactory = ({ diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/index.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/index.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/index.ts diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts similarity index 97% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts index 5e80ab4b00409..bb036e3f12e07 100644 --- a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.test.ts @@ -9,12 +9,12 @@ import type { CellValueContext, EmbeddableInput, IEmbeddable } from '@kbn/embedd import { ErrorEmbeddable } from '@kbn/embeddable-plugin/public'; import { LENS_EMBEDDABLE_TYPE } from '@kbn/lens-plugin/public'; import { createCopyToClipboardLensAction } from './copy_to_clipboard'; -import { KibanaServices } from '../../../common/lib/kibana'; -import { APP_UI_ID } from '../../../../common/constants'; +import { KibanaServices } from '../../../../common/lib/kibana'; +import { APP_UI_ID } from '../../../../../common/constants'; import { Subject } from 'rxjs'; import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -jest.mock('../../../common/lib/kibana'); +jest.mock('../../../../common/lib/kibana'); const currentAppId$ = new Subject(); KibanaServices.get().application.currentAppId$ = currentAppId$.asObservable(); const mockSuccessToast = jest.fn(); diff --git a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/lens/copy_to_clipboard.ts b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.ts similarity index 97% rename from x-pack/plugins/security_solution/public/actions/copy_to_clipboard/lens/copy_to_clipboard.ts rename to x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.ts index 1daa5bc2db061..8546f0c3260cc 100644 --- a/x-pack/plugins/security_solution/public/actions/copy_to_clipboard/lens/copy_to_clipboard.ts +++ b/x-pack/plugins/security_solution/public/app/actions/copy_to_clipboard/lens/copy_to_clipboard.ts @@ -9,7 +9,7 @@ import type { CellValueContext, IEmbeddable } from '@kbn/embeddable-plugin/publi import { isErrorEmbeddable } from '@kbn/embeddable-plugin/public'; import { createAction } from '@kbn/ui-actions-plugin/public'; import copy from 'copy-to-clipboard'; -import { KibanaServices } from '../../../common/lib/kibana'; +import { KibanaServices } from '../../../../common/lib/kibana'; import { fieldHasCellActions, isCountField, isInSecurityApp, isLensEmbeddable } from '../../utils'; import { COPY_TO_CLIPBOARD, COPY_TO_CLIPBOARD_ICON, COPY_TO_CLIPBOARD_SUCCESS } from '../constants'; diff --git a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_in.test.ts b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_in.test.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_in.test.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_in.test.ts index bb395829bcdff..65894133828fd 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_in.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_in.test.ts @@ -8,11 +8,11 @@ import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { TableId } from '@kbn/securitysolution-data-table'; -import { createMockStore, mockGlobalState } from '../../../common/mock'; +import { createMockStore, mockGlobalState } from '../../../../common/mock'; import { createFilterInCellActionFactory } from './filter_in'; import type { SecurityCellActionExecutionContext } from '../../types'; -import { TimelineId } from '../../../../common/types'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { TimelineId } from '../../../../../common/types'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; const services = createStartServicesMock(); const mockGlobalFilterManager = services.data.query.filterManager; diff --git a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_in.ts b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_in.ts similarity index 90% rename from x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_in.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_in.ts index 3a92021089361..2c5f7bd62cd63 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_in.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_in.ts @@ -5,20 +5,20 @@ * 2.0. */ -import { addFilterIn, addFilterOut, createFilterInActionFactory } from '@kbn/cell-actions'; +import { addFilterIn, addFilterOut, createFilterInActionFactory } from '@kbn/cell-actions/actions'; import { isTypeSupportedByDefaultActions, isValueSupportedByDefaultActions, - valueToArray, filterOutNullableValues, -} from '@kbn/cell-actions/src/actions/utils'; + valueToArray, +} from '@kbn/cell-actions/actions/utils'; import type { KBN_FIELD_TYPES } from '@kbn/field-types'; import { ACTION_INCOMPATIBLE_VALUE_WARNING } from '@kbn/cell-actions/src/actions/translations'; -import type { SecurityAppStore } from '../../../common/store'; +import type { SecurityAppStore } from '../../../../common/store'; import { fieldHasCellActions } from '../../utils'; -import { isTimelineScope } from '../../../helpers'; +import { isTimelineScope } from '../../../../helpers'; import { SecurityCellActionType } from '../../constants'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import type { SecurityCellAction } from '../../types'; export const createFilterInCellActionFactory = ({ diff --git a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_out.test.ts b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_out.test.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_out.test.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_out.test.ts index 43238b1d988e8..f4ba4527a2ca1 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_out.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_out.test.ts @@ -5,14 +5,14 @@ * 2.0. */ -import { createMockStore, mockGlobalState } from '../../../common/mock'; +import { createMockStore, mockGlobalState } from '../../../../common/mock'; import { createFilterOutCellActionFactory } from './filter_out'; import type { SecurityCellActionExecutionContext } from '../../types'; -import { TimelineId } from '../../../../common/types'; +import { TimelineId } from '../../../../../common/types'; import { TableId } from '@kbn/securitysolution-data-table'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; const mockServices = createStartServicesMock(); diff --git a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_out.ts b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_out.ts similarity index 90% rename from x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_out.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_out.ts index f177413901448..b6ffd15a5784d 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/cell_action/filter_out.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/cell_action/filter_out.ts @@ -5,19 +5,19 @@ * 2.0. */ -import { addFilterIn, addFilterOut, createFilterOutActionFactory } from '@kbn/cell-actions'; +import { addFilterIn, addFilterOut, createFilterOutActionFactory } from '@kbn/cell-actions/actions'; import { isTypeSupportedByDefaultActions, isValueSupportedByDefaultActions, - valueToArray, filterOutNullableValues, -} from '@kbn/cell-actions/src/actions/utils'; + valueToArray, +} from '@kbn/cell-actions/actions/utils'; import { ACTION_INCOMPATIBLE_VALUE_WARNING } from '@kbn/cell-actions/src/actions/translations'; import type { KBN_FIELD_TYPES } from '@kbn/field-types'; import { fieldHasCellActions } from '../../utils'; -import type { SecurityAppStore } from '../../../common/store'; -import type { StartServices } from '../../../types'; -import { isTimelineScope } from '../../../helpers'; +import type { SecurityAppStore } from '../../../../common/store'; +import type { StartServices } from '../../../../types'; +import { isTimelineScope } from '../../../../helpers'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; diff --git a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_in.test.ts b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_in.test.ts similarity index 92% rename from x-pack/plugins/security_solution/public/actions/filter/discover/filter_in.test.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_in.test.ts index c7136f87e05b9..08c04bceeda75 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_in.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_in.test.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { createMockStore } from '../../../common/mock'; +import { createMockStore } from '../../../../common/mock'; import { createFilterInDiscoverCellActionFactory } from './filter_in'; import type { SecurityCellActionExecutionContext } from '../../types'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; import { BehaviorSubject } from 'rxjs'; -import { APP_UI_ID } from '../../../../common'; +import { APP_UI_ID } from '../../../../../common'; const services = createStartServicesMock(); const mockGlobalFilterManager = services.data.query.filterManager; diff --git a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_in.ts b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_in.ts similarity index 89% rename from x-pack/plugins/security_solution/public/actions/filter/discover/filter_in.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_in.ts index d9d575ef5cbd6..d0cdaed61f8a2 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_in.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_in.ts @@ -6,9 +6,9 @@ */ import type { CellAction, CellActionFactory } from '@kbn/cell-actions'; -import type { SecurityAppStore } from '../../../common/store'; +import type { SecurityAppStore } from '../../../../common/store'; import { isInSecurityApp } from '../../utils'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import { createFilterInCellActionFactory } from '../cell_action/filter_in'; export const createFilterInDiscoverCellActionFactory = ({ diff --git a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_out.test.ts b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_out.test.ts similarity index 92% rename from x-pack/plugins/security_solution/public/actions/filter/discover/filter_out.test.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_out.test.ts index fa028bce4ecd9..271619f24cf9f 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_out.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_out.test.ts @@ -5,12 +5,12 @@ * 2.0. */ -import { createMockStore } from '../../../common/mock'; +import { createMockStore } from '../../../../common/mock'; import { createFilterOutDiscoverCellActionFactory } from './filter_out'; import type { SecurityCellActionExecutionContext } from '../../types'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; import { BehaviorSubject } from 'rxjs'; -import { APP_UI_ID } from '../../../../common'; +import { APP_UI_ID } from '../../../../../common'; const services = createStartServicesMock(); const mockGlobalFilterManager = services.data.query.filterManager; diff --git a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_out.ts b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_out.ts similarity index 89% rename from x-pack/plugins/security_solution/public/actions/filter/discover/filter_out.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_out.ts index 07b8d1e61b37a..757b2f41d99b5 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/discover/filter_out.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/discover/filter_out.ts @@ -7,8 +7,8 @@ import type { CellActionFactory, CellAction } from '@kbn/cell-actions'; import { isInSecurityApp } from '../../utils'; -import type { SecurityAppStore } from '../../../common/store'; -import type { StartServices } from '../../../types'; +import type { SecurityAppStore } from '../../../../common/store'; +import type { StartServices } from '../../../../types'; import { createFilterOutCellActionFactory } from '../cell_action/filter_out'; export const createFilterOutDiscoverCellActionFactory = ({ diff --git a/x-pack/plugins/security_solution/public/actions/filter/index.ts b/x-pack/plugins/security_solution/public/app/actions/filter/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/filter/index.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/index.ts diff --git a/x-pack/plugins/security_solution/public/actions/filter/lens/create_action.test.ts b/x-pack/plugins/security_solution/public/app/actions/filter/lens/create_action.test.ts similarity index 97% rename from x-pack/plugins/security_solution/public/actions/filter/lens/create_action.test.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/lens/create_action.test.ts index d8f004f063ecb..b0e61e81cf3b2 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/lens/create_action.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/lens/create_action.test.ts @@ -5,20 +5,20 @@ * 2.0. */ -import { addExistsFilter, addFilterIn, addFilterOut } from '@kbn/cell-actions'; +import { addExistsFilter, addFilterIn, addFilterOut } from '@kbn/cell-actions/actions'; import { of } from 'rxjs'; import type { CellValueContext } from '@kbn/embeddable-plugin/public'; import type { CreateFilterLensActionParams } from './create_action'; import { createFilterLensAction } from './create_action'; import type { Trigger } from '@kbn/ui-actions-plugin/public'; -jest.mock('@kbn/cell-actions', () => ({ +jest.mock('@kbn/cell-actions/actions', () => ({ addFilterIn: jest.fn(), addFilterOut: jest.fn(), addExistsFilter: jest.fn(), })); -jest.mock('../../../timelines/store', () => ({ +jest.mock('../../../../timelines/store', () => ({ timelineSelectors: { getTimelineByIdSelector: jest.fn().mockReturnValue(() => ({})), }, diff --git a/x-pack/plugins/security_solution/public/actions/filter/lens/create_action.ts b/x-pack/plugins/security_solution/public/app/actions/filter/lens/create_action.ts similarity index 92% rename from x-pack/plugins/security_solution/public/actions/filter/lens/create_action.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/lens/create_action.ts index a6d69bf1b3530..966efe9590ecc 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/lens/create_action.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/lens/create_action.ts @@ -5,23 +5,23 @@ * 2.0. */ -import { addExistsFilter, addFilterIn, addFilterOut } from '@kbn/cell-actions'; +import { addExistsFilter, addFilterIn, addFilterOut } from '@kbn/cell-actions/actions'; import { isValueSupportedByDefaultActions, - valueToArray, filterOutNullableValues, -} from '@kbn/cell-actions/src/actions/utils'; + valueToArray, +} from '@kbn/cell-actions/actions/utils'; import { isErrorEmbeddable } from '@kbn/embeddable-plugin/public'; import type { CellValueContext, IEmbeddable } from '@kbn/embeddable-plugin/public'; import { createAction } from '@kbn/ui-actions-plugin/public'; import { ACTION_INCOMPATIBLE_VALUE_WARNING } from '@kbn/cell-actions/src/actions/translations'; import { i18n } from '@kbn/i18n'; -import { timelineSelectors } from '../../../timelines/store'; +import { timelineSelectors } from '../../../../timelines/store'; import { fieldHasCellActions, isInSecurityApp, isLensEmbeddable } from '../../utils'; -import { TimelineId } from '../../../../common/types'; +import { TimelineId } from '../../../../../common/types'; import { DefaultCellActionTypes } from '../../constants'; -import type { SecurityAppStore } from '../../../common/store'; -import type { StartServices } from '../../../types'; +import type { SecurityAppStore } from '../../../../common/store'; +import type { StartServices } from '../../../../types'; function isDataColumnsValid(data?: CellValueContext['data']): boolean { return ( diff --git a/x-pack/plugins/security_solution/public/actions/filter/lens/filter_in.ts b/x-pack/plugins/security_solution/public/app/actions/filter/lens/filter_in.ts similarity index 83% rename from x-pack/plugins/security_solution/public/actions/filter/lens/filter_in.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/lens/filter_in.ts index fae9175879c9f..5c54312814f7f 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/lens/filter_in.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/lens/filter_in.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { SecurityAppStore } from '../../../common/store'; +import type { SecurityAppStore } from '../../../../common/store'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import { createFilterLensAction } from './create_action'; export const ACTION_ID = 'embeddable_filterIn'; diff --git a/x-pack/plugins/security_solution/public/actions/filter/lens/filter_out.ts b/x-pack/plugins/security_solution/public/app/actions/filter/lens/filter_out.ts similarity index 83% rename from x-pack/plugins/security_solution/public/actions/filter/lens/filter_out.ts rename to x-pack/plugins/security_solution/public/app/actions/filter/lens/filter_out.ts index 2b629ac1be861..69560bfbd1513 100644 --- a/x-pack/plugins/security_solution/public/actions/filter/lens/filter_out.ts +++ b/x-pack/plugins/security_solution/public/app/actions/filter/lens/filter_out.ts @@ -5,9 +5,9 @@ * 2.0. */ -import type { SecurityAppStore } from '../../../common/store'; +import type { SecurityAppStore } from '../../../../common/store'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import { createFilterLensAction } from './create_action'; export const ACTION_ID = 'embeddable_filterOut'; diff --git a/x-pack/plugins/security_solution/public/actions/index.ts b/x-pack/plugins/security_solution/public/app/actions/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/index.ts rename to x-pack/plugins/security_solution/public/app/actions/index.ts diff --git a/x-pack/plugins/security_solution/public/actions/register.ts b/x-pack/plugins/security_solution/public/app/actions/register.ts similarity index 98% rename from x-pack/plugins/security_solution/public/actions/register.ts rename to x-pack/plugins/security_solution/public/app/actions/register.ts index 620df75c73d27..6267539f40625 100644 --- a/x-pack/plugins/security_solution/public/actions/register.ts +++ b/x-pack/plugins/security_solution/public/app/actions/register.ts @@ -9,8 +9,8 @@ import { CELL_VALUE_TRIGGER } from '@kbn/embeddable-plugin/public'; import type { History } from 'history'; import { SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER_ID } from '@kbn/discover-plugin/public'; import type { CoreSetup } from '@kbn/core/public'; -import type { SecurityAppStore } from '../common/store/types'; -import type { StartServices } from '../types'; +import type { SecurityAppStore } from '../../common/store/types'; +import type { StartServices } from '../../types'; import { createFilterInCellActionFactory, createFilterInDiscoverCellActionFactory, diff --git a/x-pack/plugins/security_solution/public/actions/register_discover_histogram_actions.ts b/x-pack/plugins/security_solution/public/app/actions/register_discover_histogram_actions.ts similarity index 93% rename from x-pack/plugins/security_solution/public/actions/register_discover_histogram_actions.ts rename to x-pack/plugins/security_solution/public/app/actions/register_discover_histogram_actions.ts index 4a737ba901107..796550bba63ae 100644 --- a/x-pack/plugins/security_solution/public/actions/register_discover_histogram_actions.ts +++ b/x-pack/plugins/security_solution/public/app/actions/register_discover_histogram_actions.ts @@ -8,8 +8,8 @@ import { createFilterAction } from '@kbn/unified-search-plugin/public'; import type { History } from 'history'; import type { CoreSetup } from '@kbn/core/public'; -import type { SecurityAppStore } from '../common/store'; -import type { StartServices } from '../types'; +import type { SecurityAppStore } from '../../common/store'; +import type { StartServices } from '../../types'; import { EsqlInTimelineTrigger, EsqlInTimelineAction } from './constants'; const createDiscoverHistogramCustomFilterAction = ( 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/app/actions/show_top_n/cell_action/show_top_n.test.tsx similarity index 94% rename from x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.test.tsx rename to x-pack/plugins/security_solution/public/app/actions/show_top_n/cell_action/show_top_n.test.tsx index 0fb5552eb1e54..3a073935dea85 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/app/actions/show_top_n/cell_action/show_top_n.test.tsx @@ -8,11 +8,11 @@ import type { CellActionExecutionContext } from '@kbn/cell-actions'; import { createShowTopNCellActionFactory } from './show_top_n'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; -jest.mock('../../../common/lib/kibana'); +jest.mock('../../../../common/lib/kibana'); const mockServices = { ...createStartServicesMock(), 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/app/actions/show_top_n/cell_action/show_top_n.tsx similarity index 92% rename from x-pack/plugins/security_solution/public/actions/show_top_n/cell_action/show_top_n.tsx rename to x-pack/plugins/security_solution/public/app/actions/show_top_n/cell_action/show_top_n.tsx index 16916fc6ac00a..1355da9811826 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/app/actions/show_top_n/cell_action/show_top_n.tsx @@ -5,14 +5,14 @@ * 2.0. */ import { i18n } from '@kbn/i18n'; -import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions'; +import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions/actions'; import { isDataViewFieldSubtypeNested } from '@kbn/es-query'; import { first } from 'lodash/fp'; import { fieldHasCellActions } from '../../utils'; -import type { StartServices } from '../../../types'; +import type { StartServices } from '../../../../types'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; -import { isLensSupportedType } from '../../../common/utils/lens'; +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/show_top_n/index.ts b/x-pack/plugins/security_solution/public/app/actions/show_top_n/index.ts similarity index 100% rename from x-pack/plugins/security_solution/public/actions/show_top_n/index.ts rename to x-pack/plugins/security_solution/public/app/actions/show_top_n/index.ts diff --git a/x-pack/plugins/security_solution/public/actions/telemetry.test.ts b/x-pack/plugins/security_solution/public/app/actions/telemetry.test.ts similarity index 96% rename from x-pack/plugins/security_solution/public/actions/telemetry.test.ts rename to x-pack/plugins/security_solution/public/app/actions/telemetry.test.ts index 2cfdf603b4998..9b22aa03fbeaf 100644 --- a/x-pack/plugins/security_solution/public/actions/telemetry.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/telemetry.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { StartServices } from '../types'; +import type { StartServices } from '../../types'; import { enhanceActionWithTelemetry } from './telemetry'; import { createAction } from '@kbn/ui-actions-plugin/public'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; diff --git a/x-pack/plugins/security_solution/public/actions/telemetry.ts b/x-pack/plugins/security_solution/public/app/actions/telemetry.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/telemetry.ts rename to x-pack/plugins/security_solution/public/app/actions/telemetry.ts index 3179e5143a34f..319194e57f81a 100644 --- a/x-pack/plugins/security_solution/public/actions/telemetry.ts +++ b/x-pack/plugins/security_solution/public/app/actions/telemetry.ts @@ -7,7 +7,7 @@ import type { CellAction, CellActionExecutionContext } from '@kbn/cell-actions'; import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; -import type { StartServices } from '../types'; +import type { StartServices } from '../../types'; import type { SecurityCellActionExecutionContext } from './types'; export const enhanceActionWithTelemetry = ( diff --git a/x-pack/plugins/security_solution/public/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts b/x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts similarity index 93% rename from x-pack/plugins/security_solution/public/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts rename to x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts index 1350fed3b3df6..d4ec20efafa57 100644 --- a/x-pack/plugins/security_solution/public/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/cell_action/toggle_asset_column.test.ts @@ -7,10 +7,10 @@ import type { CellActionExecutionContext } from '@kbn/cell-actions'; import { createToggleUserAssetFieldCellActionFactory } from './toggle_asset_column'; -import type { SecurityAppStore } from '../../../common/store/types'; -import { mockGlobalState } from '../../../common/mock'; -import { UserAssetTableType } from '../../../explore/users/store/model'; -import { usersActions } from '../../../explore/users/store'; +import type { SecurityAppStore } from '../../../../common/store/types'; +import { mockGlobalState } from '../../../../common/mock'; +import { UserAssetTableType } from '../../../../explore/users/store/model'; +import { usersActions } from '../../../../explore/users/store'; const existingFieldName = 'existing.field'; const fieldName = 'user.name'; diff --git a/x-pack/plugins/security_solution/public/actions/toggle_asset_column/cell_action/toggle_asset_column.ts b/x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/cell_action/toggle_asset_column.ts similarity index 89% rename from x-pack/plugins/security_solution/public/actions/toggle_asset_column/cell_action/toggle_asset_column.ts rename to x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/cell_action/toggle_asset_column.ts index 0905770c8edbd..b38b27b3d6553 100644 --- a/x-pack/plugins/security_solution/public/actions/toggle_asset_column/cell_action/toggle_asset_column.ts +++ b/x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/cell_action/toggle_asset_column.ts @@ -6,11 +6,11 @@ */ import { i18n } from '@kbn/i18n'; -import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions'; -import { UserAssetTableType } from '../../../explore/users/store/model'; -import { usersActions, usersSelectors } from '../../../explore/users/store'; +import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions/actions'; +import { UserAssetTableType } from '../../../../explore/users/store/model'; +import { usersActions, usersSelectors } from '../../../../explore/users/store'; import { fieldHasCellActions } from '../../utils'; -import type { SecurityAppStore } from '../../../common/store'; +import type { SecurityAppStore } from '../../../../common/store'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; diff --git a/x-pack/plugins/security_solution/public/actions/toggle_asset_column/index.tsx b/x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/index.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/actions/toggle_asset_column/index.tsx rename to x-pack/plugins/security_solution/public/app/actions/toggle_asset_column/index.tsx diff --git a/x-pack/plugins/security_solution/public/actions/toggle_column/cell_action/toggle_column.test.ts b/x-pack/plugins/security_solution/public/app/actions/toggle_column/cell_action/toggle_column.test.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/toggle_column/cell_action/toggle_column.test.ts rename to x-pack/plugins/security_solution/public/app/actions/toggle_column/cell_action/toggle_column.test.ts index 1697d73fc86f1..d6517cab313a4 100644 --- a/x-pack/plugins/security_solution/public/actions/toggle_column/cell_action/toggle_column.test.ts +++ b/x-pack/plugins/security_solution/public/app/actions/toggle_column/cell_action/toggle_column.test.ts @@ -5,13 +5,13 @@ * 2.0. */ -import type { SecurityAppStore } from '../../../common/store/types'; +import type { SecurityAppStore } from '../../../../common/store/types'; import { TableId, dataTableActions } from '@kbn/securitysolution-data-table'; import type { CellActionExecutionContext } from '@kbn/cell-actions'; import { createToggleColumnCellActionFactory } from './toggle_column'; -import { mockGlobalState } from '../../../common/mock'; -import { createStartServicesMock } from '../../../common/lib/kibana/kibana_react.mock'; +import { mockGlobalState } from '../../../../common/mock'; +import { createStartServicesMock } from '../../../../common/lib/kibana/kibana_react.mock'; const services = createStartServicesMock(); const mockAlertConfigGetActions = jest.fn(); diff --git a/x-pack/plugins/security_solution/public/actions/toggle_column/cell_action/toggle_column.ts b/x-pack/plugins/security_solution/public/app/actions/toggle_column/cell_action/toggle_column.ts similarity index 86% rename from x-pack/plugins/security_solution/public/actions/toggle_column/cell_action/toggle_column.ts rename to x-pack/plugins/security_solution/public/app/actions/toggle_column/cell_action/toggle_column.ts index c9409252277e0..2302374bef8c5 100644 --- a/x-pack/plugins/security_solution/public/actions/toggle_column/cell_action/toggle_column.ts +++ b/x-pack/plugins/security_solution/public/app/actions/toggle_column/cell_action/toggle_column.ts @@ -6,22 +6,22 @@ */ import { i18n } from '@kbn/i18n'; -import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions'; +import { createCellActionFactory, type CellActionTemplate } from '@kbn/cell-actions/actions'; import { defaultColumnHeaderType, tableDefaults, dataTableSelectors, } from '@kbn/securitysolution-data-table'; import { fieldHasCellActions } from '../../utils'; -import type { SecurityAppStore } from '../../../common/store'; -import { getScopedActions, isInTableScope, isTimelineScope } from '../../../helpers'; -import { timelineDefaults } from '../../../timelines/store/defaults'; -import { timelineSelectors } from '../../../timelines/store'; -import { DEFAULT_COLUMN_MIN_WIDTH } from '../../../timelines/components/timeline/body/constants'; +import type { SecurityAppStore } from '../../../../common/store'; +import { getScopedActions, isInTableScope, isTimelineScope } from '../../../../helpers'; +import { timelineDefaults } from '../../../../timelines/store/defaults'; +import { timelineSelectors } from '../../../../timelines/store'; +import { DEFAULT_COLUMN_MIN_WIDTH } from '../../../../timelines/components/timeline/body/constants'; import type { SecurityCellAction } from '../../types'; import { SecurityCellActionType } from '../../constants'; -import type { StartServices } from '../../../types'; -import { getAlertConfigIdByScopeId } from '../../../common/lib/triggers_actions_ui/alert_table_scope_config'; +import type { StartServices } from '../../../../types'; +import { getAlertConfigIdByScopeId } from '../../../../common/lib/triggers_actions_ui/alert_table_scope_config'; const ICON = 'listAdd'; const COLUMN_TOGGLE = i18n.translate('xpack.securitySolution.actions.toggleColumnToggle.label', { diff --git a/x-pack/plugins/security_solution/public/actions/toggle_column/index.tsx b/x-pack/plugins/security_solution/public/app/actions/toggle_column/index.tsx similarity index 100% rename from x-pack/plugins/security_solution/public/actions/toggle_column/index.tsx rename to x-pack/plugins/security_solution/public/app/actions/toggle_column/index.tsx diff --git a/x-pack/plugins/security_solution/public/actions/types.ts b/x-pack/plugins/security_solution/public/app/actions/types.ts similarity index 93% rename from x-pack/plugins/security_solution/public/actions/types.ts rename to x-pack/plugins/security_solution/public/app/actions/types.ts index ca0ee9d8d9fa2..999bc9ed99c0f 100644 --- a/x-pack/plugins/security_solution/public/actions/types.ts +++ b/x-pack/plugins/security_solution/public/app/actions/types.ts @@ -6,7 +6,7 @@ */ import type { CellAction, CellActionExecutionContext, CellActionFactory } from '@kbn/cell-actions'; -import type { QueryOperator } from '../../common/types'; +import type { QueryOperator } from '../../../common/types'; export { EsqlInTimelineTrigger, EsqlInTimelineAction } from './constants'; export interface AndFilter { field: string; @@ -14,7 +14,7 @@ export interface AndFilter { operator?: QueryOperator; } -export interface SecurityMetadata extends Record { +export interface SecurityCellActionMetadata extends Record { /** * `metadata.scopeId` is used by some actions (e.g. filterIn/Out) to discriminate the Timeline * and the DataTables scope (alerts, events, rules preview..) in the actions execution. @@ -52,7 +52,7 @@ export interface SecurityMetadata extends Record { } export interface SecurityCellActionExecutionContext extends CellActionExecutionContext { - metadata: SecurityMetadata | undefined; + metadata: SecurityCellActionMetadata | undefined; } export type SecurityCellAction = CellAction; diff --git a/x-pack/plugins/security_solution/public/actions/utils.ts b/x-pack/plugins/security_solution/public/app/actions/utils.ts similarity index 95% rename from x-pack/plugins/security_solution/public/actions/utils.ts rename to x-pack/plugins/security_solution/public/app/actions/utils.ts index 74b40334284cf..12c5400dbcf36 100644 --- a/x-pack/plugins/security_solution/public/actions/utils.ts +++ b/x-pack/plugins/security_solution/public/app/actions/utils.ts @@ -7,7 +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 { APP_UI_ID } from '../../common/constants'; +import { APP_UI_ID } from '../../../common/constants'; // All cell actions are disabled for these fields in Security const FIELDS_WITHOUT_CELL_ACTIONS = [ diff --git a/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts b/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts index 325e2bab84d6f..16599810b6a81 100644 --- a/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/get_flattened_legend_items.test.ts @@ -12,10 +12,11 @@ import { getRiskScorePalette, RISK_SCORE_STEPS } from '../chart_palette'; import { getFlattenedLegendItems } from './get_flattened_legend_items'; import { bucketsWithStackByField1, maxRiskSubAggregations } from '../flatten/mocks/mock_buckets'; import { flattenedBuckets } from '../flatten/mocks/mock_flattened_buckets'; +import { TableId } from '@kbn/securitysolution-data-table'; describe('getFlattenedLegendItems', () => { it('returns the expected legend items', () => { - const expected: Array> = [ + const expected: Array> = [ { count: 34, field: 'kibana.alert.rule.name', @@ -137,7 +138,7 @@ describe('getFlattenedLegendItems', () => { field: 'host.name', value: 'Host-r4y6xi92ob', }, - ]; + ].map((legend) => ({ ...legend, scopeId: TableId.alertsOnAlertsPage })); const legendItems = getFlattenedLegendItems({ buckets: bucketsWithStackByField1, diff --git a/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.test.ts b/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.test.ts index 303cca251f417..229dcafb0012a 100644 --- a/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.test.ts +++ b/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.test.ts @@ -17,6 +17,7 @@ import { getLegendMap, } from '.'; import type { FlattenedBucket, RawBucket } from '../../types'; +import { TableId } from '@kbn/securitysolution-data-table'; describe('legend', () => { const colorPalette = getRiskScorePalette(RISK_SCORE_STEPS); @@ -169,6 +170,7 @@ describe('legend', () => { count: 12, field: 'host.name', value: 'Host-k8iyfzraq9', + scopeId: TableId.alertsOnAlertsPage, }); }); @@ -214,30 +216,35 @@ describe('legend', () => { count: 34, field: 'kibana.alert.rule.name', value: 'matches everything', + scopeId: TableId.alertsOnAlertsPage, }, { color: '#da8b45', count: 28, field: 'kibana.alert.rule.name', value: 'EQL process sequence', + scopeId: TableId.alertsOnAlertsPage, }, { color: '#d6bf57', count: 19, field: 'kibana.alert.rule.name', value: 'Endpoint Security', + scopeId: TableId.alertsOnAlertsPage, }, { color: '#e7664c', count: 5, field: 'kibana.alert.rule.name', value: 'mimikatz process started', + scopeId: TableId.alertsOnAlertsPage, }, { color: '#e7664c', count: 1, field: 'kibana.alert.rule.name', value: 'Threshold rule', + scopeId: TableId.alertsOnAlertsPage, }, ]); }); @@ -264,7 +271,7 @@ describe('legend', () => { it('returns the expected legend item', () => { const expected: Record< string, - Array> + Array> > = { 'matches everything': [ { @@ -272,6 +279,7 @@ describe('legend', () => { count: 34, field: 'kibana.alert.rule.name', value: 'matches everything', + scopeId: TableId.alertsOnAlertsPage, }, ], 'EQL process sequence': [ @@ -280,6 +288,7 @@ describe('legend', () => { count: 28, field: 'kibana.alert.rule.name', value: 'EQL process sequence', + scopeId: TableId.alertsOnAlertsPage, }, ], 'Endpoint Security': [ @@ -288,6 +297,7 @@ describe('legend', () => { count: 19, field: 'kibana.alert.rule.name', value: 'Endpoint Security', + scopeId: TableId.alertsOnAlertsPage, }, ], 'mimikatz process started': [ @@ -296,6 +306,7 @@ describe('legend', () => { count: 5, field: 'kibana.alert.rule.name', value: 'mimikatz process started', + scopeId: TableId.alertsOnAlertsPage, }, ], 'Threshold rule': [ @@ -304,6 +315,7 @@ describe('legend', () => { count: 1, field: 'kibana.alert.rule.name', value: 'Threshold rule', + scopeId: TableId.alertsOnAlertsPage, }, ], }; diff --git a/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.ts b/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.ts index 9736987003252..9409d4f174730 100644 --- a/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/alerts_treemap/lib/legend/index.ts @@ -7,6 +7,7 @@ import { v4 as uuidv4 } from 'uuid'; +import { TableId } from '@kbn/securitysolution-data-table'; import { firstNonNullValue } from '../../../../../../common/endpoint/models/ecs_safety_helpers'; import type { LegendItem } from '../../../charts/draggable_legend_item'; import { getFillColor } from '../chart_palette'; @@ -44,6 +45,7 @@ export const getLegendItemFromRawBucket = ({ }), field: stackByField0, value: bucket.key_as_string ?? firstNonNullValue(bucket.key) ?? 0, + scopeId: TableId.alertsOnAlertsPage, }); export const getLegendItemFromFlattenedBucket = ({ @@ -70,6 +72,7 @@ export const getLegendItemFromFlattenedBucket = ({ render: () => `${stackByField1Key}`, field: `${stackByField1}`, value: `${stackByField1Key}`, + scopeId: TableId.alertsOnAlertsPage, }); export const getFirstGroupLegendItems = ({ diff --git a/x-pack/plugins/security_solution/public/common/components/cell_actions/index.test.tsx b/x-pack/plugins/security_solution/public/common/components/cell_actions/index.test.tsx index 6e252bd11b4fa..b056d4012df4c 100644 --- a/x-pack/plugins/security_solution/public/common/components/cell_actions/index.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/cell_actions/index.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { render } from '@testing-library/react'; -import { SecurityCellActionsTrigger } from '../../../actions/constants'; +import { SecurityCellActionsTrigger } from '../../../app/actions/constants'; import { CellActionsMode, SecurityCellActions } from '.'; import { CellActions } from '@kbn/cell-actions'; diff --git a/x-pack/plugins/security_solution/public/common/components/cell_actions/index.tsx b/x-pack/plugins/security_solution/public/common/components/cell_actions/index.tsx index 70aa80a97852b..5edc574177520 100644 --- a/x-pack/plugins/security_solution/public/common/components/cell_actions/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/cell_actions/index.tsx @@ -13,14 +13,16 @@ import type { } from '@kbn/cell-actions'; import React, { useMemo } from 'react'; import type { CellActionFieldValue, CellActionsData } from '@kbn/cell-actions/src/types'; -import type { SecurityMetadata } from '../../../actions/types'; -import { SecurityCellActionsTrigger, SecurityCellActionType } from '../../../actions/constants'; +import type { SecurityCellActionMetadata } from '../../../app/actions/types'; +import { SecurityCellActionsTrigger, SecurityCellActionType } from '../../../app/actions/constants'; import { SourcererScopeName } from '../../store/sourcerer/model'; import { useGetFieldSpec } from '../../hooks/use_get_field_spec'; import { useDataViewId } from '../../hooks/use_data_view_id'; // bridge exports for convenience export * from '@kbn/cell-actions'; +export * from '@kbn/cell-actions/constants'; + export { SecurityCellActionsTrigger, SecurityCellActionType }; export interface SecurityCellActionsData { @@ -39,14 +41,14 @@ export interface SecurityCellActionsProps data: SecurityCellActionsData | SecurityCellActionsData[]; triggerId: SecurityCellActionsTrigger; disabledActionTypes?: SecurityCellActionType[]; - metadata?: SecurityMetadata; + metadata?: SecurityCellActionMetadata; } export interface UseDataGridColumnsSecurityCellActionsProps extends UseDataGridColumnsCellActionsProps { triggerId: SecurityCellActionsTrigger; disabledActionTypes?: SecurityCellActionType[]; - metadata?: SecurityMetadata; + metadata?: SecurityCellActionMetadata; } export const useDataGridColumnsSecurityCellActions: UseDataGridColumnsCellActions = diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx new file mode 100644 index 0000000000000..8f438bb9289c4 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.test.tsx @@ -0,0 +1,97 @@ +/* + * 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 React from 'react'; +import { render } from '@testing-library/react'; +import { CellActionsWrapper } from './cell_actions_wrapper'; +import { CellActionsMode, SecurityCellActionType } from '../cell_actions'; +import { TimelineId, type DataProvider } from '../../../../common/types'; + +const MockSecurityCellActions = jest.fn(({ children }: { children: React.ReactNode }) => ( +
{children}
+)); +jest.mock('../cell_actions', () => ({ + ...jest.requireActual('../cell_actions'), + SecurityCellActions: (params: { children: React.ReactNode }) => MockSecurityCellActions(params), +})); + +const mockSourcererScopeId = 'testSourcererScopeId'; +jest.mock('../../../helpers', () => ({ + getSourcererScopeId: jest.fn(() => mockSourcererScopeId), +})); + +const dataProvider = { queryMatch: { field: 'host.name', value: '12345' } } as DataProvider; +const data = { ...dataProvider.queryMatch }; + +describe('CellActionsWrapper', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render cell actions with the content', () => { + const result = render( + {'test children'} + ); + expect(result.queryByTestId('mockSecurityCellActions')).toBeInTheDocument(); + expect(result.queryByText('test children')).toBeInTheDocument(); + }); + + it('should call cell actions with the default props', () => { + render({'test children'}); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ + data, + mode: CellActionsMode.HOVER_DOWN, + sourcererScopeId: mockSourcererScopeId, + disabledActionTypes: [], + metadata: { scopeId: TimelineId.active }, + }) + ); + }); + + describe('when dataProvider value is empty', () => { + it('should set an empty array value to the SecurityCellActions component', () => { + const emptyValueDataProvider = { + queryMatch: { field: 'host.name', value: '' }, + } as DataProvider; + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ data: { ...data, value: [] } }) + ); + }); + }); + + describe('when scopeId is defined', () => { + it('should set the scopeId to the SecurityCellActions component metadata', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ metadata: { scopeId: 'testScopeId' } }) + ); + }); + }); + + describe('when hideTopN is true', () => { + it('should set the disabledActionTypes to the SecurityCellActions component', () => { + render( + + {'test children'} + + ); + expect(MockSecurityCellActions).toHaveBeenCalledWith( + expect.objectContaining({ disabledActionTypes: [SecurityCellActionType.SHOW_TOP_N] }) + ); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx new file mode 100644 index 0000000000000..d10cd5aaf1984 --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/cell_actions_wrapper.tsx @@ -0,0 +1,76 @@ +/* + * 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 type { PropsWithChildren } from 'react'; +import React, { useContext, useMemo } from 'react'; +import { TimelineId, type DataProvider } from '../../../../common/types'; +import type { SecurityCellActionsData } from '../cell_actions'; +import { + CellActionsMode, + SecurityCellActions, + SecurityCellActionsTrigger, + SecurityCellActionType, +} from '../cell_actions'; +import { getSourcererScopeId } from '../../../helpers'; +import { TimelineContext } from '../../../timelines/components/timeline'; + +import { TableContext } from '../events_viewer/shared'; + +type CellActionsWrapperProps = PropsWithChildren<{ + /** + * The `dataProvider` is used to retrieve the `field` and `value` for the cell actions execution. + * */ + dataProvider: DataProvider; + /** + * The `hideTopN` is used hide the show top N action. Defaults to `false`. + * */ + hideTopN?: boolean; + /** + * The `scopeId` is used to determine the context of the cell actions execution. + * If not provided this component will try to retrieve the timeline id or the table id from the context, in that order. + * */ + scopeId?: string; +}>; + +export const CellActionsWrapper = React.memo>( + ({ dataProvider, scopeId = TimelineId.active, children, hideTopN = false }) => { + const { timelineId: timelineIdFind } = useContext(TimelineContext); + const { tableId: tableIdFind } = useContext(TableContext); + + const sourcererScopeId = useMemo( + () => getSourcererScopeId(scopeId ?? timelineIdFind ?? tableIdFind), + [scopeId, tableIdFind, timelineIdFind] + ); + + const data = useMemo(() => { + const { value, field } = dataProvider.queryMatch; + return { value: value || [], field }; + }, [dataProvider.queryMatch]); + + const disabledActionTypes = useMemo( + () => (hideTopN ? [SecurityCellActionType.SHOW_TOP_N] : []), + [hideTopN] + ); + + return ( + + {children} + + ); + } +); + +CellActionsWrapper.displayName = 'CellActionsWrapper'; diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx index dca5ac2c063b4..cd89220c20620 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { fireEvent, render, screen, waitFor } from '@testing-library/react'; +import { render } from '@testing-library/react'; import { shallow } from 'enzyme'; import React from 'react'; import type { DraggableStateSnapshot, DraggingStyle } from '@hello-pangea/dnd'; @@ -35,6 +35,14 @@ jest.mock('@elastic/eui', () => { }; }); +const MockSecurityCellActions = jest.fn(({ children }: { children: React.ReactNode }) => ( +
{children}
+)); +jest.mock('../cell_actions', () => ({ + ...jest.requireActual('../cell_actions'), + SecurityCellActions: (props: { children: React.ReactNode }) => MockSecurityCellActions(props), +})); + const scopeIdsWithHoverActions = [ undefined, TimelineId.active, @@ -105,46 +113,11 @@ describe('DraggableWrapper', () => { expect(wrapper.text()).toEqual(message); }); - test('it does NOT render hover actions when the mouse is NOT over the draggable wrapper', () => { - const wrapper = mount( - - - message} - /> - - - ); - - expect(wrapper.find('[data-test-subj="hover-actions-copy-button"]').exists()).toBe(false); - }); - - test('it renders hover actions when the mouse is over the text of draggable wrapper', async () => { - const wrapper = mount( - - - message} - /> - - - ); - - await waitFor(() => { - wrapper.find('[data-test-subj="withHoverActionsButton"]').simulate('mouseenter'); - expect(wrapper.find('[data-test-subj="hover-actions-copy-button"]').exists()).toBe(true); - }); - }); - scopeIdsWithHoverActions.forEach((scopeId) => { test(`it renders hover actions (by default) when 'isDraggable' is false and timelineId is '${scopeId}'`, async () => { const isDraggable = false; - const { container } = render( + const { queryByTestId } = render( { ); - fireEvent.mouseEnter(container.querySelector('[data-test-subj="withHoverActionsButton"]')!); - - await waitFor(() => { - expect(screen.getByTestId('hover-actions-copy-button')).toBeInTheDocument(); - }); + expect(queryByTestId('cell-actions-mock')).toBeInTheDocument(); }); }); @@ -169,7 +138,7 @@ describe('DraggableWrapper', () => { test(`it does NOT render hover actions when 'isDraggable' is false and timelineId is '${scopeId}'`, async () => { const isDraggable = false; - const { container } = render( + const { queryByTestId } = render( { ); - fireEvent.mouseEnter(container.querySelector('[data-test-subj="withHoverActionsButton"]')!); - - await waitFor(() => { - expect(screen.queryByTestId('hover-actions-copy-button')).not.toBeInTheDocument(); - }); + expect(queryByTestId('cell-actions-mock')).not.toBeInTheDocument(); }); }); }); diff --git a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx index 790a93b99e545..9a8762cee2c07 100644 --- a/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/common/components/drag_and_drop/draggable_wrapper.tsx @@ -24,14 +24,12 @@ import type { DataProvider } from '../../../timelines/components/timeline/data_p import { ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID } from '../../../timelines/components/row_renderers_browser/constants'; import { TruncatableText } from '../truncatable_text'; -import { WithHoverActions } from '../with_hover_actions'; +import { CellActionsWrapper } from './cell_actions_wrapper'; import { getDraggableId, getDroppableId } from './helpers'; import { ProviderContainer } from './provider_container'; import * as i18n from './translations'; -import { useHoverActions } from '../hover_actions/use_hover_actions'; -import { useDraggableKeyboardWrapper } from './draggable_keyboard_wrapper_hook'; // As right now, we do not know what we want there, we will keep it as a placeholder export const DragEffects = styled.div``; @@ -99,14 +97,13 @@ type RenderFunctionProp = ( interface Props { dataProvider: DataProvider; + fieldType?: string; + isAggregatable?: boolean; hideTopN?: boolean; isDraggable?: boolean; render: RenderFunctionProp; - isAggregatable?: boolean; - fieldType?: string; scopeId?: string; truncate?: boolean; - onFilterAdded?: () => void; } export const disableHoverActions = (timelineId: string | undefined): boolean => @@ -131,288 +128,202 @@ export const getStyle = ( }; }; -const DraggableOnWrapperComponent: React.FC = ({ - dataProvider, - hideTopN = false, - onFilterAdded, - render, - fieldType = '', - isAggregatable = false, - scopeId, - truncate, -}) => { - const [providerRegistered, setProviderRegistered] = useState(false); - const isDisabled = dataProvider.id.includes(`-${ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID}-`); - const dispatch = useDispatch(); - const { - closePopOverTrigger, - handleClosePopOverTrigger, - hoverActionsOwnFocus, - hoverContent, - keyboardHandlerRef, - onCloseRequested, - openPopover, - onFocus, - setContainerRef, - isShowingTopN, - } = useHoverActions({ - dataProvider, - hideTopN, - onFilterAdded, - render, - fieldType, - isAggregatable, - scopeId, - truncate, - }); - - const registerProvider = useCallback(() => { - if (!isDisabled) { - dispatch(dragAndDropActions.registerProvider({ provider: dataProvider })); - setProviderRegistered(true); - } - }, [isDisabled, dispatch, dataProvider]); - - const unRegisterProvider = useCallback( - () => - providerRegistered && - dispatch(dragAndDropActions.unRegisterProvider({ id: dataProvider.id })), - [providerRegistered, dispatch, dataProvider.id] - ); - - useEffect( - () => () => { - unRegisterProvider(); - }, - [unRegisterProvider] - ); - - const RenderClone = useCallback( - (provided, snapshot) => ( - -
= React.memo( + ({ dataProvider, render, scopeId, truncate, hideTopN }) => { + const [providerRegistered, setProviderRegistered] = useState(false); + const isDisabled = dataProvider.id.includes(`-${ROW_RENDERER_BROWSER_EXAMPLE_TIMELINE_ID}-`); + const dispatch = useDispatch(); + + const registerProvider = useCallback(() => { + if (!isDisabled) { + dispatch(dragAndDropActions.registerProvider({ provider: dataProvider })); + setProviderRegistered(true); + } + }, [isDisabled, dispatch, dataProvider]); + + const unRegisterProvider = useCallback( + () => + providerRegistered && + dispatch(dragAndDropActions.unRegisterProvider({ id: dataProvider.id })), + [providerRegistered, dispatch, dataProvider.id] + ); + + useEffect( + () => () => { + unRegisterProvider(); + }, + [unRegisterProvider] + ); + + const RenderClone = useCallback( + (provided, snapshot) => ( + +
+ + {render(dataProvider, provided, snapshot)} + +
+
+ ), + [dataProvider, registerProvider, render] + ); + + const DraggableContent = useCallback( + (provided, snapshot) => ( + { + provided.innerRef(e); + }} data-test-subj="providerContainer" + isDragging={snapshot.isDragging} + registerProvider={registerProvider} tabIndex={-1} > - - {render(dataProvider, provided, snapshot)} - -
-
- ), - [dataProvider, registerProvider, render] - ); - - const DraggableContent = useCallback( - (provided, snapshot) => ( - { - provided.innerRef(e); - setContainerRef(e); - }} - data-test-subj="providerContainer" - isDragging={snapshot.isDragging} - registerProvider={registerProvider} - tabIndex={-1} - > - -

{dataProvider.queryMatch.field}

-
- {truncate && !snapshot.isDragging ? ( - - {render(dataProvider, provided, snapshot)} - - ) : ( - - {render(dataProvider, provided, snapshot)} - - )} - {!snapshot.isDragging && ( - -

{i18n.DRAGGABLE_KEYBOARD_INSTRUCTIONS_NOT_DRAGGING_SCREEN_READER_ONLY}

+ +

{dataProvider.queryMatch.field}

- )} -
- ), - [dataProvider, registerProvider, render, setContainerRef, truncate] - ); - - const { onBlur, onKeyDown } = useDraggableKeyboardWrapper({ - closePopover: handleClosePopOverTrigger, - draggableId: getDraggableId(dataProvider.id), - fieldName: dataProvider.queryMatch.field, - keyboardHandlerRef, - openPopover, - }); - - const DroppableContent = useCallback( - (droppableProvided) => ( -
-
- + {render(dataProvider, provided, snapshot)} + + ) : ( + + {render(dataProvider, provided, snapshot)} + + )} + {!snapshot.isDragging && ( + +

{i18n.DRAGGABLE_KEYBOARD_INSTRUCTIONS_NOT_DRAGGING_SCREEN_READER_ONLY}

+
+ )} + + ), + [dataProvider, registerProvider, render, truncate] + ); + + const DroppableContent = useCallback( + (droppableProvided) => ( +
+
- {DraggableContent} - + + {DraggableContent} + +
+ {droppableProvided.placeholder}
- {droppableProvided.placeholder} -
- ), - [DraggableContent, dataProvider.id, isDisabled, keyboardHandlerRef, onBlur, onFocus, onKeyDown] - ); - - const content = useMemo( - () => ( - - - - {DroppableContent} - - - - ), - [DroppableContent, RenderClone, dataProvider.id, isDisabled] - ); - - const renderContent = useCallback(() => content, [content]); - - if (isDisabled) return <>{content}; - - return ( - - ); -}; + ), + [DraggableContent, dataProvider.id, isDisabled] + ); -const DraggableWrapperComponent: React.FC = ({ - dataProvider, - hideTopN = false, - isDraggable = false, - onFilterAdded, - render, - isAggregatable = false, - fieldType = '', - scopeId, - truncate, -}) => { - const { - closePopOverTrigger, - hoverActionsOwnFocus, - hoverContent, - onCloseRequested, - setContainerRef, - isShowingTopN, - } = useHoverActions({ - dataProvider, - hideTopN, - isDraggable, - isAggregatable, - fieldType, - onFilterAdded, - render, - scopeId, - truncate, - }); - const renderContent = useCallback( - () => ( -
{ - setContainerRef(e); - }} - tabIndex={-1} - data-provider-id={getDraggableId(dataProvider.id)} - > - {truncate ? ( - - {render(dataProvider, null, { - isDragging: false, - isDropAnimating: false, - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - })} - - ) : ( - - {render(dataProvider, null, { - isDragging: false, - isDropAnimating: false, - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - })} - - )} -
- ), - [dataProvider, render, setContainerRef, truncate] - ); - if (!isDraggable) { + const content = useMemo( + () => ( + + + + {DroppableContent} + + + + ), + [DroppableContent, RenderClone, dataProvider.id, isDisabled] + ); + + if (isDisabled) return <>{content}; return ( - + + {content} + ); } - return ( - - ); -}; - -export const DraggableWrapper = React.memo(DraggableWrapperComponent); +); +DraggableOnWrapper.displayName = 'DraggableOnWrapper'; + +export const DraggableWrapper: React.FC = React.memo( + ({ dataProvider, isDraggable = false, render, scopeId, truncate, hideTopN }) => { + const content = useMemo( + () => ( +
+ {truncate ? ( + + {render(dataProvider, null, { + isDragging: false, + isDropAnimating: false, + isClone: false, + dropAnimation: null, + draggingOver: null, + combineWith: null, + combineTargetFor: null, + mode: null, + })} + + ) : ( + + {render(dataProvider, null, { + isDragging: false, + isDropAnimating: false, + isClone: false, + dropAnimation: null, + draggingOver: null, + combineWith: null, + combineTargetFor: null, + mode: null, + })} + + )} +
+ ), + [dataProvider, render, truncate] + ); + if (!isDraggable) { + if (disableHoverActions(scopeId)) { + return <>{content}; + } + return ( + + {content} + + ); + } + return ( + + ); + } +); DraggableWrapper.displayName = 'DraggableWrapper'; /** * Conditionally wraps children in an EuiPortal to ensure drag offsets are correct when dragging diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.test.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.test.tsx deleted file mode 100644 index 8420d2164a296..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.test.tsx +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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 { EuiButtonEmpty, EuiContextMenuItem } from '@elastic/eui'; -import { mount } from 'enzyme'; -import React from 'react'; -import { mockCasesContext } from '@kbn/cases-plugin/public/mocks/mock_cases_context'; -import { TestProviders } from '../../../mock'; -import { ShowTopNButton } from './show_top_n'; -import { TimelineId } from '../../../../../common/types'; - -jest.mock('../../visualization_actions/actions'); -jest.mock('../../visualization_actions/visualization_embeddable'); - -jest.mock('../../../lib/kibana', () => { - const original = jest.requireActual('../../../lib/kibana'); - - return { - ...original, - useKibana: () => ({ - services: { - ...original.useKibana().services, - cases: { - ui: { - getCasesContext: jest.fn().mockReturnValue(mockCasesContext), - }, - }, - }, - }), - }; -}); - -jest.mock('react-router-dom', () => { - const original = jest.requireActual('react-router-dom'); - return { - ...original, - useLocation: jest.fn().mockReturnValue({ pathname: '/test' }), - }; -}); - -describe('show topN button', () => { - const defaultProps = { - field: 'signal.rule.name', - onClick: jest.fn(), - ownFocus: false, - showTopN: false, - scopeId: TimelineId.active, - }; - - describe('button', () => { - test('should show EuiButtonIcon by default', () => { - const wrapper = mount( - - - - ); - expect(wrapper.find('EuiButtonIcon').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="show-top-field"]').first().prop('iconType')).toEqual( - 'visBarVertical' - ); - }); - - test('should support EuiButtonEmpty', () => { - const testProps = { - ...defaultProps, - Component: EuiButtonEmpty, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('EuiButtonIcon').exists()).toBeFalsy(); - expect(wrapper.find('EuiButtonEmpty').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="show-top-field"]').first().prop('iconType')).toEqual( - 'visBarVertical' - ); - }); - - test('should support EuiContextMenuItem', () => { - const testProps = { - ...defaultProps, - Component: EuiContextMenuItem, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('EuiButtonIcon').exists()).toBeFalsy(); - expect(wrapper.find('EuiContextMenuItem').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="show-top-field"]').first().prop('icon')).toEqual( - 'visBarVertical' - ); - }); - }); - - describe('tooltip', () => { - test('should show tooltip by default', () => { - const wrapper = mount( - - - - ); - expect(wrapper.find('EuiToolTip').exists()).toBeTruthy(); - }); - - test('should hide tooltip when topN is showed', () => { - const testProps = { - ...defaultProps, - showTopN: true, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('EuiToolTip').exists()).toBeFalsy(); - }); - - test('should hide tooltip by setting showTooltip to false', () => { - const testProps = { - ...defaultProps, - showTooltip: false, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('EuiToolTip').exists()).toBeFalsy(); - }); - }); - - describe('popover', () => { - test('should be able to show topN without a popover', () => { - const testProps = { - ...defaultProps, - enablePopOver: false, - showTopN: true, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('[data-test-subj="top-n"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="showTopNContainer"]').exists()).toBeFalsy(); - }); - test('should be able to show topN within a popover', () => { - const testProps = { - ...defaultProps, - enablePopOver: true, - showTopN: true, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('[data-test-subj="top-n"]').exists()).toBeTruthy(); - expect(wrapper.find('[data-test-subj="showTopNContainer"]').exists()).toBeTruthy(); - }); - }); - - describe('topN', () => { - test('should render with correct props', () => { - const onFilterAdded = jest.fn(); - const testProps = { - ...defaultProps, - enablePopOver: true, - showTopN: true, - onFilterAdded, - }; - const wrapper = mount( - - - - ); - expect(wrapper.find('[data-test-subj="top-n"]').prop('field')).toEqual(testProps.field); - expect(wrapper.find('[data-test-subj="top-n"]').prop('toggleTopN')).toEqual( - testProps.onClick - ); - expect(wrapper.find('[data-test-subj="top-n"]').prop('scopeId')).toEqual(testProps.scopeId); - expect(wrapper.find('[data-test-subj="top-n"]').prop('onFilterAdded')).toEqual( - testProps.onFilterAdded - ); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.tsx deleted file mode 100644 index 9d155ba92f119..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/actions/show_top_n.tsx +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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 React, { useMemo } from 'react'; -import type { EuiButtonEmpty, EuiContextMenuItem } from '@elastic/eui'; -import { EuiPopover, EuiButtonIcon, EuiToolTip } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import type { Filter } from '@kbn/es-query'; -import { isActiveTimeline } from '../../../../helpers'; -import { StatefulTopN } from '../../top_n'; -import { SourcererScopeName } from '../../../store/sourcerer/model'; -import { useSourcererDataView } from '../../../containers/sourcerer'; -import { TooltipWithKeyboardShortcut } from '../../accessibility'; -import { getAdditionalScreenReaderOnlyContext } from '../utils'; -import { SHOW_TOP_N_KEYBOARD_SHORTCUT } from '../keyboard_shortcut_constants'; -import { isDetectionsAlertsTable } from '../../top_n/helpers'; - -const SHOW_TOP = (fieldName: string) => - i18n.translate('xpack.securitySolution.hoverActions.showTopTooltip', { - values: { fieldName }, - defaultMessage: `Show top {fieldName}`, - }); - -interface Props { - className?: string; - /** When `Component` is used with `EuiDataGrid`; the grid keeps a reference to `Component` for show / hide functionality. - * When `Component` is used with `EuiContextMenu`, we pass EuiContextMenuItem to render the right style. - */ - Component?: typeof EuiButtonEmpty | typeof EuiButtonIcon | typeof EuiContextMenuItem; - enablePopOver?: boolean; - field: string; - flush?: 'left' | 'right' | 'both'; - globalFilters?: Filter[]; - iconSide?: 'left' | 'right'; - iconType?: string; - isExpandable?: boolean; - onClick: () => void; - onFilterAdded?: () => void; - ownFocus: boolean; - paddingSize?: 's' | 'm' | 'l' | 'none'; - showTooltip?: boolean; - showTopN: boolean; - showLegend?: boolean; - scopeId?: string | null; - title?: string; - value?: string[] | string | null; -} - -export const ShowTopNButton: React.FC = React.memo( - ({ - className, - Component, - enablePopOver, - field, - flush, - iconSide, - iconType, - isExpandable, - onClick, - onFilterAdded, - ownFocus, - paddingSize, - showLegend, - showTooltip = true, - showTopN, - scopeId, - title, - value, - globalFilters, - }) => { - const activeScope: SourcererScopeName = isActiveTimeline(scopeId ?? '') - ? SourcererScopeName.timeline - : scopeId != null && isDetectionsAlertsTable(scopeId) - ? SourcererScopeName.detections - : SourcererScopeName.default; - const { browserFields, indexPattern } = useSourcererDataView(activeScope); - - const icon = iconType ?? 'visBarVertical'; - const side = iconSide ?? 'left'; - const buttonTitle = title ?? SHOW_TOP(field); - const basicButton = useMemo( - () => - Component ? ( - - {buttonTitle} - - ) : ( - - ), - [Component, buttonTitle, className, flush, icon, onClick, side] - ); - - const button = useMemo( - () => - showTooltip && !showTopN ? ( - - } - > - {basicButton} - - ) : ( - basicButton - ), - [basicButton, buttonTitle, field, ownFocus, showTooltip, showTopN, value] - ); - - const topNPannel = useMemo( - () => ( - - ), - [ - browserFields, - field, - indexPattern, - onFilterAdded, - paddingSize, - showLegend, - scopeId, - onClick, - globalFilters, - ] - ); - - if (isExpandable) { - return ( - <> - {basicButton} - {showTopN && topNPannel} - - ); - } - - return showTopN ? ( - enablePopOver ? ( - - {topNPannel} - - ) : ( - topNPannel - ) - ) : ( - button - ); - } -); - -ShowTopNButton.displayName = 'ShowTopNButton'; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx deleted file mode 100644 index 6aab4a0afbe68..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/index.tsx +++ /dev/null @@ -1,295 +0,0 @@ -/* - * 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 { EuiFocusTrap, EuiScreenReaderOnly } from '@elastic/eui'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import type { DraggableId } from '@hello-pangea/dnd'; -import styled from 'styled-components'; -import { i18n } from '@kbn/i18n'; - -import { stopPropagationAndPreventDefault } from '@kbn/timelines-plugin/public'; -import type { ColumnHeaderOptions, DataProvider } from '../../../../common/types/timeline'; -import { TimelineId } from '../../../../common/types/timeline'; -import { SHOW_TOP_N_KEYBOARD_SHORTCUT } from './keyboard_shortcut_constants'; -import { useHoverActionItems } from './use_hover_action_items'; -import { SecurityPageName } from '../../../app/types'; - -export const YOU_ARE_IN_A_DIALOG_CONTAINING_OPTIONS = (fieldName: string) => - i18n.translate( - 'xpack.securitySolution.dragAndDrop.youAreInADialogContainingOptionsScreenReaderOnly', - { - values: { fieldName }, - defaultMessage: `You are in a dialog, containing options for field {fieldName}. Press tab to navigate options. Press escape to exit.`, - } - ); - -export const AdditionalContent = styled.div` - padding: 2px; -`; - -AdditionalContent.displayName = 'AdditionalContent'; - -const StyledHoverActionsContainer = styled.div<{ - $showTopN: boolean; - $showOwnFocus: boolean; - $hiddenActionsCount: number; - $isActive: boolean; -}>` - display: flex; - - ${(props) => - props.$isActive - ? ` - .hoverActions-active { - .timelines__hoverActionButton, - .securitySolution__hoverActionButton { - opacity: 1; - } - } - ` - : ''} - - ${(props) => - props.$showOwnFocus - ? ` - &:focus-within { - .timelines__hoverActionButton, - .securitySolution__hoverActionButton { - opacity: 1; - } - } - - &:hover { - .timelines__hoverActionButton, - .securitySolution__hoverActionButton { - opacity: 1; - } - } - - .timelines__hoverActionButton, - .securitySolution__hoverActionButton { - opacity: ${props.$showTopN ? 1 : 0}; - - &:focus { - opacity: 1; - } - } - ` - : ''} -`; - -const StyledHoverActionsContainerWithPaddingsAndMinWidth = styled(StyledHoverActionsContainer)` - min-width: ${({ $hiddenActionsCount }) => `${138 - $hiddenActionsCount * 26}px`}; - padding: ${(props) => `0 ${props.theme.eui.euiSizeS}`}; - position: relative; -`; - -interface Props { - additionalContent?: React.ReactNode; - applyWidthAndPadding?: boolean; - closeTopN?: () => void; - closePopOver?: () => void; - dataProvider?: DataProvider | DataProvider[]; - dataType?: string; - draggableId?: DraggableId; - enableOverflowButton?: boolean; - field: string; - fieldType: string; - isAggregatable: boolean; - goGetTimelineId?: (args: boolean) => void; - hideAddToTimeline?: boolean; - hideTopN?: boolean; - isObjectArray: boolean; - onFilterAdded?: () => void; - ownFocus: boolean; - showOwnFocus?: boolean; - showTopN: boolean; - scopeId?: string | null; - toggleColumn?: (column: ColumnHeaderOptions) => void; - toggleTopN: () => void; - values?: string[] | string | null; -} - -/** Returns a value for the `disabled` prop of `EuiFocusTrap` */ -const isFocusTrapDisabled = ({ - ownFocus, - showTopN, -}: { - ownFocus: boolean; - showTopN: boolean; -}): boolean => { - if (showTopN) { - return false; // we *always* want to trap focus when showing Top N - } - - return !ownFocus; -}; - -export const HoverActions: React.FC = React.memo( - ({ - additionalContent = null, - closePopOver, - closeTopN, - dataProvider, - dataType, - draggableId, - enableOverflowButton = false, - applyWidthAndPadding = true, - field, - fieldType, - isAggregatable, - goGetTimelineId, - isObjectArray, - hideAddToTimeline = false, - hideTopN = false, - onFilterAdded, - ownFocus, - showOwnFocus = true, - showTopN, - scopeId, - toggleColumn, - toggleTopN, - values, - }) => { - const [stKeyboardEvent, setStKeyboardEvent] = useState(); - const [isActive, setIsActive] = useState(false); - const [isOverflowPopoverOpen, setIsOverflowPopoverOpen] = useState(false); - const onOverflowButtonClick = useCallback(() => { - setIsActive((prev) => !prev); - setIsOverflowPopoverOpen(!isOverflowPopoverOpen); - }, [isOverflowPopoverOpen, setIsOverflowPopoverOpen]); - const handleHoverActionClicked = useCallback(() => { - if (closeTopN) { - closeTopN(); - } - - setIsActive(false); - setIsOverflowPopoverOpen(false); - if (closePopOver) { - closePopOver(); - } - }, [closePopOver, closeTopN]); - - const isInit = useRef(true); - const defaultFocusedButtonRef = useRef(null); - - useEffect(() => { - if (isInit.current && goGetTimelineId != null && scopeId == null) { - isInit.current = false; - goGetTimelineId(true); - } - }, [goGetTimelineId, scopeId]); - - useEffect(() => { - if (ownFocus) { - setTimeout(() => { - defaultFocusedButtonRef.current?.focus(); - }, 0); - } - }, [ownFocus]); - - const onKeyDown = useCallback( - (keyboardEvent: React.KeyboardEvent) => { - if (!ownFocus) { - return; - } - switch (keyboardEvent.key) { - case SHOW_TOP_N_KEYBOARD_SHORTCUT: - stopPropagationAndPreventDefault(keyboardEvent); - toggleTopN(); - break; - case 'Enter': - break; - case 'Escape': - stopPropagationAndPreventDefault(keyboardEvent); - break; - default: - setStKeyboardEvent(keyboardEvent); - break; - } - }, - [ownFocus, toggleTopN] - ); - - const isCaseView = scopeId === TimelineId.casePage; - const isTimelineView = scopeId === TimelineId.active; - // TODO Provide a list of disabled/enabled actions as props - const isEntityAnalyticsPage = scopeId === SecurityPageName.entityAnalytics; - - const hideFilters = useMemo( - () => isEntityAnalyticsPage && !isTimelineView, - [isTimelineView, isEntityAnalyticsPage] - ); - - const hiddenActionsCount = useMemo(() => { - const hiddenTopNActions = hideTopN ? 1 : 0; // hides the `Top N` button - const hiddenFilterActions = hideFilters ? 2 : 0; // hides both the `Filter In` and `Filter out` buttons - - return hiddenTopNActions + hiddenFilterActions; - }, [hideFilters, hideTopN]); - - const { overflowActionItems, allActionItems } = useHoverActionItems({ - dataProvider, - dataType, - defaultFocusedButtonRef, - draggableId, - enableOverflowButton: enableOverflowButton && !isCaseView, - field, - fieldType, - hideFilters, - isAggregatable, - handleHoverActionClicked, - hideAddToTimeline, - hideTopN, - isCaseView, - isObjectArray, - isOverflowPopoverOpen, - onFilterAdded, - onOverflowButtonClick, - ownFocus, - showTopN, - stKeyboardEvent, - toggleColumn, - toggleTopN, - values, - scopeId, - }); - - const Container = applyWidthAndPadding - ? StyledHoverActionsContainerWithPaddingsAndMinWidth - : StyledHoverActionsContainer; - - return ( - - - -

{YOU_ARE_IN_A_DIALOG_CONTAINING_OPTIONS(field)}

-
- - {additionalContent != null && {additionalContent}} - - {enableOverflowButton && !isCaseView ? overflowActionItems : allActionItems} -
-
- ); - } -); - -HoverActions.displayName = 'HoverActions'; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx deleted file mode 100644 index 65014bb3762d6..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.test.tsx +++ /dev/null @@ -1,318 +0,0 @@ -/* - * 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 { useRef } from 'react'; -import { renderHook, act } from '@testing-library/react-hooks'; -import type { UseHoverActionItemsProps } from './use_hover_action_items'; -import { useHoverActionItems } from './use_hover_action_items'; -import { useDeepEqualSelector } from '../../hooks/use_selector'; -import type { DataProvider } from '../../../../common/types/timeline'; - -jest.mock('../../lib/kibana'); -jest.mock('../../hooks/use_selector'); -const mockUseDataViewId = jest.fn(); -jest.mock('../../hooks/use_data_view_id', () => ({ - useDataViewId: (scope: string) => mockUseDataViewId(scope), -})); -jest.mock('../../containers/sourcerer', () => ({ - useSourcererDataView: jest.fn().mockReturnValue({ browserFields: {} }), -})); -const mockDispatch = jest.fn(); -jest.mock('react-redux', () => { - const original = jest.requireActual('react-redux'); - - return { - ...original, - useDispatch: () => mockDispatch, - }; -}); - -describe('useHoverActionItems', () => { - const defaultProps: UseHoverActionItemsProps = { - dataProvider: [{} as DataProvider], - defaultFocusedButtonRef: null, - field: 'kibana.alert.rule.name', - scopeId: 'timeline-test', - handleHoverActionClicked: jest.fn(), - hideAddToTimeline: false, - hideTopN: false, - isCaseView: false, - isObjectArray: false, - ownFocus: false, - showTopN: false, - stKeyboardEvent: undefined, - toggleColumn: jest.fn(), - toggleTopN: jest.fn(), - values: ['rule name'], - } as unknown as UseHoverActionItemsProps; - - beforeEach(() => { - (useDeepEqualSelector as jest.Mock).mockImplementation((cb) => { - return cb(); - }); - }); - afterEach(() => { - (useDeepEqualSelector as jest.Mock).mockClear(); - }); - - test('should return allActionItems', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const defaultFocusedButtonRef = useRef(null); - const testProps = { - ...defaultProps, - defaultFocusedButtonRef, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.allActionItems).toHaveLength(6); - expect(result.current.allActionItems[0].props['data-test-subj']).toEqual( - 'hover-actions-filter-for' - ); - expect(result.current.allActionItems[1].props['data-test-subj']).toEqual( - 'hover-actions-filter-out' - ); - expect(result.current.allActionItems[2].props['data-test-subj']).toEqual( - 'hover-actions-toggle-column' - ); - expect(result.current.allActionItems[3].props['data-test-subj']).toEqual( - 'hover-actions-add-timeline' - ); - expect(result.current.allActionItems[4].props['data-test-subj']).toEqual( - 'hover-actions-show-top-n' - ); - expect(result.current.allActionItems[5].props['data-test-subj']).toEqual( - 'hover-actions-copy-button' - ); - }); - }); - - test('should call getDataViewId with the correct scope', () => { - renderHook(() => { - const defaultFocusedButtonRef = useRef(null); - return useHoverActionItems({ ...defaultProps, defaultFocusedButtonRef }); - }); - expect(mockUseDataViewId).toHaveBeenCalledWith('timeline'); - }); - - test('should return overflowActionItems', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const defaultFocusedButtonRef = useRef(null); - const testProps = { - ...defaultProps, - defaultFocusedButtonRef, - enableOverflowButton: true, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.overflowActionItems).toHaveLength(3); - expect(result.current.overflowActionItems[0].props['data-test-subj']).toEqual( - 'hover-actions-filter-for' - ); - expect(result.current.overflowActionItems[1].props['data-test-subj']).toEqual( - 'hover-actions-filter-out' - ); - expect(result.current.overflowActionItems[2].props['data-test-subj']).toEqual( - 'more-actions-kibana.alert.rule.name' - ); - expect(result.current.overflowActionItems[2].props.items[0].props['data-test-subj']).toEqual( - 'hover-actions-toggle-column' - ); - - expect(result.current.overflowActionItems[2].props.items[1].props['data-test-subj']).toEqual( - 'hover-actions-add-timeline' - ); - expect(result.current.overflowActionItems[2].props.items[2].props['data-test-subj']).toEqual( - 'hover-actions-show-top-n' - ); - expect(result.current.overflowActionItems[2].props.items[3].props['data-test-subj']).toEqual( - 'hover-actions-copy-button' - ); - }); - }); - - test('it should hide the Top N action when hideTopN is true', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - hideTopN: true, // <-- hide the Top N action - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - result.current.allActionItems.forEach((item) => { - expect(item.props['data-test-subj']).not.toEqual('hover-actions-show-top-n'); - }); - }); - }); - - test('should not have toggle column', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const defaultFocusedButtonRef = useRef(null); - const testProps = { - ...defaultProps, - isObjectArray: true, - defaultFocusedButtonRef, - enableOverflowButton: true, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.overflowActionItems).toHaveLength(3); - expect(result.current.overflowActionItems[0].props['data-test-subj']).toEqual( - 'hover-actions-filter-for' - ); - expect(result.current.overflowActionItems[1].props['data-test-subj']).toEqual( - 'hover-actions-filter-out' - ); - - result.current.overflowActionItems[2].props.items.forEach((item: JSX.Element) => { - expect(item.props['data-test-subj']).not.toEqual('hover-actions-toggle-column'); - }); - }); - }); - - test('should not have filter in, filter out, or toggle column', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - isCaseView: true, - enableOverflowButton: false, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.allActionItems).toHaveLength(3); - expect(result.current.allActionItems[0].props['data-test-subj']).toEqual( - 'hover-actions-add-timeline' - ); - expect(result.current.allActionItems[1].props['data-test-subj']).toEqual( - 'hover-actions-show-top-n' - ); - expect(result.current.allActionItems[2].props['data-test-subj']).toEqual( - 'hover-actions-copy-button' - ); - }); - }); - - test('if not on CaseView, overflow button is enabled, ShowTopNButton should disable popOver (e.g.: alerts flyout)', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - enableOverflowButton: true, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - expect(result.current.allActionItems[4].props.enablePopOver).toEqual(false); - }); - }); - - test('if not on CaseView, overflow button is disabled, ShowTopNButton should disable popOver (e.g.: alerts table - reason field)', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - enableOverflowButton: false, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - expect(result.current.allActionItems[4].props.enablePopOver).toEqual(false); - }); - }); - - test('if on CaseView, ShowTopNButton should enable popOver', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - isCaseView: true, - enableOverflowButton: false, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.allActionItems[1].props.enablePopOver).toEqual(true); - }); - }); - - test('if on CaseView, it should show all items when shoTopN is true', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - showTopN: true, - isCaseView: true, - enableOverflowButton: false, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.allActionItems).toHaveLength(3); - expect(result.current.allActionItems[0].props['data-test-subj']).toEqual( - 'hover-actions-add-timeline' - ); - expect(result.current.allActionItems[1].props['data-test-subj']).toEqual( - 'hover-actions-show-top-n' - ); - expect(result.current.allActionItems[2].props['data-test-subj']).toEqual( - 'hover-actions-copy-button' - ); - }); - }); - - test('when disable OverflowButton, it should show only "showTopNBtn" when shoTopN is true', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - showTopN: true, - isCaseView: false, - enableOverflowButton: false, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - expect(result.current.allActionItems).toHaveLength(1); - expect(result.current.allActionItems[0].props['data-test-subj']).toEqual( - 'hover-actions-show-top-n' - ); - }); - }); - - test('when timeline button is disabled, it should not show', async () => { - await act(async () => { - const { result, waitForNextUpdate } = renderHook(() => { - const testProps = { - ...defaultProps, - hideAddToTimeline: true, - }; - return useHoverActionItems(testProps); - }); - await waitForNextUpdate(); - - result.current.allActionItems.forEach((actionItem) => { - expect(actionItem.props['data-test-subj']).not.toEqual('hover-actions-add-timeline'); - }); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx deleted file mode 100644 index 188a10c06036c..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_action_items.tsx +++ /dev/null @@ -1,347 +0,0 @@ -/* - * 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 { EuiContextMenuItem } from '@elastic/eui'; -import React, { useCallback, useMemo } from 'react'; -import type { DraggableId } from '@hello-pangea/dnd'; - -import { isEmpty } from 'lodash'; - -import { useDispatch } from 'react-redux'; -import { getSourcererScopeId, isActiveTimeline } from '../../../helpers'; -import { useKibana } from '../../lib/kibana'; -import { allowTopN } from '../drag_and_drop/helpers'; -import type { ColumnHeaderOptions, DataProvider } from '../../../../common/types/timeline'; -import { TimelineId } from '../../../../common/types/timeline'; -import { ShowTopNButton } from './actions/show_top_n'; -import { addProvider } from '../../../timelines/store/actions'; -import { useDataViewId } from '../../hooks/use_data_view_id'; -export interface UseHoverActionItemsProps { - dataProvider?: DataProvider | DataProvider[]; - dataType?: string; - defaultFocusedButtonRef: React.MutableRefObject; - draggableId?: DraggableId; - enableOverflowButton?: boolean; - field: string; - fieldType: string; - isAggregatable: boolean; - handleHoverActionClicked: () => void; - hideAddToTimeline: boolean; - hideFilters?: boolean; - hideTopN: boolean; - isCaseView: boolean; - isObjectArray: boolean; - isOverflowPopoverOpen?: boolean; - itemsToShow?: number; - onFilterAdded?: () => void; - onOverflowButtonClick?: () => void; - ownFocus: boolean; - showTopN: boolean; - stKeyboardEvent: React.KeyboardEvent | undefined; - scopeId?: string | null; - toggleColumn?: (column: ColumnHeaderOptions) => void; - toggleTopN: () => void; - values?: string[] | string | null; -} - -export interface UseHoverActionItems { - overflowActionItems: JSX.Element[]; - allActionItems: JSX.Element[]; -} - -export const useHoverActionItems = ({ - dataProvider, - dataType, - defaultFocusedButtonRef, - draggableId, - enableOverflowButton, - field, - fieldType, - isAggregatable, - handleHoverActionClicked, - hideFilters, - hideTopN, - hideAddToTimeline, - isCaseView, - isObjectArray, - isOverflowPopoverOpen, - itemsToShow = 2, - onFilterAdded, - onOverflowButtonClick, - ownFocus, - showTopN, - stKeyboardEvent, - scopeId, - toggleColumn, - toggleTopN, - values, -}: UseHoverActionItemsProps): UseHoverActionItems => { - const kibana = useKibana(); - const dispatch = useDispatch(); - const { timelines, timelineDataService, analytics, i18n, theme } = kibana.services; - const { - query: { filterManager: timelineFilterManager }, - } = timelineDataService; - const dataViewId = useDataViewId(getSourcererScopeId(scopeId ?? '')); - - // Common actions used by the alert table and alert flyout - const { - getAddToTimelineButton, - getColumnToggleButton, - getCopyButton, - getFilterForValueButton, - getFilterOutValueButton, - getOverflowButton, - } = timelines.getHoverActions(); - - const filterManager = useMemo(() => { - return isActiveTimeline(scopeId ?? '') - ? timelineFilterManager - : kibana.services.data.query.filterManager; - }, [scopeId, timelineFilterManager, kibana.services.data.query.filterManager]); - - /* - * Add to Timeline button, adds data to dataprovider but does not persists the Timeline - * to the server because of following reasons. - * - * 1. Add to Timeline button performs actions in `timelines` plugin - * 2. `timelines` plugin does not have information on how to create/update the timelines in the server - * as it is owned by Security Solution - * */ - const OnAddToTimeline = useCallback(() => { - if (!dataProvider || isEmpty(dataProvider)) return; - dispatch( - addProvider({ - id: TimelineId.active, - providers: dataProvider instanceof Array ? dataProvider : [dataProvider], - }) - ); - }, [dataProvider, dispatch]); - - const onAddToTimelineClicked = useCallback(() => { - if (handleHoverActionClicked) handleHoverActionClicked(); - OnAddToTimeline(); - }, [handleHoverActionClicked, OnAddToTimeline]); - - const showFilters = useMemo(() => { - if (hideFilters) return false; - /* - * In the case of `DisableOverflowButton`, we show filters only when topN is NOT opened. As after topN button is clicked, the chart panel replace current hover actions in the hover actions' popover, so we have to hide all the actions. - * in the case of `EnableOverflowButton`, we only need to hide all the items in the overflow popover as the chart's panel opens in the overflow popover, so non-overflowed actions are not affected. - */ - return ( - values != null && - (enableOverflowButton || (!showTopN && !enableOverflowButton)) && - !isCaseView - ); - }, [enableOverflowButton, hideFilters, isCaseView, showTopN, values]); - const shouldDisableColumnToggle = (isObjectArray && field !== 'geo_point') || isCaseView; - - const showTopNBtn = useMemo( - () => ( - - ), - [ - enableOverflowButton, - isCaseView, - field, - toggleTopN, - onFilterAdded, - ownFocus, - showTopN, - scopeId, - values, - ] - ); - - const allItems = useMemo(() => { - const startServices = { analytics, i18n, theme }; - return [ - showFilters ? ( -
- {getFilterForValueButton({ - defaultFocusedButtonRef, - field, - filterManager, - keyboardEvent: stKeyboardEvent, - onClick: handleHoverActionClicked, - onFilterAdded, - ownFocus, - showTooltip: enableOverflowButton ? false : true, - value: values, - dataViewId, - })} -
- ) : null, - showFilters ? ( -
- {getFilterOutValueButton({ - field, - filterManager, - keyboardEvent: stKeyboardEvent, - onFilterAdded, - ownFocus, - onClick: handleHoverActionClicked, - showTooltip: enableOverflowButton ? false : true, - value: values, - dataViewId, - })} -
- ) : null, - toggleColumn && !shouldDisableColumnToggle ? ( -
- {getColumnToggleButton({ - Component: enableOverflowButton ? EuiContextMenuItem : undefined, - field, - isDisabled: isObjectArray && dataType !== 'geo_point', - isObjectArray, - keyboardEvent: stKeyboardEvent, - ownFocus, - onClick: handleHoverActionClicked, - showTooltip: enableOverflowButton ? false : true, - toggleColumn, - value: values, - })} -
- ) : null, - values != null && (draggableId != null || !isEmpty(dataProvider)) && !hideAddToTimeline ? ( -
- {getAddToTimelineButton({ - Component: enableOverflowButton ? EuiContextMenuItem : undefined, - dataProvider, - draggableId, - field, - keyboardEvent: stKeyboardEvent, - ownFocus, - onClick: onAddToTimelineClicked, - showTooltip: enableOverflowButton ? false : true, - value: values, - startServices, - })} -
- ) : null, - allowTopN({ - fieldType, - isAggregatable, - fieldName: field, - hideTopN, - }) - ? showTopNBtn - : null, - field != null ? ( -
- {getCopyButton({ - Component: enableOverflowButton ? EuiContextMenuItem : undefined, - field, - isHoverAction: true, - keyboardEvent: stKeyboardEvent, - ownFocus, - onClick: handleHoverActionClicked, - showTooltip: enableOverflowButton ? false : true, - value: values, - })} -
- ) : null, - ].filter((item) => { - return item != null; - }); - }, [ - dataProvider, - dataType, - defaultFocusedButtonRef, - draggableId, - enableOverflowButton, - field, - fieldType, - isAggregatable, - filterManager, - getAddToTimelineButton, - getColumnToggleButton, - getCopyButton, - getFilterForValueButton, - getFilterOutValueButton, - handleHoverActionClicked, - onAddToTimelineClicked, - hideAddToTimeline, - hideTopN, - isObjectArray, - onFilterAdded, - ownFocus, - shouldDisableColumnToggle, - showFilters, - showTopNBtn, - stKeyboardEvent, - toggleColumn, - values, - dataViewId, - analytics, - i18n, - theme, - ]) as JSX.Element[]; - - const overflowActionItems = useMemo( - () => - [ - ...allItems.slice(0, itemsToShow), - ...(enableOverflowButton && itemsToShow > 0 && itemsToShow < allItems.length - ? [ - getOverflowButton({ - closePopOver: handleHoverActionClicked, - field, - keyboardEvent: stKeyboardEvent, - ownFocus, - onClick: onOverflowButtonClick, - showTooltip: enableOverflowButton ? false : true, - value: values, - items: showTopN ? [showTopNBtn] : allItems.slice(itemsToShow), - isOverflowPopoverOpen: !!isOverflowPopoverOpen, - }), - ] - : []), - ].filter((item) => { - return item != null; - }), - [ - allItems, - enableOverflowButton, - field, - getOverflowButton, - handleHoverActionClicked, - isOverflowPopoverOpen, - itemsToShow, - onOverflowButtonClick, - showTopNBtn, - ownFocus, - showTopN, - stKeyboardEvent, - values, - ] - ); - - const allActionItems = useMemo( - () => (showTopN && !enableOverflowButton && !isCaseView ? [showTopNBtn] : allItems), - [showTopN, enableOverflowButton, isCaseView, showTopNBtn, allItems] - ); - - return { - overflowActionItems, - allActionItems, - }; -}; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_actions.tsx b/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_actions.tsx deleted file mode 100644 index 324f5af4e16e7..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/use_hover_actions.tsx +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 React, { useCallback, useMemo, useState, useRef, useContext } from 'react'; -import type { DraggableProvided, DraggableStateSnapshot } from '@hello-pangea/dnd'; -import { TimelineContext } from '../../../timelines/components/timeline'; -import { HoverActions } from '.'; - -import type { DataProvider } from '../../../../common/types'; -import { ProviderContentWrapper } from '../drag_and_drop/draggable_wrapper'; -import { getDraggableId } from '../drag_and_drop/helpers'; -import { TableContext } from '../events_viewer/shared'; -import { useTopNPopOver } from './utils'; - -const draggableContainsLinks = (draggableElement: HTMLDivElement | null) => { - const links = draggableElement?.querySelectorAll('.euiLink') ?? []; - return links.length > 0; -}; - -type RenderFunctionProp = ( - props: DataProvider, - provided: DraggableProvided | null, - state: DraggableStateSnapshot -) => React.ReactNode; - -interface Props { - dataProvider: DataProvider; - isAggregatable: boolean; - fieldType: string; - disabled?: boolean; - hideTopN: boolean; - isDraggable?: boolean; - inline?: boolean; - render: RenderFunctionProp; - scopeId?: string; - truncate?: boolean; - onFilterAdded?: () => void; -} - -export const useHoverActions = ({ - dataProvider, - isAggregatable, - fieldType, - hideTopN, - isDraggable, - onFilterAdded, - render, - scopeId, -}: Props) => { - const { timelineId: timelineIdFind } = useContext(TimelineContext); - const { tableId: tableIdFind } = useContext(TableContext); - const containerRef = useRef(null); - const keyboardHandlerRef = useRef(null); - const [closePopOverTrigger, setClosePopOverTrigger] = useState(false); - const [hoverActionsOwnFocus, setHoverActionsOwnFocus] = useState(false); - const id = useMemo( - () => (!scopeId ? timelineIdFind ?? tableIdFind : scopeId), - [scopeId, tableIdFind, timelineIdFind] - ); - - const handleClosePopOverTrigger = useCallback(() => { - setClosePopOverTrigger((prevClosePopOverTrigger) => !prevClosePopOverTrigger); - setHoverActionsOwnFocus((prevHoverActionsOwnFocus) => { - if (prevHoverActionsOwnFocus) { - setTimeout(() => { - keyboardHandlerRef.current?.focus(); - }, 0); - } - return false; // always give up ownership - }); - - setTimeout(() => { - setHoverActionsOwnFocus(false); - }, 0); // invoked on the next tick, because we want to restore focus first - }, [keyboardHandlerRef]); - - const { closeTopN, toggleTopN, isShowingTopN } = useTopNPopOver(handleClosePopOverTrigger); - - const values = useMemo(() => { - const val = dataProvider.queryMatch.value; - - if (typeof val === 'number' || typeof val === 'boolean') { - return val.toString(); - } - - if (Array.isArray(val)) { - return val.map((item) => String(item)); - } - - return val; - }, [dataProvider.queryMatch.value]); - - const hoverContent = useMemo(() => { - // display links as additional content in the hover menu to enable keyboard - // navigation of links (when the draggable contains them): - const additionalContent = - hoverActionsOwnFocus && !isShowingTopN && draggableContainsLinks(containerRef.current) ? ( - - {render(dataProvider, null, { - isDragging: false, - isDropAnimating: false, - isClone: false, - dropAnimation: null, - draggingOver: null, - combineWith: null, - combineTargetFor: null, - mode: null, - })} - - ) : null; - - return ( - - ); - }, [ - hoverActionsOwnFocus, - isShowingTopN, - dataProvider, - render, - closeTopN, - handleClosePopOverTrigger, - isDraggable, - isAggregatable, - fieldType, - hideTopN, - onFilterAdded, - id, - toggleTopN, - values, - ]); - - const setContainerRef = useCallback((e: HTMLDivElement) => { - containerRef.current = e; - }, []); - - const onFocus = useCallback(() => { - if (!hoverActionsOwnFocus) { - keyboardHandlerRef.current?.focus(); - } - }, [hoverActionsOwnFocus, keyboardHandlerRef]); - - const onCloseRequested = useCallback(() => { - closeTopN(); - - if (hoverActionsOwnFocus) { - setHoverActionsOwnFocus(false); - - setTimeout(() => { - onFocus(); // return focus to this draggable on the next tick, because we owned focus - }, 0); - } - }, [onFocus, hoverActionsOwnFocus, closeTopN]); - - const openPopover = useCallback(() => { - setHoverActionsOwnFocus(true); - }, []); - - return useMemo( - () => ({ - closePopOverTrigger, - handleClosePopOverTrigger, - hoverActionsOwnFocus, - hoverContent, - keyboardHandlerRef, - onCloseRequested, - onFocus, - openPopover, - setContainerRef, - isShowingTopN, - }), - [ - closePopOverTrigger, - handleClosePopOverTrigger, - hoverActionsOwnFocus, - hoverContent, - onCloseRequested, - onFocus, - openPopover, - setContainerRef, - isShowingTopN, - ] - ); -}; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/utils.test.ts b/x-pack/plugins/security_solution/public/common/components/hover_actions/utils.test.ts deleted file mode 100644 index 4adb83b26cdda..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/utils.test.ts +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 { act, renderHook } from '@testing-library/react-hooks'; -import { useTopNPopOver } from './utils'; - -describe('useTopNPopOver', () => { - it('calls setIsPopoverVisible when toggling top N', () => { - const setIsPopoverVisible = jest.fn(); - const { - result: { - current: { toggleTopN }, - }, - } = renderHook(() => useTopNPopOver(setIsPopoverVisible)); - - act(() => { - toggleTopN(); - }); - - expect(setIsPopoverVisible).toHaveBeenCalled(); - }); - - it('sets isShowingTopN to true when toggleTopN is called', () => { - const { result } = renderHook(() => useTopNPopOver()); - - expect(result.current.isShowingTopN).toBeFalsy(); - - act(() => { - result.current.toggleTopN(); - }); - - expect(result.current.isShowingTopN).toBeTruthy(); - }); - - it('sets isShowingTopN to false when toggleTopN is called for the second time', () => { - const { result } = renderHook(() => useTopNPopOver()); - - expect(result.current.isShowingTopN).toBeFalsy(); - - act(() => { - result.current.toggleTopN(); - result.current.toggleTopN(); - }); - - expect(result.current.isShowingTopN).toBeFalsy(); - }); - - it('sets isShowingTopN to false when closeTopN is called', () => { - const { result } = renderHook(() => useTopNPopOver()); - act(() => { - // First, make isShowingTopN truthy. - result.current.toggleTopN(); - }); - expect(result.current.isShowingTopN).toBeTruthy(); - - act(() => { - result.current.closeTopN(); - }); - expect(result.current.isShowingTopN).toBeFalsy(); - }); -}); diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/utils.ts b/x-pack/plugins/security_solution/public/common/components/hover_actions/utils.ts deleted file mode 100644 index b3b8262d9f23a..0000000000000 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/utils.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 { useCallback, useState } from 'react'; - -export const getAdditionalScreenReaderOnlyContext = ({ - field, - value, -}: { - field: string; - value?: string[] | string | null; -}): string => { - if (value == null) { - return field; - } - - return Array.isArray(value) ? `${field} ${value.join(' ')}` : `${field} ${value}`; -}; - -export const useTopNPopOver = (setIsPopoverVisible?: (isVisible: boolean) => void) => { - const [isShowingTopN, setShowTopN] = useState(false); - const toggleTopN = useCallback(() => { - setShowTopN((prevShowTopN) => { - const newShowTopN = !prevShowTopN; - if (setIsPopoverVisible) setIsPopoverVisible(newShowTopN); - return newShowTopN; - }); - }, [setIsPopoverVisible]); - - const closeTopN = useCallback(() => { - setShowTopN(false); - }, []); - - return { closeTopN, toggleTopN, isShowingTopN }; -}; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.test.tsx b/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.test.tsx new file mode 100644 index 0000000000000..d378d217d550c --- /dev/null +++ b/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.test.tsx @@ -0,0 +1,94 @@ +/* + * 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 React from 'react'; +import { render, fireEvent, act, type RenderResult } from '@testing-library/react'; +import { HoverPopover } from './hover_popover'; + +describe('HoverPopover', () => { + jest.useFakeTimers(); + + describe('when not hovering', () => { + let result: RenderResult; + beforeEach(() => { + result = render( + + {'test children'} + + ); + }); + + it('should render the children', () => { + expect(result.queryByText('test children')).toBeInTheDocument(); + }); + + it('should not render the hover content', () => { + expect(result.queryByText('test hover content')).not.toBeInTheDocument(); + }); + }); + + describe('when hovering', () => { + let result: RenderResult; + beforeEach(() => { + result = render( + + {'test children'} + + ); + + act(() => { + fireEvent.mouseEnter(result.getByTestId('HoverPopoverButton')); + jest.runAllTimers(); + }); + }); + + it('should render the children', () => { + expect(result.queryByText('test children')).toBeInTheDocument(); + }); + + it('should render hoverContent', () => { + expect(result.queryByText('test hover content')).toBeInTheDocument(); + }); + + describe('and then unhovering', () => { + beforeEach(() => { + act(() => { + fireEvent.mouseLeave(result.getByTestId('HoverPopoverButton')); + jest.runAllTimers(); + }); + }); + + it('should render the children', () => { + expect(result.queryByText('test children')).toBeInTheDocument(); + }); + + it('should not render hoverContent', () => { + expect(result.queryByText('test hover content')).not.toBeInTheDocument(); + }); + }); + + describe('and then clicking ESC', () => { + beforeEach(() => { + act(() => { + fireEvent.keyDown(result.getByText('test hover content'), { + key: 'Escape', + code: 'Escape', + }); + jest.runAllTimers(); + }); + }); + + it('should render the children', () => { + expect(result.queryByText('test children')).toBeInTheDocument(); + }); + + it('should not render hoverContent', () => { + expect(result.queryByText('test hover content')).not.toBeInTheDocument(); + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/common/components/with_hover_actions/index.tsx b/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx similarity index 53% rename from x-pack/plugins/security_solution/public/common/components/with_hover_actions/index.tsx rename to x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx index 509d7610cb0fb..827290565f287 100644 --- a/x-pack/plugins/security_solution/public/common/components/with_hover_actions/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/hover_popover/hover_popover.tsx @@ -5,12 +5,11 @@ * 2.0. */ +import type { PopoverAnchorPosition } from '@elastic/eui'; import { EuiPopover } from '@elastic/eui'; -import { - HOVER_ACTIONS_ALWAYS_SHOW_CLASS_NAME, - IS_DRAGGING_CLASS_NAME, -} from '@kbn/securitysolution-t-grid'; -import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { IS_DRAGGING_CLASS_NAME } from '@kbn/securitysolution-t-grid'; +import type { PropsWithChildren } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; /** * To avoid expensive changes to the DOM, delay showing the popover menu @@ -18,39 +17,8 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' const HOVER_INTENT_DELAY = 100; // ms interface Props { - /** - * Always show the hover menu contents (default: false) - */ - alwaysShow?: boolean; - /** - * The hover menu is closed whenever this prop changes - */ - closePopOverTrigger?: boolean; - /** - * The contents of the hover menu. It is highly recommended you wrap this - * content in a `div` with `position: absolute` to prevent it from effecting - * layout, and to adjust it's position via `top` and `left`. - */ - hoverContent?: JSX.Element; - /** - * The content that will be wrapped with hover actions. In addition to - * rendering the `hoverContent` when the user hovers, this render prop - * passes `showHoverContent` to provide a signal that it is in the hover - * state. - */ - render: (showHoverContent: boolean) => JSX.Element; - - /** - * This optional callback is invoked when a close is requested via user - * intent, i.e. by clicking outside of the popover, moving the mouse - * away, or pressing Escape. It's only a "request" to close, because - * the hover menu will NOT be closed if `alwaysShow` is `true`. - * - * Use this callback when you're managing the state of `alwaysShow` - * (outside of this component), and you want to be informed of a user's - * intent to close the hover menu. - */ - onCloseRequested?: () => void; + hoverContent: React.ReactNode; + anchorPosition?: PopoverAnchorPosition; } /** @@ -69,9 +37,9 @@ interface Props { * otherwise it will be difficult for keyboard-only and screen * reader users to navigate to and from your popover. */ -export const WithHoverActions = React.memo( - ({ alwaysShow = false, closePopOverTrigger, hoverContent, onCloseRequested, render }) => { - const [isOpen, setIsOpen] = useState(hoverContent != null && alwaysShow); +export const HoverPopover = React.memo>( + ({ hoverContent, anchorPosition = 'downCenter', children }) => { + const [isOpen, setIsOpen] = useState(hoverContent != null); const [showHoverContent, setShowHoverContent] = useState(false); const [, setHoverTimeout] = useState(undefined); const popoverRef = useRef(null); @@ -83,13 +51,7 @@ export const WithHoverActions = React.memo( }); setShowHoverContent(false); - - if (onCloseRequested != null) { - setTimeout(() => { - onCloseRequested(); - }); - } - }, [onCloseRequested]); + }, []); const onMouseEnter = useCallback(() => { setHoverTimeout( @@ -107,10 +69,8 @@ export const WithHoverActions = React.memo( }, [setHoverTimeout, setShowHoverContent]); const onMouseLeave = useCallback(() => { - if (!alwaysShow) { - tryClosePopover(); - } - }, [alwaysShow, tryClosePopover]); + tryClosePopover(); + }, [tryClosePopover]); const onKeyDown = useCallback( (keyboardEvent: React.KeyboardEvent) => { @@ -121,22 +81,9 @@ export const WithHoverActions = React.memo( [isOpen, onMouseLeave] ); - const content = useMemo( - () => ( -
- {render(showHoverContent)} -
- ), - [onMouseEnter, render, showHoverContent] - ); - useEffect(() => { - setIsOpen(hoverContent != null && (showHoverContent || alwaysShow)); - }, [hoverContent, showHoverContent, alwaysShow]); - - useEffect(() => { - setShowHoverContent(false); - }, [closePopOverTrigger]); // NOTE: the `closePopOverTrigger` dependency here will close the hover menu whenever `closePopOverTrigger` changes + setIsOpen(hoverContent != null && showHoverContent); + }, [hoverContent, showHoverContent]); useEffect(() => { // in case of dynamic content i.e when the value of hoverContent changes, @@ -145,20 +92,22 @@ export const WithHoverActions = React.memo( }, [hoverContent, isOpen]); return ( -
+
+ {children} +
+ } closePopover={tryClosePopover} hasArrow={false} isOpen={isOpen} ownFocus={false} panelPaddingSize="none" - panelClassName="withHoverActions__popover" + panelStyle={{ minInlineSize: 'fit-content' }} + panelClassName="HoverPopover__popover" repositionOnScroll={true} > {isOpen ?
{hoverContent}
: null} @@ -167,5 +116,4 @@ export const WithHoverActions = React.memo( ); } ); - -WithHoverActions.displayName = 'WithHoverActions'; +HoverPopover.displayName = 'HoverPopover'; diff --git a/x-pack/plugins/security_solution/public/common/components/hover_actions/keyboard_shortcut_constants.ts b/x-pack/plugins/security_solution/public/common/components/hover_popover/index.ts similarity index 83% rename from x-pack/plugins/security_solution/public/common/components/hover_actions/keyboard_shortcut_constants.ts rename to x-pack/plugins/security_solution/public/common/components/hover_popover/index.ts index cef4c896e39f2..6f94a6103cd35 100644 --- a/x-pack/plugins/security_solution/public/common/components/hover_actions/keyboard_shortcut_constants.ts +++ b/x-pack/plugins/security_solution/public/common/components/hover_popover/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export const SHOW_TOP_N_KEYBOARD_SHORTCUT = 't'; +export { HoverPopover } from './hover_popover'; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts index 85c567121ac2d..e42c2cd8ab23c 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts @@ -12,7 +12,7 @@ import type { ReportAttackDiscoveriesGeneratedParams, ReportAttackDiscoveryTelemetryEventParams, } from './events/attack_discovery/types'; -import type { SecurityMetadata } from '../../../actions/types'; +import type { SecurityCellActionMetadata } from '../../../app/actions/types'; import type { ML_JOB_TELEMETRY_STATUS, TelemetryEventTypes } from './constants'; import type { AlertsGroupingTelemetryEvent, @@ -91,7 +91,7 @@ export interface ReportMLJobUpdateParams { } export interface ReportCellActionClickedParams { - metadata: SecurityMetadata | undefined; + metadata: SecurityCellActionMetadata | undefined; displayName: string; actionId: string; fieldName: string; diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_by_type_panel/columns.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_by_type_panel/columns.tsx index 150a11d8f9888..5266a51804168 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_by_type_panel/columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_by_type_panel/columns.tsx @@ -8,6 +8,7 @@ import React from 'react'; import { EuiHealth, EuiText } from '@elastic/eui'; import { ALERT_RULE_NAME } from '@kbn/rule-data-utils'; import type { EuiBasicTableColumn } from '@elastic/eui'; +import { TableId } from '@kbn/securitysolution-data-table'; import { SecurityCellActions, CellActionsMode, @@ -41,6 +42,7 @@ export const getAlertsTypeTableColumns = ( queryValue={rule} tooltipContent={null} truncate={true} + scopeId={TableId.alertsOnAlertsPage} /> ), @@ -66,7 +68,10 @@ export const getAlertsTypeTableColumns = ( field: 'event.type', }} sourcererScopeId={SourcererScopeName.detections} - metadata={{ negateFilters: type === 'Detection' }} // Detection: event.type != denied + metadata={{ + negateFilters: type === 'Detection', // Detection: event.type != denied + scopeId: TableId.alertsOnAlertsPage, + }} > {ALERT_TYPE_LABEL[type as AlertType]} diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/columns.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/columns.tsx index 7dfb3170e43e0..938afdbd97afb 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_count_panel/columns.tsx @@ -9,6 +9,7 @@ import React from 'react'; import type { EuiBasicTableColumn } from '@elastic/eui'; import numeral from '@elastic/numeral'; +import { TableId } from '@kbn/securitysolution-data-table'; import type { FlattenedBucket } from '../../../../common/components/alerts_treemap/types'; import { DefaultDraggable } from '../../../../common/components/draggables'; import type { GenericBuckets } from '../../../../../common/search_strategy/common'; @@ -35,6 +36,7 @@ export const getSingleGroupByAlertsCountTableColumns = ({ id={`alert-count-draggable-stackByField0-${stackByField0}-${value}`} value={value} tooltipContent={null} + scopeId={TableId.alertsOnAlertsPage} /> ); }, @@ -73,6 +75,7 @@ export const getMultiGroupAlertsCountTableColumns = ({ id={`alert-count-draggable-stackByField0-${stackByField0}-${stackByField1}-${value}`} value={value} tooltipContent={null} + scopeId={TableId.alertsOnAlertsPage} /> ); }, @@ -91,6 +94,7 @@ export const getMultiGroupAlertsCountTableColumns = ({ id={`alert-count-draggable-stackByField1-${stackByField0}-${stackByField1}-${value}`} value={value} tooltipContent={null} + scopeId={TableId.alertsOnAlertsPage} /> ); }, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_progress_bar_panel/alerts_progress_bar.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_progress_bar_panel/alerts_progress_bar.tsx index ba4c795214764..1776c9d5fc9cc 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_progress_bar_panel/alerts_progress_bar.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/alerts_progress_bar_panel/alerts_progress_bar.tsx @@ -18,6 +18,7 @@ import { } from '@elastic/eui'; import React, { useState } from 'react'; import styled from 'styled-components'; +import { TableId } from '@kbn/securitysolution-data-table'; import type { AlertsProgressBarData, GroupBySelection } from './types'; import type { AddFilterProps } from '../common/types'; import { getAggregateData } from './helpers'; @@ -103,6 +104,7 @@ export const AlertsProgressBar: React.FC = ({ value={key} queryValue={key} tooltipContent={null} + scopeId={TableId.alertsOnAlertsPage} > {key} diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx index 8593c12874206..3e9f7eea4fbf8 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_kpis/severity_level_panel/columns.tsx @@ -10,6 +10,7 @@ import { capitalize } from 'lodash'; import { ALERT_SEVERITY } from '@kbn/rule-data-utils'; import type { EuiBasicTableColumn } from '@elastic/eui'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; +import { TableId } from '@kbn/securitysolution-data-table'; import type { SeverityBuckets as SeverityData } from '../../../../overview/components/detection_response/alerts_by_status/types'; import { DefaultDraggable } from '../../../../common/components/draggables'; import { SEVERITY_COLOR } from '../../../../overview/components/detection_response/utils'; @@ -32,6 +33,7 @@ export const getSeverityTableColumns = (): Array ), diff --git a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx index f1d1de98a0ea3..af9a21599ea0d 100644 --- a/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/hooks/trigger_actions_alert_table/use_cell_actions.tsx @@ -11,7 +11,7 @@ import { useCallback, useMemo } from 'react'; import { TableId, tableDefaults, dataTableSelectors } from '@kbn/securitysolution-data-table'; import type { UseDataGridColumnsSecurityCellActionsProps } from '../../../common/components/cell_actions'; import { useDataGridColumnsSecurityCellActions } from '../../../common/components/cell_actions'; -import { SecurityCellActionsTrigger, SecurityCellActionType } from '../../../actions/constants'; +import { SecurityCellActionsTrigger, SecurityCellActionType } from '../../../app/actions/constants'; import { VIEW_SELECTION } from '../../../../common/constants'; import { SourcererScopeName } from '../../../common/store/sourcerer/model'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector'; diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx index 8f468f4c13e13..5893fb803342c 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/entity_analytics_risk_score/index.test.tsx @@ -69,8 +69,6 @@ jest.mock('../../../common/hooks/use_navigate_to_alerts_page_with_filters', () = }; }); -jest.mock('../../../common/components/hover_actions', () => ({ HoverActions: () => null })); - const mockOpenRightPanel = jest.fn(); jest.mock('@kbn/expandable-flyout', () => { return { diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx index 2b498fdca79ac..e010c3bd42169 100644 --- a/x-pack/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx +++ b/x-pack/plugins/security_solution/public/entity_analytics/components/severity/common/index.tsx @@ -13,7 +13,7 @@ import styled, { css } from 'styled-components'; import { euiLightVars } from '@kbn/ui-theme'; import { RISK_SEVERITY_COLOUR } from '../../../common/utils'; -import { WithHoverActions } from '../../../../common/components/with_hover_actions'; +import { HoverPopover } from '../../../../common/components/hover_popover'; import type { RiskSeverity } from '../../../../../common/search_strategy'; const RiskBadge = styled.div<{ $severity: RiskSeverity; $hideBackgroundColor: boolean }>` @@ -39,34 +39,47 @@ export const RiskScoreLevel: React.FC<{ hideBackgroundColor?: boolean; toolTipContent?: JSX.Element; ['data-test-subj']?: string; -}> = ({ - severity, - hideBackgroundColor = false, - toolTipContent, - 'data-test-subj': dataTestSubj, -}) => { - const badge = ( - - - - {severity} - - - - ); +}> = React.memo( + ({ severity, hideBackgroundColor = false, toolTipContent, 'data-test-subj': dataTestSubj }) => { + if (toolTipContent != null) { + return ( + {toolTipContent}}> + + + ); + } - if (toolTipContent != null) { return ( - {toolTipContent}} - render={() => badge} + ); } - return badge; -}; +); +RiskScoreLevel.displayName = 'RiskScoreLevel'; + +const RiskScoreBadge: React.FC<{ + severity: RiskSeverity; + hideBackgroundColor?: boolean; + ['data-test-subj']?: string; +}> = React.memo(({ severity, hideBackgroundColor = false, 'data-test-subj': dataTestSubj }) => ( + + + + {severity} + + + +)); +RiskScoreBadge.displayName = 'RiskScoreBadge'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/cell_actions.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/cell_actions.tsx index 214326b990f0f..27fb6f752f71b 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/cell_actions.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/cell_actions.tsx @@ -10,7 +10,7 @@ import React, { useMemo } from 'react'; import { useLeftPanelContext } from '../context'; import { getSourcererScopeId } from '../../../../helpers'; import { useBasicDataFromDetailsData } from '../../../../timelines/components/side_panel/event_details/helpers'; -import { SecurityCellActionType } from '../../../../actions/constants'; +import { SecurityCellActionType } from '../../../../app/actions/constants'; import { CellActionsMode, SecurityCellActions, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx index 2084024c314e7..0ab96ccb7d7ac 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/host_details.tsx @@ -152,6 +152,7 @@ export const HostDetails: React.FC = ({ hostName, timestamp, s idPrefix={''} isDraggable={false} render={(ip) => (ip != null ? : getEmptyTagValue())} + scopeId={scopeId} /> ); }, @@ -174,7 +175,7 @@ export const HostDetails: React.FC = ({ hostName, timestamp, s ] : []), ], - [isEntityAnalyticsAuthorized] + [isEntityAnalyticsAuthorized, scopeId] ); const relatedUsersCount = useMemo( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx index c4841cc35f029..557337afccb4a 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/user_details.tsx @@ -153,6 +153,7 @@ export const UserDetails: React.FC = ({ userName, timestamp, s idPrefix={''} isDraggable={false} render={(ip) => (ip != null ? : getEmptyTagValue())} + scopeId={scopeId} /> ); }, @@ -175,7 +176,7 @@ export const UserDetails: React.FC = ({ userName, timestamp, s ] : []), ], - [isEntityAnalyticsAuthorized] + [isEntityAnalyticsAuthorized, scopeId] ); const relatedHostsCount = useMemo( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/alert_reason_preview.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/alert_reason_preview.test.tsx index 5e0194c7ec91a..53e0e5547a5f7 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/alert_reason_preview.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/preview/components/alert_reason_preview.test.tsx @@ -6,16 +6,12 @@ */ import React from 'react'; -import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { render } from '@testing-library/react'; import { PreviewPanelContext } from '../context'; import { mockContextValue } from '../mocks/mock_context'; import { ALERT_REASON_PREVIEW_BODY_TEST_ID } from './test_ids'; import { AlertReasonPreview } from './alert_reason_preview'; -import { ThemeProvider } from 'styled-components'; -import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock'; - -const mockTheme = getMockTheme({ eui: { euiFontSizeXS: '' } }); +import { TestProviders } from '../../../../common/mock'; const panelContextValue = { ...mockContextValue, @@ -26,13 +22,10 @@ const NO_DATA_MESSAGE = 'There was an error displaying data.'; describe('', () => { it('should render alert reason preview', () => { const { getByTestId } = render( - - - - - - - + + + , + { wrapper: TestProviders } ); expect(getByTestId(ALERT_REASON_PREVIEW_BODY_TEST_ID)).toBeInTheDocument(); expect(getByTestId(ALERT_REASON_PREVIEW_BODY_TEST_ID)).toHaveTextContent('Alert reason'); @@ -40,13 +33,10 @@ describe('', () => { it('should render no data message if alert reason is not available', () => { const { getByText } = render( - - - - - - - + + + , + { wrapper: TestProviders } ); expect(getByText(NO_DATA_MESSAGE)).toBeInTheDocument(); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/cell_actions.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/cell_actions.tsx index 23e4a4c01e823..52c216517b9de 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/cell_actions.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/cell_actions.tsx @@ -9,7 +9,7 @@ import type { FC } from 'react'; import React, { useMemo } from 'react'; import { useRightPanelContext } from '../context'; import { getSourcererScopeId } from '../../../../helpers'; -import { SecurityCellActionType } from '../../../../actions/constants'; +import { SecurityCellActionType } from '../../../../app/actions/constants'; import { CellActionsMode, SecurityCellActions, diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_renderer.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_renderer.test.tsx index 578147cc08999..f6e91cbe31756 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/right/components/event_renderer.test.tsx @@ -6,26 +6,20 @@ */ import React from 'react'; -import { __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { render } from '@testing-library/react'; -import { ThemeProvider } from 'styled-components'; import { EventRenderer } from './event_renderer'; import { RightPanelContext } from '../context'; import { EVENT_RENDERER_TEST_ID } from './test_ids'; import { mockContextValue } from '../mocks/mock_context'; import { mockDataAsNestedObject } from '../../shared/mocks/mock_data_as_nested_object'; -import { getMockTheme } from '../../../../common/lib/kibana/kibana_react.mock'; +import { TestProviders } from '../../../../common/mock'; -const mockTheme = getMockTheme({ eui: { euiFontSizeXS: '' } }); const renderEventRenderer = (contextValue: RightPanelContext) => render( - - - - - - - + + + , + { wrapper: TestProviders } ); describe('', () => { diff --git a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx index cda6113ded653..d84e1357aaecd 100644 --- a/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx +++ b/x-pack/plugins/security_solution/public/flyout/entity_details/shared/components/entity_table/columns.tsx @@ -11,7 +11,6 @@ import { euiThemeVars } from '@kbn/ui-theme'; import { FormattedMessage } from '@kbn/i18n-react'; import { DefaultFieldRenderer } from '../../../../../timelines/components/field_renderers/field_renderers'; import { getEmptyTagValue } from '../../../../../common/components/empty_value'; -import { getSourcererScopeId } from '../../../../../helpers'; import type { BasicEntityData, EntityTableColumns } from './types'; export const getEntityTableColumns = ( @@ -58,7 +57,6 @@ export const getEntityTableColumns = ( attrName={field} idPrefix={contextID ? `entityTable-${contextID}` : 'entityTable'} isDraggable={isDraggable} - sourcererScopeId={getSourcererScopeId(scopeId)} scopeId={scopeId} render={renderField} data-test-subj="entity-table-value" diff --git a/x-pack/plugins/security_solution/public/lazy_actions.ts b/x-pack/plugins/security_solution/public/lazy_actions.ts new file mode 100644 index 0000000000000..771d03af1ef78 --- /dev/null +++ b/x-pack/plugins/security_solution/public/lazy_actions.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { registerActions } from './app/actions'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx index 0799b0ea3c610..ba0af845d2d6c 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/host_alerts_table/host_alerts_table.tsx @@ -20,7 +20,6 @@ import { } from '@elastic/eui'; import { ALERT_SEVERITY } from '@kbn/rule-data-utils'; -import { CellActionsMode } from '@kbn/cell-actions'; import { useNavigateToAlertsPageWithFilters } from '../../../../common/hooks/use_navigate_to_alerts_page_with_filters'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { HeaderSection } from '../../../../common/components/header_section'; @@ -35,6 +34,7 @@ import { ITEMS_PER_PAGE, SEVERITY_COLOR } from '../utils'; import type { HostAlertsItem } from './use_host_alerts_items'; import { useHostAlertsItems } from './use_host_alerts_items'; import { + CellActionsMode, SecurityCellActions, SecurityCellActionsTrigger, } from '../../../../common/components/cell_actions'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx index eb58820531ad0..fc92df5eb14b4 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/rule_alerts_table/rule_alerts_table.tsx @@ -21,8 +21,7 @@ import { import { FormattedRelative } from '@kbn/i18n-react'; import type { Severity } from '@kbn/securitysolution-io-ts-alerting-types'; import { ALERT_RULE_NAME, ALERT_WORKFLOW_STATUS } from '@kbn/rule-data-utils'; -import { CellActionsMode } from '@kbn/cell-actions'; -import { SecurityCellActionsTrigger } from '../../../../actions/constants'; +import { SecurityCellActionsTrigger } from '../../../../app/actions/constants'; import { useNavigateToAlertsPageWithFilters } from '../../../../common/hooks/use_navigate_to_alerts_page_with_filters'; import { HeaderSection } from '../../../../common/components/header_section'; @@ -38,7 +37,7 @@ import { HoverVisibilityContainer } from '../../../../common/components/hover_vi import { BUTTON_CLASS as INSPECT_BUTTON_CLASS } from '../../../../common/components/inspect'; import { LastUpdatedAt } from '../../../../common/components/last_updated_at'; import { FormattedCount } from '../../../../common/components/formatted_number'; -import { SecurityCellActions } from '../../../../common/components/cell_actions'; +import { SecurityCellActions, CellActionsMode } from '../../../../common/components/cell_actions'; import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; diff --git a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx index 6f9b57a1b727d..bfa86d3ac2e40 100644 --- a/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/detection_response/user_alerts_table/user_alerts_table.tsx @@ -20,8 +20,7 @@ import { } from '@elastic/eui'; import { ALERT_SEVERITY } from '@kbn/rule-data-utils'; -import { CellActionsMode } from '@kbn/cell-actions'; -import { SecurityCellActionsTrigger } from '../../../../actions/constants'; +import { SecurityCellActionsTrigger } from '../../../../app/actions/constants'; import { useNavigateToAlertsPageWithFilters } from '../../../../common/hooks/use_navigate_to_alerts_page_with_filters'; import { FormattedCount } from '../../../../common/components/formatted_number'; import { HeaderSection } from '../../../../common/components/header_section'; @@ -34,7 +33,7 @@ import * as i18n from '../translations'; import { ITEMS_PER_PAGE, SEVERITY_COLOR } from '../utils'; import type { UserAlertsItem } from './use_user_alerts_items'; import { useUserAlertsItems } from './use_user_alerts_items'; -import { SecurityCellActions } from '../../../../common/components/cell_actions'; +import { SecurityCellActions, CellActionsMode } from '../../../../common/components/cell_actions'; import { useGlobalFilterQuery } from '../../../../common/hooks/use_global_filter_query'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx index ce1ec4cab8ef4..0215ca442e220 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/endpoint_overview/index.tsx @@ -17,25 +17,24 @@ import { DefaultFieldRenderer } from '../../../../timelines/components/field_ren import * as i18n from './translations'; import type { EndpointFields } from '../../../../../common/search_strategy/security_solution/hosts'; import { HostPolicyResponseActionStatus } from '../../../../../common/search_strategy/security_solution/hosts'; -import type { SourcererScopeName } from '../../../../common/store/sourcerer/model'; interface Props { contextID?: string; data: EndpointFields | null; - sourcererScopeId?: SourcererScopeName; + scopeId?: string; } -export const EndpointOverview = React.memo(({ contextID, data, sourcererScopeId }) => { +export const EndpointOverview = React.memo(({ contextID, data, scopeId }) => { const getDefaultRenderer = useCallback( (fieldName: string, fieldData: EndpointFields, attrName: string) => ( ), - [contextID, sourcererScopeId] + [contextID, scopeId] ); const descriptionLists: Readonly = useMemo(() => { const appliedPolicy = data?.hostInfo?.metadata.Endpoint.policy.applied; diff --git a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx index 6b499b085a23c..6ac68b9522762 100644 --- a/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/host_overview/index.tsx @@ -40,12 +40,11 @@ import { EndpointOverview } from './endpoint_overview'; import { OverviewDescriptionList } from '../../../common/components/overview_description_list'; import { RiskScoreLevel } from '../../../entity_analytics/components/severity/common'; import { RiskScoreHeaderTitle } from '../../../entity_analytics/components/risk_score_onboarding/risk_score_header_title'; -import type { SourcererScopeName } from '../../../common/store/sourcerer/model'; import { RiskScoreDocTooltip } from '../common'; interface HostSummaryProps { contextID?: string; // used to provide unique draggable context when viewing in the side panel - sourcererScopeId?: SourcererScopeName; + scopeId?: string; data: HostItem; id: string; isDraggable?: boolean; @@ -72,7 +71,7 @@ export const HostOverview = React.memo( ({ anomaliesData, contextID, - sourcererScopeId, + scopeId, data, endDate, id, @@ -125,10 +124,10 @@ export const HostOverview = React.memo( attrName={fieldName} idPrefix={contextID ? `host-overview-${contextID}` : 'host-overview'} isDraggable={isDraggable} - sourcererScopeId={sourcererScopeId} + scopeId={scopeId} /> ), - [contextID, isDraggable, sourcererScopeId] + [contextID, isDraggable, scopeId] ); const [hostRiskScore, hostRiskLevel] = useMemo(() => { @@ -256,7 +255,7 @@ export const HostOverview = React.memo( rowItems={getOr([], 'host.ip', data)} attrName={'host.ip'} idPrefix={contextID ? `host-overview-${contextID}` : 'host-overview'} - sourcererScopeId={sourcererScopeId} + scopeId={scopeId} isDraggable={isDraggable} render={(ip) => (ip != null ? : getEmptyTagValue())} /> @@ -293,7 +292,7 @@ export const HostOverview = React.memo( }, ], ], - [contextID, sourcererScopeId, data, firstColumn, getDefaultRenderer, isDraggable] + [contextID, scopeId, data, firstColumn, getDefaultRenderer, isDraggable] ); return ( <> @@ -340,11 +339,7 @@ export const HostOverview = React.memo( <> - + {loading && ( ( [onOpenTimeline, timeline.savedObjectId] ); - const render = useCallback( - (showHoverContent) => ( - - - - - {timeline.description && timeline.description.length && ( - - {timeline.description} - - )} - - - {showHoverContent && ( - - + + - - - + data-test-subj="open-duplicate" + isDisabled={timeline.savedObjectId == null} + iconSize="s" + iconType="copy" + onClick={handleClick} + size="s" + /> + + } + > + + + {timeline.description && timeline.description.length && ( + + {timeline.description} + )} - - ), - [handleClick, onOpenTimeline, timeline] - ); - - return ( - <> - + <>{!isLastItem && } ); @@ -142,7 +121,7 @@ export const RecentTimelines = React.memo( ); } - return <>{content}; + return
{content}
; } ); diff --git a/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx b/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx index 321f87a3b5984..30e528509b9c1 100644 --- a/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx +++ b/x-pack/plugins/security_solution/public/overview/components/user_overview/index.tsx @@ -38,12 +38,11 @@ import { OverviewDescriptionList } from '../../../common/components/overview_des import { RiskScoreLevel } from '../../../entity_analytics/components/severity/common'; import type { UserItem } from '../../../../common/search_strategy/security_solution/users/common'; import { RiskScoreHeaderTitle } from '../../../entity_analytics/components/risk_score_onboarding/risk_score_header_title'; -import type { SourcererScopeName } from '../../../common/store/sourcerer/model'; import { RiskScoreDocTooltip } from '../common'; export interface UserSummaryProps { contextID?: string; // used to provide unique draggable context when viewing in the side panel - sourcererScopeId?: SourcererScopeName; + scopeId?: string; data: UserItem; id: string; isDraggable?: boolean; @@ -70,7 +69,7 @@ export const UserOverview = React.memo( ({ anomaliesData, contextID, - sourcererScopeId, + scopeId, data, id, isDraggable = false, @@ -123,10 +122,10 @@ export const UserOverview = React.memo( attrName={fieldName} idPrefix={contextID ? `user-overview-${contextID}` : 'user-overview'} isDraggable={isDraggable} - sourcererScopeId={sourcererScopeId} + scopeId={scopeId} /> ), - [contextID, isDraggable, sourcererScopeId] + [contextID, isDraggable, scopeId] ); const [userRiskScore, userRiskLevel] = useMemo(() => { @@ -268,7 +267,7 @@ export const UserOverview = React.memo( rowItems={getOr([], 'host.ip', data)} attrName={'host.ip'} idPrefix={contextID ? `user-overview-${contextID}` : 'user-overview'} - sourcererScopeId={sourcererScopeId} + scopeId={scopeId} isDraggable={isDraggable} render={(ip) => (ip != null ? : getEmptyTagValue())} /> @@ -281,7 +280,7 @@ export const UserOverview = React.memo( indexPatterns, getDefaultRenderer, contextID, - sourcererScopeId, + scopeId, isDraggable, userName, firstColumn, diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 5cf1ccfcbe546..7b0ff954371c0 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -501,8 +501,8 @@ export class Plugin implements IPlugin
-
+
-
- +
- Test Org + + Test Org + - +
@@ -53,28 +53,28 @@ exports[`Field Renderers #autonomousSystemRenderer it renders correctly against class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
- +
- 12345 + + 12345 + - +
@@ -105,35 +105,35 @@ exports[`Field Renderers #hostIdRenderer it renders correctly against snapshot 1 }
-
+ @@ -152,35 +152,35 @@ exports[`Field Renderers #hostNameRenderer it renders correctly against snapshot }
-
+ @@ -205,28 +205,28 @@ exports[`Field Renderers #locationRenderer it renders correctly against snapshot class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
- +
- New York + + New York + - +
@@ -237,28 +237,28 @@ exports[`Field Renderers #locationRenderer it renders correctly against snapshot class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
- +
- New York + + New York + - +
diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx index d9edcb4cf0695..c6d5c657d7790 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx @@ -43,7 +43,8 @@ describe('Field Renderers', () => { describe('#locationRenderer', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( - locationRenderer(['source.geo.city_name', 'source.geo.region_name'], mockData.complete) + locationRenderer(['source.geo.city_name', 'source.geo.region_name'], mockData.complete), + { wrapper: TestProviders } ); expect(asFragment()).toMatchSnapshot(); @@ -66,7 +67,9 @@ describe('Field Renderers', () => { describe('#dateRenderer', () => { test('it renders correctly against snapshot', () => { - const { asFragment } = render(dateRenderer(mockData.complete.source?.firstSeen)); + const { asFragment } = render(dateRenderer(mockData.complete.source?.firstSeen), { + wrapper: TestProviders, + }); expect(asFragment()).toMatchSnapshot(); }); @@ -83,7 +86,8 @@ describe('Field Renderers', () => { test('it renders correctly against snapshot', () => { const { asFragment } = render( - autonomousSystemRenderer(mockData.complete.source!.autonomousSystem!, FlowTarget.source) + autonomousSystemRenderer(mockData.complete.source!.autonomousSystem!, FlowTarget.source), + { wrapper: TestProviders } ); expect(asFragment()).toMatchSnapshot(); diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx index afdb79365ff5c..4d67684324423 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.tsx @@ -12,6 +12,7 @@ import React, { useCallback, Fragment, useMemo, useState, useContext } from 'rea import styled from 'styled-components'; import type { HostEcs } from '@kbn/securitysolution-ecs'; +import { getSourcererScopeId } from '../../../helpers'; import { SecurityCellActions, CellActionsMode, @@ -200,7 +201,6 @@ interface DefaultFieldRendererProps { moreMaxHeight?: string; render?: (item: string) => React.ReactNode; rowItems: string[] | null | undefined; - sourcererScopeId?: SourcererScopeName; scopeId?: string; } @@ -212,7 +212,6 @@ export const DefaultFieldRendererComponent: React.FC moreMaxHeight = DEFAULT_MORE_MAX_HEIGHT, render, rowItems, - sourcererScopeId, scopeId, }) => { if (rowItems != null && rowItems.length > 0) { @@ -235,8 +234,8 @@ export const DefaultFieldRendererComponent: React.FC field={attrName} value={rowItem} isAggregatable={true} - fieldType={'keyword'} scopeId={scopeId} + fieldType={'keyword'} > {render ? render(rowItem) : rowItem} @@ -261,7 +260,7 @@ export const DefaultFieldRendererComponent: React.FC overflowIndexStart={displayCount} render={render} rowItems={rowItems} - sourcererScopeId={sourcererScopeId} + scopeId={scopeId} /> @@ -284,7 +283,7 @@ interface DefaultFieldRendererOverflowProps { render?: (item: string) => React.ReactNode; overflowIndexStart?: number; moreMaxHeight: string; - sourcererScopeId?: SourcererScopeName; + scopeId?: string; } interface MoreContainerProps { @@ -294,20 +293,14 @@ interface MoreContainerProps { moreMaxHeight: string; overflowIndexStart: number; render?: (item: string) => React.ReactNode; - sourcererScopeId?: SourcererScopeName; + scopeId?: string; } export const MoreContainer = React.memo( - ({ - fieldName, - idPrefix, - moreMaxHeight, - overflowIndexStart, - render, - values, - sourcererScopeId, - }) => { + ({ fieldName, idPrefix, moreMaxHeight, overflowIndexStart, render, values, scopeId }) => { const { timelineId } = useContext(TimelineContext); + const defaultedScopeId = scopeId ?? timelineId; + const sourcererScopeId = getSourcererScopeId(defaultedScopeId ?? ''); const moreItemsWithHoverActions = useMemo( () => @@ -323,14 +316,9 @@ export const MoreContainer = React.memo( visibleCellActions={5} showActionTooltips triggerId={SecurityCellActionsTrigger.DEFAULT} - data={{ - value, - field: fieldName, - }} + data={{ value, field: fieldName }} sourcererScopeId={sourcererScopeId ?? SourcererScopeName.default} - metadata={{ - scopeId: timelineId ?? undefined, - }} + metadata={{ scopeId: defaultedScopeId ?? undefined }} > <>{render ? render(value) : defaultToEmptyTag(value)} @@ -340,7 +328,7 @@ export const MoreContainer = React.memo( return acc; }, []), - [values, overflowIndexStart, idPrefix, fieldName, timelineId, render, sourcererScopeId] + [values, overflowIndexStart, idPrefix, fieldName, sourcererScopeId, defaultedScopeId, render] ); return ( @@ -362,15 +350,7 @@ export const MoreContainer = React.memo( MoreContainer.displayName = 'MoreContainer'; export const DefaultFieldRendererOverflow = React.memo( - ({ - attrName, - idPrefix, - moreMaxHeight, - overflowIndexStart = 5, - render, - rowItems, - sourcererScopeId, - }) => { + ({ attrName, idPrefix, moreMaxHeight, overflowIndexStart = 5, render, rowItems, scopeId }) => { const [isOpen, setIsOpen] = useState(false); const togglePopover = useCallback(() => setIsOpen((currentIsOpen) => !currentIsOpen), []); const button = useMemo( @@ -411,7 +391,7 @@ export const DefaultFieldRendererOverflow = React.memo )} diff --git a/x-pack/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap index 6aa17ff879ccc..ce3d8e7f58936 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/netflow/__snapshots__/index.test.tsx.snap @@ -209,68 +209,68 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
- - - first.last + + + first.last + - +
@@ -283,71 +283,59 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
+ - - - - - rat - - - + rat -
-
-
+ + +
@@ -366,65 +354,53 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ - -
- - -
- 1ms -
-
-
-
-
+ 1ms +
+
-
+
@@ -434,61 +410,49 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ - -
- - - Nov 12, 2018 @ 19:03:25.836 - -
-
-
+ Nov 12, 2018 @ 19:03:25.836 +
-
+
@@ -498,58 +462,58 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
- -
- - - Nov 12, 2018 @ 19:03:25.936 - -
-
+ + + Nov 12, 2018 @ 19:03:25.936 + +
+ +
@@ -576,71 +540,59 @@ tr:hover .c2:focus::before { class="euiFlexItem c6 emotion-euiFlexItem-growZero" >
-
-
-
+ - - - - - outgoing - - - + outgoing -
-
-
+ + +
@@ -650,66 +602,54 @@ tr:hover .c2:focus::before { class="euiFlexItem c6 emotion-euiFlexItem-growZero" >
-
-
-
- - - - http - - - + http -
-
-
+ + +
@@ -719,59 +659,47 @@ tr:hover .c2:focus::before { class="euiFlexItem c6 emotion-euiFlexItem-growZero" >
-
-
- - -
- - 100B - -
-
+ + 100B
-
-
+ +
@@ -781,59 +709,47 @@ tr:hover .c2:focus::before { class="euiFlexItem c6 emotion-euiFlexItem-growZero" >
-
-
- - -
- - 3 pkts - -
-
+ + 3 pkts
-
-
+ +
@@ -843,66 +759,54 @@ tr:hover .c2:focus::before { class="euiFlexItem c6 emotion-euiFlexItem-growZero" >
-
-
-
- - - - tcp - - - + tcp -
-
-
+ + +
@@ -912,66 +816,54 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - - we.live.in.a - - - + we.live.in.a -
-
-
+ + +
@@ -1028,57 +920,57 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+ @@ -1153,53 +1045,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - North America - - -
-
-
+ North America + +
@@ -1217,53 +1097,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - United States - - -
-
-
+ United States + +
@@ -1291,53 +1159,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - US - - -
-
-
+ US + +
@@ -1355,53 +1211,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - Georgia - - -
-
-
+ Georgia + +
@@ -1419,53 +1263,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - Atlanta - - -
-
-
+ Atlanta + +
@@ -1501,64 +1333,52 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
- -
- - (60.00%) - - - 60B - -
-
+ (60.00%) +
+ + 60B
-
-
+ +
@@ -1576,59 +1396,47 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
- - -
- - 2 pkts - -
-
+ + 2 pkts
-
-
+ +
@@ -1680,61 +1488,61 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
- -
- - (40.00%) - - - 40B - -
+ + (40.00%) + + + 40B + +
+ - +
@@ -1755,59 +1563,47 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
- - -
- - 1 pkts - -
-
+ + 1 pkts
-
-
+ +
@@ -1867,57 +1663,57 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+ @@ -1992,53 +1788,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - North America - - -
-
-
+ North America + +
@@ -2056,53 +1840,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - United States - - -
-
-
+ United States + +
@@ -2130,53 +1902,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - US - - -
-
-
+ US + +
@@ -2194,53 +1954,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - New York - - -
-
-
+ New York + +
@@ -2258,53 +2006,41 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
- - - New York - - -
-
-
+ New York + +
@@ -2336,95 +2072,83 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -2434,95 +2158,83 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
@@ -2532,95 +2244,83 @@ tr:hover .c2:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx index c5f805a53ac87..3c0ae21ac81cb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/host_details/expandable_host.tsx @@ -21,7 +21,6 @@ import { AnomalyTableProvider } from '../../../../common/components/ml/anomaly/a import { hostToCriteria } from '../../../../common/components/ml/criteria/host_to_criteria'; import { scoreIntervalToDateTime } from '../../../../common/components/ml/score/score_interval_to_datetime'; import { useHostDetails, ID } from '../../../../explore/hosts/containers/hosts/details'; -import { getSourcererScopeId } from '../../../../helpers'; interface ExpandableHostProps { hostName: string; @@ -100,7 +99,7 @@ export const ExpandableHostDetails = ({ {({ isLoadingAnomaliesData, anomaliesData, jobNameById }) => ( ) : ( defaultToEmptyTag(value) diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/user_details/expandable_user.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/user_details/expandable_user.tsx index b85b31c2185c5..db75d224682fd 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/user_details/expandable_user.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/user_details/expandable_user.tsx @@ -21,7 +21,6 @@ import { getCriteriaFromUsersType } from '../../../../common/components/ml/crite import { scoreIntervalToDateTime } from '../../../../common/components/ml/score/score_interval_to_datetime'; import { AnomalyTableProvider } from '../../../../common/components/ml/anomaly/anomaly_table_provider'; import { UsersType } from '../../../../explore/users/store/model'; -import { getSourcererScopeId } from '../../../../helpers'; export const QUERY_ID = 'usersDetailsQuery'; export interface ExpandableUserProps { @@ -99,7 +98,7 @@ export const ExpandableUserDetails = ({ data={userDetails} loading={loading} contextID={contextID} - sourcererScopeId={getSourcererScopeId(scopeId)} + scopeId={scopeId} isDraggable={isDraggable} id={QUERY_ID} anomaliesData={anomaliesData} diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap index fa510b06b588a..9d2956c56d588 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/netflow/__snapshots__/netflow_row_renderer.test.tsx.snap @@ -233,78 +233,78 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- user.name -

- +

+ user.name +

- - first.last + + + first.last + - -

- Press enter for options, or press space to begin dragging. -

+

+ Press enter for options, or press space to begin dragging. +

+
@@ -317,81 +317,69 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- process.name -

+ - - - - - rat - - - + rat -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -410,75 +398,63 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+ event.duration +

+
-
+ -

- event.duration -

- -
- - -
- 1ms -
-
-
-
-

- Press enter for options, or press space to begin dragging. -

-
+ 1ms +
+
-
+ +

+ Press enter for options, or press space to begin dragging. +

@@ -488,71 +464,59 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+ event.start +

+
-
+ -

- event.start -

- -
- - - Nov 12, 2018 @ 19:03:25.836 - -
-
-

- Press enter for options, or press space to begin dragging. -

-
+ Nov 12, 2018 @ 19:03:25.836 +
-
+ +

+ Press enter for options, or press space to begin dragging. +

@@ -562,68 +526,68 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- event.end -

- -
- - + +
- Nov 12, 2018 @ 19:03:25.936 - -
-
-

- Press enter for options, or press space to begin dragging. -

+ + + Nov 12, 2018 @ 19:03:25.936 + +
+
+

+ Press enter for options, or press space to begin dragging. +

+
@@ -650,81 +614,69 @@ tr:hover .c4:focus::before { class="euiFlexItem c8 emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- network.direction -

+ - - - - - outgoing - - - + outgoing -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -734,76 +686,64 @@ tr:hover .c4:focus::before { class="euiFlexItem c8 emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- network.protocol -

- - - - http - - - + http -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -813,69 +753,57 @@ tr:hover .c4:focus::before { class="euiFlexItem c8 emotion-euiFlexItem-growZero" >
-
-
+ +
-

- network.bytes -

- - -
- - 100B - -
-
+ + 100B -

- Press enter for options, or press space to begin dragging. -

-
-
+ + +

+ Press enter for options, or press space to begin dragging. +

@@ -885,69 +813,57 @@ tr:hover .c4:focus::before { class="euiFlexItem c8 emotion-euiFlexItem-growZero" >
-
-
+ +
-

- network.packets -

- - -
- - 3 pkts - -
-
+ + 3 pkts -

- Press enter for options, or press space to begin dragging. -

-
-
+ + +

+ Press enter for options, or press space to begin dragging. +

@@ -957,76 +873,64 @@ tr:hover .c4:focus::before { class="euiFlexItem c8 emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- network.transport -

- - - - tcp - - - + tcp -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1036,76 +940,64 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- network.community_id -

- - - - we.live.in.a - - - + we.live.in.a -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1162,67 +1054,67 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- source.ip -

- +

+ source.ip +

- - 192.168.1.2 - + + 192.168.1.2 + +
- -

- Press enter for options, or press space to begin dragging. -

+

+ Press enter for options, or press space to begin dragging. +

+
@@ -1251,83 +1143,83 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- source.port -

- +

+ source.port +

- + 9987 + + External link + + + (opens in a new tab or window) + + +
+ - -

- Press enter for options, or press space to begin dragging. -

+

+ Press enter for options, or press space to begin dragging. +

+
@@ -1358,63 +1250,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- source.geo.continent_name -

- - - North America - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ North America + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1432,63 +1312,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- source.geo.country_name -

- - - United States - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ United States + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1516,63 +1384,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- source.geo.country_iso_code -

- - - US - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ US + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1590,63 +1446,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- source.geo.region_name -

- - - Georgia - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ Georgia + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1664,63 +1508,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- source.geo.city_name -

- - - Atlanta - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ Atlanta + + +

+ Press enter for options, or press space to begin dragging. +

@@ -1756,74 +1588,62 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ +
-

- source.bytes -

- -
- - (60.00%) - - - 60B - -
-
+ (60.00%) +
+ + 60B -

- Press enter for options, or press space to begin dragging. -

-
-
+ + +

+ Press enter for options, or press space to begin dragging. +

@@ -1841,69 +1661,57 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ +
-

- source.packets -

- - -
- - 2 pkts - -
-
+ + 2 pkts -

- Press enter for options, or press space to begin dragging. -

-
-
+ + +

+ Press enter for options, or press space to begin dragging. +

@@ -1955,71 +1763,71 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- destination.bytes -

- +

+ destination.bytes +

-
- - (40.00%) - - - 40B - -
+ + (40.00%) + + + 40B + +
+ - -

- Press enter for options, or press space to begin dragging. -

+

+ Press enter for options, or press space to begin dragging. +

+
@@ -2040,69 +1848,57 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
-
-

- destination.packets -

- - -
- - 1 pkts - -
-
+ destination.packets +

+ + +
+ + 1 pkts -

- Press enter for options, or press space to begin dragging. -

-
-
+ + +

+ Press enter for options, or press space to begin dragging. +

@@ -2162,67 +1958,67 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- destination.ip -

- +

+ destination.ip +

- - 10.1.2.3 - + + 10.1.2.3 + +
- -

- Press enter for options, or press space to begin dragging. -

+

+ Press enter for options, or press space to begin dragging. +

+
@@ -2251,83 +2047,83 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
+
-
+
-

- destination.port -

- +

+ destination.port +

- + 80 + + External link + + + (opens in a new tab or window) + + +
+ - -

- Press enter for options, or press space to begin dragging. -

+

+ Press enter for options, or press space to begin dragging. +

+
@@ -2358,63 +2154,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- destination.geo.continent_name -

- - - North America - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ North America + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2432,63 +2216,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- destination.geo.country_name -

- - - United States - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ United States + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2516,63 +2288,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- destination.geo.country_iso_code -

- - - US - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ US + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2590,63 +2350,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- destination.geo.region_name -

- - - New York - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ New York + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2664,63 +2412,51 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- destination.geo.city_name -

- - - New York - - -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ New York + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2752,105 +2488,93 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- tls.fingerprints.ja3.hash -

+ + ja3 + + + tls.fingerprints.ja3.hash-value - - - - ja3 - - - tls.fingerprints.ja3.hash-value - - External link - - - (opens in a new tab or window) - - - + External link - + + (opens in a new tab or window) + + -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2860,105 +2584,93 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- tls.client_certificate.fingerprint.sha1 -

+ + client cert + + + tls.client_certificate.fingerprint.sha1-value - - - - client cert - - - tls.client_certificate.fingerprint.sha1-value - - External link - - - (opens in a new tab or window) - - - + External link - + + (opens in a new tab or window) + + -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

@@ -2968,105 +2680,93 @@ tr:hover .c4:focus::before { class="euiFlexItem emotion-euiFlexItem-growZero" >
-
-
+ + -
-

- tls.server_certificate.fingerprint.sha1 -

+ + server cert + + + tls.server_certificate.fingerprint.sha1-value - - - - server cert - - - tls.server_certificate.fingerprint.sha1-value - - External link - - - (opens in a new tab or window) - - - + External link - + + (opens in a new tab or window) + + -

- Press enter for options, or press space to begin dragging. -

-
-
-
+ + + +

+ Press enter for options, or press space to begin dragging. +

diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/customizations/use_histogram_customizations.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/customizations/use_histogram_customizations.tsx index 493e5b1bd0338..783c667ee7207 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/customizations/use_histogram_customizations.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/customizations/use_histogram_customizations.tsx @@ -14,7 +14,7 @@ import type { CustomizationCallback } from '@kbn/discover-plugin/public'; import type { UnifiedHistogramContainerProps } from '@kbn/unified-histogram-plugin/public'; import { ACTION_GLOBAL_APPLY_FILTER } from '@kbn/unified-search-plugin/public'; import { useCallback } from 'react'; -import { EsqlInTimelineTrigger } from '../../../../../../actions/constants'; +import { EsqlInTimelineTrigger } from '../../../../../../app/actions/constants'; import { useKibana } from '../../../../../../common/lib/kibana'; export type WithPreventableEvent = T & { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/mocks/index.ts b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/mocks/index.ts index 176d6d3c56d38..90358b0f07f90 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/mocks/index.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/tabs/esql/mocks/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { EsqlInTimelineTrigger } from '../../../../../../actions/constants'; +import { EsqlInTimelineTrigger } from '../../../../../../app/actions/constants'; export { MockEsqlTabContent } from './esql_tab_content'; export const mockApplyFilterTrigger = { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx index e49549d30b244..1c9a6a91c0aac 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/unified_components/data_table/index.tsx @@ -35,7 +35,7 @@ import { SourcererScopeName } from '../../../../../common/store/sourcerer/model' import { useSourcererDataView } from '../../../../../common/containers/sourcerer'; import { activeTimeline } from '../../../../containers/active_timeline_context'; import { DetailsPanel } from '../../../side_panel'; -import { SecurityCellActionsTrigger } from '../../../../../actions/constants'; +import { SecurityCellActionsTrigger } from '../../../../../app/actions/constants'; import { getFormattedFields } from '../../body/renderers/formatted_field_udt'; import ToolbarAdditionalControls from './toolbar_additional_controls'; import { StyledTimelineUnifiedDataTable, StyledEuiProgress } from '../styles'; diff --git a/x-pack/plugins/timelines/public/types.ts b/x-pack/plugins/timelines/public/types.ts index a91d8669debc7..4dabbe9ceb512 100644 --- a/x-pack/plugins/timelines/public/types.ts +++ b/x-pack/plugins/timelines/public/types.ts @@ -17,6 +17,9 @@ import { HoverActionsConfig } from './components/hover_actions'; import { LastUpdatedAtProps } from './components/last_updated'; import { LoadingPanelProps } from './components/loading'; export interface TimelinesUIStart { + /** + * @deprecated Use cell-actions package instead + */ getHoverActions: () => HoverActionsConfig; // eslint-disable-next-line @typescript-eslint/no-explicit-any getTimelineReducer: () => any; diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 08f8f4820c31b..afaaeeac4fcd4 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -33066,7 +33066,6 @@ "xpack.securitySolution.detectionResponse.noDataCurrent": "Aucune donnée {dataType} à comparer à partir de la plage temporelle actuelle", "xpack.securitySolution.detectionResponse.timeDifference": "Votre {statType} est {upOrDown} de {percentageChange} par rapport à {stat}", "xpack.securitySolution.detections.hostIsolation.impactedCases": "Cette action sera ajoutée aux {cases}.", - "xpack.securitySolution.dragAndDrop.youAreInADialogContainingOptionsScreenReaderOnly": "Vous êtes dans une boîte de dialogue contenant des options pour le champ {fieldName}. Appuyez sur Tab pour naviguer entre les options. Appuyez sur Échap pour quitter.", "xpack.securitySolution.editDataProvider.unavailableOperator": "L'opérateur {operator} n'est pas disponible avec les modèles", "xpack.securitySolution.enableRiskScore.enableRiskScore": "Activer le score de risque de {riskEntity}", "xpack.securitySolution.enableRiskScore.enableRiskScoreDescription": "Une fois que vous avez activé cette fonctionnalité, vous pouvez obtenir un accès rapide aux scores de risque de {riskEntity} dans cette section. Les données pourront prendre jusqu'à une heure pour être générées après l'activation du module.", @@ -33259,7 +33258,6 @@ "xpack.securitySolution.hoverActions.investigateInResolverForRowAriaLabel": "Analyser l'alerte ou l'événement de la ligne {ariaRowindex}, avec les colonnes {columnValues}", "xpack.securitySolution.hoverActions.moreActionsForRowAriaLabel": "Sélectionner davantage d'actions pour l'alerte ou l'événement de la ligne {ariaRowindex}, avec les colonnes {columnValues}", "xpack.securitySolution.hoverActions.sendAlertToTimelineForRowAriaLabel": "Envoyer l'alerte de la ligne {ariaRowindex} à la chronologie, avec les colonnes {columnValues}", - "xpack.securitySolution.hoverActions.showTopTooltip": "Afficher les premiers {fieldName}", "xpack.securitySolution.hoverActions.viewDetailsForRowAriaLabel": "Afficher les détails pour l'alerte ou l'événement de la ligne {ariaRowindex}, avec les colonnes {columnValues}", "xpack.securitySolution.indexPatterns.failureToastText": "Une erreur inattendue s'est produite lors de la mise à jour. Si vous souhaitez modifier vos données, vous pouvez sélectionner manuellement une vue de données {link}.", "xpack.securitySolution.indexPatterns.missingPatterns": "La vue de données Security ne contient pas les modèles d'indexation suivants nécessaires pour recréer la vue de données de la chronologie précédente : {callout}", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index d93db92a0bd55..599d3d89fec9d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -33034,7 +33034,6 @@ "xpack.securitySolution.detectionResponse.noDataCurrent": "現在の時間範囲から比較する{dataType}データがありません", "xpack.securitySolution.detectionResponse.timeDifference": "ご使用の{statType}は{stat}から{percentageChange}{upOrDown}", "xpack.securitySolution.detections.hostIsolation.impactedCases": "このアクションは{cases}に追加されます。", - "xpack.securitySolution.dragAndDrop.youAreInADialogContainingOptionsScreenReaderOnly": "フィールド {fieldName} のオプションを含む、ダイアログを表示しています。Tab を押すと、オプションを操作します。Escape を押すと、終了します。", "xpack.securitySolution.editDataProvider.unavailableOperator": "{operator}演算子はテンプレートで使用できません", "xpack.securitySolution.enableRiskScore.enableRiskScore": "{riskEntity}リスクスコアを有効化", "xpack.securitySolution.enableRiskScore.enableRiskScoreDescription": "この機能を有効化すると、このセクションで{riskEntity}リスクスコアにすばやくアクセスできます。モジュールを有効化した後、データの生成までに1時間かかる場合があります。", @@ -33226,7 +33225,6 @@ "xpack.securitySolution.hoverActions.investigateInResolverForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のアラートまたはイベントを分析", "xpack.securitySolution.hoverActions.moreActionsForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のアラートまたはイベントのその他のアクションを選択", "xpack.securitySolution.hoverActions.sendAlertToTimelineForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のイベントのアラートを送信", - "xpack.securitySolution.hoverActions.showTopTooltip": "上位の{fieldName}を表示", "xpack.securitySolution.hoverActions.viewDetailsForRowAriaLabel": "行 {ariaRowindex}、列 {columnValues} のアラートまたはイベントの詳細を表示", "xpack.securitySolution.indexPatterns.failureToastText": "更新時に予期しないエラーが発生しました。データを変更する場合は、手動でデータビュー{link}を選択できます。", "xpack.securitySolution.indexPatterns.missingPatterns": "以前のタイムラインのデータビューを再作成するには、セキュリティデータビューに次のインデックスパターンがありません:{callout}", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 01c8c4944f8f0..994f52f703fd4 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -33077,7 +33077,6 @@ "xpack.securitySolution.detectionResponse.noDataCurrent": "当前时间范围中没有可比较的 {dataType} 数据", "xpack.securitySolution.detectionResponse.timeDifference": "您的 {statType} 已从 {stat} {upOrDown} {percentageChange}", "xpack.securitySolution.detections.hostIsolation.impactedCases": "此操作将添加到 {cases}。", - "xpack.securitySolution.dragAndDrop.youAreInADialogContainingOptionsScreenReaderOnly": "您在对话框中,其中包含 {fieldName} 字段的选项。按 tab 键导航选项。按 escape 退出。", "xpack.securitySolution.editDataProvider.unavailableOperator": "{operator} 运算符不可用于模板", "xpack.securitySolution.enableRiskScore.enableRiskScore": "启用{riskEntity}风险分数", "xpack.securitySolution.enableRiskScore.enableRiskScoreDescription": "一旦启用此功能,您将可以在此部分快速访问{riskEntity}风险分数。启用此模板后,可能需要一小时才能生成数据。", @@ -33269,7 +33268,6 @@ "xpack.securitySolution.hoverActions.investigateInResolverForRowAriaLabel": "分析第 {ariaRowindex} 行的告警或事件,其中列为 {columnValues}", "xpack.securitySolution.hoverActions.moreActionsForRowAriaLabel": "为第 {ariaRowindex} 行中的告警或事件选择更多操作,其中列为 {columnValues}", "xpack.securitySolution.hoverActions.sendAlertToTimelineForRowAriaLabel": "将第 {ariaRowindex} 行的告警发送到时间线,其中列为 {columnValues}", - "xpack.securitySolution.hoverActions.showTopTooltip": "显示排名靠前的{fieldName}", "xpack.securitySolution.hoverActions.viewDetailsForRowAriaLabel": "查看第 {ariaRowindex} 行的告警或事件的详细信息,其中列为 {columnValues}", "xpack.securitySolution.indexPatterns.failureToastText": "更新时发生意外错误。如果要修改数据,您可以手动选择数据视图 {link}。", "xpack.securitySolution.indexPatterns.missingPatterns": "要重新创建上一时间线的数据视图,安全数据视图缺少以下索引模式:{callout}", diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts index 8426a4c178a3d..7b2f6796a05eb 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/investigations/timelines/filters.cy.ts @@ -17,10 +17,9 @@ import { ALERTS_URL } from '../../../urls/navigation'; import { getTimeline } from '../../../objects/timeline'; import { GET_TIMELINE_GRID_CELL, - TIMELINE_FILTER_FOR, - TIMELINE_FILTER_OUT, TIMELINE_EVENT, TIMELINE_FILTER_BADGE_ENABLED, + HOVER_ACTIONS, } from '../../../screens/timeline'; const mockTimeline = getTimeline(); @@ -40,13 +39,13 @@ describe( }); it('filter in', () => { cy.get(GET_TIMELINE_GRID_CELL('event.category')).trigger('mouseover'); - cy.get(TIMELINE_FILTER_FOR).should('be.visible').click(); + cy.get(HOVER_ACTIONS.FILTER_FOR).should('be.visible').click(); cy.get(TIMELINE_FILTER_BADGE_ENABLED).should('be.visible'); }); it('filter out', () => { cy.get(GET_TIMELINE_GRID_CELL('event.category')).trigger('mouseover'); - cy.get(TIMELINE_FILTER_OUT).should('be.visible').click(); + cy.get(HOVER_ACTIONS.FILTER_OUT).should('be.visible').click(); cy.get(TIMELINE_EVENT).should('not.exist'); }); } diff --git a/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts b/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts index e21d7fe46fea7..a348cc98d12ec 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/alerts.ts @@ -180,7 +180,7 @@ export const ALERT_TABLE_EVENT_RENDERED_VIEW_OPTION = '[data-test-subj="eventRen export const ALERT_RENDERER_HOST_NAME = '[data-test-subj="alertFieldBadge"] [data-test-subj="render-content-host.name"]'; -export const HOVER_ACTIONS_CONTAINER = getDataTestSubjectSelector('hover-actions-container'); +export const HOVER_ACTIONS_CONTAINER = getDataTestSubjectSelector('hoverActionsPopover'); export const SECURITY_SOLUTION_USERS_AVATAR = (user: string) => `[data-test-subj="securitySolutionUsersAvatar-${user}"]`; diff --git a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts index 5576a6c498f0f..8d24d64a38cd6 100644 --- a/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts +++ b/x-pack/test/security_solution_cypress/cypress/screens/timeline.ts @@ -284,17 +284,13 @@ export const TIMELINE_VIEW_IN_ANALYZER = '[data-test-subj="view-in-analyzer"]'; export const EMPTY_DATA_PROVIDER_AREA = `.timeline-drop-area-empty`; export const HOVER_ACTIONS = { - ADD_TO_TIMELINE: '[data-test-subj="hover-actions-add-timeline"]', - FILTER_FOR: '[data-test-subj="hover-actions-filter-for"]', - FILTER_OUT: '[data-test-subj="hovhover-actions-filter-out"]', - COPY: '[data-test-subj="hover-actions-copy-button"]', - SHOW_TOP: '[data-test-subj=show-top-field]', + ADD_TO_TIMELINE: '[data-test-subj="actionItem-security-default-cellActions-addToTimeline"]', + FILTER_FOR: '[data-test-subj="actionItem-security-default-cellActions-filterIn"]', + FILTER_OUT: '[data-test-subj="actionItem-security-default-cellActions-filterOut"]', + COPY: '[data-test-subj="actionItem-security-default-cellActions-copyToClipboard"]', + SHOW_TOP: '[data-test-subj="actionItem-security-default-cellActions-showTopN"]', }; -export const TIMELINE_FILTER_OUT = '[data-test-subj="filter-out-value"]'; - -export const TIMELINE_FILTER_FOR = '[data-test-subj="filter-for-value"]'; - export const TIMELINE_FILTER_BADGE_ENABLED = '[data-test-subj~="filter-enabled"]'; export const GET_TIMELINE_HEADER = (fieldName: string) => { diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/search_bar.ts b/x-pack/test/security_solution_cypress/cypress/tasks/search_bar.ts index b1849738677a6..2ac369e61b68d 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/search_bar.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/search_bar.ts @@ -52,19 +52,23 @@ export const removeKqlFilter = () => { }; export const fillAddFilterForm = ({ key, operator, value }: SearchBarFilter) => { - // workaround for field input sometimes not focusing correctly - cy.get(ADD_FILTER_FORM_FIELD_INPUT).click(); - // /workaround - cy.get(ADD_FILTER_FORM_FIELD_INPUT).type(`${key}{downarrow}{enter}`); + // workaround for field input sometimes rerenders losing focus + cy.waitUntil(() => { + cy.get(ADD_FILTER_FORM_FIELD_INPUT).should('be.enabled'); + cy.get(ADD_FILTER_FORM_FIELD_INPUT).focus(); + cy.get(ADD_FILTER_FORM_FIELD_INPUT).invoke('val', ''); // .clear() not working well + cy.get(ADD_FILTER_FORM_FIELD_INPUT).type(`${key}{downarrow}{enter}`); + return cy.get(ADD_FILTER_FORM_OPERATOR_FIELD).then(($el) => !$el.attr('disabled')); + }).then(() => { + cy.get(ADD_FILTER_FORM_OPERATOR_FIELD).type(`${operator}{downarrow}{enter}`); - cy.get(ADD_FILTER_FORM_OPERATOR_FIELD).type(`${operator}{downarrow}{enter}`); + if (value) { + cy.get(ADD_FILTER_FORM_FILTER_VALUE_INPUT).type(value); + } - if (value) { - cy.get(ADD_FILTER_FORM_FILTER_VALUE_INPUT).type(value); - } - - cy.get(ADD_FILTER_FORM_SAVE_BUTTON).click(); - cy.get(ADD_FILTER_FORM_SAVE_BUTTON).should('not.exist'); + cy.get(ADD_FILTER_FORM_SAVE_BUTTON).click(); + cy.get(ADD_FILTER_FORM_SAVE_BUTTON).should('not.exist'); + }); }; export const fillLocalSearchBar = (query: string) => { From ed14bafa42d62862b92b920a0a0b7624e8fc3a00 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Thu, 9 May 2024 16:01:43 +0100 Subject: [PATCH 2/2] skip failing es promotion suites (#183046) --- .../functional/apps/ml/data_visualizer/esql_data_visualizer.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts b/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts index 047b24f8be233..471c0c89f6b9c 100644 --- a/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts +++ b/x-pack/test/functional/apps/ml/data_visualizer/esql_data_visualizer.ts @@ -310,7 +310,8 @@ export default function ({ getPageObject, getService }: FtrProviderContext) { await ml.securityUI.loginAsMlPowerUser(); }); - describe('with farequote', function () { + // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/183046 + describe.skip('with farequote', function () { runTests(esqlFarequoteData); });