diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx index f7022a3d48304..822c95a0b9598 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/authentication_panel/authentication_panel.tsx @@ -9,10 +9,12 @@ import React from 'react'; import { useValues } from 'kea'; -import { EuiFlexGroup, EuiFlexItem, EuiText, EuiTitle } from '@elastic/eui'; +import { EuiTitle, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; + import { AuthenticationPanelDeleteConfirmationModal } from './auth_panel_delete_confirm_modal'; import { AuthenticationPanelActions } from './authentication_panel_actions'; import { AuthenticationPanelEditContent } from './authentication_panel_edit_content'; @@ -27,8 +29,17 @@ export const AuthenticationPanel: React.FC = () => { return ( <>
- - + ]} + description={ +

+ +

+ } + title={

{i18n.translate('xpack.enterpriseSearch.crawler.authenticationPanel.title', { @@ -36,19 +47,9 @@ export const AuthenticationPanel: React.FC = () => { })}

-
- - - -
- -

- -

-
+ } + /> + {isEditing ? : }
{isModalVisible && } diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx index 7eb4c04db4480..e2c3074f41750 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.test.tsx @@ -30,6 +30,7 @@ describe('CrawlRulesTable', () => { crawlRules, domainId: '6113e1407a2f2e6f42489794', indexName, + title: 'Crawl rules', }; beforeEach(() => { jest.clearAllMocks(); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx index db98f1fb987f7..5c96617e1fb2d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawl_rules_table.tsx @@ -18,6 +18,7 @@ import { EuiLink, EuiSelect, EuiText, + EuiSpacer, } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -39,6 +40,7 @@ export interface CrawlRulesTableProps { description?: React.ReactNode; domainId: string; indexName: string; + title?: React.ReactNode; } export const getReadableCrawlerRule = (rule: CrawlerRules) => { @@ -99,17 +101,14 @@ const DEFAULT_DESCRIPTION = (

- {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.descriptionLinkText', { - defaultMessage: 'Learn more about crawl rules', - })} - - ), - }} + defaultMessage="Create a crawl rule to include or exclude pages whose URL matches the rule. Rules run in sequential order, and each URL is evaluated according to the first match." /> + + + {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.descriptionLinkText', { + defaultMessage: 'Learn more about crawl rules', + })} +

); @@ -119,6 +118,7 @@ export const CrawlRulesTable: React.FC = ({ indexName, crawlRules, defaultCrawlRule, + title, }) => { const { updateCrawlRules } = useActions(CrawlerDomainDetailLogic); @@ -251,7 +251,7 @@ export const CrawlRulesTable: React.FC = ({ updateCrawlRules(newCrawlRules as CrawlRule[]); clearFlashMessages(); }} - title="" + title={title || ''} uneditableItems={defaultCrawlRule ? [defaultCrawlRule] : undefined} canRemoveLastItem /> diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx index 9ca36ba97f7b4..a00c353eaab0b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/crawler_domain_detail_tabs.tsx @@ -43,14 +43,20 @@ export const CrawlerDomainDetailTabs: React.FC = ( content: ( <> - -

- {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.title', { - defaultMessage: 'Entry points', - })} -

-
- + +

+ {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.title', { + defaultMessage: 'Entry points', + })} +

+ + } + /> ), id: CrawlerDomainTabId.ENTRY_POINTS, @@ -74,14 +80,20 @@ export const CrawlerDomainDetailTabs: React.FC = ( content: ( <> - -

- {i18n.translate('xpack.enterpriseSearch.crawler.sitemapsTable.title', { - defaultMessage: 'Sitemaps', - })} -

-
- + +

+ {i18n.translate('xpack.enterpriseSearch.crawler.sitemapsTable.title', { + defaultMessage: 'Sitemaps', + })} +

+ + } + /> ), id: CrawlerDomainTabId.SITE_MAPS, @@ -93,18 +105,20 @@ export const CrawlerDomainDetailTabs: React.FC = ( content: ( <> - -

- {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.title', { - defaultMessage: 'Crawl rules', - })} -

-
+

+ {i18n.translate('xpack.enterpriseSearch.crawler.crawlRulesTable.title', { + defaultMessage: 'Crawl rules', + })} +

+ + } /> ), diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx index 54c93ff744ede..a7ffe1bc81bd3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.test.tsx @@ -14,7 +14,6 @@ import { shallow } from 'enzyme'; import { act } from 'react-dom/test-utils'; import { - EuiButton, EuiButtonEmpty, EuiContextMenuItem, EuiPopover, @@ -26,6 +25,8 @@ import { import { mountWithIntl } from '@kbn/test-jest-helpers'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; + import { rerender } from '../../../../../../test_helpers'; import { DeduplicationPanel } from './deduplication_panel'; @@ -61,8 +62,11 @@ describe('DeduplicationPanel', () => { it('contains a button to reset to defaults', () => { const wrapper = shallow(); + const dedupeButton = shallow( +
{wrapper.find(PageIntroduction).prop('actions')}
+ ).children(); - wrapper.find('EuiFlexGroup').first().dive().find(EuiButton).simulate('click'); + dedupeButton.simulate('click'); expect(MOCK_ACTIONS.submitDeduplicationUpdate).toHaveBeenCalledWith({ fields: [], diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx index e17815765169e..c4bedce7a43c4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/deduplication_panel/deduplication_panel.tsx @@ -21,7 +21,6 @@ import { EuiSelectable, EuiSpacer, EuiSwitch, - EuiText, EuiTitle, } from '@elastic/eui'; @@ -31,6 +30,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import { docLinks } from '../../../../../../shared/doc_links'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; import { CrawlerDomainDetailLogic } from '../crawler_domain_detail_logic'; import { getCheckedOptionLabels, getSelectableOptions } from './utils'; @@ -55,8 +55,8 @@ export const DeduplicationPanel: React.FC = () => { return (
- - +

{i18n.translate('xpack.enterpriseSearch.crawler.deduplicationPanel.title', { @@ -64,8 +64,8 @@ export const DeduplicationPanel: React.FC = () => { })}

-
- + } + actions={ { } )} - -
- - -

- - {i18n.translate( - 'xpack.enterpriseSearch.crawler.deduplicationPanel.learnMoreMessage', - { - defaultMessage: 'Learn more about content hashing', - } - )} - - ), - }} - /> -

-
+ documents on this domain." + /> +

+ } + links={ + + {i18n.translate('xpack.enterpriseSearch.crawler.deduplicationPanel.learnMoreMessage', { + defaultMessage: 'Learn more about content hashing', + })} + + } + /> = ({ domain, indexName, items }) => { +export const EntryPointsTable: React.FC = ({ + domain, + indexName, + items, + title, +}) => { const { onAdd, onDelete, onUpdate } = useActions(EntryPointsTableLogic); const field = 'value'; @@ -76,7 +82,8 @@ export const EntryPointsTable: React.FC = ({ domain, inde {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.description', { defaultMessage: 'Include the most important URLs for your website here. Entry point URLs will be the first pages to be indexed and processed for links to other pages.', - })}{' '} + })} + {i18n.translate('xpack.enterpriseSearch.crawler.entryPointsTable.learnMoreLinkText', { defaultMessage: 'Learn more about entry points.', @@ -130,7 +137,7 @@ export const EntryPointsTable: React.FC = ({ domain, inde onAdd={onAdd} onDelete={onDelete} onUpdate={onUpdate} - title="" + title={title} disableReordering /> ); diff --git a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx index b8fdab12acbc6..0887db23c7789 100644 --- a/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/enterprise_search_content/components/search_index/crawler/crawler_domain_detail/extraction_rules/extraction_rules.tsx @@ -13,9 +13,8 @@ import { EuiButton, EuiConfirmModal, EuiEmptyPrompt, - EuiFlexGroup, - EuiFlexItem, EuiLink, + EuiFlexGroup, EuiSpacer, EuiText, EuiTitle, @@ -26,6 +25,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import { CANCEL_BUTTON_LABEL } from '../../../../../../shared/constants'; import { docLinks } from '../../../../../../shared/doc_links'; +import { PageIntroduction } from '../../../../../../shared/page_introduction/page_introduction'; import { EditExtractionRule } from './edit_extraction_rule'; import { ExtractionRulesLogic } from './extraction_rules_logic'; @@ -81,56 +81,56 @@ export const ExtractionRules: React.FC = () => { )} - - -

- {i18n.translate('xpack.enterpriseSearch.content.crawler.extractionRules.title', { - defaultMessage: 'Extraction rules', - })} -

-
-
- {extractionRules.length === 0 ? ( - <> - ) : ( - - + +

+ {i18n.translate('xpack.enterpriseSearch.content.crawler.extractionRules.title', { + defaultMessage: 'Extraction rules', + })} +

+ + } + description={ +

+ +

+ } + links={ + {i18n.translate( - 'xpack.enterpriseSearch.content.crawler.extractionRulesTable.addRuleLabel', + 'xpack.enterpriseSearch.content.crawler.extractionRules.learnMoreLink', { - defaultMessage: 'Add extraction rule', + defaultMessage: 'Learn more about content extraction rules.', } )} -
-
- )} +
+ } + actions={ + extractionRules.length === 0 + ? [] + : [ + + {i18n.translate( + 'xpack.enterpriseSearch.content.crawler.extractionRulesTable.addRuleLabel', + { + defaultMessage: 'Add extraction rule', + } + )} + , + ] + } + /> - - -

- - {i18n.translate( - 'xpack.enterpriseSearch.content.crawler.extractionRules.learnMoreLink', - { - defaultMessage: 'Learn more about content extraction rules.', - } - )} - - ), - }} - /> -

-
- + {editingExtractionRule ? ( = ({ domain, indexName, items }) => { +export const SitemapsTable: React.FC = ({ + domain, + indexName, + items, + title, +}) => { const { updateSitemaps } = useActions(CrawlerDomainDetailLogic); const field = 'url'; @@ -113,7 +119,7 @@ export const SitemapsTable: React.FC = ({ domain, indexName, updateSitemaps(newSitemaps as Sitemap[]); clearFlashMessages(); }} - title="" + title={title || ''} disableReordering /> ); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx new file mode 100644 index 0000000000000..4077dac076839 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.test.tsx @@ -0,0 +1,129 @@ +/* + * 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 { mount } from 'enzyme'; + +import { EuiLink } from '@elastic/eui'; + +import { PageIntroduction } from './page_introduction'; + +describe('PageIntroduction component', () => { + it('renders with title as a string', () => { + const wrapper = mount(); + // .hostNodes is required due to Emotion injection causing problems with enzyme + const titleContainer = wrapper + .find('[data-test-subj="pageIntroductionTitleContainer"]') + .hostNodes(); + expect(titleContainer).toHaveLength(1); + + expect(titleContainer.text()).toEqual('string title'); + }); + + it('renders title as React node', () => { + const wrapper = mount( + react node title} + description="some description" + /> + ); + // .hostNodes is required due to Emotion injection causing problems with enzyme + const titleContainer = wrapper.find('[data-test-subj="injected"]').hostNodes(); + expect(titleContainer).toHaveLength(1); + + expect(titleContainer.text()).toEqual('react node title'); + }); + + it('renders with description only', () => { + const wrapper = mount(); + // .hostNodes is required due to Emotion injection causing problems with enzyme + const titleContainer = wrapper + .find('[data-test-subj="pageIntroductionTitleContainer"]') + .hostNodes(); + + const descriptionContainer = wrapper + .find('[data-test-subj="pageIntroductionDescriptionText"]') + .hostNodes(); + expect(titleContainer).toHaveLength(1); + expect(descriptionContainer).toHaveLength(1); + + expect(titleContainer.text()).toEqual(''); + expect(descriptionContainer.text()).toEqual('some description'); + }); + + it('renders with single link', () => { + const wrapper = mount( + + test link to nowhere + + } + /> + ); + const links = wrapper.find(EuiLink); + expect(links).toHaveLength(1); + expect(links.prop('href')).toEqual('testlink'); + // due to accesibility injections text includes screen reader text as well + expect(links.text().startsWith('test link to nowhere')).toBe(true); + }); + + it('renders with multiple links', () => { + const wrapper = mount( + + test link to nowhere + , + + test link to nowhere2 + , + ]} + /> + ); + const links = wrapper.find(EuiLink); + expect(links).toHaveLength(2); + expect(links.at(0).prop('href')).toEqual('testlink'); + // due to accesibility injections text includes screen reader text as well + expect(links.at(0).text().startsWith('test link to nowhere')).toBe(true); + expect(links.at(1).prop('href')).toEqual('testlink2'); + // due to accesibility injections text includes screen reader text as well + expect(links.at(1).text().startsWith('test link to nowhere2')).toBe(true); + }); + + it('renders with single actions', () => { + const wrapper = mount( + some action} + /> + ); + const actions = wrapper.find('button'); + expect(actions).toHaveLength(1); + expect(actions.text()).toEqual('some action'); + }); + + it('renders with multiple action', () => { + const wrapper = mount( + some action, ]} + /> + ); + const actions = wrapper.find('button'); + expect(actions).toHaveLength(2); + expect(actions.at(0).text()).toEqual('some action'); + expect(actions.at(1).text()).toEqual('another action'); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx new file mode 100644 index 0000000000000..1f2e5951bb94f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/shared/page_introduction/page_introduction.tsx @@ -0,0 +1,69 @@ +/* + * 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 { EuiText, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiTitle } from '@elastic/eui'; + +export interface PageIntroductionProps { + actions?: React.ReactNode | React.ReactNode[]; + description: React.ReactNode | string; + links?: React.ReactNode | React.ReactNode[]; + title?: string | React.ReactNode; +} + +export const PageIntroduction: React.FC = ({ + actions, + description, + links, + title = '', +}) => { + return ( + + + + + {typeof title === 'string' ? ( + +

{title}

+
+ ) : ( + title + )} +
+ + + + {description} + + + {!!links && ( + <> + + + + {Array.isArray(links) ? links.map((link) => link) : links} + + + + )} +
+
+ + + {Array.isArray(actions) + ? actions?.map((action, index) => ( + + {action} + + )) + : actions} + + +
+ ); +}; diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx index 9725abcd6eba7..3d2a243664edf 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.test.tsx @@ -12,6 +12,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { BindLogic } from 'kea'; +import { PageIntroduction } from '../../page_introduction/page_introduction'; import { ReorderableTable } from '../reorderable_table'; jest.mock('./get_updated_columns', () => ({ @@ -86,18 +87,19 @@ describe('InlineEditableTable', () => { it('renders a ReorderableTable', () => { const wrapper = shallow(); const reorderableTable = wrapper.find(ReorderableTable); + const addButton = shallow( +
{wrapper.find(PageIntroduction).prop('actions')}
+ ).children(); expect(reorderableTable.exists()).toBe(true); expect(reorderableTable.prop('items')).toEqual(items); - expect( - wrapper.find('[data-test-subj="inlineEditableTableActionButton"]').children().text() - ).toEqual('New row'); + expect(addButton.children().text()).toEqual('New row'); }); it('renders a title if one is provided', () => { const wrapper = shallow( Some Description

} /> ); - expect(wrapper.find('[data-test-subj="inlineEditableTableTitle"]').exists()).toBe(true); + expect(wrapper.find(PageIntroduction).prop('title')).toEqual(requiredParams.title); }); it('does not render a title if none is provided', () => { @@ -114,7 +116,7 @@ describe('InlineEditableTable', () => { const wrapper = shallow( Some Description

} /> ); - expect(wrapper.find('[data-test-subj="inlineEditableTableDescription"]').exists()).toBe(true); + expect(wrapper.find(PageIntroduction).prop('description')).toEqual(

Some Description

); }); it('renders no description if none is provided', () => { @@ -141,9 +143,10 @@ describe('InlineEditableTable', () => { const wrapper = shallow( ); - expect( - wrapper.find('[data-test-subj="inlineEditableTableActionButton"]').children().text() - ).toEqual('Add a new row custom text'); + const addButton = shallow( +
{wrapper.find(PageIntroduction).prop('actions')}
+ ).children(); + expect(addButton.children().text()).toEqual('Add a new row custom text'); }); describe('when a user is editing an unsaved item', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx index 232ad491b1397..d14acc91ac581 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/shared/tables/inline_editable_table/inline_editable_table.tsx @@ -11,9 +11,11 @@ import classNames from 'classnames'; import { useActions, useValues, BindLogic } from 'kea'; -import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; +import { EuiButton, EuiSpacer } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; +import { PageIntroduction } from '../../page_introduction/page_introduction'; + import { ReorderableTable } from '../reorderable_table'; import { ItemWithAnID } from '../types'; @@ -29,7 +31,7 @@ export interface InlineEditableTableProps { items: Item[]; defaultItem?: Partial; emptyPropertyAllowed?: boolean; - title: string; + title: string | React.ReactNode; addButtonText?: string; canRemoveLastItem?: boolean; className?: string; @@ -129,28 +131,10 @@ export const InlineEditableTableContents = ({ return ( <> - - - {!!title && ( - -

{title}

-
- )} - {!!description && ( - <> - - - {description} - - - )} -
- + ({ i18n.translate('xpack.enterpriseSearch.inlineEditableTable.newRowButtonLabel', { defaultMessage: 'New row', })} - - -
- + , + ]} + /> +