mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[8.4] [Kubernetes Security] Add beta tag to dashboard kubernetes title and grouped nav (#137211) (#137490)
* Add beta tag to dashboard kubernetes title and grouped nav
* Add props used to BetaBadge
* Fix PR comments
* Implement workaround for eui beta badge type
* Move flex link to styles file and comment
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit bb93f02740
)
Co-authored-by: Jack <zizhou.wang@elastic.co>
This commit is contained in:
parent
6adce2d03f
commit
4471e81098
11 changed files with 114 additions and 9 deletions
|
@ -31,6 +31,7 @@ const formatNavLinkItems = (appLinks: AppLinkItems): NavLinkItem[] =>
|
|||
...(link.landingIcon != null ? { icon: link.landingIcon } : {}),
|
||||
...(link.landingImage != null ? { image: link.landingImage } : {}),
|
||||
...(link.skipUrlState != null ? { skipUrlState: link.skipUrlState } : {}),
|
||||
...(link.isBeta != null ? { isBeta: link.isBeta } : {}),
|
||||
...(link.links && link.links.length
|
||||
? {
|
||||
links: formatNavLinkItems(link.links),
|
||||
|
|
|
@ -24,6 +24,7 @@ const manageNavLink: NavLinkItem = {
|
|||
id: SecurityPageName.endpoints,
|
||||
title: 'title 2',
|
||||
description: 'description 2',
|
||||
isBeta: true,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
@ -129,6 +130,7 @@ describe('SecuritySideNav', () => {
|
|||
label: 'title 2',
|
||||
description: 'description 2',
|
||||
href: '/endpoints',
|
||||
isBeta: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -148,6 +150,7 @@ describe('SecuritySideNav', () => {
|
|||
title: 'title 2',
|
||||
description: 'description 2',
|
||||
disabled: true,
|
||||
isBeta: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
|
@ -77,6 +77,7 @@ const useFormatSideNavItem = (): FormatSideNavItems => {
|
|||
id: current.id,
|
||||
label: current.title,
|
||||
description: current.description,
|
||||
isBeta: current.isBeta,
|
||||
...getSecuritySolutionLinkProps({ deepLinkId: current.id }),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { EuiPanel } from '@elastic/eui';
|
||||
import { EuiBetaBadge, EuiPanel } from '@elastic/eui';
|
||||
import styled from 'styled-components';
|
||||
|
||||
export const EuiPanelStyled = styled(EuiPanel)<{ $bottomOffset?: string }>`
|
||||
|
@ -30,3 +30,14 @@ export const EuiPanelStyled = styled(EuiPanel)<{ $bottomOffset?: string }>`
|
|||
inset 0 -${theme.eui.euiSizeXS} ${theme.eui.euiSizeXS} -${theme.eui.euiSizeXS} rgb(0 0 0 / 6%);
|
||||
`}
|
||||
`;
|
||||
|
||||
// Remove explicit typing after eui update https://github.com/elastic/eui/pull/6086
|
||||
export const EuiBetaBadgeStyled: typeof EuiBetaBadge = styled(EuiBetaBadge)`
|
||||
margin-left: ${({ theme }) => theme.eui.euiSizeS};
|
||||
color: ${(props) => props.theme.eui.euiTextColor};
|
||||
`;
|
||||
|
||||
export const FlexLink = styled.a`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
|
|
@ -14,6 +14,7 @@ import type { SolutionNavPanelProps } from './solution_grouped_nav_panel';
|
|||
import { SolutionNavPanel } from './solution_grouped_nav_panel';
|
||||
import type { DefaultSideNavItem } from './types';
|
||||
import { bottomNavOffset } from '../../../lib/helpers';
|
||||
import { BETA } from '@kbn/kubernetes-security-plugin/common/translations';
|
||||
|
||||
const mockUseIsWithinBreakpoints = jest.fn(() => true);
|
||||
jest.mock('@elastic/eui', () => {
|
||||
|
@ -37,8 +38,17 @@ const mockItems: DefaultSideNavItem[] = [
|
|||
href: '/network',
|
||||
description: 'Network description',
|
||||
},
|
||||
{
|
||||
id: SecurityPageName.kubernetes,
|
||||
label: 'Kubernetes',
|
||||
href: '/kubernetes',
|
||||
description: 'Kubernetes description',
|
||||
isBeta: true,
|
||||
},
|
||||
];
|
||||
|
||||
const betaMockItemsCount = mockItems.filter((item) => item.isBeta).length;
|
||||
|
||||
const mockCategories: LinkCategories = [
|
||||
{
|
||||
label: 'HOSTS CATEGORY',
|
||||
|
@ -86,6 +96,7 @@ describe('SolutionGroupedNav', () => {
|
|||
expect(result.getByText(item.description)).toBeInTheDocument();
|
||||
}
|
||||
});
|
||||
expect(result.queryAllByText(BETA).length).toBe(betaMockItemsCount);
|
||||
});
|
||||
|
||||
it('should only render categories with items', () => {
|
||||
|
|
|
@ -23,9 +23,10 @@ import {
|
|||
useIsWithinBreakpoints,
|
||||
} from '@elastic/eui';
|
||||
import classNames from 'classnames';
|
||||
import { EuiPanelStyled } from './solution_grouped_nav_panel.styles';
|
||||
import { EuiBetaBadgeStyled, EuiPanelStyled, FlexLink } from './solution_grouped_nav_panel.styles';
|
||||
import type { DefaultSideNavItem } from './types';
|
||||
import type { LinkCategories } from '../../../links/types';
|
||||
import { BETA } from '../../../translations';
|
||||
|
||||
export interface SolutionNavPanelProps {
|
||||
onClose: () => void;
|
||||
|
@ -155,10 +156,10 @@ const SolutionNavPanelCategories: React.FC<SolutionNavPanelCategoriesProps> = ({
|
|||
|
||||
const SolutionNavPanelItems: React.FC<SolutionNavPanelItemsProps> = ({ items, onClose }) => (
|
||||
<>
|
||||
{items.map(({ id, href, onClick, label, description }) => (
|
||||
{items.map(({ id, href, onClick, label, description, isBeta }) => (
|
||||
<Fragment key={id}>
|
||||
<EuiDescriptionListTitle>
|
||||
<a
|
||||
<FlexLink
|
||||
data-test-subj={`groupedNavPanelLink-${id}`}
|
||||
href={href}
|
||||
onClick={(ev) => {
|
||||
|
@ -169,7 +170,8 @@ const SolutionNavPanelItems: React.FC<SolutionNavPanelItemsProps> = ({ items, on
|
|||
}}
|
||||
>
|
||||
{label}
|
||||
</a>
|
||||
{isBeta && <EuiBetaBadgeStyled label={BETA} size="s" />}
|
||||
</FlexLink>
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription>{description}</EuiDescriptionListDescription>
|
||||
</Fragment>
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface DefaultSideNavItem {
|
|||
description?: string;
|
||||
items?: DefaultSideNavItem[];
|
||||
categories?: LinkCategories;
|
||||
isBeta?: boolean;
|
||||
}
|
||||
|
||||
export interface CustomSideNavItem {
|
||||
|
|
|
@ -110,4 +110,5 @@ export interface NavLinkItem {
|
|||
image?: string;
|
||||
title: string;
|
||||
skipUrlState?: boolean;
|
||||
isBeta?: boolean;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ export const links: LinkItem = {
|
|||
}),
|
||||
path: KUBERNETES_PATH,
|
||||
globalNavEnabled: false,
|
||||
isBeta: true,
|
||||
experimentalKey: 'kubernetesEnabled',
|
||||
globalSearchKeywords: ['Kubernetes'],
|
||||
globalNavOrder: 9005,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { render } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { BETA } from '@kbn/kubernetes-security-plugin/common/translations';
|
||||
import { SecurityPageName } from '../../app/types';
|
||||
import type { NavLinkItem } from '../../common/components/navigation/types';
|
||||
import { TestProviders } from '../../common/mock';
|
||||
|
@ -19,6 +20,14 @@ const DEFAULT_NAV_ITEM: NavLinkItem = {
|
|||
image: 'TEST_IMAGE.png',
|
||||
};
|
||||
|
||||
const BETA_NAV_ITEM: NavLinkItem = {
|
||||
id: SecurityPageName.kubernetes,
|
||||
title: 'TEST LABEL',
|
||||
description: 'TEST DESCRIPTION',
|
||||
image: 'TEST_IMAGE.png',
|
||||
isBeta: true,
|
||||
};
|
||||
|
||||
jest.mock('../../common/lib/kibana/kibana_react', () => {
|
||||
return {
|
||||
useKibana: jest.fn().mockReturnValue({
|
||||
|
@ -56,6 +65,26 @@ describe('LandingLinksImages', () => {
|
|||
|
||||
expect(getByTestId('LandingLinksImage')).toHaveAttribute('src', image);
|
||||
});
|
||||
|
||||
it('renders beta tag when isBeta is true', () => {
|
||||
const { queryByText } = render(
|
||||
<TestProviders>
|
||||
<LandingLinksImages items={[BETA_NAV_ITEM]} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(queryByText(BETA)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render beta tag when isBeta is false', () => {
|
||||
const { queryByText } = render(
|
||||
<TestProviders>
|
||||
<LandingLinksImages items={[DEFAULT_NAV_ITEM]} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(queryByText(BETA)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('LandingImageCards', () => {
|
||||
|
@ -83,4 +112,24 @@ describe('LandingImageCards', () => {
|
|||
|
||||
expect(getByTestId('LandingImageCard-image')).toHaveAttribute('src', image);
|
||||
});
|
||||
|
||||
it('renders beta tag when isBeta is true', () => {
|
||||
const { queryByText } = render(
|
||||
<TestProviders>
|
||||
<LandingImageCards items={[BETA_NAV_ITEM]} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(queryByText(BETA)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not render beta tag when isBeta is false', () => {
|
||||
const { queryByText } = render(
|
||||
<TestProviders>
|
||||
<LandingImageCards items={[DEFAULT_NAV_ITEM]} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
expect(queryByText(BETA)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
import {
|
||||
EuiBetaBadge,
|
||||
EuiCard,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
|
@ -17,6 +18,7 @@ import React from 'react';
|
|||
import styled from 'styled-components';
|
||||
import { withSecuritySolutionLink } from '../../common/components/links';
|
||||
import type { NavLinkItem } from '../../common/components/navigation/types';
|
||||
import { BETA } from '../../common/translations';
|
||||
|
||||
interface LandingImagesProps {
|
||||
items: NavLinkItem[];
|
||||
|
@ -43,11 +45,27 @@ const Content = styled(EuiFlexItem)`
|
|||
padding-left: ${({ theme }) => theme.eui.euiSizeS};
|
||||
`;
|
||||
|
||||
const FlexTitle = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const TitleText = styled.h2`
|
||||
display: inline;
|
||||
`;
|
||||
|
||||
// Remove explicit typing after eui update https://github.com/elastic/eui/pull/6086
|
||||
const BetaBadge: typeof EuiBetaBadge = styled(EuiBetaBadge)`
|
||||
vertical-align: text-top;
|
||||
margin-left: ${({ theme }) => theme.eui.euiSizeS};
|
||||
color: ${(props) => props.theme.eui.euiTextColor};
|
||||
`;
|
||||
|
||||
const SecuritySolutionLink = withSecuritySolutionLink(Link);
|
||||
|
||||
export const LandingLinksImages: React.FC<LandingImagesProps> = ({ items }) => (
|
||||
<EuiFlexGroup direction="column">
|
||||
{items.map(({ title, description, image, id }) => (
|
||||
{items.map(({ title, description, image, id, isBeta }) => (
|
||||
<EuiFlexItem key={id} data-test-subj="LandingItem">
|
||||
<SecuritySolutionLink deepLinkId={id} tabIndex={-1}>
|
||||
{/* Empty onClick is to force hover style on `EuiPanel` */}
|
||||
|
@ -66,7 +84,10 @@ export const LandingLinksImages: React.FC<LandingImagesProps> = ({ items }) => (
|
|||
</StyledFlexItem>
|
||||
<Content>
|
||||
<PrimaryEuiTitle size="s">
|
||||
<h2>{title}</h2>
|
||||
<FlexTitle>
|
||||
<TitleText>{title}</TitleText>
|
||||
{isBeta && <BetaBadge label={BETA} size="s" />}
|
||||
</FlexTitle>
|
||||
</PrimaryEuiTitle>
|
||||
<LandingLinksDescripton size="s" color="text">
|
||||
{description}
|
||||
|
@ -101,7 +122,7 @@ const SecuritySolutionCard = withSecuritySolutionLink(PrimaryTitleCard);
|
|||
|
||||
export const LandingImageCards: React.FC<LandingImagesProps> = React.memo(({ items }) => (
|
||||
<EuiFlexGroup direction="row" wrap>
|
||||
{items.map(({ id, image, title, description }) => (
|
||||
{items.map(({ id, image, title, description, isBeta }) => (
|
||||
<LandingImageCardItem key={id} data-test-subj="LandingImageCard-item" grow={false}>
|
||||
<SecuritySolutionCard
|
||||
deepLinkId={id}
|
||||
|
@ -121,7 +142,10 @@ export const LandingImageCards: React.FC<LandingImagesProps> = React.memo(({ ite
|
|||
}
|
||||
title={
|
||||
<PrimaryEuiTitle size="xs">
|
||||
<h2>{title}</h2>
|
||||
<div>
|
||||
<TitleText>{title}</TitleText>
|
||||
{isBeta && <BetaBadge label={BETA} size="s" />}
|
||||
</div>
|
||||
</PrimaryEuiTitle>
|
||||
}
|
||||
description={<LandingCardDescription>{description}</LandingCardDescription>}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue