Skip to content

Commit

Permalink
Refactor Asset Inventory page
Browse files Browse the repository at this point in the history
  • Loading branch information
albertoblaz committed Mar 3, 2025
1 parent 86973f5 commit eeea887
Show file tree
Hide file tree
Showing 17 changed files with 252 additions and 280 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,9 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { css } from '@emotion/react';
import illustration from '../../common/images/illustration_product_no_results_magnifying_glass.svg';
import { DOCS_URL, TEST_SUBJ_EMPTY_STATE, I18N_PREFIX } from '../constants';

const ASSET_INVENTORY_DOCS_URL = 'https://ela.st/asset-inventory';
const EMPTY_STATE_TEST_SUBJ = 'assetInventory:empty-state';

export const EmptyState = ({
onResetFilters,
docsUrl = ASSET_INVENTORY_DOCS_URL,
}: {
onResetFilters: () => void;
docsUrl?: string;
}) => {
export const EmptyState = ({ onResetFilters }: { onResetFilters: () => void }) => {
const { euiTheme } = useEuiTheme();

return (
Expand All @@ -35,11 +27,11 @@ export const EmptyState = ({
margin-top: ${euiTheme.size.xxxl}};
}
`}
data-test-subj={EMPTY_STATE_TEST_SUBJ}
data-test-subj={TEST_SUBJ_EMPTY_STATE}
icon={
<EuiImage
url={illustration}
alt={i18n.translate('xpack.securitySolution.assetInventory.emptyState.illustrationAlt', {
alt={i18n.translate(`${I18N_PREFIX}.emptyState.illustrationAlt`, {
defaultMessage: 'No results',
})}
css={css`
Expand All @@ -50,7 +42,7 @@ export const EmptyState = ({
title={
<h2>
<FormattedMessage
id="xpack.securitySolution.assetInventory.emptyState.title"
id={`${I18N_PREFIX}.emptyState.title`}
defaultMessage="No results match your search criteria"
/>
</h2>
Expand All @@ -61,7 +53,7 @@ export const EmptyState = ({
<>
<p>
<FormattedMessage
id="xpack.securitySolution.assetInventory.emptyState.description"
id={`${I18N_PREFIX}.emptyState.description`}
defaultMessage="Try modifying your search or filter set"
/>
</p>
Expand All @@ -70,13 +62,13 @@ export const EmptyState = ({
actions={[
<EuiButton color="primary" fill onClick={onResetFilters}>
<FormattedMessage
id="xpack.securitySolution.assetInventory.emptyState.resetFiltersButton"
id={`${I18N_PREFIX}.emptyState.resetFiltersButton`}
defaultMessage="Reset filters"
/>
</EuiButton>,
<EuiLink href={docsUrl} target="_blank">
<EuiLink href={DOCS_URL} target="_blank">
<FormattedMessage
id="xpack.securitySolution.assetInventory.emptyState.readDocsLink"
id={`${I18N_PREFIX}.emptyState.readDocsLink`}
defaultMessage="Read the docs"
/>
</EuiLink>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,44 +12,42 @@ import type { FilterControlConfig } from '@kbn/alerts-ui-shared';
import type { Filter } from '@kbn/es-query';
import { Storage } from '@kbn/kibana-utils-plugin/public';
import { ControlGroupRenderer } from '@kbn/controls-plugin/public';
import { useDataViewContext } from '../../hooks/data_view_context';

import { useSpaceId } from '../../../common/hooks/use_space_id';
import { ASSET_INVENTORY_INDEX_PATTERN } from '../../constants';

import { useDataViewContext } from '../../hooks/data_view_context';
import type { AssetsBaseURLQuery } from '../../hooks/use_asset_inventory_data_table';
import { ASSET_INVENTORY_INDEX_PATTERN, I18N_PREFIX } from '../../constants';

import { FilterGroupLoading } from './filters_loading';
import { ASSET_INVENTORY_RULE_TYPE_IDS } from './rule_type_ids';

type Query = Pick<AssetsBaseURLQuery, 'query' | 'filters'>;

const DEFAULT_ASSET_INVENTORY_FILTERS: FilterControlConfig[] = [
{
title: i18n.translate('xpack.securitySolution.assetInventory.filters.type', {
defaultMessage: 'Type',
}),
title: i18n.translate(`${I18N_PREFIX}.filters.type`, { defaultMessage: 'Type' }),
fieldName: 'entity.category',
},
{
title: i18n.translate('xpack.securitySolution.assetInventory.filters.criticality', {
defaultMessage: 'Criticality',
}),
title: i18n.translate(`${I18N_PREFIX}.filters.criticality`, { defaultMessage: 'Criticality' }),
fieldName: 'asset.criticality',
},
{
title: i18n.translate('xpack.securitySolution.assetInventory.filters.tags', {
defaultMessage: 'Tags',
}),
title: i18n.translate(`${I18N_PREFIX}.filters.tags`, { defaultMessage: 'Tags' }),
fieldName: 'asset.tags.name',
},
{
title: i18n.translate('xpack.securitySolution.assetInventory.filters.name', {
defaultMessage: 'Name',
}),
title: i18n.translate(`${I18N_PREFIX}.filters.name`, { defaultMessage: 'Name' }),
fieldName: 'asset.name',
},
];

export interface FiltersProps {
onFiltersChange: (newFilters: Filter[]) => void;
setQuery: (v: Partial<Query>) => void;
}

export const Filters = ({ onFiltersChange }: FiltersProps) => {
export const Filters = ({ setQuery }: FiltersProps) => {
const { dataView, dataViewIsLoading } = useDataViewContext();
const spaceId = useSpaceId();

Expand Down Expand Up @@ -85,7 +83,9 @@ export const Filters = ({ onFiltersChange }: FiltersProps) => {
<EuiSpacer size="l" />
<FilterGroup
dataViewId={dataViewSpec?.id || null}
onFiltersChange={onFiltersChange}
onFiltersChange={(filters: Filter[]) => {
setQuery({ filters });
}}
ruleTypeIds={ASSET_INVENTORY_RULE_TYPE_IDS}
Storage={Storage}
defaultControls={DEFAULT_ASSET_INVENTORY_FILTERS}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@ import React from 'react';
import { EuiTitle } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';

import { I18N_PREFIX } from '../constants';

export const InventoryTitle = () => {
return (
<EuiTitle size="l" data-test-subj="inventory-title">
<h1>
<FormattedMessage
id="xpack.securitySolution.assetInventory.inventoryTitle"
defaultMessage="Inventory"
/>
<FormattedMessage id={`${I18N_PREFIX}.inventoryTitle`} defaultMessage="Inventory" />
</h1>
</EuiTitle>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
import React from 'react';
import { waitForEuiToolTipVisible } from '@elastic/eui/lib/test/rtl';
import { screen, render, cleanup, fireEvent } from '@testing-library/react';

import { RiskSeverity } from '../../../common/search_strategy';

import { RiskBadge } from './risk_badge';

describe('AssetInventory', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,34 @@
import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiBadge, EuiToolTip } from '@elastic/eui';

import { RiskSeverity } from '../../../common/search_strategy';
import { RISK_SEVERITY_COLOUR } from '../../entity_analytics/common/utils';
import { getRiskLevel } from '../../../common/entity_analytics/risk_engine/risk_levels';

import { I18N_PREFIX } from '../constants';

export interface RiskBadgeProps {
risk: number;
'data-test-subj'?: string;
}

const tooltips = {
[RiskSeverity.Unknown]: i18n.translate(
'xpack.securitySolution.assetInventory.allAssets.risks.unknown',
{ defaultMessage: RiskSeverity.Unknown }
),
[RiskSeverity.Low]: i18n.translate('xpack.securitySolution.assetInventory.allAssets.risks.low', {
[RiskSeverity.Unknown]: i18n.translate(`${I18N_PREFIX}.risks.unknown`, {
defaultMessage: RiskSeverity.Unknown,
}),
[RiskSeverity.Low]: i18n.translate(`${I18N_PREFIX}.risks.low`, {
defaultMessage: RiskSeverity.Low,
}),
[RiskSeverity.Moderate]: i18n.translate(
'xpack.securitySolution.assetInventory.allAssets.risks.moderate',
{ defaultMessage: RiskSeverity.Moderate }
),
[RiskSeverity.High]: i18n.translate(
'xpack.securitySolution.assetInventory.allAssets.risks.high',
{ defaultMessage: RiskSeverity.High }
),
[RiskSeverity.Critical]: i18n.translate(
'xpack.securitySolution.assetInventory.allAssets.risks.critical',
{ defaultMessage: RiskSeverity.Critical }
),
[RiskSeverity.Moderate]: i18n.translate(`${I18N_PREFIX}.risks.moderate`, {
defaultMessage: RiskSeverity.Moderate,
}),
[RiskSeverity.High]: i18n.translate(`${I18N_PREFIX}.risks.high`, {
defaultMessage: RiskSeverity.High,
}),
[RiskSeverity.Critical]: i18n.translate(`${I18N_PREFIX}.risks.critical`, {
defaultMessage: RiskSeverity.Critical,
}),
};

export const RiskBadge = ({ risk, ...props }: RiskBadgeProps) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,31 @@ import { css } from '@emotion/react';
import { type EuiThemeComputed, useEuiTheme } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import type { Filter } from '@kbn/es-query';

import { useKibana } from '../../common/lib/kibana';
import { FiltersGlobal } from '../../common/components/filters_global/filters_global';

import { useDataViewContext } from '../hooks/data_view_context';
import type { AssetsBaseURLQuery } from '../hooks/use_asset_inventory_data_table';

type SearchBarQueryProps = Pick<AssetsBaseURLQuery, 'query' | 'filters'>;
import { I18N_PREFIX } from '../constants';

type Query = Pick<AssetsBaseURLQuery, 'query' | 'filters'>;

interface AssetInventorySearchBarProps {
setQuery(v: Partial<SearchBarQueryProps>): void;
setQuery(v: Partial<Query>): void;
loading: boolean;
placeholder?: string;
query: SearchBarQueryProps;
query: Query;
}

export const AssetInventorySearchBar = ({
loading,
query,
setQuery,
placeholder = i18n.translate(
'xpack.securitySolution.assetInventory.searchBar.searchPlaceholder',
{
defaultMessage: 'Filter your data using KQL syntax',
}
),
placeholder = i18n.translate(`${I18N_PREFIX}.searchBar.searchPlaceholder`, {
defaultMessage: 'Filter your data using KQL syntax',
}),
}: AssetInventorySearchBarProps) => {
const { euiTheme } = useEuiTheme();
const {
Expand All @@ -54,7 +55,7 @@ export const AssetInventorySearchBar = ({
isLoading={loading}
indexPatterns={[dataView]}
onQuerySubmit={setQuery}
onFiltersUpdated={(value: Filter[]) => setQuery({ filters: value })}
onFiltersUpdated={(filters: Filter[]) => setQuery({ filters })}
placeholder={placeholder}
query={{
query: query?.query?.query || '',
Expand All @@ -69,6 +70,6 @@ export const AssetInventorySearchBar = ({

const getContainerStyle = (theme: EuiThemeComputed) => css`
border-bottom: ${theme.border.thin};
background-color: ${theme.colors.body};
background-color: ${theme.colors.backgroundBaseSubdued};
padding: ${theme.size.base};
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 { css } from '@emotion/react';
import { EuiBetaBadge, useEuiTheme } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { I18N_PREFIX } from '../constants';

export const TechnicalPreviewBadge = () => {
const { euiTheme } = useEuiTheme();

return (
<EuiBetaBadge
css={css`
margin-left: ${euiTheme.size.s};
`}
label={i18n.translate(`${I18N_PREFIX}.technicalPreviewLabel`, {
defaultMessage: 'Technical Preview',
})}
size="s"
color="subdued"
tooltipContent={i18n.translate(`${I18N_PREFIX}.technicalPreviewTooltip`, {
defaultMessage:
'This functionality is experimental and not supported. It may change or be removed at any time.',
})}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,18 @@ import { EuiProgress, EuiFlexGroup, EuiLoadingChart } from '@elastic/eui';
import { Chart, Settings, Axis, BarSeries, Position, ScaleType } from '@elastic/charts';
import { useElasticChartsTheme } from '@kbn/charts-theme';
import { i18n } from '@kbn/i18n';

import type { AggregationResult } from '../hooks/use_fetch_chart_data';

const chartTitle = i18n.translate(
'xpack.securitySolution.assetInventory.topAssetsBarChart.chartTitle',
{
defaultMessage: 'Top 10 Asset Types',
}
);
import { I18N_PREFIX } from '../constants';

const chartTitle = i18n.translate(`${I18N_PREFIX}.topAssetsBarChart.chartTitle`, {
defaultMessage: 'Top 10 Asset Types',
});

const yAxisTitle = i18n.translate(
'xpack.securitySolution.assetInventory.topAssetsBarChart.yAxisTitle',
{
defaultMessage: 'Count of Assets',
}
);
const yAxisTitle = i18n.translate(`${I18N_PREFIX}.topAssetsBarChart.yAxisTitle`, {
defaultMessage: 'Count of Assets',
});

const chartStyles = { height: '260px' };

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,25 @@
* 2.0.
*/

export const MAX_ASSETS_TO_LOAD = 500; // equivalent to MAX_FINDINGS_TO_LOAD in @kbn/cloud-security-posture-common
export const MAX_ASSETS_TO_LOAD = 500;
export const DEFAULT_VISIBLE_ROWS_PER_PAGE = 25;
export const ASSET_INVENTORY_INDEX_PATTERN = 'logs-cloud_asset_inventory.asset_inventory-*';

export const GRID_DATA_QUERY_KEY = 'asset_inventory_grid_data';
export const CHART_DATA_QUERY_KEY = 'asset_inventory_chart_data';

export const ASSET_INVENTORY_TABLE_ID = 'asset-inventory-table';

const LOCAL_STORAGE_PREFIX = 'assetInventory';
export const LOCAL_STORAGE_COLUMNS_KEY = `${LOCAL_STORAGE_PREFIX}:columns`;
export const LOCAL_STORAGE_COLUMNS_SETTINGS_KEY = `${LOCAL_STORAGE_COLUMNS_KEY}:settings`;
export const LOCAL_STORAGE_DATA_TABLE_PAGE_SIZE_KEY = `${LOCAL_STORAGE_PREFIX}:dataTable:pageSize`;
export const LOCAL_STORAGE_DATA_TABLE_COLUMNS_KEY = `${LOCAL_STORAGE_PREFIX}:dataTable:columns`;

export const ASSET_INVENTORY_TEST_SUBJ_GRID = 'asset-inventory-test-subj-grid-wrapper';
export const ASSET_INVENTORY_TEST_SUBJ_PAGE_TITLE = 'all-assets-title'; // 'asset-inventory-test-subj-page-title'
export const TEST_SUBJ_EMPTY_STATE = 'asset-inventory-empty-state';

export const I18N_PREFIX = 'xpack.securitySolution.assetInventory';

export const DOCS_URL = 'https://ela.st/asset-inventory';
Loading

0 comments on commit eeea887

Please sign in to comment.