Skip to content

Commit

Permalink
[Enterprise Search] Overview - add missing setup guide CTAs (#81420) (#…
Browse files Browse the repository at this point in the history
…81503)

* Misc enterprise search overview cleanup

- remove extra comment block
- tests
  - use setMockValues
  - remove unused EuiPage
  - error connecting test - clarify assertion

* Add Setup Guide CTA component

* Update Product Selector to show Setup Guide CTAs

+ tests clean up - use setMockValues, import reorder

* Add EuiPanel RR link to setup guide
  • Loading branch information
Constance authored Oct 22, 2020
1 parent d81fcd5 commit 462d37f
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,30 @@
* you may not use this file except in compliance with the Elastic License.
*/

import '../../../__mocks__/kea.mock';
import { setMockValues } from '../../../__mocks__/kea.mock';

import React from 'react';
import { useValues } from 'kea';
import { shallow } from 'enzyme';
import { EuiPage } from '@elastic/eui';

import { ProductSelector } from './';
import { SetupGuideCta } from '../setup_guide';
import { ProductCard } from '../product_card';

import { ProductSelector } from './';

describe('ProductSelector', () => {
it('renders the overview page and product cards with no host set', () => {
(useValues as jest.Mock).mockImplementationOnce(() => ({ config: { host: '' } }));
it('renders the overview page, product cards, & setup guide CTAs with no host set', () => {
setMockValues({ config: { host: '' } });
const wrapper = shallow(<ProductSelector access={{}} />);

expect(wrapper.find(EuiPage).hasClass('enterpriseSearchOverview')).toBe(true);
expect(wrapper.find(ProductCard)).toHaveLength(2);
expect(wrapper.find(SetupGuideCta)).toHaveLength(1);
});

describe('access checks when host is set', () => {
beforeEach(() => {
(useValues as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } }));
setMockValues({ config: { host: 'localhost' } });
});

it('does not render the App Search card if the user does not have access to AS', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,6 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { useValues } from 'kea';
Expand All @@ -30,6 +25,7 @@ import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kiba
import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';

import { ProductCard } from '../product_card';
import { SetupGuideCta } from '../setup_guide';

import AppSearchImage from '../../assets/app_search.png';
import WorkplaceSearchImage from '../../assets/workplace_search.png';
Expand Down Expand Up @@ -66,9 +62,13 @@ export const ProductSelector: React.FC<IProductSelectorProps> = ({ access }) =>
</EuiTitle>
<EuiTitle size="s">
<p className="enterpriseSearchOverview__subheading">
{i18n.translate('xpack.enterpriseSearch.overview.subheading', {
defaultMessage: 'Select a product to get started',
})}
{config.host
? i18n.translate('xpack.enterpriseSearch.overview.subheading', {
defaultMessage: 'Select a product to get started.',
})
: i18n.translate('xpack.enterpriseSearch.overview.setupHeading', {
defaultMessage: 'Choose a product to set up and get started.',
})}
</p>
</EuiTitle>
</EuiPageHeaderSection>
Expand All @@ -87,6 +87,7 @@ export const ProductSelector: React.FC<IProductSelectorProps> = ({ access }) =>
)}
</EuiFlexGroup>
<EuiSpacer />
{!config.host && <SetupGuideCta />}
</EuiPageContentBody>
</EuiPageBody>
</EuiPage>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
*/

export { SetupGuide } from './setup_guide';
export { SetupGuideCta } from './setup_guide_cta';
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

.enterpriseSearchSetupCta {
margin: $euiSize auto $euiSizeXL;

// Clickable EuiPanel override - line panel up with product cards
&.euiPanel--isClickable {
width: calc(100% - #{$euiSize});
}

&__text {
max-width: $euiSize * 40;
}

&__image {
display: block;
max-width: 100%;
width: $euiSize * 10;
margin: 0 auto;

@include euiBreakpoint('xs', 's') {
width: $euiSize * 15;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { shallow } from 'enzyme';

import { SetupGuideCta } from './';

describe('SetupGuideCta', () => {
it('renders', () => {
const wrapper = shallow(<SetupGuideCta />);

expect(wrapper.find('.enterpriseSearchSetupCta')).toHaveLength(1);
expect(wrapper.find('img')).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import React from 'react';
import { i18n } from '@kbn/i18n';
import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiText } from '@elastic/eui';
import { EuiPanel } from '../../../shared/react_router_helpers';

import CtaImage from './assets/getting_started.png';
import './setup_guide_cta.scss';

export const SetupGuideCta: React.FC = () => (
<EuiPanel to="/setup_guide" paddingSize="l" className="enterpriseSearchSetupCta">
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween">
<EuiFlexItem className="enterpriseSearchSetupCta__text">
<EuiTitle size="s">
<h2>
{i18n.translate('xpack.enterpriseSearch.overview.setupCta.title', {
defaultMessage: 'Enterprise-grade functionality for teams big and small',
})}
</h2>
</EuiTitle>
<EuiText size="s" color="subdued">
{i18n.translate('xpack.enterpriseSearch.overview.setupCta.description', {
defaultMessage:
'Add search to your app or internal organization with Elastic App Search and Workplace Search. Watch the video to see what you can do when search is made easy.',
})}
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<img src={CtaImage} alt="" className="enterpriseSearchSetupCta__image" />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

import React from 'react';
import { shallow } from 'enzyme';
import { EuiPage } from '@elastic/eui';

import '../__mocks__/kea.mock';
import { useValues } from 'kea';
import { setMockValues } from '../__mocks__/kea.mock';

import { EnterpriseSearch } from './';
import { SetupGuide } from './components/setup_guide';
Expand All @@ -18,7 +16,7 @@ import { ProductSelector } from './components/product_selector';

describe('EnterpriseSearch', () => {
it('renders the Setup Guide and Product Selector', () => {
(useValues as jest.Mock).mockReturnValue({
setMockValues({
errorConnecting: false,
config: { host: 'localhost' },
});
Expand All @@ -28,15 +26,23 @@ describe('EnterpriseSearch', () => {
expect(wrapper.find(ProductSelector)).toHaveLength(1);
});

it('renders the error connecting prompt when host is not configured', () => {
(useValues as jest.Mock).mockReturnValueOnce({
it('renders the error connecting prompt only if host is configured', () => {
setMockValues({
errorConnecting: true,
config: { host: '' },
config: { host: 'localhost' },
});
const wrapper = shallow(<EnterpriseSearch />);

expect(wrapper.find(ErrorConnecting)).toHaveLength(1);
expect(wrapper.find(EuiPage)).toHaveLength(0);
expect(wrapper.find(ProductSelector)).toHaveLength(0);

setMockValues({
errorConnecting: true,
config: { host: '' },
});
wrapper.setProps({}); // Re-render

expect(wrapper.find(ErrorConnecting)).toHaveLength(0);
expect(wrapper.find(ProductSelector)).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export const EnterpriseSearch: React.FC<IInitialAppData> = ({ access = {} }) =>
const { errorConnecting } = useValues(HttpLogic);
const { config } = useValues(KibanaLogic);

const showErrorConnecting = config.host && errorConnecting;
const showErrorConnecting = !!(config.host && errorConnecting);

return (
<Switch>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import '../../__mocks__/kea.mock';

import React from 'react';
import { shallow, mount } from 'enzyme';
import { EuiLink, EuiButton } from '@elastic/eui';
import { EuiLink, EuiButton, EuiPanel } from '@elastic/eui';

import { mockKibanaValues, mockHistory } from '../../__mocks__';

import { EuiReactRouterLink, EuiReactRouterButton } from './eui_link';
import { EuiReactRouterLink, EuiReactRouterButton, EuiReactRouterPanel } from './eui_link';

describe('EUI & React Router Component Helpers', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('renders', () => {
it('renders an EuiLink', () => {
const wrapper = shallow(<EuiReactRouterLink to="/" />);

expect(wrapper.find(EuiLink)).toHaveLength(1);
Expand All @@ -31,6 +31,13 @@ describe('EUI & React Router Component Helpers', () => {
expect(wrapper.find(EuiButton)).toHaveLength(1);
});

it('renders an EuiPanel', () => {
const wrapper = shallow(<EuiReactRouterPanel to="/" paddingSize="l" />);

expect(wrapper.find(EuiPanel)).toHaveLength(1);
expect(wrapper.find(EuiPanel).prop('paddingSize')).toEqual('l');
});

it('passes down all ...rest props', () => {
const wrapper = shallow(<EuiReactRouterLink to="/" data-test-subj="foo" external={true} />);
const link = wrapper.find(EuiLink);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

import React from 'react';
import { useValues } from 'kea';
import { EuiLink, EuiButton, EuiButtonProps, EuiLinkAnchorProps } from '@elastic/eui';
import { EuiLink, EuiButton, EuiButtonProps, EuiLinkAnchorProps, EuiPanel } from '@elastic/eui';
import { EuiPanelProps } from '@elastic/eui/src/components/panel/panel';

import { KibanaLogic } from '../kibana';
import { HttpLogic } from '../http';
import { letBrowserHandleEvent, createHref } from './';

/**
* Generates either an EuiLink or EuiButton with a React-Router-ified link
* Generates EUI components with React-Router-ified links
*
* Based off of EUI's recommendations for handling React Router:
* https://github.com/elastic/eui/blob/master/wiki/react-router.md#react-router-51
Expand Down Expand Up @@ -54,9 +55,11 @@ export const EuiReactRouterHelper: React.FC<IEuiReactRouterProps> = ({
return React.cloneElement(children as React.ReactElement, reactRouterProps);
};

type TEuiReactRouterLinkProps = EuiLinkAnchorProps & IEuiReactRouterProps;
type TEuiReactRouterButtonProps = EuiButtonProps & IEuiReactRouterProps;
/**
* Component helpers
*/

type TEuiReactRouterLinkProps = EuiLinkAnchorProps & IEuiReactRouterProps;
export const EuiReactRouterLink: React.FC<TEuiReactRouterLinkProps> = ({
to,
onClick,
Expand All @@ -68,6 +71,7 @@ export const EuiReactRouterLink: React.FC<TEuiReactRouterLinkProps> = ({
</EuiReactRouterHelper>
);

type TEuiReactRouterButtonProps = EuiButtonProps & IEuiReactRouterProps;
export const EuiReactRouterButton: React.FC<TEuiReactRouterButtonProps> = ({
to,
onClick,
Expand All @@ -78,3 +82,15 @@ export const EuiReactRouterButton: React.FC<TEuiReactRouterButtonProps> = ({
<EuiButton {...rest} />
</EuiReactRouterHelper>
);

type TEuiReactRouterPanelProps = EuiPanelProps & IEuiReactRouterProps;
export const EuiReactRouterPanel: React.FC<TEuiReactRouterPanelProps> = ({
to,
onClick,
shouldNotCreateHref,
...rest
}) => (
<EuiReactRouterHelper {...{ to, onClick, shouldNotCreateHref }}>
<EuiPanel {...rest} />
</EuiReactRouterHelper>
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@

export { letBrowserHandleEvent } from './link_events';
export { createHref, ICreateHrefOptions } from './create_href';
export { EuiReactRouterLink as EuiLink } from './eui_link';
export { EuiReactRouterButton as EuiButton } from './eui_link';
export {
EuiReactRouterLink as EuiLink,
EuiReactRouterButton as EuiButton,
EuiReactRouterPanel as EuiPanel,
} from './eui_link';

0 comments on commit 462d37f

Please sign in to comment.