[App Search] Refactor EuiPageHeader components to use new props instead of children (#95454)

* Update EuiPageHeaders with basic titles

* Update engine creation views

- meta engine - move to description
+ misc fix - non-heading EuiTitles that do not match the standalone UI

* Update EuiPageHeaders with simpler actions

* Update Documents page header

+ test reorg - move DocumentCreationButton tests to its own test block

* Update EnginesOverviewHeader (+ refactors)

- Switch from FormattedMessage to i18n to match rest of repo
- Switch to eslint-disbable instead of doing a buttonProps workaround (this will get deleted anyway post-migration)

* whoops
This commit is contained in:
Constance 2021-03-26 11:17:00 -07:00 committed by GitHub
parent 95e308a473
commit 6b59fe3d01
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 143 additions and 199 deletions

View file

@ -11,7 +11,6 @@ import { useActions, useValues } from 'kea';
import {
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
EuiPageContentBody,
EuiPanel,
@ -55,13 +54,7 @@ export const Credentials: React.FC = () => {
return (
<>
<SetPageChrome trail={[CREDENTIALS_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{CREDENTIALS_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageHeader pageTitle={CREDENTIALS_TITLE} />
<EuiPageContentBody>
{shouldShowCredentialsForm && <CredentialsFlyout />}
<EuiPanel className="eui-textCenter">

View file

@ -17,7 +17,7 @@ import React from 'react';
import { shallow, ReactWrapper } from 'enzyme';
import { EuiBasicTable, EuiEmptyPrompt } from '@elastic/eui';
import { EuiPageHeader, EuiBasicTable, EuiEmptyPrompt } from '@elastic/eui';
import { Loading } from '../../../../shared/loading';
@ -64,7 +64,7 @@ describe('Curations', () => {
it('renders', () => {
const wrapper = shallow(<Curations />);
expect(wrapper.find('h1').text()).toEqual('Curated results');
expect(wrapper.find(EuiPageHeader).prop('pageTitle')).toEqual('Curated results');
expect(wrapper.find(CurationsTable)).toHaveLength(1);
});

View file

@ -11,9 +11,7 @@ import { useValues, useActions } from 'kea';
import {
EuiPageHeader,
EuiPageHeaderSection,
EuiPageContent,
EuiTitle,
EuiBasicTable,
EuiBasicTableColumn,
EuiEmptyPrompt,
@ -47,18 +45,14 @@ export const Curations: React.FC = () => {
return (
<>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{CURATIONS_OVERVIEW_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
<EuiPageHeaderSection>
<EuiPageHeader
pageTitle={CURATIONS_OVERVIEW_TITLE}
rightSideItems={[
<EuiButtonTo to={generateEnginePath(ENGINE_CURATIONS_NEW_PATH)} fill>
{CREATE_NEW_CURATION_TITLE}
</EuiButtonTo>
</EuiPageHeaderSection>
</EuiPageHeader>
</EuiButtonTo>,
]}
/>
<EuiPageContent>
<FlashMessages />
<CurationsTable />

View file

@ -14,7 +14,7 @@ import { useParams } from 'react-router-dom';
import { shallow } from 'enzyme';
import { EuiPageContent, EuiBasicTable } from '@elastic/eui';
import { EuiPageHeader, EuiPageContent, EuiBasicTable } from '@elastic/eui';
import { Loading } from '../../../shared/loading';
import { ResultFieldValue } from '../result';
@ -102,7 +102,8 @@ describe('DocumentDetail', () => {
it('will delete the document when the delete button is pressed', () => {
const wrapper = shallow(<DocumentDetail engineBreadcrumb={['test']} />);
const button = wrapper.find('[data-test-subj="DeleteDocumentButton"]');
const header = wrapper.find(EuiPageHeader).dive().children().dive();
const button = header.find('[data-test-subj="DeleteDocumentButton"]');
button.simulate('click');

View file

@ -13,8 +13,6 @@ import { useActions, useValues } from 'kea';
import {
EuiButton,
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
EuiPageContentBody,
EuiPageContent,
EuiBasicTable,
@ -79,13 +77,9 @@ export const DocumentDetail: React.FC<Props> = ({ engineBreadcrumb }) => {
return (
<>
<SetPageChrome trail={[...engineBreadcrumb, DOCUMENTS_TITLE, documentTitle]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{DOCUMENT_DETAIL_TITLE(documentTitle)}</h1>
</EuiTitle>
</EuiPageHeaderSection>
<EuiPageHeaderSection>
<EuiPageHeader
pageTitle={DOCUMENT_DETAIL_TITLE(documentTitle)}
rightSideItems={[
<EuiButton
color="danger"
iconType="trash"
@ -95,9 +89,9 @@ export const DocumentDetail: React.FC<Props> = ({ engineBreadcrumb }) => {
{i18n.translate('xpack.enterpriseSearch.appSearch.documentDetail.deleteButton', {
defaultMessage: 'Delete',
})}
</EuiButton>
</EuiPageHeaderSection>
</EuiPageHeader>
</EuiButton>,
]}
/>
<EuiPageContent>
<EuiPageContentBody>
<FlashMessages />

View file

@ -9,7 +9,9 @@ import { setMockValues } from '../../../__mocks__/kea.mock';
import React from 'react';
import { shallow } from 'enzyme';
import { shallow, ShallowWrapper } from 'enzyme';
import { EuiPageHeader } from '@elastic/eui';
import { DocumentCreationButton } from './document_creation_button';
import { SearchExperience } from './search_experience';
@ -32,14 +34,40 @@ describe('Documents', () => {
expect(wrapper.find(SearchExperience).exists()).toBe(true);
});
it('renders a DocumentCreationButton if the user can manage engine documents', () => {
setMockValues({
...values,
myRole: { canManageEngineDocuments: true },
describe('DocumentCreationButton', () => {
const getHeader = (wrapper: ShallowWrapper) =>
wrapper.find(EuiPageHeader).dive().children().dive();
it('renders a DocumentCreationButton if the user can manage engine documents', () => {
setMockValues({
...values,
myRole: { canManageEngineDocuments: true },
});
const wrapper = shallow(<Documents engineBreadcrumb={['test']} />);
expect(getHeader(wrapper).find(DocumentCreationButton).exists()).toBe(true);
});
const wrapper = shallow(<Documents engineBreadcrumb={['test']} />);
expect(wrapper.find(DocumentCreationButton).exists()).toBe(true);
it('does not render a DocumentCreationButton if the user cannot manage engine documents', () => {
setMockValues({
...values,
myRole: { canManageEngineDocuments: false },
});
const wrapper = shallow(<Documents engineBreadcrumb={['test']} />);
expect(getHeader(wrapper).find(DocumentCreationButton).exists()).toBe(false);
});
it('does not render a DocumentCreationButton for meta engines even if the user can manage engine documents', () => {
setMockValues({
...values,
myRole: { canManageEngineDocuments: true },
isMetaEngine: true,
});
const wrapper = shallow(<Documents engineBreadcrumb={['test']} />);
expect(getHeader(wrapper).find(DocumentCreationButton).exists()).toBe(false);
});
});
describe('Meta Engines', () => {
@ -62,16 +90,5 @@ describe('Documents', () => {
const wrapper = shallow(<Documents engineBreadcrumb={['test']} />);
expect(wrapper.find('[data-test-subj="MetaEnginesCallout"]').exists()).toBe(false);
});
it('does not render a DocumentCreationButton even if the user can manage engine documents', () => {
setMockValues({
...values,
myRole: { canManageEngineDocuments: true },
isMetaEngine: true,
});
const wrapper = shallow(<Documents engineBreadcrumb={['test']} />);
expect(wrapper.find(DocumentCreationButton).exists()).toBe(false);
});
});
});

View file

@ -9,7 +9,7 @@ import React from 'react';
import { useValues } from 'kea';
import { EuiPageHeader, EuiPageHeaderSection, EuiTitle, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { EuiPageHeader, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FlashMessages } from '../../../shared/flash_messages';
@ -33,18 +33,14 @@ export const Documents: React.FC<Props> = ({ engineBreadcrumb }) => {
return (
<>
<SetPageChrome trail={[...engineBreadcrumb, DOCUMENTS_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{DOCUMENTS_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
{myRole.canManageEngineDocuments && !isMetaEngine && (
<EuiPageHeaderSection>
<DocumentCreationButton />
</EuiPageHeaderSection>
)}
</EuiPageHeader>
<EuiPageHeader
pageTitle={DOCUMENTS_TITLE}
rightSideItems={
myRole.canManageEngineDocuments && !isMetaEngine
? [<DocumentCreationButton />]
: undefined
}
/>
<FlashMessages />
{isMetaEngine && (
<>

View file

@ -18,9 +18,7 @@ import {
EuiSelect,
EuiPageBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiSpacer,
EuiText,
EuiTitle,
EuiButton,
EuiPanel,
@ -49,13 +47,7 @@ export const EngineCreation: React.FC = () => {
return (
<div data-test-subj="EngineCreation">
<SetPageChrome trail={[ENGINE_CREATION_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{ENGINE_CREATION_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageHeader pageTitle={ENGINE_CREATION_TITLE} />
<EuiPageBody>
<FlashMessages />
<EuiPanel>
@ -68,7 +60,7 @@ export const EngineCreation: React.FC = () => {
}}
>
<EuiTitle>
<EuiText>{ENGINE_CREATION_FORM_TITLE}</EuiText>
<h2>{ENGINE_CREATION_FORM_TITLE}</h2>
</EuiTitle>
<EuiSpacer />
<EuiFlexGroup>

View file

@ -9,7 +9,7 @@ import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { EuiButton } from '@elastic/eui';
import { EuiPageHeader, EuiButton } from '@elastic/eui';
import { docLinks } from '../../../shared/doc_links';
@ -25,11 +25,12 @@ describe('EmptyEngineOverview', () => {
});
it('renders', () => {
expect(wrapper.find('h1').text()).toEqual('Engine setup');
expect(wrapper.find(EuiPageHeader).prop('pageTitle')).toEqual('Engine setup');
});
it('renders a documentation link', () => {
expect(wrapper.find(EuiButton).prop('href')).toEqual(`${docLinks.appSearchBase}/index.html`);
const header = wrapper.find(EuiPageHeader).dive().children().dive();
expect(header.find(EuiButton).prop('href')).toEqual(`${docLinks.appSearchBase}/index.html`);
});
it('renders document creation components', () => {

View file

@ -7,13 +7,7 @@
import React from 'react';
import {
EuiPageHeader,
EuiPageHeaderSection,
EuiPageContentBody,
EuiTitle,
EuiButton,
} from '@elastic/eui';
import { EuiPageHeader, EuiPageContentBody, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FlashMessages } from '../../../shared/flash_messages';
@ -23,25 +17,20 @@ import { DocumentCreationButtons, DocumentCreationFlyout } from '../document_cre
export const EmptyEngineOverview: React.FC = () => {
return (
<>
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.overview.empty.heading', {
defaultMessage: 'Engine setup',
})}
</h1>
</EuiTitle>
</EuiPageHeaderSection>
<EuiPageHeaderSection>
<EuiPageHeader
pageTitle={i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.overview.empty.heading',
{ defaultMessage: 'Engine setup' }
)}
rightSideItems={[
<EuiButton href={`${DOCS_PREFIX}/index.html`} target="_blank">
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.overview.empty.headingAction',
{ defaultMessage: 'View documentation' }
)}
</EuiButton>
</EuiPageHeaderSection>
</EuiPageHeader>
</EuiButton>,
]}
/>
<FlashMessages />
<EuiPageContentBody>
<DocumentCreationButtons />

View file

@ -11,13 +11,15 @@ import React from 'react';
import { shallow } from 'enzyme';
import { EuiPageHeader } from '@elastic/eui';
import { UnavailablePrompt, TotalStats, TotalCharts, RecentApiLogs } from './components';
import { EngineOverviewMetrics } from './engine_overview_metrics';
describe('EngineOverviewMetrics', () => {
it('renders', () => {
const wrapper = shallow(<EngineOverviewMetrics />);
expect(wrapper.find('h1').text()).toEqual('Engine overview');
expect(wrapper.find(EuiPageHeader).prop('pageTitle')).toEqual('Engine overview');
});
it('renders an unavailable prompt if engine data is still indexing', () => {

View file

@ -9,7 +9,7 @@ import React from 'react';
import { useValues } from 'kea';
import { EuiFlexGroup, EuiFlexItem, EuiPageHeader, EuiTitle, EuiSpacer } from '@elastic/eui';
import { EuiFlexGroup, EuiFlexItem, EuiPageHeader, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FlashMessages } from '../../../shared/flash_messages';
@ -23,15 +23,11 @@ export const EngineOverviewMetrics: React.FC = () => {
return (
<>
<EuiPageHeader>
<EuiTitle size="l">
<h1>
{i18n.translate('xpack.enterpriseSearch.appSearch.engine.overview.heading', {
defaultMessage: 'Engine overview',
})}
</h1>
</EuiTitle>
</EuiPageHeader>
<EuiPageHeader
pageTitle={i18n.translate('xpack.enterpriseSearch.appSearch.engine.overview.heading', {
defaultMessage: 'Engine overview',
})}
/>
<FlashMessages />
{apiLogsUnavailable ? (
<UnavailablePrompt />

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import '../../../../__mocks__/kea.mock';
import '../../../../__mocks__/enterprise_search_url.mock';
import { mockTelemetryActions } from '../../../../__mocks__';
@ -16,13 +15,16 @@ import { shallow } from 'enzyme';
import { EnginesOverviewHeader } from './';
describe('EnginesOverviewHeader', () => {
const wrapper = shallow(<EnginesOverviewHeader />)
.dive()
.children()
.dive();
it('renders', () => {
const wrapper = shallow(<EnginesOverviewHeader />);
expect(wrapper.find('h1')).toHaveLength(1);
expect(wrapper.find('h1').text()).toEqual('Engines overview');
});
it('renders a launch app search button that sends telemetry on click', () => {
const wrapper = shallow(<EnginesOverviewHeader />);
const button = wrapper.find('[data-test-subj="launchButton"]');
expect(button.prop('href')).toBe('http://localhost:3002/as');

View file

@ -9,15 +9,8 @@ import React from 'react';
import { useActions } from 'kea';
import {
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
EuiButton,
EuiButtonProps,
EuiLinkProps,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { EuiPageHeader, EuiButton } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { getAppSearchUrl } from '../../../../shared/enterprise_search_url';
import { TelemetryLogic } from '../../../../shared/telemetry';
@ -25,39 +18,31 @@ import { TelemetryLogic } from '../../../../shared/telemetry';
export const EnginesOverviewHeader: React.FC = () => {
const { sendAppSearchTelemetry } = useActions(TelemetryLogic);
const buttonProps = {
fill: true,
iconType: 'popout',
'data-test-subj': 'launchButton',
href: getAppSearchUrl(),
target: '_blank',
onClick: () =>
sendAppSearchTelemetry({
action: 'clicked',
metric: 'header_launch_button',
}),
} as EuiButtonProps & EuiLinkProps;
return (
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.enginesOverview.title"
defaultMessage="Engines Overview"
/>
</h1>
</EuiTitle>
</EuiPageHeaderSection>
<EuiPageHeaderSection>
<EuiButton {...buttonProps}>
<FormattedMessage
id="xpack.enterpriseSearch.appSearch.productCta"
defaultMessage="Launch App Search"
/>
</EuiButton>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageHeader
pageTitle={i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.title', {
defaultMessage: 'Engines overview',
})}
rightSideItems={[
// eslint-disable-next-line @elastic/eui/href-or-on-click
<EuiButton
fill
iconType="popout"
href={getAppSearchUrl()}
target="_blank"
onClick={() =>
sendAppSearchTelemetry({
action: 'clicked',
metric: 'header_launch_button',
})
}
data-test-subj="launchButton"
>
{i18n.translate('xpack.enterpriseSearch.appSearch.productCta', {
defaultMessage: 'Launch App Search',
})}
</EuiButton>,
]}
/>
);
};

View file

@ -10,7 +10,6 @@ import React, { useState } from 'react';
import {
EuiSpacer,
EuiPageHeader,
EuiPageHeaderSection,
EuiTitle,
EuiPageContentBody,
EuiPageContent,
@ -86,13 +85,7 @@ export const Library: React.FC = () => {
return (
<>
<SetPageChrome trail={['Library']} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>Library</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageHeader pageTitle="Library" />
<EuiPageContent>
<EuiPageContentBody>
<EuiTitle size="m">

View file

@ -20,9 +20,7 @@ import {
EuiFieldText,
EuiPageContent,
EuiPageHeader,
EuiPageHeaderSection,
EuiSpacer,
EuiText,
EuiTitle,
EuiButton,
} from '@elastic/eui';
@ -78,15 +76,16 @@ export const MetaEngineCreation: React.FC = () => {
return (
<div data-test-subj="MetaEngineCreation">
<SetPageChrome trail={[META_ENGINE_CREATION_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{META_ENGINE_CREATION_TITLE}</h1>
</EuiTitle>
<EuiText>{META_ENGINE_CREATION_FORM_META_ENGINE_DESCRIPTION}</EuiText>
<EuiText>{META_ENGINE_CREATION_FORM_DOCUMENTATION_DESCRIPTION}</EuiText>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageHeader
pageTitle={META_ENGINE_CREATION_TITLE}
description={
<>
{META_ENGINE_CREATION_FORM_META_ENGINE_DESCRIPTION}
<br />
{META_ENGINE_CREATION_FORM_DOCUMENTATION_DESCRIPTION}
</>
}
/>
<FlashMessages />
<EuiPageContent>
<EuiForm
@ -98,7 +97,7 @@ export const MetaEngineCreation: React.FC = () => {
}}
>
<EuiTitle>
<EuiText>{META_ENGINE_CREATION_FORM_TITLE}</EuiText>
<h2>{META_ENGINE_CREATION_FORM_TITLE}</h2>
</EuiTitle>
<EuiSpacer />
<EuiFlexGroup>
@ -140,14 +139,16 @@ export const MetaEngineCreation: React.FC = () => {
}}
/>
</EuiFormRow>
<EuiSpacer />
{selectedIndexedEngineNames.length > maxEnginesPerMetaEngine && (
<EuiCallOut
color="warning"
title={META_ENGINE_CREATION_FORM_MAX_SOURCE_ENGINES_WARNING_TITLE(
maxEnginesPerMetaEngine
)}
/>
<>
<EuiSpacer />
<EuiCallOut
color="warning"
title={META_ENGINE_CREATION_FORM_MAX_SOURCE_ENGINES_WARNING_TITLE(
maxEnginesPerMetaEngine
)}
/>
</>
)}
<EuiSpacer />
<EuiButton

View file

@ -7,13 +7,7 @@
import React from 'react';
import {
EuiPageHeader,
EuiPageHeaderSection,
EuiPageContent,
EuiPageContentBody,
EuiTitle,
} from '@elastic/eui';
import { EuiPageHeader, EuiPageContent, EuiPageContentBody } from '@elastic/eui';
import { FlashMessages } from '../../../shared/flash_messages';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
@ -26,13 +20,7 @@ export const Settings: React.FC = () => {
return (
<>
<SetPageChrome trail={[SETTINGS_TITLE]} />
<EuiPageHeader>
<EuiPageHeaderSection>
<EuiTitle size="l">
<h1>{SETTINGS_TITLE}</h1>
</EuiTitle>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiPageHeader pageTitle={SETTINGS_TITLE} />
<EuiPageContent>
<EuiPageContentBody>
<FlashMessages />