Skip to content

Commit 318147a

Browse files
committed
[SIEM][Detections Engine] - Exceptions viewer cleanup (#68651)
### Summary This PR is a follow up to #68027 where some feedback didn't make it in. It cleans up the and_or_badge component, updates some css, and cleans up stories.
1 parent 86ea134 commit 318147a

18 files changed

Lines changed: 371 additions & 255 deletions

File tree

x-pack/plugins/security_solution/public/common/components/and_or_badge/__examples__/index.stories.tsx

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66
import { storiesOf } from '@storybook/react';
7-
import React from 'react';
7+
import React, { ReactNode } from 'react';
88
import { ThemeProvider } from 'styled-components';
99
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
1010
import { EuiFlexItem, EuiFlexGroup } from '@elastic/eui';
@@ -14,26 +14,21 @@ import { AndOrBadge } from '..';
1414
const sampleText =
1515
'Doggo ipsum i am bekom fat snoot wow such tempt waggy wags floofs, ruff heckin good boys and girls mlem. Ruff heckin good boys and girls mlem stop it fren borkf borking doggo very hand that feed shibe, you are doing me the shock big ol heck smol borking doggo with a long snoot for pats heckin good boys. You are doing me the shock smol borking doggo with a long snoot for pats wow very biscit, length boy. Doggo ipsum i am bekom fat snoot wow such tempt waggy wags floofs, ruff heckin good boys and girls mlem. Ruff heckin good boys and girls mlem stop it fren borkf borking doggo very hand that feed shibe, you are doing me the shock big ol heck smol borking doggo with a long snoot for pats heckin good boys.';
1616

17+
const withTheme = (storyFn: () => ReactNode) => (
18+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: true })}>{storyFn()}</ThemeProvider>
19+
);
20+
1721
storiesOf('components/AndOrBadge', module)
18-
.add('and', () => (
19-
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: true })}>
20-
<AndOrBadge type="and" />
21-
</ThemeProvider>
22-
))
23-
.add('or', () => (
24-
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: true })}>
25-
<AndOrBadge type="or" />
26-
</ThemeProvider>
27-
))
22+
.addDecorator(withTheme)
23+
.add('and', () => <AndOrBadge type="and" />)
24+
.add('or', () => <AndOrBadge type="or" />)
2825
.add('antennas', () => (
29-
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: true })}>
30-
<EuiFlexGroup>
31-
<EuiFlexItem grow={false}>
32-
<AndOrBadge type="and" includeAntennas />
33-
</EuiFlexItem>
34-
<EuiFlexItem>
35-
<p>{sampleText}</p>
36-
</EuiFlexItem>
37-
</EuiFlexGroup>
38-
</ThemeProvider>
26+
<EuiFlexGroup>
27+
<EuiFlexItem grow={false}>
28+
<AndOrBadge type="and" includeAntennas />
29+
</EuiFlexItem>
30+
<EuiFlexItem>
31+
<p>{sampleText}</p>
32+
</EuiFlexItem>
33+
</EuiFlexGroup>
3934
));

x-pack/plugins/security_solution/public/common/components/and_or_badge/index.test.tsx

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,20 @@ describe('AndOrBadge', () => {
2020
);
2121

2222
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND');
23-
expect(wrapper.find('EuiFlexItem[data-test-subj="andOrBadgeBarTop"]')).toHaveLength(1);
24-
expect(wrapper.find('EuiFlexItem[data-test-subj="andOrBadgeBarBottom"]')).toHaveLength(1);
23+
expect(wrapper.find('[data-test-subj="andOrBadgeBarTop"]').exists()).toBeTruthy();
24+
expect(wrapper.find('[data-test-subj="andOrBadgeBarBottom"]').exists()).toBeTruthy();
25+
});
26+
27+
test('it does not render top and bottom antenna bars when "includeAntennas" is false', () => {
28+
const wrapper = mount(
29+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
30+
<AndOrBadge type="or" />
31+
</ThemeProvider>
32+
);
33+
34+
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR');
35+
expect(wrapper.find('[data-test-subj="andOrBadgeBarTop"]').exists()).toBeFalsy();
36+
expect(wrapper.find('[data-test-subj="andOrBadgeBarBottom"]').exists()).toBeFalsy();
2537
});
2638

2739
test('it renders "and" when "type" is "and"', () => {
@@ -32,7 +44,6 @@ describe('AndOrBadge', () => {
3244
);
3345

3446
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND');
35-
expect(wrapper.find('EuiFlexItem[data-test-subj="and-or-badge-bar"]')).toHaveLength(0);
3647
});
3748

3849
test('it renders "or" when "type" is "or"', () => {
@@ -43,6 +54,5 @@ describe('AndOrBadge', () => {
4354
);
4455

4556
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR');
46-
expect(wrapper.find('EuiFlexItem[data-test-subj="and-or-badge-bar"]')).toHaveLength(0);
4757
});
4858
});

