[Security Solution][Tech Debt] Move remaining chart related components to alert KPI folder (#223570)

## Summary

This PR moves the `chart_settings_popover` and `field_selections` to
`~security_solution/public/detections/components/alerts_kpis` since they
are used exclusively by the KPI charts. These were left out in the
original folder reorg effort in
https://github.com/elastic/kibana/pull/189234


### Checklist

- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
christineweng 2025-06-24 16:17:21 -05:00 committed by GitHub
parent 26a14f36bf
commit c04d1782b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 108 additions and 111 deletions

View file

@ -185,7 +185,6 @@ module.exports = {
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]endpoint[\/\\]agents[\/\\]agent_status[\/\\]agent_status.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]endpoint[\/\\]agents[\/\\]agent_status[\/\\]agent_status.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]events_viewer[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]events_viewer[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]events_viewer[\/\\]summary_view_select[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]events_viewer[\/\\]summary_view_select[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]field_selection[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_actions[\/\\]actions.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]header_actions[\/\\]actions.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]health_truncate_text[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]health_truncate_text[\/\\]index.tsx/,
/x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]hover_visibility_container[\/\\]index.tsx/, /x-pack[\/\\]solutions[\/\\]security[\/\\]plugins[\/\\]security_solution[\/\\]public[\/\\]common[\/\\]components[\/\\]hover_visibility_container[\/\\]index.tsx/,

View file

@ -1,90 +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 type { EuiComboBox } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import React from 'react';
import styled from 'styled-components';
import { StackByComboBox } from '../../../detections/components/alerts_kpis/common/components';
import {
GROUP_BY_LABEL,
GROUP_BY_TOP_LABEL,
} from '../../../detections/components/alerts_kpis/common/translations';
const ChartOptionsFlexItem = styled(EuiFlexItem)`
margin-left: ${({ theme }) => theme.eui.euiSizeS};
`;
export interface Props {
chartOptionsContextMenu?: (queryId: string) => React.ReactNode;
setStackByField0: (stackBy: string) => void;
setStackByField0ComboboxInputRef?: (inputRef: HTMLInputElement | null) => void;
setStackByField1: (stackBy: string | undefined) => void;
setStackByField1ComboboxInputRef?: (inputRef: HTMLInputElement | null) => void;
stackByField0: string;
stackByField0ComboboxRef?: React.RefObject<EuiComboBox<string | number | string[] | undefined>>;
stackByField1: string | undefined;
stackByField1ComboboxRef?: React.RefObject<EuiComboBox<string | number | string[] | undefined>>;
stackByWidth?: number;
uniqueQueryId: string;
useLensCompatibleFields?: boolean;
}
const FieldSelectionComponent: React.FC<Props> = ({
chartOptionsContextMenu,
setStackByField0,
setStackByField0ComboboxInputRef,
setStackByField1,
setStackByField1ComboboxInputRef,
stackByField0,
stackByField0ComboboxRef,
stackByField1,
stackByField1ComboboxRef,
stackByWidth,
uniqueQueryId,
useLensCompatibleFields,
}: Props) => (
<EuiFlexGroup alignItems="flexStart" data-test-subj="fieldSelection" gutterSize="none">
<EuiFlexItem grow={false}>
<StackByComboBox
aria-label={GROUP_BY_LABEL}
ref={stackByField0ComboboxRef}
data-test-subj="groupBy"
onSelect={setStackByField0}
prepend={GROUP_BY_LABEL}
selected={stackByField0}
inputRef={setStackByField0ComboboxInputRef}
width={stackByWidth}
useLensCompatibleFields={useLensCompatibleFields}
/>
<EuiSpacer size="s" />
<StackByComboBox
aria-label={GROUP_BY_TOP_LABEL}
ref={stackByField1ComboboxRef}
data-test-subj="groupByTop"
onSelect={setStackByField1}
prepend={GROUP_BY_TOP_LABEL}
selected={stackByField1 ?? ''}
inputRef={setStackByField1ComboboxInputRef}
width={stackByWidth}
useLensCompatibleFields={useLensCompatibleFields}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
{chartOptionsContextMenu != null && (
<ChartOptionsFlexItem grow={false}>
{chartOptionsContextMenu(uniqueQueryId)}
</ChartOptionsFlexItem>
)}
</EuiFlexItem>
</EuiFlexGroup>
);
FieldSelectionComponent.displayName = 'FieldSelectionComponent';
export const FieldSelection = React.memo(FieldSelectionComponent);

View file

@ -15,7 +15,7 @@ import { HeaderSection } from '../../../../common/components/header_section';
import { InspectButtonContainer } from '../../../../common/components/inspect'; import { InspectButtonContainer } from '../../../../common/components/inspect';
import * as i18n from './translations'; import * as i18n from './translations';
import { KpiPanel } from '../common/components'; import { KpiPanel } from '../common/components';
import { FieldSelection } from '../../../../common/components/field_selection'; import { FieldSelection } from '../common/field_selection';
import { getAlertsTableLensAttributes as getLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/common/alerts/alerts_table'; import { getAlertsTableLensAttributes as getLensAttributes } from '../../../../common/components/visualization_actions/lens_attributes/common/alerts/alerts_table';
import { SourcererScopeName } from '../../../../sourcerer/store/model'; import { SourcererScopeName } from '../../../../sourcerer/store/model';
import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable'; import { VisualizationEmbeddable } from '../../../../common/components/visualization_actions/visualization_embeddable';

View file

@ -6,7 +6,7 @@
*/ */
import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
import { RESET_GROUP_BY_FIELDS } from '../../../../common/components/chart_settings_popover/configurations/default/translations'; import { RESET_GROUP_BY_FIELDS } from '../chart_panels/chart_settings_popover/configurations/default/translations';
import type { LensDataTableEmbeddable } from '../../../../common/components/visualization_actions/types'; import type { LensDataTableEmbeddable } from '../../../../common/components/visualization_actions/types';
interface LegacyLensEmbeddable { interface LegacyLensEmbeddable {

View file

@ -20,7 +20,7 @@ import { KpiPanel } from '../common/components';
import { useInspectButton } from '../common/hooks'; import { useInspectButton } from '../common/hooks';
import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query'; import { useQueryAlerts } from '../../../containers/detection_engine/alerts/use_query';
import { ALERTS_QUERY_NAMES } from '../../../containers/detection_engine/alerts/constants'; import { ALERTS_QUERY_NAMES } from '../../../containers/detection_engine/alerts/constants';
import { FieldSelection } from '../../../../common/components/field_selection'; import { FieldSelection } from '../common/field_selection';
import { HeaderSection } from '../../../../common/components/header_section'; import { HeaderSection } from '../../../../common/components/header_section';
import { InspectButtonContainer } from '../../../../common/components/inspect'; import { InspectButtonContainer } from '../../../../common/components/inspect';
import { DEFAULT_STACK_BY_FIELD0_SIZE, getAlertsRiskQuery } from './alerts_treemap/query'; import { DEFAULT_STACK_BY_FIELD0_SIZE, getAlertsRiskQuery } from './alerts_treemap/query';

View file

@ -9,8 +9,8 @@ import { fireEvent, render, screen } from '@testing-library/react';
import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl'; import { waitForEuiPopoverOpen } from '@elastic/eui/lib/test/rtl';
import React from 'react'; import React from 'react';
import { RESET_GROUP_BY_FIELDS } from '../../../../../common/components/chart_settings_popover/configurations/default/translations'; import { RESET_GROUP_BY_FIELDS } from '../chart_settings_popover/configurations/default/translations';
import { CHART_SETTINGS_POPOVER_ARIA_LABEL } from '../../../../../common/components/chart_settings_popover/translations'; import { CHART_SETTINGS_POPOVER_ARIA_LABEL } from '../chart_settings_popover/translations';
import { INSPECT } from '../../../../../common/components/inspect/translations'; import { INSPECT } from '../../../../../common/components/inspect/translations';
import { DEFAULT_STACK_BY_FIELD, DEFAULT_STACK_BY_FIELD1 } from '../../common/config'; import { DEFAULT_STACK_BY_FIELD, DEFAULT_STACK_BY_FIELD1 } from '../../common/config';
import { TestProviders } from '../../../../../common/mock'; import { TestProviders } from '../../../../../common/mock';

View file

@ -8,8 +8,8 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import { ChartSettingsPopover } from '../../../../../common/components/chart_settings_popover'; import { ChartSettingsPopover } from '../chart_settings_popover';
import { useChartSettingsPopoverConfiguration } from '../../../../../common/components/chart_settings_popover/configurations/default'; import { useChartSettingsPopoverConfiguration } from '../chart_settings_popover/configurations/default';
interface Props { interface Props {
defaultStackByField: string; defaultStackByField: string;

View file

@ -8,13 +8,13 @@
import { renderHook } from '@testing-library/react'; import { renderHook } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { TestProviders } from '../../../../mock'; import { TestProviders } from '../../../../../../../common/mock';
import * as i18n from './translations'; import * as i18n from './translations';
import { useChartSettingsPopoverConfiguration } from '.'; import { useChartSettingsPopoverConfiguration } from '.';
const mockHandleClick = jest.fn(); const mockHandleClick = jest.fn();
jest.mock('../../../inspect/use_inspect', () => ({ jest.mock('../../../../../../../common/components/inspect/use_inspect', () => ({
useInspect: () => ({ handleClick: mockHandleClick }), useInspect: () => ({ handleClick: mockHandleClick }),
})); }));

View file

@ -9,7 +9,7 @@ import type { EuiContextMenuPanelDescriptor } from '@elastic/eui';
import type { Dispatch, SetStateAction } from 'react'; import type { Dispatch, SetStateAction } from 'react';
import { useMemo, useState } from 'react'; import { useMemo, useState } from 'react';
import { useInspect } from '../../../inspect/use_inspect'; import { useInspect } from '../../../../../../../common/components/inspect/use_inspect';
import * as i18n from './translations'; import * as i18n from './translations';

View file

@ -9,7 +9,7 @@ import type { EuiContextMenuPanelDescriptor } from '@elastic/eui';
import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui'; import { EuiButtonIcon, EuiContextMenu, EuiPopover } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { BUTTON_CLASS } from '../inspect'; import { BUTTON_CLASS } from '../../../../../common/components/inspect';
import * as i18n from './translations'; import * as i18n from './translations';
interface Props { interface Props {

View file

@ -10,8 +10,8 @@ import React from 'react';
import { useAlertsLocalStorage } from './alerts_local_storage'; import { useAlertsLocalStorage } from './alerts_local_storage';
import type { Status } from '../../../../../common/api/detection_engine'; import type { Status } from '../../../../../common/api/detection_engine';
import { RESET_GROUP_BY_FIELDS } from '../../../../common/components/chart_settings_popover/configurations/default/translations'; import { RESET_GROUP_BY_FIELDS } from './chart_settings_popover/configurations/default/translations';
import { CHART_SETTINGS_POPOVER_ARIA_LABEL } from '../../../../common/components/chart_settings_popover/translations'; import { CHART_SETTINGS_POPOVER_ARIA_LABEL } from './chart_settings_popover/translations';
import { mockBrowserFields } from '../../../../common/containers/source/mock'; import { mockBrowserFields } from '../../../../common/containers/source/mock';
import { useSourcererDataView } from '../../../../sourcerer/containers'; import { useSourcererDataView } from '../../../../sourcerer/containers';
import { TestProviders } from '../../../../common/mock'; import { TestProviders } from '../../../../common/mock';

View file

@ -8,13 +8,10 @@
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { TestProviders } from '../../mock'; import { TestProviders } from '../../../../common/mock';
import type { Props } from '.'; import type { Props } from './field_selection';
import { FieldSelection } from '.'; import { FieldSelection } from './field_selection';
import { import { GROUP_BY_LABEL, GROUP_BY_TOP_LABEL } from './translations';
GROUP_BY_LABEL,
GROUP_BY_TOP_LABEL,
} from '../../../detections/components/alerts_kpis/common/translations';
jest.mock('react-router-dom', () => { jest.mock('react-router-dom', () => {
const actual = jest.requireActual('react-router-dom'); const actual = jest.requireActual('react-router-dom');

View file

@ -0,0 +1,91 @@
/*
* 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 type { EuiComboBox } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';
import { StackByComboBox } from './components';
import { GROUP_BY_LABEL, GROUP_BY_TOP_LABEL } from './translations';
export interface Props {
chartOptionsContextMenu?: (queryId: string) => React.ReactNode;
setStackByField0: (stackBy: string) => void;
setStackByField0ComboboxInputRef?: (inputRef: HTMLInputElement | null) => void;
setStackByField1: (stackBy: string | undefined) => void;
setStackByField1ComboboxInputRef?: (inputRef: HTMLInputElement | null) => void;
stackByField0: string;
stackByField0ComboboxRef?: React.RefObject<EuiComboBox<string | number | string[] | undefined>>;
stackByField1: string | undefined;
stackByField1ComboboxRef?: React.RefObject<EuiComboBox<string | number | string[] | undefined>>;
stackByWidth?: number;
uniqueQueryId: string;
useLensCompatibleFields?: boolean;
}
const FieldSelectionComponent: React.FC<Props> = ({
chartOptionsContextMenu,
setStackByField0,
setStackByField0ComboboxInputRef,
setStackByField1,
setStackByField1ComboboxInputRef,
stackByField0,
stackByField0ComboboxRef,
stackByField1,
stackByField1ComboboxRef,
stackByWidth,
uniqueQueryId,
useLensCompatibleFields,
}: Props) => {
const { euiTheme } = useEuiTheme();
return (
<EuiFlexGroup alignItems="flexStart" data-test-subj="fieldSelection" gutterSize="none">
<EuiFlexItem grow={false}>
<StackByComboBox
aria-label={GROUP_BY_LABEL}
ref={stackByField0ComboboxRef}
data-test-subj="groupBy"
onSelect={setStackByField0}
prepend={GROUP_BY_LABEL}
selected={stackByField0}
inputRef={setStackByField0ComboboxInputRef}
width={stackByWidth}
useLensCompatibleFields={useLensCompatibleFields}
/>
<EuiSpacer size="s" />
<StackByComboBox
aria-label={GROUP_BY_TOP_LABEL}
ref={stackByField1ComboboxRef}
data-test-subj="groupByTop"
onSelect={setStackByField1}
prepend={GROUP_BY_TOP_LABEL}
selected={stackByField1 ?? ''}
inputRef={setStackByField1ComboboxInputRef}
width={stackByWidth}
useLensCompatibleFields={useLensCompatibleFields}
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
{chartOptionsContextMenu != null && (
<EuiFlexItem
grow={false}
css={css`
margin-left: ${euiTheme.size.s};
`}
>
{chartOptionsContextMenu(uniqueQueryId)}
</EuiFlexItem>
)}
</EuiFlexItem>
</EuiFlexGroup>
);
};
FieldSelectionComponent.displayName = 'FieldSelectionComponent';
export const FieldSelection = React.memo(FieldSelectionComponent);