Skip to content

Commit

Permalink
Merge branch 'main' into de_on_week/esql-ai-assistant
Browse files Browse the repository at this point in the history
  • Loading branch information
vitaliidm authored Jul 1, 2024
2 parents 1d6f7f7 + ccfc5d3 commit 800a1e5
Show file tree
Hide file tree
Showing 45 changed files with 442 additions and 216 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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 type { CoreStart } from '@kbn/core/public';
import type { NavigationLink } from '../types';
import type { LandingLinksImagesProps } from './landing_links_images_cards';
import { LandingLinksImageCard as LandingLinksImageCardComponent } from './landing_links_image_card';
import { NavigationProvider } from '../context';

const items: NavigationLink[] = [
{
id: 'link1',
title: 'link #1',
description: 'This is the description of the link #1',
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
{
id: 'link2',
title: 'link #2',
description: 'This is the description of the link #2',
isBeta: true,
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
{
id: 'link3',
title: 'link #3',
description: 'This is the description of the link #3',
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
{
id: 'link4',
title: 'link #4',
description: 'This is the description of the link #4',
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
{
id: 'link5',
title: 'link #5',
description: 'This is the description of the link #5',
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
{
id: 'link6',
title: 'link #6',
description: 'This is the description of the link #6',
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
{
id: 'link7',
title: 'link #7',
description: 'This is the description of the link #7',
landingImage: 'https://dummyimage.com/360x200/efefef/000',
},
];

export default {
title: 'Landing Links/Landing Links Image Card',
description: 'Renders the links with images in a horizontal layout',
decorators: [
(storyFn: Function) => (
<div
css={{
height: '100%',
width: '100%',
background: '#fff',
}}
>
{storyFn()}
</div>
),
],
};

const mockCore = {
application: {
navigateToApp: () => {},
getUrlForApp: () => '#',
},
} as unknown as CoreStart;

export const LandingLinksImageCards = (params: LandingLinksImagesProps) => (
<div style={{ padding: '25px' }}>
<NavigationProvider core={mockCore}>
<div
css={{
display: 'grid',
gridTemplateColumns: 'auto auto auto',
height: '100%',
width: '100%',
gap: 8,
background: '#fff',
}}
>
{items.map((item) => {
const { id } = item;
return <LandingLinksImageCardComponent {...params} key={id} item={item} />;
})}
</div>
</NavigationProvider>
</div>
);

LandingLinksImageCards.argTypes = {
items: {
control: 'object',
defaultValue: items,
},
};

LandingLinksImageCards.parameters = {
layout: 'fullscreen',
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* 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 { SecurityPageName } from '../constants';
import { mockNavigateTo, mockGetAppUrl } from '../../mocks/navigation';
import { LandingLinksImageCard } from './landing_links_image_card';
import { BETA } from './beta_badge';

jest.mock('../navigation');

mockGetAppUrl.mockImplementation(({ deepLinkId }: { deepLinkId: string }) => `/${deepLinkId}`);
const mockOnLinkClick = jest.fn();

const DEFAULT_NAV_ITEM = {
id: SecurityPageName.overview,
title: 'TEST LABEL',
description: 'TEST DESCRIPTION',
landingImage: 'TEST_IMAGE.png',
};

describe('LandingLinksImageCard', () => {
it('should render', () => {
const title = 'test label';

const { queryByText } = render(
<LandingLinksImageCard
item={{ ...DEFAULT_NAV_ITEM, title }}
urlState=""
onLinkClick={mockOnLinkClick}
/>
);

expect(queryByText(title)).toBeInTheDocument();
});

it('should render landingImage', () => {
const landingImage = 'test_image.jpeg';
const title = 'TEST_LABEL';

const { getByTestId } = render(
<LandingLinksImageCard
item={{ ...DEFAULT_NAV_ITEM, landingImage, title }}
urlState=""
onLinkClick={mockOnLinkClick}
/>
);

expect(getByTestId('LandingImageCard-image')).toHaveStyle({
backgroundImage: `url(${landingImage})`,
});
});

it('should render beta tag when isBeta is true', () => {
const { queryByText } = render(
<LandingLinksImageCard item={{ ...DEFAULT_NAV_ITEM, isBeta: true }} />
);
expect(queryByText(BETA)).toBeInTheDocument();
});

it('should not render beta tag when isBeta is false', () => {
const { queryByText } = render(<LandingLinksImageCard item={DEFAULT_NAV_ITEM} />);
expect(queryByText(BETA)).not.toBeInTheDocument();
});

it('should navigate link', () => {
const id = SecurityPageName.administration;
const title = 'test label 2';

const { getByText } = render(
<LandingLinksImageCard item={{ ...DEFAULT_NAV_ITEM, id, title }} />
);

getByText(title).click();

expect(mockGetAppUrl).toHaveBeenCalledWith({
deepLinkId: SecurityPageName.administration,
absolute: false,
path: '',
});
expect(mockNavigateTo).toHaveBeenCalledWith({ url: '/administration' });
});

it('should call onLinkClick', () => {
const id = SecurityPageName.administration;
const title = 'myTestLabel';

const { getByText } = render(
<LandingLinksImageCard
item={{ ...DEFAULT_NAV_ITEM, id, title }}
onLinkClick={mockOnLinkClick}
/>
);

getByText(title).click();

expect(mockOnLinkClick).toHaveBeenCalledWith(id);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* 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 { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiText, EuiTitle, useEuiTheme } from '@elastic/eui';
import React, { useMemo } from 'react';
import { css } from '@emotion/react';
import { withLink } from '../links';
import type { NavigationLink } from '../types';
import { BetaBadge } from './beta_badge';
import { getKibanaLinkProps } from './utils';

export interface LandingLinksImageCardProps {
item: NavigationLink;
urlState?: string;
onLinkClick?: (id: string) => void;
}

const CARD_HEIGHT = 116;
const CARD_WIDTH = 370;
const CARD_HEIGHT_IMAGE = 98;

const useStyles = () => {
const { euiTheme } = useEuiTheme();
return {
card: css`
height: ${CARD_HEIGHT}px;
max-width: ${CARD_WIDTH}px;
`,
cardWrapper: css`
height: 100%;
`,
titleContainer: css`
height: ${euiTheme.size.l};
`,
title: css`
color: ${euiTheme.colors.primaryText};
font-weight: ${euiTheme.font.weight.semiBold};
`,
getImageContainer: (imageUrl: string | undefined) => css`
height: ${CARD_HEIGHT_IMAGE}px;
width: ${CARD_HEIGHT_IMAGE}px;
background-position: center center;
background-repeat: no-repeat;
background-image: url(${imageUrl ?? ''});
background-size: auto 98px;
`,
};
};

const EuiPanelWithLink = withLink(EuiPanel);

export const LandingLinksImageCard: React.FC<LandingLinksImageCardProps> = React.memo(
function LandingLinksImageCard({ item, urlState, onLinkClick }) {
const styles = useStyles();

const linkProps = getKibanaLinkProps({ item, urlState, onLinkClick });
const { landingImage, title, description, isBeta, betaOptions } = item;

const imageBackground = useMemo(
() => styles.getImageContainer(landingImage),
[landingImage, styles]
);

return (
<EuiFlexItem data-test-subj="LandingImageCard-item" grow={false}>
<EuiPanelWithLink {...linkProps} hasBorder paddingSize="s" css={styles.card}>
<EuiFlexGroup
gutterSize="s"
direction="row"
justifyContent="flexStart"
alignItems="flexStart"
css={styles.cardWrapper}
>
<EuiFlexItem grow={false}>
{landingImage && (
<EuiPanel
data-test-subj="LandingImageCard-image"
paddingSize="none"
hasShadow={false}
hasBorder
borderRadius="m"
css={imageBackground}
/>
)}
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup gutterSize="s" direction="column">
<EuiFlexItem>
<EuiFlexGroup
gutterSize="none"
direction="row"
css={styles.titleContainer}
alignItems="center"
>
<EuiFlexItem component="span" grow={false}>
<EuiTitle size="xxxs" css={styles.title}>
<h3>{title}</h3>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem>{isBeta && <BetaBadge text={betaOptions?.text} />}</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem>
<EuiText size="xs">{description}</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanelWithLink>
</EuiFlexItem>
);
}
);

// eslint-disable-next-line import/no-default-export
export default LandingLinksImageCard;
Loading

0 comments on commit 800a1e5

Please sign in to comment.