x-pack/plugins/security_solution/public/common/components/and_or_badge/index.tsx

Lines changed: 3 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -3,105 +3,18 @@
33
* or more contributor license agreements. Licensed under the Elastic License;
44
* you may not use this file except in compliance with the Elastic License.
55
*/
6-
7-
import { EuiFlexGroup, EuiBadge, EuiFlexItem } from '@elastic/eui';
86
import React from 'react';
9-
import styled, { css } from 'styled-components';
10-
11-
import * as i18n from './translations';
12-
13-
const AndOrBadgeAntenna = styled(EuiFlexItem)`
14-
${({ theme }) => css`
15-
background: ${theme.eui.euiColorLightShade};
16-
position: relative;
17-
width: 2px;
18-
&:after {
19-
background: ${theme.eui.euiColorLightShade};
20-
content: '';
21-
height: 8px;
22-
right: -4px;
23-
position: absolute;
24-
width: 9px;
25-
clip-path: circle();
26-
}
27-
&.topAndOrBadgeAntenna {
28-
&:after {
29-
top: -1px;
30-
}
31-
}
32-
&.bottomAndOrBadgeAntenna {
33-
&:after {
34-
bottom: -1px;
35-
}
36-
}
37-
&.euiFlexItem {
38-
margin: 0 12px 0 0;
39-
}
40-
`}
41-
`;
42-
43-
const EuiFlexItemWrapper = styled(EuiFlexItem)`
44-
&.euiFlexItem {
45-
margin: 0 12px 0 0;
46-
}
47-
`;
487

49-
const RoundedBadge = (styled(EuiBadge)`
50-
align-items: center;
51-
border-radius: 100%;
52-
display: inline-flex;
53-
font-size: 9px;
54-
height: 34px;
55-
justify-content: center;
56-
margin: 0 5px 0 5px;
57-
padding: 7px 6px 4px 6px;
58-
user-select: none;
59-
width: 34px;
60-
.euiBadge__content {
61-
position: relative;
62-
top: -1px;
63-
}
64-
.euiBadge__text {
65-
text-overflow: clip;
66-
}
67-
` as unknown) as typeof EuiBadge;
68-
69-
RoundedBadge.displayName = 'RoundedBadge';
8+
import { RoundedBadge } from './rounded_badge';
9+
import { RoundedBadgeAntenna } from './rounded_badge_antenna';
7010

7111
export type AndOr = 'and' | 'or';
7212

7313
/** Displays AND / OR in a round badge */
7414
// Ref: https://github.com/elastic/eui/issues/1655
7515
export const AndOrBadge = React.memo<{ type: AndOr; includeAntennas?: boolean }>(
7616
({ type, includeAntennas = false }) => {
77-
const getBadge = () => (
78-
<RoundedBadge data-test-subj="and-or-badge" color="hollow">
79-
{type === 'and' ? i18n.AND : i18n.OR}
80-
</RoundedBadge>
81-
);
82-
83-
const getBadgeWithAntennas = () => (
84-
<EuiFlexGroup
85-
className="andBadgeContainer"
86-
gutterSize="none"
87-
direction="column"
88-
alignItems="center"
89-
>
90-
<AndOrBadgeAntenna
91-
className="topAndOrBadgeAntenna"
92-
data-test-subj="andOrBadgeBarTop"
93-
grow={1}
94-
/>
95-
<EuiFlexItemWrapper grow={false}>{getBadge()}</EuiFlexItemWrapper>
96-
<AndOrBadgeAntenna
97-
className="bottomAndOrBadgeAntenna"
98-
data-test-subj="andOrBadgeBarBottom"
99-
grow={1}
100-
/>
101-
</EuiFlexGroup>
102-
);
103-
104-
return includeAntennas ? getBadgeWithAntennas() : getBadge();
17+
return includeAntennas ? <RoundedBadgeAntenna type={type} /> : <RoundedBadge type={type} />;
10518
}
10619
);
10720

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React from 'react';
8+
import { ThemeProvider } from 'styled-components';
9+
import { mount } from 'enzyme';
10+
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
11+
12+
import { RoundedBadge } from './rounded_badge';
13+
14+
describe('RoundedBadge', () => {
15+
test('it renders "and" when "type" is "and"', () => {
16+
const wrapper = mount(
17+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
18+
<RoundedBadge type="and" />
19+
</ThemeProvider>
20+
);
21+
22+
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND');
23+
});
24+
25+
test('it renders "or" when "type" is "or"', () => {
26+
const wrapper = mount(
27+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
28+
<RoundedBadge type="or" />
29+
</ThemeProvider>
30+
);
31+
32+
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR');
33+
});
34+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { EuiBadge } from '@elastic/eui';
8+
import React from 'react';
9+
import styled from 'styled-components';
10+
11+
import * as i18n from './translations';
12+
import { AndOr } from '.';
13+
14+
const RoundBadge = (styled(EuiBadge)`
15+
align-items: center;
16+
border-radius: 100%;
17+
display: inline-flex;
18+
font-size: 9px;
19+
height: 34px;
20+
justify-content: center;
21+
margin: 0 5px 0 5px;
22+
padding: 7px 6px 4px 6px;
23+
user-select: none;
24+
width: 34px;
25+
.euiBadge__content {
26+
position: relative;
27+
top: -1px;
28+
}
29+
.euiBadge__text {
30+
text-overflow: clip;
31+
}
32+
` as unknown) as typeof EuiBadge;
33+
34+
RoundBadge.displayName = 'RoundBadge';
35+
36+
export const RoundedBadge: React.FC<{ type: AndOr }> = ({ type }) => (
37+
<RoundBadge data-test-subj="and-or-badge" color="hollow">
38+
{type === 'and' ? i18n.AND : i18n.OR}
39+
</RoundBadge>
40+
);
41+
42+
RoundedBadge.displayName = 'RoundedBadge';
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import React from 'react';
8+
import { ThemeProvider } from 'styled-components';
9+
import { mount } from 'enzyme';
10+
import euiLightVars from '@elastic/eui/dist/eui_theme_light.json';
11+
12+
import { RoundedBadgeAntenna } from './rounded_badge_antenna';
13+
14+
describe('RoundedBadgeAntenna', () => {
15+
test('it renders top and bottom antenna bars', () => {
16+
const wrapper = mount(
17+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
18+
<RoundedBadgeAntenna type="and" />
19+
</ThemeProvider>
20+
);
21+
22+
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND');
23+
expect(wrapper.find('[data-test-subj="andOrBadgeBarTop"]').exists()).toBeTruthy();
24+
expect(wrapper.find('[data-test-subj="andOrBadgeBarBottom"]').exists()).toBeTruthy();
25+
});
26+
27+
test('it renders "and" when "type" is "and"', () => {
28+
const wrapper = mount(
29+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
30+
<RoundedBadgeAntenna type="and" />
31+
</ThemeProvider>
32+
);
33+
34+
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('AND');
35+
});
36+
37+
test('it renders "or" when "type" is "or"', () => {
38+
const wrapper = mount(
39+
<ThemeProvider theme={() => ({ eui: euiLightVars, darkMode: false })}>
40+
<RoundedBadgeAntenna type="or" />
41+
</ThemeProvider>
42+
);
43+
44+
expect(wrapper.find('[data-test-subj="and-or-badge"]').at(0).text()).toEqual('OR');
45+
});
46+
});
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
7+
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
8+
import React from 'react';
9+
import styled, { css } from 'styled-components';
10+
11+
import { RoundedBadge } from './rounded_badge';
12+
import { AndOr } from '.';
13+
14+
const antennaStyles = css`
15+
background: ${({ theme }) => theme.eui.euiColorLightShade};
16+
position: relative;
17+
width: 2px;
18+
margin: 0 12px 0 0;
19+
&:after {
20+
background: ${({ theme }) => theme.eui.euiColorLightShade};
21+
content: '';
22+
height: 8px;
23+
right: -4px;
24+
position: absolute;
25+
width: 10px;
26+
clip-path: circle();
27+
}
28+
`;
29+
30+
const TopAntenna = styled(EuiFlexItem)`
31+
${antennaStyles}
32+
&:after {
33+
top: 0;
34+
}
35+
`;
36+
const BottomAntenna = styled(EuiFlexItem)`
37+
${antennaStyles}
38+
&:after {
39+
bottom: 0;
40+
}
41+
`;
42+
43+
const EuiFlexItemWrapper = styled(EuiFlexItem)`
44+
margin: 0 12px 0 0;
45+
`;
46+
47+
export const RoundedBadgeAntenna: React.FC<{ type: AndOr }> = ({ type }) => (
48+
<EuiFlexGroup
49+
className="andBadgeContainer"
50+
gutterSize="none"
51+
direction="column"
52+
alignItems="center"
53+
>
54+
<TopAntenna data-test-subj="andOrBadgeBarTop" grow={1} />
55+
<EuiFlexItemWrapper grow={false}>
56+
<RoundedBadge type={type} />
57+
</EuiFlexItemWrapper>
58+
<BottomAntenna data-test-subj="andOrBadgeBarBottom" grow={1} />
59+
</EuiFlexGroup>
60+
);
61+
62+
RoundedBadgeAntenna.displayName = 'RoundedBadgeAntenna';

0 commit comments

Comments
 (0)