mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Cloud Security] kick off the work on the DistributionBar component (#188509)
## Summary Contributes to: - https://github.com/elastic/security-team/issues/9954 The PR contains the base for the `DistributionBar` component to be used in the new Entity Flyout Insights. Not included: - badges per distribution with the number of documents and pretty names - on hover interaction ## Screenshots <img width="980" alt="Screenshot 2024-07-17 at 15 13 48" src="https://github.com/user-attachments/assets/f2ca53ee-c054-4923-aa3f-7dd4017754cb"> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
253266256a
commit
6e73444ca3
12 changed files with 249 additions and 0 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -738,6 +738,7 @@ x-pack/plugins/security @elastic/kibana-security
|
|||
x-pack/packages/security/plugin_types_common @elastic/kibana-security
|
||||
x-pack/packages/security/plugin_types_public @elastic/kibana-security
|
||||
x-pack/packages/security/plugin_types_server @elastic/kibana-security
|
||||
x-pack/packages/security-solution/distribution_bar @elastic/kibana-cloud-security-posture
|
||||
x-pack/plugins/security_solution_ess @elastic/security-solution
|
||||
x-pack/packages/security-solution/features @elastic/security-threat-hunting-explore
|
||||
x-pack/test/cases_api_integration/common/plugins/security_solution @elastic/response-ops
|
||||
|
|
|
@ -749,6 +749,7 @@
|
|||
"@kbn/security-plugin-types-common": "link:x-pack/packages/security/plugin_types_common",
|
||||
"@kbn/security-plugin-types-public": "link:x-pack/packages/security/plugin_types_public",
|
||||
"@kbn/security-plugin-types-server": "link:x-pack/packages/security/plugin_types_server",
|
||||
"@kbn/security-solution-distribution-bar": "link:x-pack/packages/security-solution/distribution_bar",
|
||||
"@kbn/security-solution-ess": "link:x-pack/plugins/security_solution_ess",
|
||||
"@kbn/security-solution-features": "link:x-pack/packages/security-solution/features",
|
||||
"@kbn/security-solution-fixtures-plugin": "link:x-pack/test/cases_api_integration/common/plugins/security_solution",
|
||||
|
|
|
@ -1470,6 +1470,8 @@
|
|||
"@kbn/security-plugin-types-public/*": ["x-pack/packages/security/plugin_types_public/*"],
|
||||
"@kbn/security-plugin-types-server": ["x-pack/packages/security/plugin_types_server"],
|
||||
"@kbn/security-plugin-types-server/*": ["x-pack/packages/security/plugin_types_server/*"],
|
||||
"@kbn/security-solution-distribution-bar": ["x-pack/packages/security-solution/distribution_bar"],
|
||||
"@kbn/security-solution-distribution-bar/*": ["x-pack/packages/security-solution/distribution_bar/*"],
|
||||
"@kbn/security-solution-ess": ["x-pack/plugins/security_solution_ess"],
|
||||
"@kbn/security-solution-ess/*": ["x-pack/plugins/security_solution_ess/*"],
|
||||
"@kbn/security-solution-features": ["x-pack/packages/security-solution/features"],
|
||||
|
|
|
@ -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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export { DistributionBar } from './src/distribution_bar';
|
||||
export type { DistributionBarProps } from './src/distribution_bar';
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* 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',
|
||||
roots: ['<rootDir>/x-pack/packages/security-solution/distribution_bar'],
|
||||
rootDir: '../../../..',
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type": "shared-browser",
|
||||
"id": "@kbn/security-solution-distribution-bar",
|
||||
"owner": "@elastic/kibana-cloud-security-posture"
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "@kbn/security-solution-distribution-bar",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "Elastic License 2.0",
|
||||
"sideEffects": false
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* 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 { euiThemeVars } from '@kbn/ui-theme';
|
||||
import { EuiTitle, EuiSpacer } from '@elastic/eui';
|
||||
import { DistributionBar as DistributionBarComponent } from '..';
|
||||
|
||||
const mockStatsFindings = [
|
||||
{
|
||||
key: 'passed',
|
||||
count: 90,
|
||||
color: euiThemeVars.euiColorVis0,
|
||||
},
|
||||
{
|
||||
key: 'failed',
|
||||
count: 10,
|
||||
color: euiThemeVars.euiColorVis9,
|
||||
},
|
||||
];
|
||||
|
||||
const mockStatsAlerts = [
|
||||
{
|
||||
key: 'low',
|
||||
count: 30,
|
||||
color: euiThemeVars.euiColorVis0,
|
||||
},
|
||||
{
|
||||
key: 'medium',
|
||||
count: 30,
|
||||
color: euiThemeVars.euiColorVis5,
|
||||
},
|
||||
{
|
||||
key: 'high',
|
||||
count: 10,
|
||||
color: euiThemeVars.euiColorVis7,
|
||||
},
|
||||
{
|
||||
key: 'critical',
|
||||
count: 10,
|
||||
color: euiThemeVars.euiColorVis9,
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
title: 'DistributionBar',
|
||||
description: 'Distribution Bar',
|
||||
};
|
||||
|
||||
export const DistributionBar = () => {
|
||||
return [
|
||||
<EuiTitle size={'xs'}>
|
||||
<h4>{'Findings'}</h4>
|
||||
</EuiTitle>,
|
||||
<EuiSpacer size={'s'} />,
|
||||
<DistributionBarComponent stats={mockStatsFindings} />,
|
||||
<EuiSpacer size={'m'} />,
|
||||
<EuiTitle size={'xs'}>
|
||||
<h4>{'Alerts'}</h4>
|
||||
</EuiTitle>,
|
||||
<EuiSpacer size={'s'} />,
|
||||
<DistributionBarComponent stats={mockStatsAlerts} />,
|
||||
<EuiSpacer size={'m'} />,
|
||||
<EuiTitle size={'xs'}>
|
||||
<h4>{'Empty state'}</h4>
|
||||
</EuiTitle>,
|
||||
<EuiSpacer size={'s'} />,
|
||||
<DistributionBarComponent stats={[]} />,
|
||||
];
|
||||
};
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { DistributionBar } from '..';
|
||||
|
||||
describe('DistributionBar', () => {
|
||||
it('should render', () => {
|
||||
const stats = [
|
||||
{
|
||||
key: 'passed',
|
||||
count: 90,
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
key: 'failed',
|
||||
count: 10,
|
||||
color: 'red',
|
||||
},
|
||||
];
|
||||
|
||||
const { container } = render(<DistributionBar stats={stats} />);
|
||||
expect(container).toBeInTheDocument();
|
||||
expect(container.querySelectorAll('span').length).toEqual(stats.length);
|
||||
});
|
||||
|
||||
it('should render empty bar', () => {
|
||||
const { container } = render(
|
||||
<DistributionBar data-test-subj={'distribution-bar'} stats={[]} />
|
||||
);
|
||||
expect(container).toBeInTheDocument();
|
||||
expect(container.querySelectorAll('span').length).toEqual(1);
|
||||
expect(
|
||||
container.querySelector('[data-test-subj="distribution-bar__emptyBar"]')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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 { EuiFlexGroup, useEuiTheme } from '@elastic/eui';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
/** DistributionBar component props */
|
||||
export interface DistributionBarProps {
|
||||
/** distribution data points */
|
||||
stats: Array<{ key: string; count: number; color: string }>;
|
||||
/** data-test-subj used for querying the component in tests */
|
||||
['data-test-subj']?: string;
|
||||
}
|
||||
|
||||
export interface EmptyBarProps {
|
||||
['data-test-subj']?: string;
|
||||
}
|
||||
|
||||
const styles = {
|
||||
base: css`
|
||||
border-radius: 2px;
|
||||
height: 5px;
|
||||
`,
|
||||
};
|
||||
|
||||
const EmptyBar: React.FC<EmptyBarProps> = ({ 'data-test-subj': dataTestSubj }) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
|
||||
const emptyBarStyle = [
|
||||
styles.base,
|
||||
css`
|
||||
background-color: ${euiTheme.colors.lightShade};
|
||||
flex: 1;
|
||||
`,
|
||||
];
|
||||
|
||||
return <span css={emptyBarStyle} data-test-subj={`${dataTestSubj}__emptyBar`} />;
|
||||
};
|
||||
|
||||
/**
|
||||
* Security Solution DistributionBar component.
|
||||
* Shows visual representation of distribution of stats, such as alerts by criticality or misconfiguration findings by evaluation result.
|
||||
*/
|
||||
export const DistributionBar: React.FC<DistributionBarProps> = React.memo(function DistributionBar(
|
||||
props
|
||||
) {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const { stats, 'data-test-subj': dataTestSubj } = props;
|
||||
const parts = stats.map((stat) => {
|
||||
const partStyle = [
|
||||
styles.base,
|
||||
css`
|
||||
background-color: ${stat.color};
|
||||
flex: ${stat.count};
|
||||
`,
|
||||
];
|
||||
|
||||
return <span key={stat.key} css={partStyle} />;
|
||||
});
|
||||
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
css={css`
|
||||
gap: ${euiTheme.size.xxs};
|
||||
`}
|
||||
data-test-subj={dataTestSubj}
|
||||
>
|
||||
{parts.length ? parts : <EmptyBar data-test-subj={dataTestSubj} />}
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"extends": "../../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types",
|
||||
"types": [
|
||||
"jest",
|
||||
"node",
|
||||
"react",
|
||||
"@emotion/react/types/css-prop",
|
||||
"@testing-library/jest-dom",
|
||||
"@testing-library/react",
|
||||
]
|
||||
},
|
||||
"include": ["**/*.ts", "**/*.tsx"],
|
||||
"kbn_references": [
|
||||
"@kbn/ui-theme",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
|
@ -6190,6 +6190,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/security-solution-distribution-bar@link:x-pack/packages/security-solution/distribution_bar":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/security-solution-ess@link:x-pack/plugins/security_solution_ess":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue