mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Enterprise Search] New overview page (#136586)
This commit is contained in:
parent
1cbf53e355
commit
4b52441a53
22 changed files with 534 additions and 271 deletions
|
@ -47,10 +47,6 @@ export const ELASTICSEARCH_PLUGIN = {
|
|||
DESCRIPTION: i18n.translate('xpack.enterpriseSearch.elasticsearch.productDescription', {
|
||||
defaultMessage: 'Low-level tools for creating performant and relevant search experiences.',
|
||||
}),
|
||||
CARD_DESCRIPTION: i18n.translate('xpack.enterpriseSearch.elasticsearch.productCardDescription', {
|
||||
defaultMessage:
|
||||
'Design and build performant, relevant search-powered applications or large-scale search implementations directly in Elasticsearch.',
|
||||
}),
|
||||
URL: '/app/enterprise_search/elasticsearch',
|
||||
SUPPORT_URL: 'https://discuss.elastic.co/c/elastic-stack/elasticsearch/',
|
||||
};
|
||||
|
@ -64,10 +60,6 @@ export const APP_SEARCH_PLUGIN = {
|
|||
defaultMessage:
|
||||
'Leverage dashboards, analytics, and APIs for advanced application search made simple.',
|
||||
}),
|
||||
CARD_DESCRIPTION: i18n.translate('xpack.enterpriseSearch.appSearch.productCardDescription', {
|
||||
defaultMessage:
|
||||
'Design, deploy, and manage powerful search experiences for your websites and web/mobile apps.',
|
||||
}),
|
||||
URL: '/app/enterprise_search/app_search',
|
||||
SUPPORT_URL: 'https://discuss.elastic.co/c/enterprise-search/app-search/',
|
||||
};
|
||||
|
@ -81,13 +73,6 @@ export const WORKPLACE_SEARCH_PLUGIN = {
|
|||
defaultMessage:
|
||||
'Search all documents, files, and sources available across your virtual workplace.',
|
||||
}),
|
||||
CARD_DESCRIPTION: i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.productCardDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Unify your content in one place, with instant connectivity to popular productivity and collaboration tools.',
|
||||
}
|
||||
),
|
||||
URL: '/app/enterprise_search/workplace_search',
|
||||
NON_ADMIN_URL: '/app/enterprise_search/workplace_search/p',
|
||||
SUPPORT_URL: 'https://discuss.elastic.co/c/enterprise-search/workplace-search/',
|
||||
|
|
|
@ -9,5 +9,5 @@ import { i18n } from '@kbn/i18n';
|
|||
|
||||
export const LICENSE_CALLOUT_BODY = i18n.translate('xpack.enterpriseSearch.licenseCalloutBody', {
|
||||
defaultMessage:
|
||||
'Enterprise authentication via SAML, document-level permission and authorization support, custom search experiences and more are available with a valid Platinum license.',
|
||||
'Enterprise authentication via SAML, document-level permission and authorization support, custom search experiences and more are available with a valid Premium license.',
|
||||
});
|
||||
|
|
|
@ -11,23 +11,22 @@ import React from 'react';
|
|||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiPanel, EuiText } from '@elastic/eui';
|
||||
|
||||
import { ManageLicenseButton } from '../../../shared/licensing';
|
||||
import { EuiPanel } from '@elastic/eui';
|
||||
|
||||
import { LicenseCallout } from '.';
|
||||
|
||||
// TODO: Remove this license callout code completely (eventually)
|
||||
// for now, the test is merely updated to reflect that it shouldn't
|
||||
// render at all
|
||||
describe('LicenseCallout', () => {
|
||||
it('renders when non-platinum or on trial', () => {
|
||||
it('never renders a license callout', () => {
|
||||
setMockValues({
|
||||
hasPlatinumLicense: false,
|
||||
isTrial: true,
|
||||
});
|
||||
const wrapper = shallow(<LicenseCallout />);
|
||||
|
||||
expect(wrapper.find(EuiPanel)).toHaveLength(1);
|
||||
expect(wrapper.find(EuiText)).toHaveLength(2);
|
||||
expect(wrapper.find(ManageLicenseButton)).toHaveLength(1);
|
||||
expect(wrapper.find(EuiPanel)).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('does not render for platinum', () => {
|
||||
|
|
|
@ -9,7 +9,7 @@ import React from 'react';
|
|||
|
||||
import { useValues } from 'kea';
|
||||
|
||||
import { EuiPanel, EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
|
||||
import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
|
||||
|
||||
import { LicensingLogic, ManageLicenseButton } from '../../../shared/licensing';
|
||||
|
||||
|
@ -23,19 +23,18 @@ export const LicenseCallout: React.FC = () => {
|
|||
if (hasPlatinumLicense && !isTrial) return null;
|
||||
|
||||
return (
|
||||
<EuiPanel hasBorder color="transparent" paddingSize="l">
|
||||
<EuiFlexGroup gutterSize="s" alignItems="center" justifyContent="spaceBetween">
|
||||
<EuiFlexItem grow={7}>
|
||||
<EuiText>
|
||||
<h3>{PRODUCT_SELECTOR_CALLOUT_HEADING}</h3>
|
||||
</EuiText>
|
||||
<EuiText size="s">{LICENSE_CALLOUT_BODY}</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={1} />
|
||||
<EuiFlexItem grow={false}>
|
||||
<ManageLicenseButton />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
<EuiFlexGroup gutterSize="s" direction="column">
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="xs">
|
||||
<h3>{PRODUCT_SELECTOR_CALLOUT_HEADING}</h3>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText size="s">{LICENSE_CALLOUT_BODY}</EuiText>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem />
|
||||
<EuiFlexItem>
|
||||
<ManageLicenseButton />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -6,10 +6,7 @@
|
|||
*/
|
||||
|
||||
.productCard {
|
||||
&__imageContainer {
|
||||
@include euiBreakpoint('xs') {
|
||||
max-height: 115px;
|
||||
overflow: hidden;
|
||||
}
|
||||
& &-features {
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,67 +5,83 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { setMockValues, mockTelemetryActions } from '../../../__mocks__/kea_logic';
|
||||
import { mockTelemetryActions } from '../../../__mocks__/kea_logic';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { shallow } from 'enzyme';
|
||||
|
||||
import { EuiCard } from '@elastic/eui';
|
||||
import { snakeCase } from 'lodash';
|
||||
|
||||
import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants';
|
||||
import { EuiButtonTo } from '../../../shared/react_router_helpers';
|
||||
import { EuiListGroup, EuiPanel } from '@elastic/eui';
|
||||
|
||||
import { ProductCard } from '.';
|
||||
import { EuiButtonTo, EuiButtonEmptyTo } from '../../../shared/react_router_helpers';
|
||||
|
||||
import { ProductCard, ProductCardProps } from './product_card';
|
||||
|
||||
const MOCK_VALUES: ProductCardProps = {
|
||||
cta: 'Click me',
|
||||
description: 'Mock description',
|
||||
features: ['first feature', 'second feature'],
|
||||
icon: 'logoElasticsearch',
|
||||
name: 'Mock product',
|
||||
productId: 'mockProduct',
|
||||
resourceLinks: [
|
||||
{
|
||||
label: 'Link one',
|
||||
to: 'https://www.elastic.co/guide/one',
|
||||
},
|
||||
{
|
||||
label: 'Link twwo',
|
||||
to: 'https://www.elastic.co/guide/two',
|
||||
},
|
||||
],
|
||||
url: '/app/mock_app',
|
||||
};
|
||||
|
||||
describe('ProductCard', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('renders an App Search card', () => {
|
||||
const wrapper = shallow(<ProductCard product={APP_SEARCH_PLUGIN} image="as.jpg" />);
|
||||
const card = wrapper.find(EuiCard).dive().shallow();
|
||||
it('renders a product card', () => {
|
||||
const wrapper = shallow(<ProductCard {...MOCK_VALUES} />);
|
||||
const card = wrapper.find(EuiPanel);
|
||||
|
||||
expect(card.find('h2').text()).toEqual('Elastic App Search');
|
||||
expect(card.find('.productCard__image').prop('src')).toEqual('as.jpg');
|
||||
expect(card.find('h3').text()).toEqual(MOCK_VALUES.name);
|
||||
expect(card.find(EuiListGroup).children()).toHaveLength(MOCK_VALUES.features.length);
|
||||
expect(card.find('[data-test-subj="productCard-resources"]').text()).toEqual('Resources');
|
||||
expect(card.find('[data-test-subj="productCard-resourceLinks"]').children()).toHaveLength(
|
||||
MOCK_VALUES.resourceLinks.length
|
||||
);
|
||||
|
||||
const button = card.find(EuiButtonEmptyTo);
|
||||
|
||||
expect(button).toHaveLength(1);
|
||||
expect(button.prop('to')).toEqual(MOCK_VALUES.url);
|
||||
expect(card.find(EuiButtonTo)).toHaveLength(0);
|
||||
|
||||
button.simulate('click');
|
||||
|
||||
expect(mockTelemetryActions.sendEnterpriseSearchTelemetry).toHaveBeenCalledWith({
|
||||
action: 'clicked',
|
||||
metric: snakeCase(MOCK_VALUES.productId),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders an empty cta', () => {
|
||||
const wrapper = shallow(<ProductCard {...MOCK_VALUES} emptyCta />);
|
||||
const card = wrapper.find(EuiPanel);
|
||||
const button = card.find(EuiButtonTo);
|
||||
expect(button.prop('to')).toEqual('/app/enterprise_search/app_search');
|
||||
expect(button.prop('children')).toEqual('Open App Search');
|
||||
|
||||
expect(button).toHaveLength(1);
|
||||
expect(button.prop('to')).toEqual(MOCK_VALUES.url);
|
||||
expect(card.find(EuiButtonEmptyTo)).toHaveLength(0);
|
||||
|
||||
button.simulate('click');
|
||||
expect(mockTelemetryActions.sendEnterpriseSearchTelemetry).toHaveBeenCalledWith({
|
||||
action: 'clicked',
|
||||
metric: 'app_search',
|
||||
metric: snakeCase(MOCK_VALUES.productId),
|
||||
});
|
||||
});
|
||||
|
||||
it('renders a Workplace Search card', () => {
|
||||
const wrapper = shallow(<ProductCard product={WORKPLACE_SEARCH_PLUGIN} image="ws.jpg" />);
|
||||
const card = wrapper.find(EuiCard).dive().shallow();
|
||||
|
||||
expect(card.find('h2').text()).toEqual('Elastic Workplace Search');
|
||||
expect(card.find('.productCard__image').prop('src')).toEqual('ws.jpg');
|
||||
|
||||
const button = card.find(EuiButtonTo);
|
||||
expect(button.prop('to')).toEqual('/app/enterprise_search/workplace_search');
|
||||
expect(button.prop('children')).toEqual('Open Workplace Search');
|
||||
|
||||
button.simulate('click');
|
||||
expect(mockTelemetryActions.sendEnterpriseSearchTelemetry).toHaveBeenCalledWith({
|
||||
action: 'clicked',
|
||||
metric: 'workplace_search',
|
||||
});
|
||||
});
|
||||
|
||||
it('renders correct button text when host not present', () => {
|
||||
setMockValues({ config: { host: '' } });
|
||||
|
||||
const wrapper = shallow(<ProductCard product={WORKPLACE_SEARCH_PLUGIN} image="ws.jpg" />);
|
||||
const card = wrapper.find(EuiCard).dive().shallow();
|
||||
const button = card.find(EuiButtonTo);
|
||||
|
||||
expect(button.prop('children')).toEqual('Set up Workplace Search');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,81 +7,147 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { useValues, useActions } from 'kea';
|
||||
import { useActions } from 'kea';
|
||||
import { snakeCase } from 'lodash';
|
||||
|
||||
import { EuiCard, EuiTextColor } from '@elastic/eui';
|
||||
import {
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiIcon,
|
||||
EuiLink,
|
||||
EuiListGroup,
|
||||
EuiListGroupItem,
|
||||
EuiPanel,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
IconType,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { KibanaLogic } from '../../../shared/kibana';
|
||||
import { EuiButtonTo } from '../../../shared/react_router_helpers';
|
||||
import { EuiButtonTo, EuiButtonEmptyTo } from '../../../shared/react_router_helpers';
|
||||
import { TelemetryLogic } from '../../../shared/telemetry';
|
||||
|
||||
import './product_card.scss';
|
||||
|
||||
interface ProductCardProps {
|
||||
// Expects product plugin constants (@see common/constants.ts)
|
||||
product: {
|
||||
ID: string;
|
||||
NAME: string;
|
||||
CARD_DESCRIPTION: string;
|
||||
URL: string;
|
||||
};
|
||||
image: string;
|
||||
url?: string;
|
||||
interface ProductResourceLink {
|
||||
label: string;
|
||||
to: string;
|
||||
}
|
||||
|
||||
export const ProductCard: React.FC<ProductCardProps> = ({ product, image, url }) => {
|
||||
export interface ProductCardProps {
|
||||
cta: string;
|
||||
description: string;
|
||||
emptyCta?: boolean;
|
||||
features: string[];
|
||||
icon: IconType;
|
||||
name: string;
|
||||
productId: string;
|
||||
resourceLinks: ProductResourceLink[];
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const ProductCard: React.FC<ProductCardProps> = ({
|
||||
cta,
|
||||
description,
|
||||
emptyCta = false,
|
||||
features,
|
||||
icon,
|
||||
productId,
|
||||
name,
|
||||
resourceLinks,
|
||||
url,
|
||||
}) => {
|
||||
const { sendEnterpriseSearchTelemetry } = useActions(TelemetryLogic);
|
||||
const { config } = useValues(KibanaLogic);
|
||||
|
||||
const LAUNCH_BUTTON_TEXT = i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.productCard.launchButton',
|
||||
{
|
||||
defaultMessage: 'Open {productName}',
|
||||
values: { productName: product.NAME },
|
||||
}
|
||||
);
|
||||
|
||||
const SETUP_BUTTON_TEXT = i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.productCard.setupButton',
|
||||
{
|
||||
defaultMessage: 'Set up {productName}',
|
||||
values: { productName: product.NAME },
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiCard
|
||||
className="productCard"
|
||||
titleElement="h2"
|
||||
title={i18n.translate('xpack.enterpriseSearch.overview.productCard.heading', {
|
||||
defaultMessage: 'Elastic {productName}',
|
||||
values: { productName: product.NAME },
|
||||
})}
|
||||
image={
|
||||
<div className="productCard__imageContainer">
|
||||
<img src={image} className="productCard__image" alt="" role="presentation" />
|
||||
</div>
|
||||
}
|
||||
<EuiPanel
|
||||
hasBorder
|
||||
paddingSize="l"
|
||||
description={<EuiTextColor color="subdued">{product.CARD_DESCRIPTION}</EuiTextColor>}
|
||||
footer={
|
||||
<EuiButtonTo
|
||||
fill
|
||||
to={url || product.URL}
|
||||
shouldNotCreateHref
|
||||
onClick={() =>
|
||||
sendEnterpriseSearchTelemetry({
|
||||
action: 'clicked',
|
||||
metric: snakeCase(product.ID),
|
||||
})
|
||||
}
|
||||
>
|
||||
{config.host ? LAUNCH_BUTTON_TEXT : SETUP_BUTTON_TEXT}
|
||||
</EuiButtonTo>
|
||||
}
|
||||
data-test-subj={`${product.ID}ProductCard`}
|
||||
/>
|
||||
data-test-subj={`${productId}ProductCard`}
|
||||
className="productCard"
|
||||
>
|
||||
<EuiFlexGroup>
|
||||
<EuiFlexItem grow={false} data-test-subj="productCard-icon">
|
||||
<EuiIcon size="xl" type={icon} />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem data-test-subj="productCard-details">
|
||||
<EuiTitle size="s">
|
||||
<h3>{name}</h3>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiText color="subdued" size="s">
|
||||
{description}
|
||||
</EuiText>
|
||||
<EuiSpacer />
|
||||
<div>
|
||||
{emptyCta ? (
|
||||
<EuiButtonTo
|
||||
to={url}
|
||||
shouldNotCreateHref
|
||||
onClick={() =>
|
||||
sendEnterpriseSearchTelemetry({
|
||||
action: 'clicked',
|
||||
metric: snakeCase(productId),
|
||||
})
|
||||
}
|
||||
>
|
||||
{cta}
|
||||
</EuiButtonTo>
|
||||
) : (
|
||||
<EuiButtonEmptyTo
|
||||
flush="both"
|
||||
to={url}
|
||||
shouldNotCreateHref
|
||||
onClick={() =>
|
||||
sendEnterpriseSearchTelemetry({
|
||||
action: 'clicked',
|
||||
metric: snakeCase(productId),
|
||||
})
|
||||
}
|
||||
>
|
||||
{cta}
|
||||
</EuiButtonEmptyTo>
|
||||
)}
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem data-test-subj="productCard-features">
|
||||
<EuiListGroup flush className="productCard-features">
|
||||
{features.map((item: string, index: number) => (
|
||||
<EuiListGroupItem
|
||||
key={index}
|
||||
size="s"
|
||||
label={item}
|
||||
icon={<EuiIcon color="success" type="checkInCircleFilled" />}
|
||||
/>
|
||||
))}
|
||||
</EuiListGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiTitle size="xs">
|
||||
<h4 data-test-subj="productCard-resources">
|
||||
{i18n.translate('xpack.enterpriseSearch.productCard.resourcesTitle', {
|
||||
defaultMessage: 'Resources',
|
||||
})}
|
||||
</h4>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="s" />
|
||||
<EuiFlexGroup
|
||||
direction="column"
|
||||
gutterSize="m"
|
||||
data-test-subj="productCard-resourceLinks"
|
||||
>
|
||||
{resourceLinks.map((resource, index) => (
|
||||
<EuiFlexItem key={index} grow={false}>
|
||||
<EuiLink href={resource.to} external>
|
||||
{resource.label}
|
||||
</EuiLink>
|
||||
</EuiFlexItem>
|
||||
))}
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</EuiPanel>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -15,8 +15,6 @@ import { EuiEmptyPrompt } from '@elastic/eui';
|
|||
|
||||
import { WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants';
|
||||
|
||||
import { ElasticsearchCard } from '../elasticsearch_card';
|
||||
import { LicenseCallout } from '../license_callout';
|
||||
import { ProductCard } from '../product_card';
|
||||
import { SetupGuideCta } from '../setup_guide';
|
||||
import { TrialCallout } from '../trial_callout';
|
||||
|
@ -33,10 +31,8 @@ describe('ProductSelector', () => {
|
|||
setMockValues({ config: { host: '' } });
|
||||
const wrapper = shallow(<ProductSelector {...props} />);
|
||||
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(2);
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(3);
|
||||
expect(wrapper.find(SetupGuideCta)).toHaveLength(1);
|
||||
expect(wrapper.find(LicenseCallout)).toHaveLength(0);
|
||||
expect(wrapper.find(ElasticsearchCard)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('renders the trial callout', () => {
|
||||
|
@ -60,15 +56,6 @@ describe('ProductSelector', () => {
|
|||
setMockValues({ config: { host: 'localhost' } });
|
||||
});
|
||||
|
||||
it('renders the license callout when user has access to a product', () => {
|
||||
setMockValues({ config: { host: 'localhost' } });
|
||||
const wrapper = shallow(
|
||||
<ProductSelector {...props} access={{ hasWorkplaceSearchAccess: true }} />
|
||||
);
|
||||
|
||||
expect(wrapper.find(LicenseCallout)).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('does not render the App Search card if the user does not have access to AS', () => {
|
||||
const wrapper = shallow(
|
||||
<ProductSelector
|
||||
|
@ -77,8 +64,9 @@ describe('ProductSelector', () => {
|
|||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductCard).prop('product').ID).toEqual('workplaceSearch');
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(2);
|
||||
expect(wrapper.find('[data-test-subj="productCard-workplaceSearch"]')).toHaveLength(1);
|
||||
expect(wrapper.find('[data-test-subj="productCard-elasticsearch"]')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('does not render the Workplace Search card if the user does not have access to WS', () => {
|
||||
|
@ -89,8 +77,9 @@ describe('ProductSelector', () => {
|
|||
/>
|
||||
);
|
||||
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductCard).prop('product').ID).toEqual('appSearch');
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(2);
|
||||
expect(wrapper.find('[data-test-subj="productCard-appSearch"]')).toHaveLength(1);
|
||||
expect(wrapper.find('[data-test-subj="productCard-elasticsearch"]')).toHaveLength(1);
|
||||
});
|
||||
|
||||
it('renders empty prompt and no cards or license callout if the user does not have access', () => {
|
||||
|
@ -98,8 +87,6 @@ describe('ProductSelector', () => {
|
|||
|
||||
expect(wrapper.find(EuiEmptyPrompt)).toHaveLength(1);
|
||||
expect(wrapper.find(ProductCard)).toHaveLength(0);
|
||||
expect(wrapper.find(LicenseCallout)).toHaveLength(0);
|
||||
expect(wrapper.find(ElasticsearchCard)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,28 +17,23 @@ import {
|
|||
EuiImage,
|
||||
EuiLink,
|
||||
EuiSpacer,
|
||||
EuiText,
|
||||
EuiTitle,
|
||||
} from '@elastic/eui';
|
||||
import { Chat } from '@kbn/cloud-plugin/public';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import {
|
||||
KibanaPageTemplateSolutionNavAvatar,
|
||||
NO_DATA_PAGE_TEMPLATE_PROPS,
|
||||
} from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
import { APP_SEARCH_PLUGIN, WORKPLACE_SEARCH_PLUGIN } from '../../../../../common/constants';
|
||||
APP_SEARCH_PLUGIN,
|
||||
ELASTICSEARCH_PLUGIN,
|
||||
WORKPLACE_SEARCH_PLUGIN,
|
||||
} from '../../../../../common/constants';
|
||||
import { AddContentEmptyPrompt } from '../../../shared/add_content_empty_prompt';
|
||||
import { docLinks } from '../../../shared/doc_links';
|
||||
import { KibanaLogic } from '../../../shared/kibana';
|
||||
import { SetEnterpriseSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
|
||||
import { SendEnterpriseSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
|
||||
|
||||
import AppSearchImage from '../../assets/app_search.png';
|
||||
import WorkplaceSearchImage from '../../assets/workplace_search.png';
|
||||
import { ElasticsearchCard } from '../elasticsearch_card';
|
||||
import { EnterpriseSearchOverviewPageTemplate } from '../layout';
|
||||
import { LicenseCallout } from '../license_callout';
|
||||
import { ProductCard } from '../product_card';
|
||||
import { SetupGuideCta } from '../setup_guide';
|
||||
import { TrialCallout } from '../trial_callout';
|
||||
|
@ -74,30 +69,236 @@ export const ProductSelector: React.FC<ProductSelectorProps> = ({
|
|||
|
||||
const productCards = (
|
||||
<>
|
||||
<ElasticsearchCard />
|
||||
|
||||
<AddContentEmptyPrompt
|
||||
title={i18n.translate('xpack.enterpriseSearch.overview.emptyPromptTitle', {
|
||||
defaultMessage: 'A new start for search',
|
||||
})}
|
||||
buttonLabel={i18n.translate('xpack.enterpriseSearch.overview.emptyPromptButtonLabel', {
|
||||
defaultMessage: 'Create an Elasticsearch index',
|
||||
})}
|
||||
/>
|
||||
<EuiSpacer size="xxl" />
|
||||
|
||||
<EuiFlexGroup justifyContent="center" gutterSize="xl">
|
||||
<EuiSpacer size="xxl" />
|
||||
<EuiTitle>
|
||||
<h3>
|
||||
{i18n.translate('xpack.enterpriseSearch.overview.productSelector.title', {
|
||||
defaultMessage: 'Search experiences for every use case',
|
||||
})}
|
||||
</h3>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="xl" />
|
||||
<EuiFlexGroup direction="column" gutterSize="m">
|
||||
<EuiFlexItem>
|
||||
<ProductCard
|
||||
data-test-subj="productCard-elasticsearch"
|
||||
cta={i18n.translate('xpack.enterpriseSearch.elasticsearch.productCardCTA', {
|
||||
defaultMessage: 'View the setup guide',
|
||||
})}
|
||||
description={i18n.translate(
|
||||
'xpack.enterpriseSearch.elasticsearch.productCardDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Ideal for bespoke applications, Elasticsearch helps you build highly customizable search and offers many different ingestion methods.',
|
||||
}
|
||||
)}
|
||||
features={[
|
||||
i18n.translate('xpack.enterpriseSearch.elasticsearch.features.integrate', {
|
||||
defaultMessage: 'Integrate with databases, websites, and more',
|
||||
}),
|
||||
i18n.translate('xpack.enterpriseSearch.elasticsearch.features.buildTooling', {
|
||||
defaultMessage: 'Build custom tooling',
|
||||
}),
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.elasticsearch.features.buildSearchExperiences',
|
||||
{
|
||||
defaultMessage: 'Build custom search experiences',
|
||||
}
|
||||
),
|
||||
]}
|
||||
emptyCta
|
||||
icon="logoElasticsearch"
|
||||
name={ELASTICSEARCH_PLUGIN.NAME}
|
||||
productId={ELASTICSEARCH_PLUGIN.ID}
|
||||
resourceLinks={[
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.elasticsearch.resources.gettingStartedLabel',
|
||||
{
|
||||
defaultMessage: 'Getting started with Elasticsearch',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.elasticsearch.resources.createNewIndexLabel',
|
||||
{
|
||||
defaultMessage: 'Create a new index',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.elasticsearch.resources.languageClientLabel',
|
||||
{
|
||||
defaultMessage: 'Set up a language client',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.elasticsearch.resources.searchUILabel',
|
||||
{
|
||||
defaultMessage: 'Search UI for Elasticsearch',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
]}
|
||||
url={ELASTICSEARCH_PLUGIN.URL}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
{shouldShowAppSearchCard && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<ProductCard product={APP_SEARCH_PLUGIN} image={AppSearchImage} />
|
||||
<EuiFlexItem>
|
||||
<ProductCard
|
||||
data-test-subj="productCard-appSearch"
|
||||
cta={i18n.translate('xpack.enterpriseSearch.appSearch.productCardCTA', {
|
||||
defaultMessage: 'Open App Search',
|
||||
})}
|
||||
description={i18n.translate(
|
||||
'xpack.enterpriseSearch.appSearch.productCardDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Ideal for apps and websites, App Search helps you design, deploy, and manage powerful search experiences.',
|
||||
}
|
||||
)}
|
||||
features={[
|
||||
i18n.translate('xpack.enterpriseSearch.appSearch.features.ingest', {
|
||||
defaultMessage: 'Ingest with a web crawler, API, or Elasticsearch',
|
||||
}),
|
||||
i18n.translate('xpack.enterpriseSearch.appSearch.features.managementDashboards', {
|
||||
defaultMessage: 'Search management dashboards',
|
||||
}),
|
||||
i18n.translate('xpack.enterpriseSearch.appSearch.features.searchApis', {
|
||||
defaultMessage: 'Search-optimized APIs',
|
||||
}),
|
||||
]}
|
||||
icon="logoAppSearch"
|
||||
name={APP_SEARCH_PLUGIN.NAME}
|
||||
productId={APP_SEARCH_PLUGIN.ID}
|
||||
resourceLinks={[
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.appSearch.resources.gettingStartedLabel',
|
||||
{
|
||||
defaultMessage: 'Getting started with App Search',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.appSearch.resources.searchUILabel',
|
||||
{
|
||||
defaultMessage: 'Search UI for App Search',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.appSearch.resources.searchRelevanceLabel',
|
||||
{
|
||||
defaultMessage: 'Tune your search relevance',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.appSearch.resources.adaptiveRelevanceLabel',
|
||||
{
|
||||
defaultMessage: 'Automate with Adaptive Relevance',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
]}
|
||||
url={APP_SEARCH_PLUGIN.URL}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{shouldShowWorkplaceSearchCard && (
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexItem>
|
||||
<ProductCard
|
||||
product={WORKPLACE_SEARCH_PLUGIN}
|
||||
data-test-subj="productCard-workplaceSearch"
|
||||
cta={i18n.translate('xpack.enterpriseSearch.workplaceSearch.productCardCTA', {
|
||||
defaultMessage: 'Open Workplace Search',
|
||||
})}
|
||||
description={i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.productCardDescription',
|
||||
{
|
||||
defaultMessage:
|
||||
'Ideal for internal teams, Workplace Search helps unify your content in one place with instant connectivity to popular productivity tools.',
|
||||
}
|
||||
)}
|
||||
features={[
|
||||
i18n.translate('xpack.enterpriseSearch.workplaceSearch.features.ingest', {
|
||||
defaultMessage: 'Ingest from third-party sources',
|
||||
}),
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.features.managementDashboards',
|
||||
{
|
||||
defaultMessage: 'Search management dashboards',
|
||||
}
|
||||
),
|
||||
i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.features.searchExperiences',
|
||||
{
|
||||
defaultMessage: 'Search experiences for authenticated users',
|
||||
}
|
||||
),
|
||||
]}
|
||||
icon="logoWorkplaceSearch"
|
||||
name={WORKPLACE_SEARCH_PLUGIN.NAME}
|
||||
productId={WORKPLACE_SEARCH_PLUGIN.ID}
|
||||
resourceLinks={[
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.resources.gettingStartedLabel',
|
||||
{
|
||||
defaultMessage: 'Getting started with Workplace Search',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.resources.setUpConnectorsLabel',
|
||||
{
|
||||
defaultMessage: 'Set up your connectors',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.workplaceSearch.resources.managePermissionsLabel',
|
||||
{
|
||||
defaultMessage: 'Manage permissions',
|
||||
}
|
||||
),
|
||||
to: '', // TODO Update docLink
|
||||
},
|
||||
]}
|
||||
url={WORKPLACE_SEARCH_URL}
|
||||
image={WorkplaceSearchImage}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
</EuiFlexGroup>
|
||||
|
||||
<EuiSpacer size="xxl" />
|
||||
|
||||
{config.host ? <LicenseCallout /> : <SetupGuideCta />}
|
||||
{!config.host && <SetupGuideCta />}
|
||||
</>
|
||||
);
|
||||
|
||||
|
@ -152,38 +353,17 @@ export const ProductSelector: React.FC<ProductSelectorProps> = ({
|
|||
/>
|
||||
);
|
||||
return (
|
||||
<EnterpriseSearchOverviewPageTemplate {...NO_DATA_PAGE_TEMPLATE_PROPS}>
|
||||
<EnterpriseSearchOverviewPageTemplate
|
||||
restrictWidth
|
||||
pageHeader={{
|
||||
pageTitle: i18n.translate('xpack.enterpriseSearch.overview.pageTitle', {
|
||||
defaultMessage: 'Welcome to Enterprise Search',
|
||||
}),
|
||||
}}
|
||||
>
|
||||
<SetPageChrome />
|
||||
<SendTelemetry action="viewed" metric="overview" />
|
||||
<TrialCallout />
|
||||
<EuiFlexGroup responsive={false} alignItems="center">
|
||||
<EuiFlexItem grow={false}>
|
||||
<KibanaPageTemplateSolutionNavAvatar
|
||||
name="Enterprise Search"
|
||||
iconType="logoEnterpriseSearch"
|
||||
size="xxl"
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<EuiText>
|
||||
<h1>
|
||||
{i18n.translate('xpack.enterpriseSearch.overview.heading', {
|
||||
defaultMessage: 'Welcome to Elastic Enterprise Search',
|
||||
})}
|
||||
</h1>
|
||||
<p>
|
||||
{config.host
|
||||
? i18n.translate('xpack.enterpriseSearch.overview.subheading', {
|
||||
defaultMessage: 'Add search to your app or organization.',
|
||||
})
|
||||
: i18n.translate('xpack.enterpriseSearch.overview.setupHeading', {
|
||||
defaultMessage: 'Choose a product to set up and get started.',
|
||||
})}
|
||||
</p>
|
||||
</EuiText>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
<EuiSpacer size="xxl" />
|
||||
{shouldShowEnterpriseSearchCards ? productCards : insufficientAccessMessage}
|
||||
<Chat />
|
||||
</EnterpriseSearchOverviewPageTemplate>
|
||||
|
|
|
@ -10,6 +10,6 @@ import { i18n } from '@kbn/i18n';
|
|||
export const PRODUCT_SELECTOR_CALLOUT_HEADING = i18n.translate(
|
||||
'xpack.enterpriseSearch.productSelectorCalloutTitle',
|
||||
{
|
||||
defaultMessage: 'Enterprise-grade features for teams big and small',
|
||||
defaultMessage: 'Upgrade to get enterprise-level features for your team',
|
||||
}
|
||||
);
|
||||
|
|
|
@ -2,6 +2,4 @@
|
|||
@include euiBreakpoint('xs','s') {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
border-bottom: $euiBorderThin;
|
||||
}
|
||||
|
|
|
@ -19,29 +19,39 @@ import {
|
|||
EuiTitle,
|
||||
EuiText,
|
||||
EuiSpacer,
|
||||
useEuiTheme,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { ENTERPRISE_SEARCH_CONTENT_PLUGIN } from '../../../../common/constants';
|
||||
import welcomeGraphicDark from '../../../assets/images/welcome_dark.svg';
|
||||
import welcomeGraphicLight from '../../../assets/images/welcome_light.svg';
|
||||
import { NEW_INDEX_PATH } from '../../enterprise_search_content/routes';
|
||||
import { EuiLinkTo } from '../react_router_helpers';
|
||||
|
||||
import searchIndicesIllustration from './search_indices.svg';
|
||||
import './add_content_empty_prompt.scss';
|
||||
|
||||
export const AddContentEmptyPrompt: React.FC = () => {
|
||||
interface EmptyPromptProps {
|
||||
title?: string;
|
||||
buttonLabel?: string;
|
||||
}
|
||||
|
||||
export const AddContentEmptyPrompt: React.FC<EmptyPromptProps> = ({ title, buttonLabel }) => {
|
||||
const { colorMode } = useEuiTheme();
|
||||
|
||||
return (
|
||||
<EuiPanel color="transparent" paddingSize="l">
|
||||
<EuiPanel color="transparent" paddingSize="none">
|
||||
<EuiFlexGroup className="addContentEmptyPrompt" justifyContent="spaceBetween" direction="row">
|
||||
<EuiFlexItem grow>
|
||||
<EuiFlexGroup direction="column" responsive={false}>
|
||||
<EuiFlexItem grow>
|
||||
<EuiTitle>
|
||||
<h2>
|
||||
{i18n.translate('xpack.enterpriseSearch.overview.emptyState.heading', {
|
||||
defaultMessage: 'Add content to Enterprise Search',
|
||||
})}
|
||||
{title ||
|
||||
i18n.translate('xpack.enterpriseSearch.overview.emptyState.heading', {
|
||||
defaultMessage: 'Add content to Enterprise Search',
|
||||
})}
|
||||
</h2>
|
||||
</EuiTitle>
|
||||
<EuiSpacer size="l" />
|
||||
|
@ -49,7 +59,13 @@ export const AddContentEmptyPrompt: React.FC = () => {
|
|||
<p>
|
||||
{i18n.translate('xpack.enterpriseSearch.emptyState.description', {
|
||||
defaultMessage:
|
||||
"Data you add in Enterprise Search is called a Search index and it's searchable in both App and Workplace Search. Now you can use your connectors in App Search and your web crawlers in Workplace Search.",
|
||||
'You can now easily create and add content to Elasticsearch indices with Enterprise Search - including website content with the Elastic Web Crawler or third-party data sources with Custom Connectors.',
|
||||
})}
|
||||
</p>
|
||||
<p>
|
||||
{i18n.translate('xpack.enterpriseSearch.emptyState.description.line2', {
|
||||
defaultMessage:
|
||||
"Whether you're building a search experience with App Search or Elasticsearch, you can now get started here.",
|
||||
})}
|
||||
</p>
|
||||
</EuiText>
|
||||
|
@ -62,9 +78,10 @@ export const AddContentEmptyPrompt: React.FC = () => {
|
|||
shouldNotCreateHref
|
||||
>
|
||||
<EuiButton color="primary" fill>
|
||||
{i18n.translate('xpack.enterpriseSearch.overview.emptyState.buttonTitle', {
|
||||
defaultMessage: 'Add content to Enterprise Search',
|
||||
})}
|
||||
{buttonLabel ||
|
||||
i18n.translate('xpack.enterpriseSearch.overview.emptyState.buttonTitle', {
|
||||
defaultMessage: 'Add content to Enterprise Search',
|
||||
})}
|
||||
</EuiButton>
|
||||
</EuiLinkTo>
|
||||
</EuiFlexItem>
|
||||
|
@ -82,9 +99,9 @@ export const AddContentEmptyPrompt: React.FC = () => {
|
|||
</EuiFlexItem>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiImage
|
||||
size="l"
|
||||
size="xl"
|
||||
float="right"
|
||||
src={searchIndicesIllustration}
|
||||
src={colorMode === 'LIGHT' ? welcomeGraphicLight : welcomeGraphicDark}
|
||||
alt={i18n.translate('xpack.enterpriseSearch.overview.searchIndices.image.altText', {
|
||||
defaultMessage: 'Search indices illustration',
|
||||
})}
|
||||
|
|
|
@ -7,13 +7,13 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
import { EuiSpacer, EuiPanel, EuiTitle, EuiLink } from '@elastic/eui';
|
||||
import { EuiSpacer, EuiTitle, EuiLink } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { docLinks } from '../doc_links';
|
||||
|
||||
export const ElasticsearchResources: React.FC = () => (
|
||||
<EuiPanel hasShadow grow={false} color="subdued">
|
||||
<>
|
||||
<EuiTitle size="xs">
|
||||
<h4>
|
||||
{i18n.translate('xpack.enterpriseSearch.overview.elasticsearchResources.title', {
|
||||
|
@ -53,5 +53,5 @@ export const ElasticsearchResources: React.FC = () => (
|
|||
defaultMessage: 'Search UI for Elasticsearch',
|
||||
})}
|
||||
</EuiLink>
|
||||
</EuiPanel>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -44,15 +44,15 @@ describe('GettingStartedSteps', () => {
|
|||
...rest,
|
||||
}));
|
||||
|
||||
expect(steps[0].title).toEqual('Add your documents and data to Enterprise Search');
|
||||
expect(steps[0].title).toEqual('Select or create an Elasticsearch index');
|
||||
expect(steps[0].status).toEqual('current');
|
||||
expect(steps[0].children.find(IconRow).length).toEqual(1);
|
||||
|
||||
expect(steps[1].title).toEqual('Build a search experience');
|
||||
expect(steps[1].title).toEqual('Assign your index to an App Search engine');
|
||||
expect(steps[1].status).toEqual('incomplete');
|
||||
expect(steps[1].children.find(EuiLinkTo).prop('to')).toEqual(ELASTICSEARCH_PLUGIN.URL);
|
||||
|
||||
expect(steps[2].title).toEqual('Tune your search relevance');
|
||||
expect(steps[2].title).toEqual('Build a client-side search experience with Search UI');
|
||||
expect(steps[2].status).toEqual('incomplete');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -29,17 +29,17 @@ export const GettingStartedSteps: React.FC<GettingStartedStepsProps> = ({ step =
|
|||
{
|
||||
title: i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.gettingStartedSteps.addData.title',
|
||||
{ defaultMessage: 'Add your documents and data to Enterprise Search' }
|
||||
{ defaultMessage: 'Select or create an Elasticsearch index' }
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
<EuiText>
|
||||
<EuiText color="subdued">
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.gettingStartedSteps.addData.message',
|
||||
{
|
||||
defaultMessage:
|
||||
'Get started by adding your data to Enterprise Search. You can use the Elastic Web Crawler, API endpoints, existing Elasticsearch indices or third party connectors like Google Drive, Microsoft Sharepoint and more.',
|
||||
'Get started by adding your data to Enterprise Search. You can use the Elastic Web Crawler, API endpoints, existing Elasticsearch indices , or third-party connectors like Google Drive, Microsoft Sharepoint and more.',
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
|
@ -53,17 +53,17 @@ export const GettingStartedSteps: React.FC<GettingStartedStepsProps> = ({ step =
|
|||
{
|
||||
title: i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.gettingStartedSteps.buildSearchExperience.title',
|
||||
{ defaultMessage: 'Build a search experience' }
|
||||
{ defaultMessage: 'Assign your index to an App Search engine' }
|
||||
),
|
||||
children: (
|
||||
<>
|
||||
<EuiText>
|
||||
<EuiText color="subdued">
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.gettingStartedSteps.buildSearchExperience.message',
|
||||
{
|
||||
defaultMessage:
|
||||
'You can use Search Engines to build customized search experiences for your customers or internal teams with App Search or Workplace Search. Or you can use Search UI to connect directly to an Elasticsearch index to build client-side search experinces for your users.',
|
||||
'You can use search engines to build customizable search experiences for your customers with App Search.',
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
|
@ -88,16 +88,16 @@ export const GettingStartedSteps: React.FC<GettingStartedStepsProps> = ({ step =
|
|||
{
|
||||
title: i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.title',
|
||||
{ defaultMessage: 'Tune your search relevance' }
|
||||
{ defaultMessage: 'Build a client-side search experience with Search UI' }
|
||||
),
|
||||
children: (
|
||||
<EuiText>
|
||||
<EuiText color="subdued">
|
||||
<p>
|
||||
{i18n.translate(
|
||||
'xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.message',
|
||||
{
|
||||
defaultMessage:
|
||||
"Dive into analytics and tune the result settings to help your users find exactly what they're looking for",
|
||||
'Take full control over your client-side search experience by building with the Search UI library. Connect directly to App Search or Elasticsearch.',
|
||||
}
|
||||
)}
|
||||
</p>
|
||||
|
|
|
@ -21,7 +21,12 @@ export const ManageLicenseButton: React.FC<EuiButtonProps> = (props) => {
|
|||
const { canManageLicense } = useValues(LicensingLogic);
|
||||
|
||||
return canManageLicense ? (
|
||||
<EuiButtonTo {...props} to="/app/management/stack/license_management" shouldNotCreateHref>
|
||||
<EuiButtonTo
|
||||
color="success"
|
||||
{...props}
|
||||
to="/app/management/stack/license_management"
|
||||
shouldNotCreateHref
|
||||
>
|
||||
{i18n.translate('xpack.enterpriseSearch.licenseManagementLink', {
|
||||
defaultMessage: 'Manage your license',
|
||||
})}
|
||||
|
|
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 116 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 122 KiB |
|
@ -11856,7 +11856,6 @@
|
|||
"xpack.enterpriseSearch.overview.gettingStartedSteps.searchWithElasticsearchLink": "Rechercher avec l'API Elasticsearch",
|
||||
"xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.message": "Plonger dans les analyses et ajuster les paramètres de recherche pour aider vos utilisateurs à trouver exactement ce qu'ils cherchent",
|
||||
"xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.title": "Ajuster votre pertinence de recherche",
|
||||
"xpack.enterpriseSearch.overview.heading": "Bienvenue dans Elastic Enterprise Search",
|
||||
"xpack.enterpriseSearch.overview.iconRow.api.title": "API",
|
||||
"xpack.enterpriseSearch.overview.iconRow.api.tooltip": "Publier des documents sur un point de terminaison d'API à partir de vos propres applications",
|
||||
"xpack.enterpriseSearch.overview.iconRow.confluence.title": "Confluence",
|
||||
|
@ -11877,14 +11876,9 @@
|
|||
"xpack.enterpriseSearch.overview.insufficientPermissionsFooterLinkLabel": "Lire la documentation",
|
||||
"xpack.enterpriseSearch.overview.insufficientPermissionsTitle": "Permissions insuffisantes",
|
||||
"xpack.enterpriseSearch.overview.navTitle": "Aperçu",
|
||||
"xpack.enterpriseSearch.overview.productCard.heading": "Elastic {productName}",
|
||||
"xpack.enterpriseSearch.overview.productCard.launchButton": "Ouvrir {productName}",
|
||||
"xpack.enterpriseSearch.overview.productCard.setupButton": "Configurer {productName}",
|
||||
"xpack.enterpriseSearch.overview.productName": "Enterprise Search",
|
||||
"xpack.enterpriseSearch.overview.productName": "Enterprise Search",
|
||||
"xpack.enterpriseSearch.overview.searchIndices.image.altText": "Illustration d'index de recherche",
|
||||
"xpack.enterpriseSearch.overview.setupCta.description": "Ajoutez des fonctions de recherche à votre application ou à votre organisation interne avec Elastic App Search et Workplace Search. Regardez la vidéo pour savoir ce qu'il est possible de faire lorsque la recherche est facilitée.",
|
||||
"xpack.enterpriseSearch.overview.setupHeading": "Choisissez un produit à configurer et lancez-vous.",
|
||||
"xpack.enterpriseSearch.overview.subheading": "Ajoutez une fonction de recherche à votre application ou à votre organisation.",
|
||||
"xpack.enterpriseSearch.overview.setupCta.description": "Ajoutez des fonctions de recherche à votre application ou à votre organisation interne avec Elastic App Search et Workplace Search. Regardez la vidéo pour savoir ce qu'il est possible de faire lorsque la recherche est facilitée.",
|
||||
"xpack.enterpriseSearch.productSelectorCalloutTitle": "Des fonctionnalités de niveau entreprise pour les grandes et petites équipes",
|
||||
"xpack.enterpriseSearch.readOnlyMode.warning": "Enterprise Search est en mode de lecture seule. Vous ne pourrez pas effectuer de changements tels que création, modification ou suppression.",
|
||||
"xpack.enterpriseSearch.roleMapping.addRoleMappingButtonLabel": "Ajouter un mapping",
|
||||
|
|
|
@ -11848,7 +11848,6 @@
|
|||
"xpack.enterpriseSearch.overview.gettingStartedSteps.searchWithElasticsearchLink": "Elasticsearch APIで検索",
|
||||
"xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.message": "分析を行い、結果設定を調整して、ユーザーが検索している内容を正確に見つけられるようにします。",
|
||||
"xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.title": "検索関連性の調整",
|
||||
"xpack.enterpriseSearch.overview.heading": "Elasticエンタープライズサーチへようこそ",
|
||||
"xpack.enterpriseSearch.overview.iconRow.api.title": "API",
|
||||
"xpack.enterpriseSearch.overview.iconRow.api.tooltip": "独自のアプリケーションからAPIエンドポイントにドキュメントをPOST",
|
||||
"xpack.enterpriseSearch.overview.iconRow.confluence.title": "Confluence",
|
||||
|
@ -11869,14 +11868,9 @@
|
|||
"xpack.enterpriseSearch.overview.insufficientPermissionsFooterLinkLabel": "ドキュメンテーションを表示",
|
||||
"xpack.enterpriseSearch.overview.insufficientPermissionsTitle": "パーミッションがありません",
|
||||
"xpack.enterpriseSearch.overview.navTitle": "概要",
|
||||
"xpack.enterpriseSearch.overview.productCard.heading": "Elastic {productName}",
|
||||
"xpack.enterpriseSearch.overview.productCard.launchButton": "{productName}を開く",
|
||||
"xpack.enterpriseSearch.overview.productCard.setupButton": "{productName}をセットアップ",
|
||||
"xpack.enterpriseSearch.overview.productName": "Enterprise Search",
|
||||
"xpack.enterpriseSearch.overview.searchIndices.image.altText": "検索インデックスの例",
|
||||
"xpack.enterpriseSearch.overview.setupCta.description": "Elastic App Search および Workplace Search を使用して、アプリまたは社内組織に検索を追加できます。検索が簡単になるとどのような利点があるのかについては、動画をご覧ください。",
|
||||
"xpack.enterpriseSearch.overview.setupHeading": "セットアップする製品を選択し、開始してください。",
|
||||
"xpack.enterpriseSearch.overview.subheading": "アプリまたは組織に検索機能を追加できます。",
|
||||
"xpack.enterpriseSearch.productSelectorCalloutTitle": "あらゆる規模のチームに対応するエンタープライズ級の機能",
|
||||
"xpack.enterpriseSearch.readOnlyMode.warning": "エンタープライズ サーチは読み取り専用モードです。作成、編集、削除などの変更を実行できません。",
|
||||
"xpack.enterpriseSearch.roleMapping.addRoleMappingButtonLabel": "マッピングを追加",
|
||||
|
|
|
@ -11864,7 +11864,6 @@
|
|||
"xpack.enterpriseSearch.overview.gettingStartedSteps.searchWithElasticsearchLink": "使用 Elasticsearch API 进行搜索",
|
||||
"xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.message": "深入进行分析并调整结果设置,以帮助用户准确找到他们寻找的内容",
|
||||
"xpack.enterpriseSearch.overview.gettingStartedSteps.tuneSearchExperience.title": "调整搜索相关性",
|
||||
"xpack.enterpriseSearch.overview.heading": "欢迎使用 Elastic 企业搜索",
|
||||
"xpack.enterpriseSearch.overview.iconRow.api.title": "API",
|
||||
"xpack.enterpriseSearch.overview.iconRow.api.tooltip": "从您自己的应用程序将文档 POST 到 API 终端",
|
||||
"xpack.enterpriseSearch.overview.iconRow.confluence.title": "Confluence",
|
||||
|
@ -11885,14 +11884,9 @@
|
|||
"xpack.enterpriseSearch.overview.insufficientPermissionsFooterLinkLabel": "阅读文档",
|
||||
"xpack.enterpriseSearch.overview.insufficientPermissionsTitle": "权限不足",
|
||||
"xpack.enterpriseSearch.overview.navTitle": "概览",
|
||||
"xpack.enterpriseSearch.overview.productCard.heading": "Elastic {productName}",
|
||||
"xpack.enterpriseSearch.overview.productCard.launchButton": "打开 {productName}",
|
||||
"xpack.enterpriseSearch.overview.productCard.setupButton": "设置 {productName}",
|
||||
"xpack.enterpriseSearch.overview.productName": "Enterprise Search",
|
||||
"xpack.enterpriseSearch.overview.searchIndices.image.altText": "搜索索引图示",
|
||||
"xpack.enterpriseSearch.overview.setupCta.description": "通过 Elastic App Search 和 Workplace Search,将搜索添加到您的应用或内部组织中。观看视频,了解方便易用的搜索功能可以帮您做些什么。",
|
||||
"xpack.enterpriseSearch.overview.setupHeading": "选择产品进行设置并开始使用。",
|
||||
"xpack.enterpriseSearch.overview.subheading": "将搜索功能添加到您的应用或组织。",
|
||||
"xpack.enterpriseSearch.productSelectorCalloutTitle": "适用于大型和小型团队的企业级功能",
|
||||
"xpack.enterpriseSearch.readOnlyMode.warning": "企业搜索处于只读模式。您将无法执行更改,例如创建、编辑或删除。",
|
||||
"xpack.enterpriseSearch.roleMapping.addRoleMappingButtonLabel": "添加映射",
|
||||
|
|
|
@ -33,11 +33,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
it('loads a landing page with product cards', async function () {
|
||||
await retry.waitFor(
|
||||
'AS product card visible',
|
||||
'Elasticsearch product card visible',
|
||||
async () => await testSubjects.exists('elasticsearchProductCard')
|
||||
);
|
||||
await retry.waitFor(
|
||||
'App Search product card visible',
|
||||
async () => await testSubjects.exists('appSearchProductCard')
|
||||
);
|
||||
await retry.waitFor(
|
||||
'WS product card visible',
|
||||
'Workplace Search product card visible',
|
||||
async () => await testSubjects.exists('workplaceSearchProductCard')
|
||||
);
|
||||
await a11y.testAppSnapshot();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue