Skip to content

Commit

Permalink
[App Search] Convert Search UI view to new page template + minor UI p…
Browse files Browse the repository at this point in the history
…olish (#102813)

* Convert Search UI view to use new page template

+ update tests TODO

* [UX polish] Add empty state to Search UI view

- On a totally new engine, all pages except this one* had an empty state, so per Davey's recommendations I whipped up a new empty state for this page

* Overview has a custom 'empty' state, analytics does not have an empty state

* Update router

* Fix bad merge conflict resolution

* [Polish] Copy feedback proposed by Davey

- see cbc3706
  • Loading branch information
Constance committed Jun 22, 2021
1 parent 2323b98 commit 84d999d
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,11 @@ export const EngineRouter: React.FC = () => {
<Documents />
</Route>
)}
{canManageEngineSearchUi && (
<Route path={ENGINE_SEARCH_UI_PATH}>
<SearchUI />
</Route>
)}
{/* TODO: Remove layout once page template migration is over */}
<Layout navigation={<AppSearchNav />}>
{canViewEngineSchema && (
Expand Down Expand Up @@ -141,11 +146,6 @@ export const EngineRouter: React.FC = () => {
<ApiLogs />
</Route>
)}
{canManageEngineSearchUi && (
<Route path={ENGINE_SEARCH_UI_PATH}>
<SearchUI />
</Route>
)}
{canViewMetaEngineSourceEngines && (
<Route path={META_ENGINE_SOURCE_ENGINES_PATH}>
<SourceEngines />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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 { shallow } from 'enzyme';

import { EuiEmptyPrompt, EuiButton } from '@elastic/eui';

import { EmptyState } from './empty_state';

describe('EmptyState', () => {
it('renders', () => {
const wrapper = shallow(<EmptyState />)
.find(EuiEmptyPrompt)
.dive();

expect(wrapper.find('h2').text()).toEqual('Add documents to generate a Search UI');
expect(wrapper.find(EuiButton).prop('href')).toEqual(
expect.stringContaining('/reference-ui-guide.html')
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* 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 { EuiButton, EuiEmptyPrompt } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { DOCS_PREFIX } from '../../../routes';

export const EmptyState: React.FC = () => (
<EuiEmptyPrompt
iconType="search"
title={
<h2>
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.searchUI.empty.title', {
defaultMessage: 'Add documents to generate a Search UI',
})}
</h2>
}
body={
<p>
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.searchUI.empty.description', {
defaultMessage:
'A schema will be automatically created for you after you index some documents.',
})}
</p>
}
actions={
<EuiButton
size="s"
target="_blank"
iconType="popout"
href={`${DOCS_PREFIX}/reference-ui-guide.html`}
>
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.searchUI.empty.buttonLabel', {
defaultMessage: 'Read the Search UI guide',
})}
</EuiButton>
}
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
*/

import '../../../__mocks__/shallow_useeffect.mock';
import '../../__mocks__/engine_logic.mock';

import { setMockActions } from '../../../__mocks__/kea_logic';
import { setMockActions, setMockValues } from '../../../__mocks__/kea_logic';
import { mockEngineValues } from '../../__mocks__/engine_logic.mock';

import React from 'react';

import { shallow } from 'enzyme';

import { SearchUIForm } from './components/search_ui_form';
import { SearchUIGraphic } from './components/search_ui_graphic';

import { SearchUI } from './';

describe('SearchUI', () => {
Expand All @@ -24,11 +27,13 @@ describe('SearchUI', () => {
beforeEach(() => {
jest.clearAllMocks();
setMockActions(actions);
setMockValues(mockEngineValues);
});

it('renders', () => {
shallow(<SearchUI />);
// TODO: Check for form
const wrapper = shallow(<SearchUI />);
expect(wrapper.find(SearchUIForm).exists()).toBe(true);
expect(wrapper.find(SearchUIGraphic).exists()).toBe(true);
});

it('initializes data on mount', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,87 +7,79 @@

import React, { useEffect } from 'react';

import { useActions } from 'kea';
import { useActions, useValues } from 'kea';

import {
EuiPageHeader,
EuiPageContentBody,
EuiText,
EuiFlexItem,
EuiFlexGroup,
EuiSpacer,
EuiLink,
} from '@elastic/eui';
import { EuiText, EuiFlexItem, EuiFlexGroup, EuiSpacer, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';

import { DOCS_PREFIX } from '../../routes';
import { getEngineBreadcrumbs } from '../engine';
import { EngineLogic, getEngineBreadcrumbs } from '../engine';
import { AppSearchPageTemplate } from '../layout';

import { EmptyState } from './components/empty_state';
import { SearchUIForm } from './components/search_ui_form';
import { SearchUIGraphic } from './components/search_ui_graphic';
import { SEARCH_UI_TITLE } from './i18n';
import { SearchUILogic } from './search_ui_logic';

export const SearchUI: React.FC = () => {
const { loadFieldData } = useActions(SearchUILogic);
const { engine } = useValues(EngineLogic);

useEffect(() => {
loadFieldData();
}, []);

return (
<>
<SetPageChrome trail={getEngineBreadcrumbs([SEARCH_UI_TITLE])} />
<EuiPageHeader pageTitle={SEARCH_UI_TITLE} />
<FlashMessages />
<EuiPageContentBody>
<EuiFlexGroup alignItems="flexStart">
<EuiFlexItem>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.bodyDescription"
defaultMessage="Search UI is a free and open library for building search experiences with React. {link}."
values={{
link: (
<EuiLink target="_blank" href="https://github.com/elastic/search-ui">
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.repositoryLinkText"
defaultMessage="Learn more"
/>
</EuiLink>
),
}}
/>
</p>
<p>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.lowerBodyDescription"
defaultMessage="Use the fields below to generate a sample search experience built with Search UI. Use the sample to preview search results, or build upon it to create your own custom search experience. {link}."
values={{
link: (
<EuiLink target="_blank" href={`${DOCS_PREFIX}/reference-ui-guide.html`}>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.guideLinkText"
defaultMessage="Learn more"
/>
</EuiLink>
),
}}
/>
</p>
</EuiText>
<EuiSpacer />
<SearchUIForm />
</EuiFlexItem>
<EuiFlexItem>
<SearchUIGraphic />
</EuiFlexItem>
</EuiFlexGroup>
</EuiPageContentBody>
</>
<AppSearchPageTemplate
pageChrome={getEngineBreadcrumbs([SEARCH_UI_TITLE])}
pageHeader={{ pageTitle: SEARCH_UI_TITLE }}
isEmptyState={Object.keys(engine.schema || {}).length === 0}
emptyState={<EmptyState />}
>
<EuiFlexGroup alignItems="flexStart">
<EuiFlexItem>
<EuiText size="s" color="subdued">
<p>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.bodyDescription"
defaultMessage="Search UI is a free and open library for building search experiences with React. {link}."
values={{
link: (
<EuiLink target="_blank" href="https://github.com/elastic/search-ui">
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.repositoryLinkText"
defaultMessage="View the Github repo"
/>
</EuiLink>
),
}}
/>
</p>
<p>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.lowerBodyDescription"
defaultMessage="Use the fields below to generate a sample search experience built with Search UI. Use the sample to preview search results, or build upon it to create your own custom search experience. {link}."
values={{
link: (
<EuiLink target="_blank" href={`${DOCS_PREFIX}/reference-ui-guide.html`}>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.engine.searchUI.guideLinkText"
defaultMessage="Learn more about Search UI"
/>
</EuiLink>
),
}}
/>
</p>
</EuiText>
<EuiSpacer />
<SearchUIForm />
</EuiFlexItem>
<EuiFlexItem>
<SearchUIGraphic />
</EuiFlexItem>
</EuiFlexGroup>
</AppSearchPageTemplate>
);
};

0 comments on commit 84d999d

Please sign in to comment.