-
Notifications
You must be signed in to change notification settings - Fork 8.5k
[Enterprise Search] Update Product Selector and add Setup Guide #78233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 14 commits
2e4e766
bacdc4d
1b1335c
b71aaa4
bc6f4fc
07bdfda
def8361
9a81fbf
84b7a85
b2a6329
a43ecc4
b047435
c668c19
d8fe17c
76aa5b9
0540515
f351e00
5f2a108
12e43a0
ce91c42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /* | ||
| * 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. | ||
| */ | ||
|
|
||
| export { ProductSelector } from './product_selector'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* | ||
| * 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 '../../../__mocks__/shallow_usecontext.mock'; | ||
|
|
||
| import React, { useContext } from 'react'; | ||
| import { shallow } from 'enzyme'; | ||
| import { EuiPage } from '@elastic/eui'; | ||
|
|
||
| import '../../../__mocks__/kea.mock'; | ||
| import { useValues } from 'kea'; | ||
|
|
||
| import { ProductSelector } from './'; | ||
| import { ProductCard } from '../product_card'; | ||
|
|
||
| describe('ProductSelector', () => { | ||
| beforeEach(() => { | ||
| (useValues as jest.Mock).mockReturnValue({ errorConnecting: false }); | ||
| }); | ||
|
|
||
scottybollinger marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| it('renders the overview page and product cards with no host set', () => { | ||
| (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: '' } })); | ||
| const wrapper = shallow(<ProductSelector access={{}} />); | ||
|
|
||
| expect(wrapper.find(EuiPage).hasClass('enterpriseSearchOverview')).toBe(true); | ||
| expect(wrapper.find(ProductCard)).toHaveLength(2); | ||
| }); | ||
|
|
||
| describe('access checks when host is set', () => { | ||
| beforeEach(() => { | ||
| (useContext as jest.Mock).mockImplementationOnce(() => ({ config: { host: 'localhost' } })); | ||
| }); | ||
| it('does not render the App Search card if the user does not have access to AS', () => { | ||
scottybollinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const wrapper = shallow( | ||
| <ProductSelector access={{ hasAppSearchAccess: false, hasWorkplaceSearchAccess: true }} /> | ||
| ); | ||
|
|
||
| expect(wrapper.find(ProductCard)).toHaveLength(1); | ||
| expect(wrapper.find(ProductCard).prop('product').ID).toEqual('workplaceSearch'); | ||
| }); | ||
|
|
||
| it('does not render the Workplace Search card if the user does not have access to WS', () => { | ||
| const wrapper = shallow( | ||
| <ProductSelector access={{ hasAppSearchAccess: true, hasWorkplaceSearchAccess: false }} /> | ||
| ); | ||
|
|
||
| expect(wrapper.find(ProductCard)).toHaveLength(1); | ||
| expect(wrapper.find(ProductCard).prop('product').ID).toEqual('appSearch'); | ||
| }); | ||
|
|
||
| it('does not render any cards if the user does not have access', () => { | ||
| const wrapper = shallow(<ProductSelector access={{}} />); | ||
|
|
||
| expect(wrapper.find(ProductCard)).toHaveLength(0); | ||
| }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| /* | ||
scottybollinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| * 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. | ||
| */ | ||
| /* | ||
| * 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, { useContext } from 'react'; | ||
|
|
||
| import { | ||
| EuiPage, | ||
| EuiPageBody, | ||
| EuiPageHeader, | ||
| EuiPageHeaderSection, | ||
| EuiPageContentBody, | ||
| EuiFlexGroup, | ||
| EuiFlexItem, | ||
| EuiSpacer, | ||
| EuiTitle, | ||
| } from '@elastic/eui'; | ||
| import { i18n } from '@kbn/i18n'; | ||
|
|
||
| import { KibanaContext, IKibanaContext } from '../../../index'; | ||
|
|
||
| import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants'; | ||
|
|
||
| import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we alias this? I feel like it confuses things a bit.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying Constance's pattern from other components. If we want to change IMO that is beyond the scope of this PR and we should discuss as a team and change all in a separate PR
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey! This pattern's on me (also one we use in multiple places, e.g., with telemetry, so def open to discussing and refactoring separately from this PR). Most of these components I thought it would feel and read more nicely from a dev experience perspective - for example, if you're an App Search dev you know you're already working in the App Search plugin, so no need to be overly specific when calling the component - just rename it to a more generic Definitely happy to discuss the overall pattern and if you have any thoughts on refactoring, but would very likely be in a separate PR if that sounds cool! |
||
| import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; | ||
|
|
||
| import { ProductCard } from '../product_card'; | ||
|
|
||
| import AppSearchImage from '../../assets/app_search.png'; | ||
| import WorkplaceSearchImage from '../../assets/workplace_search.png'; | ||
|
|
||
| interface IProductSelectorProps { | ||
| access: { | ||
| hasAppSearchAccess?: boolean; | ||
| hasWorkplaceSearchAccess?: boolean; | ||
| }; | ||
| } | ||
|
|
||
| export const ProductSelector: React.FC<IProductSelectorProps> = ({ access }) => { | ||
| const { hasAppSearchAccess, hasWorkplaceSearchAccess } = access; | ||
| const { | ||
| config: { host }, | ||
| } = useContext(KibanaContext) as IKibanaContext; | ||
|
|
||
| return ( | ||
| <EuiPage restrictWidth className="enterpriseSearchOverview"> | ||
| <SetPageChrome isRoot /> | ||
| <SendTelemetry action="viewed" metric="overview" /> | ||
|
|
||
| <EuiPageBody> | ||
| <EuiPageHeader> | ||
| <EuiPageHeaderSection className="enterpriseSearchOverview__header"> | ||
| <EuiTitle size="l"> | ||
| <h1 className="enterpriseSearchOverview__heading"> | ||
| {i18n.translate('xpack.enterpriseSearch.overview.heading', { | ||
| defaultMessage: 'Welcome to Elastic Enterprise Search', | ||
| })} | ||
| </h1> | ||
| </EuiTitle> | ||
| <EuiTitle size="s"> | ||
| <p className="enterpriseSearchOverview__subheading"> | ||
| {i18n.translate('xpack.enterpriseSearch.overview.subheading', { | ||
| defaultMessage: 'Select a product to get started', | ||
| })} | ||
| </p> | ||
| </EuiTitle> | ||
| </EuiPageHeaderSection> | ||
| </EuiPageHeader> | ||
| <EuiPageContentBody> | ||
| <EuiFlexGroup justifyContent="center" gutterSize="xl"> | ||
| {(!host || hasAppSearchAccess) && ( | ||
scottybollinger marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| <EuiFlexItem grow={false} className="enterpriseSearchOverview__card"> | ||
| <ProductCard product={APP_SEARCH_PLUGIN} image={AppSearchImage} /> | ||
| </EuiFlexItem> | ||
| )} | ||
| {(!host || hasWorkplaceSearchAccess) && ( | ||
| <EuiFlexItem grow={false} className="enterpriseSearchOverview__card"> | ||
| <ProductCard product={WORKPLACE_SEARCH_PLUGIN} image={WorkplaceSearchImage} /> | ||
| </EuiFlexItem> | ||
| )} | ||
| </EuiFlexGroup> | ||
| <EuiSpacer /> | ||
| </EuiPageContentBody> | ||
| </EuiPageBody> | ||
| </EuiPage> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| /* | ||
| * 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. | ||
| */ | ||
|
|
||
| export { SetupGuide } from './setup_guide'; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /* | ||
| * 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 { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; | ||
| import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel we should just rename
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copying Constance's pattern from other components. If we want to change IMO that is beyond the scope of this PR and we should discuss as a team and change all in a separate PR
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one's on me again, and almost definitely an alias we don't need 🤔 Historical context for this shenanigans:
EDIT: Went back and actually re-looked at what I was doing, I'm +1 for just renaming this
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ^ Sorry, to clarify - in a separate PR of course |
||
| import { SetupGuide } from './'; | ||
|
|
||
| describe('SetupGuide', () => { | ||
| it('renders', () => { | ||
| const wrapper = shallow(<SetupGuide />); | ||
|
|
||
| expect(wrapper.find(SetupGuideLayout)).toHaveLength(1); | ||
| expect(wrapper.find(SetPageChrome)).toHaveLength(1); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| /* | ||
| * 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 { EuiSpacer, EuiTitle, EuiText } from '@elastic/eui'; | ||
| import { FormattedMessage } from '@kbn/i18n/react'; | ||
| import { i18n } from '@kbn/i18n'; | ||
|
|
||
| import { ENTERPRISE_SEARCH_PLUGIN } from '../../../../../common/constants'; | ||
| import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide'; | ||
| import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome'; | ||
| import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry'; | ||
| import GettingStarted from './assets/getting_started.png'; | ||
|
|
||
| export const SetupGuide: React.FC = () => ( | ||
| <SetupGuideLayout | ||
| productName={ENTERPRISE_SEARCH_PLUGIN.NAME} | ||
| productEuiIcon="logoEnterpriseSearch" | ||
| standardAuthLink="https://www.elastic.co/guide/en/app-search/current/security-and-users.html#app-search-self-managed-security-and-user-management-standard" | ||
scottybollinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| elasticsearchNativeAuthLink="https://www.elastic.co/guide/en/app-search/current/security-and-users.html#app-search-self-managed-security-and-user-management-elasticsearch-native-realm" | ||
| > | ||
| <SetPageChrome | ||
| text={i18n.translate('xpack.enterpriseSearch.setupGuide.title', { | ||
| defaultMessage: 'Setup Guide', | ||
| })} | ||
| /> | ||
| <SendTelemetry action="viewed" metric="setup_guide" /> | ||
scottybollinger marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| <a href="https://www.elastic.co/enterprise-search" target="_blank" rel="noopener noreferrer"> | ||
| <img | ||
| className="setupGuide__thumbnail" | ||
| src={GettingStarted} | ||
| alt={i18n.translate('xpack.enterpriseSearch.enterpriseSearch.setupGuide.videoAlt', { | ||
| defaultMessage: 'Getting started with Enterprise Search', | ||
| })} | ||
| width="1280" | ||
| height-="720" | ||
| /> | ||
| </a> | ||
|
|
||
| <EuiTitle size="s"> | ||
| <p> | ||
| <FormattedMessage | ||
| id="xpack.enterpriseSearch.enterpriseSearch.setupGuide.description" | ||
| defaultMessage="Search everything, anywhere. Easily implement powerful, modern search experiences for your busy team. Quickly add pre-tuned search to your website, app, or workplace. Search it all, simply." | ||
| /> | ||
| </p> | ||
| </EuiTitle> | ||
| <EuiSpacer size="m" /> | ||
| <EuiText> | ||
| <p> | ||
| <FormattedMessage | ||
| id="xpack.enterpriseSearch.enterpriseSearch.setupGuide.notConfigured" | ||
| defaultMessage="Enterprise Search is not configured in your Kibana instance yet." | ||
| /> | ||
| </p> | ||
| </EuiText> | ||
| </SetupGuideLayout> | ||
| ); | ||
Uh oh!
There was an error while loading. Please reload this page.