mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[Asset Inventory] Added filter functionality onClick Bar Graph (#224896)
## Summary This PR adds functionality for User to filter data using `entity.type` and `entity.sub_type` and add it to the Filter Manager https://github.com/user-attachments/assets/460aa3a4-4052-46d0-824d-6d09e86e645e
This commit is contained in:
parent
da41b47f1d
commit
b3aad140ae
3 changed files with 118 additions and 1 deletions
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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 { ASSET_FIELDS } from '../constants';
|
||||
import { handleElementClick } from './asset_inventory_bar_chart';
|
||||
|
||||
describe('handleElementClick', () => {
|
||||
it('should call setQuery with the correct filters', () => {
|
||||
const setQuery = jest.fn();
|
||||
|
||||
const mockDatum = {
|
||||
[ASSET_FIELDS.ENTITY_TYPE]: 'host_type',
|
||||
[ASSET_FIELDS.ENTITY_SUB_TYPE]: 'host_sub_type',
|
||||
count: 1,
|
||||
};
|
||||
|
||||
const mockGeometryValue = {
|
||||
value: 'geometry-value',
|
||||
datum: mockDatum,
|
||||
};
|
||||
|
||||
const mockSeriesIdentifier = {
|
||||
key: 'series-identifier',
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const elements: Array<[any, any]> = [[mockGeometryValue, mockSeriesIdentifier]];
|
||||
|
||||
const mockIndexId = 'mock-index-id';
|
||||
|
||||
handleElementClick(elements, setQuery, mockIndexId);
|
||||
|
||||
expect(setQuery).toHaveBeenCalledWith({
|
||||
filters: [
|
||||
expect.objectContaining({
|
||||
meta: expect.objectContaining({
|
||||
key: 'entity.type',
|
||||
params: { query: 'host_type' },
|
||||
}),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
meta: expect.objectContaining({
|
||||
key: 'entity.sub_type',
|
||||
params: { query: 'host_sub_type' },
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
|
@ -15,12 +15,16 @@ import {
|
|||
type EuiThemeFontSize,
|
||||
} from '@elastic/eui';
|
||||
import { getAbbreviatedNumber } from '@kbn/cloud-security-posture-common';
|
||||
import type { GeometryValue, SeriesIdentifier } from '@elastic/charts';
|
||||
import { Axis, BarSeries, Chart, Position, Settings, ScaleType } from '@elastic/charts';
|
||||
import { useElasticChartsTheme } from '@kbn/charts-theme';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { css } from '@emotion/react';
|
||||
import { FilterStateStore } from '@kbn/es-query';
|
||||
import type { AssetInventoryChartData } from '../hooks/use_fetch_chart_data/types';
|
||||
import { ASSET_FIELDS } from '../constants';
|
||||
import type { AssetsURLQuery } from '../hooks/use_asset_inventory_url_state/use_asset_inventory_url_state';
|
||||
import { useDataViewContext } from '../hooks/data_view_context';
|
||||
|
||||
const chartTitle = i18n.translate(
|
||||
'xpack.securitySolution.assetInventory.topAssetsBarChart.chartTitle',
|
||||
|
@ -61,19 +65,70 @@ export interface AssetInventoryBarChartProps {
|
|||
isLoading: boolean;
|
||||
isFetching: boolean;
|
||||
assetInventoryChartData: AssetInventoryChartData[];
|
||||
setQuery(v: Partial<AssetsURLQuery>): void;
|
||||
}
|
||||
|
||||
const createAssetFilter = (key: string, value: string, index: string) => {
|
||||
return {
|
||||
$state: { store: FilterStateStore.APP_STATE },
|
||||
meta: {
|
||||
alias: null,
|
||||
disabled: false,
|
||||
index,
|
||||
key,
|
||||
negate: false,
|
||||
params: { query: value },
|
||||
type: 'phrase',
|
||||
},
|
||||
query: {
|
||||
match_phrase: {
|
||||
[key]: value,
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const handleElementClick = (
|
||||
elements: Array<[GeometryValue, SeriesIdentifier]>,
|
||||
setQuery: (v: Partial<AssetsURLQuery>) => void,
|
||||
index: string
|
||||
): void => {
|
||||
if (!elements.length) return;
|
||||
|
||||
const [[geometryValue]] = elements;
|
||||
const datum = geometryValue.datum as AssetInventoryChartData;
|
||||
|
||||
const subtype = datum[ASSET_FIELDS.ENTITY_SUB_TYPE];
|
||||
const type = datum[ASSET_FIELDS.ENTITY_TYPE];
|
||||
|
||||
const filters = [
|
||||
createAssetFilter(ASSET_FIELDS.ENTITY_TYPE, type, index),
|
||||
createAssetFilter(ASSET_FIELDS.ENTITY_SUB_TYPE, subtype, index),
|
||||
];
|
||||
|
||||
setQuery({ filters });
|
||||
};
|
||||
|
||||
export const AssetInventoryBarChart = ({
|
||||
isLoading,
|
||||
isFetching,
|
||||
assetInventoryChartData,
|
||||
setQuery,
|
||||
}: AssetInventoryBarChartProps) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const xsFontSize = useEuiFontSize('xs');
|
||||
const baseTheme = useElasticChartsTheme();
|
||||
const { dataView } = useDataViewContext();
|
||||
|
||||
if (!dataView.id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const dataViewId = dataView.id;
|
||||
|
||||
return (
|
||||
<div css={getChartStyles(euiTheme, xsFontSize)}>
|
||||
<EuiProgress size="xs" color="accent" style={getProgressStyle(isFetching)} />
|
||||
<EuiProgress size="xs" color="accent" css={getProgressStyle(isFetching)} />
|
||||
{isLoading ? (
|
||||
<EuiFlexGroup
|
||||
justifyContent="center"
|
||||
|
@ -116,6 +171,13 @@ export const AssetInventoryBarChart = ({
|
|||
const count = !seriesData ? 0 : getAbbreviatedNumber(seriesData.count);
|
||||
return <span>{count}</span>;
|
||||
}}
|
||||
onElementClick={(elements) =>
|
||||
handleElementClick(
|
||||
elements as Array<[GeometryValue, SeriesIdentifier]>,
|
||||
setQuery,
|
||||
dataViewId
|
||||
)
|
||||
}
|
||||
/>
|
||||
<Axis
|
||||
id="X-axis"
|
||||
|
|
|
@ -101,6 +101,7 @@ const AllAssetsComponent = () => {
|
|||
isLoading={isLoadingChartData}
|
||||
isFetching={isFetchingChartData}
|
||||
assetInventoryChartData={!!chartData && chartData.length > 0 ? chartData : []}
|
||||
setQuery={setUrlQuery}
|
||||
/>
|
||||
<EuiSpacer size="xl" />
|
||||
<AssetInventoryTableSection state={state} />
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue