mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[8.8] [SecuritySolution] Restore lens table columns when Reset group by field clicked. (#156393) (#156454)
# Backport This will backport the following commits from `main` to `8.8`: - [[SecuritySolution] Restore lens table columns when Reset group by field clicked. (#156393)](https://github.com/elastic/kibana/pull/156393) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Angela Chuang","email":"6295984+angorayc@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-05-02T22:02:12Z","message":"[SecuritySolution] Restore lens table columns when Reset group by field clicked. (#156393)\n\n## Summary\r\n\r\nissue: https://github.com/elastic/kibana/issues/155859\r\nSteps to reproduce: Please find the issue above.\r\n\r\n`Reset group by field` action should:\r\n1. Revert `Group by` and `Group by top` to default fields\r\n`kibana.alert.rule.name` and `host.name`\r\n2. Unhide all the columns in the table.\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"db02784f98c6c41cbb0a0ccbc4895d67b698c4aa","branchLabelMapping":{"^v8.9.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","Team:Threat Hunting","Team: SecuritySolution","Team:Threat Hunting:Explore","v8.8.0","Feature:Lens Charts","v8.9.0"],"number":156393,"url":"https://github.com/elastic/kibana/pull/156393","mergeCommit":{"message":"[SecuritySolution] Restore lens table columns when Reset group by field clicked. (#156393)\n\n## Summary\r\n\r\nissue: https://github.com/elastic/kibana/issues/155859\r\nSteps to reproduce: Please find the issue above.\r\n\r\n`Reset group by field` action should:\r\n1. Revert `Group by` and `Group by top` to default fields\r\n`kibana.alert.rule.name` and `host.name`\r\n2. Unhide all the columns in the table.\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"db02784f98c6c41cbb0a0ccbc4895d67b698c4aa"}},"sourceBranch":"main","suggestedTargetBranches":["8.8"],"targetPullRequestStates":[{"branch":"8.8","label":"v8.8.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.9.0","labelRegex":"^v8.9.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/156393","number":156393,"mergeCommit":{"message":"[SecuritySolution] Restore lens table columns when Reset group by field clicked. (#156393)\n\n## Summary\r\n\r\nissue: https://github.com/elastic/kibana/issues/155859\r\nSteps to reproduce: Please find the issue above.\r\n\r\n`Reset group by field` action should:\r\n1. Revert `Group by` and `Group by top` to default fields\r\n`kibana.alert.rule.name` and `host.name`\r\n2. Unhide all the columns in the table.\r\n\r\n\r\n### Checklist\r\n\r\nDelete any items that are not applicable to this PR.\r\n\r\n\r\n- [x] [Unit or functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere updated or added to match the most common scenarios","sha":"db02784f98c6c41cbb0a0ccbc4895d67b698c4aa"}}]}] BACKPORT--> Co-authored-by: Angela Chuang <6295984+angorayc@users.noreply.github.com>
This commit is contained in:
parent
372d38fc1d
commit
44753b22eb
4 changed files with 222 additions and 31 deletions
|
@ -5,9 +5,14 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { TypedLensByValueInput } from '@kbn/lens-plugin/public';
|
||||
import type {
|
||||
DatatableVisualizationState,
|
||||
FormBasedPersistedState,
|
||||
TypedLensByValueInput,
|
||||
} from '@kbn/lens-plugin/public';
|
||||
import type { DataViewSpec } from '@kbn/data-views-plugin/common';
|
||||
import type { Action } from '@kbn/ui-actions-plugin/public';
|
||||
import type { Filter } from '@kbn/es-query';
|
||||
import type { Filter, Query } from '@kbn/es-query';
|
||||
|
||||
import type { InputsModelId } from '../../store/inputs/constants';
|
||||
import type { SourcererScopeName } from '../../store/sourcerer/model';
|
||||
|
@ -143,3 +148,36 @@ export interface VisualizationResponse<Hit = {}, Aggregations = {} | undefined>
|
|||
hits: Hit[];
|
||||
};
|
||||
}
|
||||
|
||||
export interface SavedObjectReference {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface LensDataTableAttributes<TVisType, TVisState> {
|
||||
description?: string;
|
||||
references: SavedObjectReference[];
|
||||
visualizationType: TVisType;
|
||||
state: {
|
||||
query: Query;
|
||||
globalPalette?: {
|
||||
activePaletteId: string;
|
||||
state?: unknown;
|
||||
};
|
||||
filters: Filter[];
|
||||
adHocDataViews?: Record<string, DataViewSpec>;
|
||||
internalReferences?: SavedObjectReference[];
|
||||
datasourceStates: {
|
||||
formBased: FormBasedPersistedState;
|
||||
};
|
||||
visualization: TVisState;
|
||||
};
|
||||
title: string;
|
||||
}
|
||||
|
||||
export interface LensDataTableEmbeddable {
|
||||
attributes: LensDataTableAttributes<'lnsDatatable', DatatableVisualizationState>;
|
||||
id: string;
|
||||
timeRange: { from: string; to: string; fromStr: string; toStr: string };
|
||||
}
|
||||
|
|
|
@ -4,9 +4,16 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
|
||||
import type { Embeddable } from '@kbn/embeddable-plugin/public';
|
||||
|
||||
import { formatAlertsData, showInitialLoadingSpinner } from './helpers';
|
||||
import {
|
||||
createResetGroupByFieldAction,
|
||||
formatAlertsData,
|
||||
showInitialLoadingSpinner,
|
||||
} from './helpers';
|
||||
import { result, textResult, stackedByBooleanField, stackedByTextField } from './mock_data';
|
||||
import type { LensDataTableEmbeddable } from '../../../../common/components/visualization_actions/types';
|
||||
|
||||
describe('helpers', () => {
|
||||
describe('showInitialLoadingSpinner', () => {
|
||||
|
@ -47,3 +54,103 @@ describe('formatAlertsData', () => {
|
|||
expect(res).toEqual(textResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createResetGroupByFieldAction', () => {
|
||||
let action: Action;
|
||||
const embeddable = {
|
||||
getInput: jest.fn().mockReturnValue({
|
||||
attributes: {
|
||||
title: 'test',
|
||||
description: '',
|
||||
visualizationType: 'lnsDatatable',
|
||||
state: {
|
||||
visualization: {
|
||||
columns: [
|
||||
{
|
||||
columnId: '2881fedd-54b7-42ba-8c97-5175dec86166',
|
||||
isTransposed: false,
|
||||
width: 362,
|
||||
},
|
||||
{
|
||||
columnId: 'f04a71a3-399f-4d32-9efc-8a005e989991',
|
||||
isTransposed: false,
|
||||
},
|
||||
{
|
||||
columnId: '75ce269b-ee9c-4c7d-a14e-9226ba0fe059',
|
||||
isTransposed: false,
|
||||
hidden: true,
|
||||
},
|
||||
],
|
||||
layerId: '03b95315-16ce-4146-a76a-621f9d4422f9',
|
||||
layerType: 'data',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as unknown as Embeddable<LensDataTableEmbeddable>),
|
||||
updateInput: jest.fn(),
|
||||
};
|
||||
|
||||
const context = {
|
||||
embeddable,
|
||||
} as unknown as ActionExecutionContext<Embeddable<LensDataTableEmbeddable>>;
|
||||
const mockCallback = jest.fn();
|
||||
beforeAll(async () => {
|
||||
action = createResetGroupByFieldAction({ callback: mockCallback });
|
||||
await action.execute(context);
|
||||
});
|
||||
test('should return a correct id', () => {
|
||||
expect(action.id).toEqual('resetGroupByField');
|
||||
});
|
||||
|
||||
test('should return display name', () => {
|
||||
expect(action.getDisplayName(context)).toEqual('Reset group by fields');
|
||||
});
|
||||
|
||||
test('should return an icon', () => {
|
||||
expect(action.getIconType(context)).toEqual('editorRedo');
|
||||
});
|
||||
|
||||
test('should return icon type', () => {
|
||||
expect(action.type).toEqual('actionButton');
|
||||
});
|
||||
|
||||
test('should execute callback', () => {
|
||||
expect(mockCallback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('should unhide all the columns', () => {
|
||||
expect(embeddable.updateInput).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
attributes: {
|
||||
description: '',
|
||||
state: {
|
||||
visualization: {
|
||||
columns: [
|
||||
{
|
||||
columnId: '2881fedd-54b7-42ba-8c97-5175dec86166',
|
||||
hidden: false,
|
||||
isTransposed: false,
|
||||
width: 362,
|
||||
},
|
||||
{
|
||||
columnId: 'f04a71a3-399f-4d32-9efc-8a005e989991',
|
||||
hidden: false,
|
||||
isTransposed: false,
|
||||
},
|
||||
{
|
||||
columnId: '75ce269b-ee9c-4c7d-a14e-9226ba0fe059',
|
||||
hidden: false,
|
||||
isTransposed: false,
|
||||
},
|
||||
],
|
||||
layerId: '03b95315-16ce-4146-a76a-621f9d4422f9',
|
||||
layerType: 'data',
|
||||
},
|
||||
},
|
||||
title: 'test',
|
||||
visualizationType: 'lnsDatatable',
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -9,8 +9,12 @@ import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesW
|
|||
import { isEmpty } from 'lodash/fp';
|
||||
import moment from 'moment';
|
||||
|
||||
import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
|
||||
import type { Embeddable } from '@kbn/embeddable-plugin/public';
|
||||
import type { HistogramData, AlertsAggregation, AlertsBucket, AlertsGroupBucket } from './types';
|
||||
import type { AlertSearchResponse } from '../../../containers/detection_engine/alerts/types';
|
||||
import { RESET_GROUP_BY_FIELDS } from '../../../../common/components/chart_settings_popover/configurations/default/translations';
|
||||
import type { LensDataTableEmbeddable } from '../../../../common/components/visualization_actions/types';
|
||||
|
||||
const EMPTY_ALERTS_DATA: HistogramData[] = [];
|
||||
|
||||
|
@ -119,3 +123,61 @@ export const buildCombinedQueries = (query?: string) => {
|
|||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
interface CreateResetGroupByFieldActionProps {
|
||||
callback?: () => void;
|
||||
order?: number;
|
||||
}
|
||||
|
||||
type CreateResetGroupByFieldAction = (params?: CreateResetGroupByFieldActionProps) => Action;
|
||||
export const createResetGroupByFieldAction: CreateResetGroupByFieldAction = ({
|
||||
callback,
|
||||
order,
|
||||
} = {}) => ({
|
||||
id: 'resetGroupByField',
|
||||
getDisplayName(): string {
|
||||
return RESET_GROUP_BY_FIELDS;
|
||||
},
|
||||
getIconType(): string | undefined {
|
||||
return 'editorRedo';
|
||||
},
|
||||
type: 'actionButton',
|
||||
async isCompatible(): Promise<boolean> {
|
||||
return true;
|
||||
},
|
||||
async execute({
|
||||
embeddable,
|
||||
}: ActionExecutionContext<{
|
||||
embeddable: Embeddable<LensDataTableEmbeddable>;
|
||||
}>): Promise<void> {
|
||||
callback?.();
|
||||
|
||||
const input = embeddable.getInput();
|
||||
const {
|
||||
attributes: {
|
||||
state: {
|
||||
visualization: { columns },
|
||||
},
|
||||
},
|
||||
} = input;
|
||||
|
||||
// Unhide all the columns
|
||||
embeddable.updateInput({
|
||||
...input,
|
||||
attributes: {
|
||||
...input.attributes,
|
||||
state: {
|
||||
...input.attributes.state,
|
||||
visualization: {
|
||||
...input.attributes.state.visualization,
|
||||
columns: columns.map((c) => ({
|
||||
...c,
|
||||
hidden: false,
|
||||
})),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
order,
|
||||
});
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import type { MappingRuntimeFields } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import type { ActionExecutionContext } from '@kbn/ui-actions-plugin/public';
|
||||
import type { Filter, Query } from '@kbn/es-query';
|
||||
import { EuiFlexItem, EuiLoadingContent } from '@elastic/eui';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
|
@ -30,9 +29,9 @@ import {
|
|||
} from '../../../components/alerts_kpis/common/config';
|
||||
import { AlertsCountPanel } from '../../../components/alerts_kpis/alerts_count_panel';
|
||||
import { GROUP_BY_LABEL } from '../../../components/alerts_kpis/common/translations';
|
||||
import { RESET_GROUP_BY_FIELDS } from '../../../../common/components/chart_settings_popover/configurations/default/translations';
|
||||
import { useQueryToggle } from '../../../../common/containers/query_toggle';
|
||||
import type { AddFilterProps } from '../../../components/alerts_kpis/common/types';
|
||||
import { createResetGroupByFieldAction } from '../../../components/alerts_kpis/alerts_histogram_panel/helpers';
|
||||
|
||||
const TREND_CHART_HEIGHT = 280; // px
|
||||
const CHART_PANEL_HEIGHT = 375; // px
|
||||
|
@ -124,33 +123,18 @@ const ChartPanelsComponent: React.FC<Props> = ({
|
|||
onResetStackByField1();
|
||||
}, [onResetStackByField0, onResetStackByField1]);
|
||||
|
||||
const handleResetGroupByFieldAction = useCallback(() => {
|
||||
onReset();
|
||||
updateCommonStackBy0(DEFAULT_STACK_BY_FIELD);
|
||||
|
||||
if (updateCommonStackBy1 != null) {
|
||||
updateCommonStackBy1(DEFAULT_STACK_BY_FIELD1);
|
||||
}
|
||||
}, [onReset, updateCommonStackBy0, updateCommonStackBy1]);
|
||||
|
||||
const resetGroupByFieldAction = useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'resetGroupByField',
|
||||
|
||||
getDisplayName(context: ActionExecutionContext<object>): string {
|
||||
return RESET_GROUP_BY_FIELDS;
|
||||
},
|
||||
getIconType(context: ActionExecutionContext<object>): string | undefined {
|
||||
return 'editorRedo';
|
||||
},
|
||||
type: 'actionButton',
|
||||
async isCompatible(context: ActionExecutionContext<object>): Promise<boolean> {
|
||||
return true;
|
||||
},
|
||||
async execute(context: ActionExecutionContext<object>): Promise<void> {
|
||||
onReset();
|
||||
updateCommonStackBy0(DEFAULT_STACK_BY_FIELD);
|
||||
|
||||
if (updateCommonStackBy1 != null) {
|
||||
updateCommonStackBy1(DEFAULT_STACK_BY_FIELD1);
|
||||
}
|
||||
},
|
||||
order: 5,
|
||||
},
|
||||
],
|
||||
[onReset, updateCommonStackBy0, updateCommonStackBy1]
|
||||
() => [createResetGroupByFieldAction({ callback: handleResetGroupByFieldAction, order: 5 })],
|
||||
[handleResetGroupByFieldAction]
|
||||
);
|
||||
|
||||
const chartOptionsContextMenu = useCallback(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue