diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index cae64a24ec2cd..bafa023cf3f35 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -144,6 +144,8 @@ /x-pack/test/functional/apps/maps/ @elastic/kibana-gis /x-pack/test/functional/es_archives/maps/ @elastic/kibana-gis /x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis +/x-pack/plugins/stack_alerts/server/alert_types/geo_containment @elastic/kibana-gis +/x-pack/plugins/stack_alerts/public/alert_types/geo_containment @elastic/kibana-gis #CC# /src/plugins/maps_legacy/ @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis /src/plugins/tile_map/ @elastic/kibana-gis diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx index 737b87816ba46..53fa6312b9c49 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/analytics/components/analytics_tables/analytics_table.tsx @@ -68,7 +68,7 @@ export const AnalyticsTable: React.FC = ({ items, hasClicks, isSmall }) =

{i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.analytics.table.empty.noQueriesTitle', - { defaultMessage: 'No queries' } + { defaultMessage: 'No queries to display' } )}

} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.test.tsx index 768295ec1389c..780c198a9fac5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.test.tsx @@ -95,7 +95,7 @@ describe('ApiLogsTable', () => { const wrapper = mountWithIntl(); const promptContent = wrapper.find(EuiEmptyPrompt).text(); - expect(promptContent).toContain('No recent logs'); + expect(promptContent).toContain('Perform your first API call'); }); describe('hasPagination', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.tsx index 5ecf8e1ba3330..bb1327ce2da30 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/api_logs/components/api_logs_table.tsx @@ -115,7 +115,7 @@ export const ApiLogsTable: React.FC = ({ hasPagination }) => { title={

{i18n.translate('xpack.enterpriseSearch.appSearch.engine.apiLogs.emptyTitle', { - defaultMessage: 'No recent logs', + defaultMessage: 'Perform your first API call', })}

} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx index 386ea09d5da0b..619d9d07bf5f3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/credentials/credentials_list/credentials_list.tsx @@ -116,7 +116,7 @@ export const CredentialsList: React.FC = () => { title={

{i18n.translate('xpack.enterpriseSearch.appSearch.credentials.empty.title', { - defaultMessage: 'No API Keys have been created yet.', + defaultMessage: 'Create your first API key', })}

} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx new file mode 100644 index 0000000000000..60ae386bea58e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.test.tsx @@ -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 './'; + +describe('EmptyState', () => { + it('renders', () => { + const wrapper = shallow() + .find(EuiEmptyPrompt) + .dive(); + + expect(wrapper.find('h2').text()).toEqual('Create your first curation'); + expect(wrapper.find(EuiButton).prop('href')).toEqual( + expect.stringContaining('/curations-guide.html') + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx new file mode 100644 index 0000000000000..872a7282136e3 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/empty_state.tsx @@ -0,0 +1,48 @@ +/* + * 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 = () => ( + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.curations.empty.noCurationsTitle', + { defaultMessage: 'Create your first curation' } + )} + + } + body={ +

+ {i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.empty.description', { + defaultMessage: + 'Use curations to promote and hide documents. Help people discover what you would most like them to discover.', + })} +

+ } + actions={ + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.empty.buttonLabel', { + defaultMessage: 'Read the curations guide', + })} + + } + /> +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/index.ts similarity index 54% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.scss rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/index.ts index 026d7e4ffa72a..8c9e58e6ba0f4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.scss +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/components/index.ts @@ -5,16 +5,4 @@ * 2.0. */ -/** - * Empty/Error UI states - */ -.emptyState { - min-height: $euiSizeXXL * 11.25; - display: flex; - flex-direction: column; - justify-content: center; - - &__prompt > .euiIcon { - margin-bottom: $euiSizeS; - } -} +export { EmptyState } from './empty_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.test.tsx index e680579f7b0b7..1be21c97c623b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.test.tsx @@ -17,9 +17,10 @@ import React from 'react'; import { shallow, ReactWrapper } from 'enzyme'; -import { EuiPageHeader, EuiBasicTable, EuiEmptyPrompt } from '@elastic/eui'; +import { EuiPageHeader, EuiBasicTable } from '@elastic/eui'; import { Loading } from '../../../../shared/loading'; +import { EmptyState } from '../components'; import { Curations, CurationsTable } from './curations'; @@ -82,11 +83,12 @@ describe('Curations', () => { }); describe('CurationsTable', () => { - it('renders an EuiEmptyPrompt if curations is empty', () => { + it('renders an empty state', () => { setMockValues({ ...values, curations: [] }); - const wrapper = shallow(); + const table = shallow().find(EuiBasicTable); + const noItemsMessage = table.prop('noItemsMessage') as React.ReactElement; - expect(wrapper.find(EuiBasicTable).prop('noItemsMessage').type).toEqual(EuiEmptyPrompt); + expect(noItemsMessage.type).toEqual(EmptyState); }); it('passes loading prop based on dataLoading', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.tsx index 624790c847167..80de9aba77258 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curations.tsx @@ -9,13 +9,7 @@ import React, { useEffect } from 'react'; import { useValues, useActions } from 'kea'; -import { - EuiPageHeader, - EuiPageContent, - EuiBasicTable, - EuiBasicTableColumn, - EuiEmptyPrompt, -} from '@elastic/eui'; +import { EuiBasicTable, EuiBasicTableColumn, EuiPageContent, EuiPageHeader } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { EDIT_BUTTON_LABEL, DELETE_BUTTON_LABEL } from '../../../../shared/constants'; @@ -29,6 +23,7 @@ import { ENGINE_CURATIONS_NEW_PATH, ENGINE_CURATION_PATH } from '../../../routes import { FormattedDateTime } from '../../../utils/formatted_date_time'; import { generateEnginePath } from '../../engine'; +import { EmptyState } from '../components'; import { CURATIONS_OVERVIEW_TITLE, CREATE_NEW_CURATION_TITLE } from '../constants'; import { CurationsLogic } from '../curations_logic'; import { Curation } from '../types'; @@ -144,19 +139,7 @@ export const CurationsTable: React.FC = () => { responsive hasActions loading={dataLoading} - noItemsMessage={ - - {i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.curations.table.empty.noCurationsTitle', - { defaultMessage: 'No curations yet' } - )} - - } - /> - } + noItemsMessage={} pagination={{ ...convertMetaToPagination(meta), hidePerPageOptions: true, diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/document_creation_button.test.tsx similarity index 88% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/document_creation_button.test.tsx index 82fa9d3c82ce9..a6ccdc180b415 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/document_creation_button.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { setMockActions } from '../../../__mocks__/kea.mock'; +import { setMockActions } from '../../../../__mocks__/kea.mock'; import React from 'react'; @@ -13,7 +13,7 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { EuiButton } from '@elastic/eui'; -import { DocumentCreationFlyout } from '../document_creation'; +import { DocumentCreationFlyout } from '../../document_creation'; import { DocumentCreationButton } from './document_creation_button'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/document_creation_button.tsx similarity index 97% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/document_creation_button.tsx index 687f589d37594..cded18094c5f2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/document_creation_button.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/document_creation_button.tsx @@ -12,7 +12,7 @@ import { useActions } from 'kea'; import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { DocumentCreationLogic, DocumentCreationFlyout } from '../document_creation'; +import { DocumentCreationLogic, DocumentCreationFlyout } from '../../document_creation'; export const DocumentCreationButton: React.FC = () => { const { showCreationModes } = useActions(DocumentCreationLogic); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx new file mode 100644 index 0000000000000..907dcf8c9c208 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.test.tsx @@ -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 './'; + +describe('EmptyState', () => { + it('renders', () => { + const wrapper = shallow() + .find(EuiEmptyPrompt) + .dive(); + + expect(wrapper.find('h2').text()).toEqual('Add your first documents'); + expect(wrapper.find(EuiButton).prop('href')).toEqual( + expect.stringContaining('/indexing-documents-guide.html') + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx new file mode 100644 index 0000000000000..0f9455a3b9228 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/empty_state.tsx @@ -0,0 +1,49 @@ +/* + * 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, EuiPanel } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { DOCS_PREFIX } from '../../../routes'; + +export const EmptyState = () => ( + + + {i18n.translate('xpack.enterpriseSearch.appSearch.documents.empty.title', { + defaultMessage: 'Add your first documents', + })} + + } + body={ +

+ {i18n.translate('xpack.enterpriseSearch.appSearch.documents.empty.description', { + defaultMessage: + 'You can index documents using the App Search Web Crawler, by uploading JSON, or by using the API.', + })} +

+ } + actions={ + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.documents.empty.buttonLabel', { + defaultMessage: 'Read the documents guide', + })} + + } + /> +
+); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/index.ts new file mode 100644 index 0000000000000..af6425d7c610a --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/components/index.ts @@ -0,0 +1,9 @@ +/* + * 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. + */ + +export { DocumentCreationButton } from './document_creation_button'; +export { EmptyState } from './empty_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx index ba971a3405e91..88f5b6a1c49e6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.test.tsx @@ -14,7 +14,7 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { EuiPageHeader } from '@elastic/eui'; -import { DocumentCreationButton } from './document_creation_button'; +import { DocumentCreationButton } from './components'; import { SearchExperience } from './search_experience'; import { Documents } from '.'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx index 58aa6acc59783..b4122a715f927 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/documents.tsx @@ -18,8 +18,8 @@ import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chro import { AppLogic } from '../../app_logic'; import { EngineLogic, getEngineBreadcrumbs } from '../engine'; +import { DocumentCreationButton } from './components'; import { DOCUMENTS_TITLE } from './constants'; -import { DocumentCreationButton } from './document_creation_button'; import { SearchExperience } from './search_experience'; export const Documents: React.FC = () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx index bfa5c8264fece..e5f2978e5ba92 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.test.tsx @@ -20,9 +20,11 @@ jest.mock('../../../../shared/use_local_storage', () => ({ })); import { useLocalStorage } from '../../../../shared/use_local_storage'; +import { EmptyState } from '../components'; + import { CustomizationCallout } from './customization_callout'; import { CustomizationModal } from './customization_modal'; - +import { SearchExperienceContent } from './search_experience_content'; import { Fields } from './types'; import { SearchExperience } from './'; @@ -32,6 +34,7 @@ describe('SearchExperience', () => { engine: { name: 'some-engine', apiKey: '1234', + document_count: 50, }, }; const mockSetFields = jest.fn(); @@ -50,7 +53,17 @@ describe('SearchExperience', () => { it('renders', () => { const wrapper = shallow(); - expect(wrapper.find(SearchProvider).length).toBe(1); + + expect(wrapper.find(SearchProvider)).toHaveLength(1); + expect(wrapper.find(SearchExperienceContent)).toHaveLength(1); + }); + + it('renders an empty state when the engine does not have documents', () => { + setMockValues({ ...values, engine: { ...values.engine, document_count: 0 } }); + const wrapper = shallow(); + + expect(wrapper.find(EmptyState)).toHaveLength(1); + expect(wrapper.find(SearchExperienceContent)).toHaveLength(0); }); describe('when there are no selected filter fields', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx index 6fbc6305edb25..22029956601a6 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience.tsx @@ -9,7 +9,7 @@ import React, { useState } from 'react'; import { useValues } from 'kea'; -import { EuiButton, EuiSpacer, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; +import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; // @ts-expect-error types are not available for this package yet; import { SearchProvider, SearchBox, Sorting, Facet } from '@elastic/react-search-ui'; // @ts-expect-error types are not available for this package yet @@ -21,6 +21,7 @@ import './search_experience.scss'; import { externalUrl } from '../../../../shared/enterprise_search_url'; import { useLocalStorage } from '../../../../shared/use_local_storage'; import { EngineLogic } from '../../engine'; +import { EmptyState } from '../components'; import { buildSearchUIConfig } from './build_search_ui_config'; import { buildSortOptions } from './build_sort_options'; @@ -140,7 +141,11 @@ export const SearchExperience: React.FC = () => { )} - + {engine.document_count && engine.document_count > 0 ? ( + + ) : ( + + )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx index 96fcd8997f674..0905000f55139 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.test.tsx @@ -10,7 +10,7 @@ import { setMockSearchContextState } from './__mocks__/hooks.mock'; import React from 'react'; -import { shallow, mount } from 'enzyme'; +import { shallow } from 'enzyme'; // @ts-expect-error types are not available for this package yet import { Results } from '@elastic/react-search-ui'; @@ -113,81 +113,15 @@ describe('SearchExperienceContent', () => { expect(wrapper.find('[data-test-subj="documentsSearchNoResults"]').length).toBe(1); }); - describe('when an empty search was performed and there are no results, meaning there are no documents indexed', () => { - beforeEach(() => { - setMockSearchContextState({ - ...searchState, - resultSearchTerm: '', - wasSearched: true, - totalResults: 0, - }); - }); - - it('renders a no documents message', () => { - const wrapper = shallow(); - expect(wrapper.find('[data-test-subj="documentsSearchResults"]').length).toBe(0); - expect(wrapper.find('[data-test-subj="documentsSearchNoDocuments"]').length).toBe(1); - }); - - it('will include a button to index new documents', () => { - const wrapper = mount(); - expect( - wrapper - .find( - '[data-test-subj="documentsSearchNoDocuments"] [data-test-subj="IndexDocumentsButton"]' - ) - .exists() - ).toBe(true); - }); - - it('will include a button to documentation if this is a meta engine', () => { - setMockValues({ - ...values, - isMetaEngine: true, - }); - - const wrapper = mount(); - - expect( - wrapper - .find( - '[data-test-subj="documentsSearchNoDocuments"] [data-test-subj="IndexDocumentsButton"]' - ) - .exists() - ).toBe(false); - - expect( - wrapper - .find( - '[data-test-subj="documentsSearchNoDocuments"] [data-test-subj="documentsSearchDocsLink"]' - ) - .exists() - ).toBe(true); - }); - - it('will include a button to documentation if the user cannot manage documents', () => { - setMockValues({ - ...values, - myRole: { canManageEngineDocuments: false }, - }); - - const wrapper = mount(); - - expect( - wrapper - .find( - '[data-test-subj="documentsSearchNoDocuments"] [data-test-subj="IndexDocumentsButton"]' - ) - .exists() - ).toBe(false); - - expect( - wrapper - .find( - '[data-test-subj="documentsSearchNoDocuments"] [data-test-subj="documentsSearchDocsLink"]' - ) - .exists() - ).toBe(true); + it('renders empty if an empty search was performed and there are no results', () => { + // In a real world scenario this does not happen - wasSearched returns false before this final branch + setMockSearchContextState({ + ...searchState, + resultSearchTerm: '', + totalResults: 0, + wasSearched: true, }); + const wrapper = shallow(); + expect(wrapper.isEmptyRender()).toBe(true); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx index 91db26ac676c9..84fe721f9eb7f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/documents/search_experience/search_experience_content.tsx @@ -9,16 +9,13 @@ import React from 'react'; import { useValues } from 'kea'; -import { EuiFlexGroup, EuiSpacer, EuiButton, EuiEmptyPrompt } from '@elastic/eui'; +import { EuiFlexGroup, EuiSpacer, EuiEmptyPrompt } from '@elastic/eui'; // @ts-expect-error types are not available for this package yet import { Results, Paging, ResultsPerPage } from '@elastic/react-search-ui'; import { i18n } from '@kbn/i18n'; -import { AppLogic } from '../../../app_logic'; -import { DOCS_PREFIX } from '../../../routes'; import { EngineLogic } from '../../engine'; import { Result } from '../../result/types'; -import { DocumentCreationButton } from '../document_creation_button'; import { useSearchContextState } from './hooks'; import { Pagination } from './pagination'; @@ -27,7 +24,6 @@ import { ResultView } from './views'; export const SearchExperienceContent: React.FC = () => { const { resultSearchTerm, totalResults, wasSearched } = useSearchContextState(); - const { myRole } = useValues(AppLogic); const { isMetaEngine, engine } = useValues(EngineLogic); if (!wasSearched) return null; @@ -84,34 +80,5 @@ export const SearchExperienceContent: React.FC = () => { ); } - // If we have no results AND no search term, show a CTA for the user to index documents - return ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.documents.search.indexDocumentsTitle', { - defaultMessage: 'No documents yet!', - })} - - } - body={i18n.translate('xpack.enterpriseSearch.appSearch.documents.search.indexDocuments', { - defaultMessage: 'Indexed documents will show up here.', - })} - actions={ - !isMetaEngine && myRole.canManageEngineDocuments ? ( - - ) : ( - - {i18n.translate('xpack.enterpriseSearch.appSearch.documents.search.indexingGuide', { - defaultMessage: 'Read the indexing guide', - })} - - ) - } - /> - ); + return null; }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx index d48664febb5f7..959d544a67324 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview_empty.tsx @@ -23,7 +23,7 @@ export const EmptyEngineOverview: React.FC = () => { { defaultMessage: 'Engine setup' } )} rightSideItems={[ - + {i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.overview.empty.headingAction', { defaultMessage: 'View documentation' } diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx new file mode 100644 index 0000000000000..1eab32d64b77f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.test.tsx @@ -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 { EmptyMetaEnginesState } from './'; + +describe('EmptyMetaEnginesState', () => { + it('renders', () => { + const wrapper = shallow() + .find(EuiEmptyPrompt) + .dive(); + + expect(wrapper.find('h2').text()).toEqual('Create your first meta engine'); + expect(wrapper.find(EuiButton).prop('href')).toEqual( + expect.stringContaining('/meta-engines-guide.html') + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx new file mode 100644 index 0000000000000..58bf3f0a0195e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_meta_engines_state.tsx @@ -0,0 +1,49 @@ +/* + * 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 { EuiEmptyPrompt, EuiButton } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { DOCS_PREFIX } from '../../../routes'; + +export const EmptyMetaEnginesState: React.FC = () => ( + + {i18n.translate('xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPromptTitle', { + defaultMessage: 'Create your first meta engine', + })} + + } + body={ +

+ {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPromptDescription', + { + defaultMessage: + 'Meta engines allow you to combine multiple engines into one searchable engine.', + } + )} +

+ } + actions={ + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPromptButtonLabel', + { defaultMessage: 'Learn more about meta engines' } + )} + + } + /> +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx index 6911015e39d4a..6b4a081d2c515 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/empty_state.tsx @@ -15,14 +15,13 @@ import { i18n } from '@kbn/i18n'; import { EuiButtonTo } from '../../../../shared/react_router_helpers'; import { TelemetryLogic } from '../../../../shared/telemetry'; import { AppLogic } from '../../../app_logic'; +import { EngineIcon } from '../../../icons'; import { ENGINE_CREATION_PATH } from '../../../routes'; import { SampleEngineCreationCta } from '../../sample_engine_creation_cta/sample_engine_creation_cta'; import { EnginesOverviewHeader } from './header'; -import './empty_state.scss'; - export const EmptyState: React.FC = () => { const { myRole: { canManageEngines }, @@ -32,12 +31,11 @@ export const EmptyState: React.FC = () => { return ( <> - + {canManageEngines ? ( {i18n.translate('xpack.enterpriseSearch.appSearch.emptyState.title', { @@ -57,6 +55,7 @@ export const EmptyState: React.FC = () => { actions={ <> { { defaultMessage: 'Create an engine' } )} - + } @@ -80,8 +79,7 @@ export const EmptyState: React.FC = () => { ) : ( {i18n.translate('xpack.enterpriseSearch.appSearch.emptyState.nonAdmin.title', { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts index 89c57672fb529..234d3ba31f44b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/components/index.ts @@ -8,3 +8,4 @@ export { EnginesOverviewHeader } from './header'; export { LoadingState } from './loading_state'; export { EmptyState } from './empty_state'; +export { EmptyMetaEnginesState } from './empty_meta_engines_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts index c6c077e984efe..8d03e3d23ae23 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/constants.ts @@ -22,11 +22,17 @@ export const SOURCE_ENGINES_TITLE = i18n.translate( ); export const CREATE_AN_ENGINE_BUTTON_LABEL = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engines.createAnEngineButton.ButtonLabel', + 'xpack.enterpriseSearch.appSearch.engines.createEngineButtonLabel', { defaultMessage: 'Create an engine', } ); +export const CREATE_A_META_ENGINE_BUTTON_LABEL = i18n.translate( + 'xpack.enterpriseSearch.appSearch.engines.createMetaEngineButtonLabel', + { + defaultMessage: 'Create a meta engine', + } +); export const DELETE_ENGINE_MESSAGE = (engineName: string) => i18n.translate( @@ -38,25 +44,3 @@ export const DELETE_ENGINE_MESSAGE = (engineName: string) => }, } ); - -export const CREATE_A_META_ENGINE_BUTTON_LABEL = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engines.createAMetaEngineButton.ButtonLabel', - { - defaultMessage: 'Create a meta engine', - } -); - -export const META_ENGINE_EMPTY_PROMPT_TITLE = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPrompTitle', - { - defaultMessage: 'No meta engines yet', - } -); - -export const META_ENGINE_EMPTY_PROMPT_DESCRIPTION = i18n.translate( - 'xpack.enterpriseSearch.appSearch.engines.metaEngines.emptyPromptDescription', - { - defaultMessage: - 'Meta engines allow you to combine multiple engines into one searchable engine.', - } -); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.scss deleted file mode 100644 index 04a6033c5078a..0000000000000 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.scss +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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. - */ - -.enginesOverview { - padding: $euiSize; - - @include euiBreakpoint('m', 'l', 'xl') { - padding: $euiSizeXL; - } -} - -.engineIcon { - display: inline-block; - width: $euiSize; - // Use line-height of EuiTitle - SVG will vertically center accordingly - height: map-get(map-get($euiTitles, 's'), 'line-height'); - vertical-align: top; - margin-right: $euiSizeXS; -} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx index c47b169ede364..b326a7d3ee075 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.test.tsx @@ -12,8 +12,6 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; -import { EuiEmptyPrompt } from '@elastic/eui'; - import { LoadingState, EmptyState } from './components'; import { EnginesTable } from './components/tables/engines_table'; import { MetaEnginesTable } from './components/tables/meta_engines_table'; @@ -142,26 +140,6 @@ describe('EnginesOverview', () => { wrapper.find('[data-test-subj="appSearchEnginesMetaEngineCreationButton"]').prop('to') ).toEqual('/meta_engine_creation'); }); - - describe('when metaEngines is empty', () => { - it('contains an EuiEmptyPrompt that takes users to the create meta engine page', () => { - setMockValues({ - ...valuesWithEngines, - hasPlatinumLicense: true, - myRole: { canManageEngines: true }, - metaEngines: [], - }); - const wrapper = shallow(); - const metaEnginesTable = wrapper.find(MetaEnginesTable).dive(); - const emptyPrompt = metaEnginesTable.dive().find(EuiEmptyPrompt).dive(); - - expect( - emptyPrompt - .find('[data-test-subj="appSearchMetaEnginesEmptyStateCreationButton"]') - .prop('to') - ).toEqual('/meta_engine_creation'); - }); - }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx index 4e17278d25d1a..7001ecada999a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/engines/engines_overview.tsx @@ -10,13 +10,14 @@ import React, { useEffect } from 'react'; import { useValues, useActions } from 'kea'; import { + EuiFlexGroup, + EuiFlexItem, EuiPageContent, EuiPageContentHeader, EuiPageContentHeaderSection, EuiPageContentBody, EuiTitle, EuiSpacer, - EuiEmptyPrompt, } from '@elastic/eui'; import { FlashMessages } from '../../../shared/flash_messages'; @@ -28,21 +29,22 @@ import { AppLogic } from '../../app_logic'; import { EngineIcon, MetaEngineIcon } from '../../icons'; import { ENGINE_CREATION_PATH, META_ENGINE_CREATION_PATH } from '../../routes'; -import { EnginesOverviewHeader, LoadingState, EmptyState } from './components'; +import { + EnginesOverviewHeader, + LoadingState, + EmptyState, + EmptyMetaEnginesState, +} from './components'; import { EnginesTable } from './components/tables/engines_table'; import { MetaEnginesTable } from './components/tables/meta_engines_table'; import { CREATE_AN_ENGINE_BUTTON_LABEL, CREATE_A_META_ENGINE_BUTTON_LABEL, ENGINES_TITLE, - META_ENGINE_EMPTY_PROMPT_DESCRIPTION, - META_ENGINE_EMPTY_PROMPT_TITLE, META_ENGINES_TITLE, } from './constants'; import { EnginesLogic } from './engines_logic'; -import './engines_overview.scss'; - export const EnginesOverview: React.FC = () => { const { hasPlatinumLicense } = useValues(LicensingLogic); const { @@ -79,15 +81,20 @@ export const EnginesOverview: React.FC = () => { - + - + - -

- {ENGINES_TITLE} -

-
+ + + + + + +

{ENGINES_TITLE}

+
+
+
{canManageEngines && ( @@ -104,7 +111,7 @@ export const EnginesOverview: React.FC = () => {
- + { {hasPlatinumLicense && ( <> - + - -

- {META_ENGINES_TITLE} -

-
+ + + + + + +

{META_ENGINES_TITLE}

+
+
+
{canManageEngines && ( @@ -142,6 +154,7 @@ export const EnginesOverview: React.FC = () => {
+ { ...convertMetaToPagination(metaEnginesMeta), hidePerPageOptions: true, }} - noItemsMessage={ - {META_ENGINE_EMPTY_PROMPT_TITLE}} - body={

{META_ENGINE_EMPTY_PROMPT_DESCRIPTION}

} - actions={ - canManageEngines && ( - - {CREATE_A_META_ENGINE_BUTTON_LABEL} - - ) - } - /> - } + noItemsMessage={} onChange={handlePageChange(onMetaEnginesPagination)} />
diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.test.tsx index 7ee921eef0e09..0af20982bb970 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.test.tsx @@ -11,11 +11,9 @@ import { shallow, ShallowWrapper } from 'enzyme'; import { EuiAccordion } from '@elastic/eui'; -import { BoostIcon } from '../boost_icon'; +import { BoostIcon, ValueBadge } from '../components'; import { BoostType } from '../types'; -import { ValueBadge } from '../value_badge'; - import { BoostItem } from './boost_item'; import { BoostItemContent } from './boost_item_content'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.tsx index 98d83619866d1..2954ffc5e8c2f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boost_item.tsx @@ -9,10 +9,9 @@ import React, { useMemo } from 'react'; import { EuiFlexItem, EuiAccordion, EuiFlexGroup, EuiHideFor } from '@elastic/eui'; -import { BoostIcon } from '../boost_icon'; +import { BoostIcon, ValueBadge } from '../components'; import { BOOST_TYPE_TO_DISPLAY_MAP } from '../constants'; import { Boost } from '../types'; -import { ValueBadge } from '../value_badge'; import { BoostItemContent } from './boost_item_content'; import { getBoostSummary } from './get_boost_summary'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx index 297365896bb6d..7a407491ffef3 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boosts/boosts.tsx @@ -16,7 +16,7 @@ import { i18n } from '@kbn/i18n'; import { GEOLOCATION, TEXT, DATE } from '../../../../shared/constants/field_types'; import { SchemaTypes } from '../../../../shared/types'; -import { BoostIcon } from '../boost_icon'; +import { BoostIcon } from '../components'; import { FUNCTIONAL_DISPLAY, PROXIMITY_DISPLAY, VALUE_DISPLAY } from '../constants'; import { RelevanceTuningLogic } from '../relevance_tuning_logic'; import { Boost, BoostType } from '../types'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boost_icon.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/boost_icon.test.tsx similarity index 87% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boost_icon.test.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/boost_icon.test.tsx index fd567f52ada24..15281be9ddd6c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boost_icon.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/boost_icon.test.tsx @@ -11,14 +11,11 @@ import { shallow } from 'enzyme'; import { EuiToken } from '@elastic/eui'; +import { BoostType } from '../types'; + import { BoostIcon } from './boost_icon'; -import { BoostType } from './types'; describe('BoostIcon', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - it('renders a token according to the provided type', () => { const wrapper = shallow(); expect(wrapper.find(EuiToken).prop('iconType')).toBe('tokenNumber'); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boost_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/boost_icon.tsx similarity index 86% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boost_icon.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/boost_icon.tsx index 2570a29274d06..8af03fd63b438 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/boost_icon.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/boost_icon.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { EuiToken } from '@elastic/eui'; -import { BOOST_TYPE_TO_ICON_MAP } from './constants'; -import { BoostType } from './types'; +import { BOOST_TYPE_TO_ICON_MAP } from '../constants'; +import { BoostType } from '../types'; interface Props { type: BoostType; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx new file mode 100644 index 0000000000000..a60f68c19f6dc --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.test.tsx @@ -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 './'; + +describe('EmptyState', () => { + it('renders', () => { + const wrapper = shallow() + .find(EuiEmptyPrompt) + .dive(); + + expect(wrapper.find('h2').text()).toEqual('Add documents to tune relevance'); + expect(wrapper.find(EuiButton).prop('href')).toEqual( + expect.stringContaining('/relevance-tuning-guide.html') + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx new file mode 100644 index 0000000000000..e6a14d7b5cd72 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/empty_state.tsx @@ -0,0 +1,48 @@ +/* + * 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, EuiPanel } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { DOCS_PREFIX } from '../../../routes'; + +export const EmptyState: React.FC = () => ( + + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.relevanceTuning.empty.title', { + defaultMessage: 'Add documents to tune relevance', + })} + + } + body={i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.empty.description', + { + defaultMessage: + 'A schema will be automatically created for you after you index some documents.', + } + )} + actions={ + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.empty.buttonLabel', + { defaultMessage: 'Read the relevance tuning guide' } + )} + + } + /> + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/index.ts new file mode 100644 index 0000000000000..f456e11b160f6 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/index.ts @@ -0,0 +1,10 @@ +/* + * 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. + */ + +export { BoostIcon } from './boost_icon'; +export { ValueBadge } from './value_badge'; +export { EmptyState } from './empty_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/value_badge.scss b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.scss similarity index 100% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/value_badge.scss rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.scss diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.test.tsx new file mode 100644 index 0000000000000..0d09148d3de3f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.test.tsx @@ -0,0 +1,25 @@ +/* + * 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 { ValueBadge } from './'; + +describe('ValueBadge', () => { + it('renders', () => { + const wrapper = shallow(Hello world); + expect(wrapper.hasClass('valueBadge')).toBe(true); + expect(wrapper.text()).toEqual('Hello world'); + }); + + it('renders a disabled class', () => { + const wrapper = shallow(Test); + expect(wrapper.hasClass('valueBadge--disabled')).toBe(true); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/value_badge.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.tsx similarity index 76% rename from x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/value_badge.tsx rename to x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.tsx index 8397087ca69b4..a5e86892b4c6c 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/value_badge.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/components/value_badge.tsx @@ -11,10 +11,11 @@ import classNames from 'classnames'; import './value_badge.scss'; -export const ValueBadge: React.FC<{ children: React.ReactNode; disabled?: boolean }> = ({ - children, - disabled = false, -}) => { +interface Props { + children: React.ReactNode; + disabled?: boolean; +} +export const ValueBadge: React.FC = ({ children, disabled = false }) => { const className = classNames('valueBadge', { 'valueBadge--disabled': disabled, }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx index c76c50094aedd..574d2ae02af99 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.test.tsx @@ -18,6 +18,7 @@ import { EuiEmptyPrompt } from '@elastic/eui'; import { Loading } from '../../../shared/loading'; import { UnsavedChangesPrompt } from '../../../shared/unsaved_changes_prompt'; +import { EmptyState } from './components'; import { RelevanceTuning } from './relevance_tuning'; import { RelevanceTuningForm } from './relevance_tuning_form'; @@ -51,7 +52,7 @@ describe('RelevanceTuning', () => { const wrapper = subject(); expect(wrapper.find(RelevanceTuningForm).exists()).toBe(true); expect(wrapper.find(Loading).exists()).toBe(false); - expect(wrapper.find('EmptyCallout').exists()).toBe(false); + expect(wrapper.find(EmptyState).exists()).toBe(false); }); it('initializes relevance tuning data', () => { @@ -65,7 +66,7 @@ describe('RelevanceTuning', () => { engineHasSchemaFields: false, }); const wrapper = subject(); - expect(wrapper.find('EmptyCallout').dive().find(EuiEmptyPrompt).exists()).toBe(true); + expect(wrapper.find(EmptyState).dive().find(EuiEmptyPrompt).exists()).toBe(true); expect(wrapper.find(Loading).exists()).toBe(false); expect(wrapper.find(RelevanceTuningForm).exists()).toBe(false); }); @@ -77,7 +78,7 @@ describe('RelevanceTuning', () => { }); const wrapper = subject(); expect(wrapper.find(Loading).exists()).toBe(true); - expect(wrapper.find('EmptyCallout').exists()).toBe(false); + expect(wrapper.find(EmptyState).exists()).toBe(false); expect(wrapper.find(RelevanceTuningForm).exists()).toBe(false); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx index ab9bbaa9a1773..b98541a963890 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning.tsx @@ -9,58 +9,18 @@ import React, { useEffect } from 'react'; import { useActions, useValues } from 'kea'; -import { EuiButton, EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; +import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { Loading } from '../../../shared/loading'; import { UnsavedChangesPrompt } from '../../../shared/unsaved_changes_prompt'; -import { DOCS_PREFIX } from '../../routes'; +import { EmptyState } from './components'; import { RelevanceTuningForm } from './relevance_tuning_form'; import { RelevanceTuningLayout } from './relevance_tuning_layout'; - import { RelevanceTuningPreview } from './relevance_tuning_preview'; import { RelevanceTuningLogic } from '.'; -const EmptyCallout: React.FC = () => { - return ( - - {i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.emptyErrorMessageTitle', - { - defaultMessage: 'Tuning requires schema fields', - } - )} - - } - body={i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.emptyErrorMessage', - { - defaultMessage: 'Index documents to tune relevance.', - } - )} - actions={ - - {i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.relevanceTuning.emptyButtonLabel', - { - defaultMessage: 'Read the relevance tuning guide', - } - )} - - } - /> - ); -}; - export const RelevanceTuning: React.FC = () => { const { dataLoading, engineHasSchemaFields, unsavedChanges } = useValues(RelevanceTuningLogic); const { initializeRelevanceTuning } = useActions(RelevanceTuningLogic); @@ -69,31 +29,23 @@ export const RelevanceTuning: React.FC = () => { initializeRelevanceTuning(); }, []); - const body = () => { - if (dataLoading) { - return ; - } - - if (!engineHasSchemaFields) { - return ; - } - - return ( - - - - - - - - - ); - }; + if (dataLoading) return ; return ( - {body()} + {engineHasSchemaFields ? ( + + + + + + + + + ) : ( + + )} ); }; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.test.tsx index 97913ed49fefd..b6061a326365b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.test.tsx @@ -11,9 +11,8 @@ import { shallow } from 'enzyme'; import { SchemaTypes } from '../../../../shared/types'; -import { BoostIcon } from '../boost_icon'; +import { BoostIcon, ValueBadge } from '../components'; import { Boost, BoostType, SearchField } from '../types'; -import { ValueBadge } from '../value_badge'; import { RelevanceTuningItem } from './relevance_tuning_item'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.tsx index f7f4c64622fa6..9264078ca40f5 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_form/relevance_tuning_item.tsx @@ -11,9 +11,8 @@ import { EuiText, EuiFlexGroup, EuiFlexItem, EuiTitle, EuiTextColor, EuiIcon } f import { SchemaTypes } from '../../../../shared/types'; -import { BoostIcon } from '../boost_icon'; +import { BoostIcon, ValueBadge } from '../components'; import { Boost, SearchField } from '../types'; -import { ValueBadge } from '../value_badge'; interface Props { name: string; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx index 69043d80bd8d0..4fa694300a779 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/relevance_tuning/relevance_tuning_layout.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { useActions, useValues } from 'kea'; -import { EuiPageHeader, EuiSpacer, EuiButton } from '@elastic/eui'; +import { EuiPageHeader, EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -67,7 +67,6 @@ export const RelevanceTuningLayout: React.FC = ({ children }) => { {pageHeader()} - {children} ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx new file mode 100644 index 0000000000000..537fd9ec6a0d4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.test.tsx @@ -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 './'; + +describe('EmptyState', () => { + it('renders', () => { + const wrapper = shallow() + .find(EuiEmptyPrompt) + .dive(); + + expect(wrapper.find('h2').text()).toEqual('Add documents to adjust settings'); + expect(wrapper.find(EuiButton).prop('href')).toEqual( + expect.stringContaining('/result-settings-guide.html') + ); + }); +}); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx new file mode 100644 index 0000000000000..299156984724e --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/empty_state.tsx @@ -0,0 +1,48 @@ +/* + * 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, EuiPanel } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; + +import { DOCS_PREFIX } from '../../../routes'; + +export const EmptyState: React.FC = () => ( + + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.resultSettings.empty.title', { + defaultMessage: 'Add documents to adjust settings', + })} + + } + body={i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.resultSettings.empty.description', + { + defaultMessage: + 'A schema will be automatically created for you after you index some documents.', + } + )} + actions={ + + {i18n.translate( + 'xpack.enterpriseSearch.appSearch.engine.resultSettings.empty.buttonLabel', + { defaultMessage: 'Read the result settings guide' } + )} + + } + /> + +); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/index.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/index.ts new file mode 100644 index 0000000000000..8c9e58e6ba0f4 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/components/index.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { EmptyState } from './empty_state'; diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx index 48a25d4f1f4bd..dd99dc6c505da 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.test.tsx @@ -13,10 +13,11 @@ import React from 'react'; import { shallow, ShallowWrapper } from 'enzyme'; -import { EuiPageHeader, EuiEmptyPrompt } from '@elastic/eui'; +import { EuiPageHeader } from '@elastic/eui'; import { UnsavedChangesPrompt } from '../../../shared/unsaved_changes_prompt'; +import { EmptyState } from './components'; import { ResultSettings } from './result_settings'; import { ResultSettingsTable } from './result_settings_table'; import { SampleResponse } from './sample_response'; @@ -151,8 +152,8 @@ describe('ResultSettings', () => { expect(wrapper.find(SampleResponse).exists()).toBe(false); }); - it('will render an "empty" message', () => { - expect(wrapper.find(EuiEmptyPrompt).exists()).toBe(true); + it('will render an empty state', () => { + expect(wrapper.find(EmptyState).exists()).toBe(true); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx index 51cdc3aea21f2..45cb9ea1cfcb4 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/result_settings/result_settings.tsx @@ -9,15 +9,7 @@ import React, { useEffect } from 'react'; import { useActions, useValues } from 'kea'; -import { - EuiPageHeader, - EuiFlexGroup, - EuiFlexItem, - EuiButton, - EuiButtonEmpty, - EuiEmptyPrompt, - EuiPanel, -} from '@elastic/eui'; +import { EuiPageHeader, EuiFlexGroup, EuiFlexItem, EuiButton, EuiButtonEmpty } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; @@ -29,6 +21,7 @@ import { UnsavedChangesPrompt } from '../../../shared/unsaved_changes_prompt'; import { RESTORE_DEFAULTS_BUTTON_LABEL } from '../../constants'; import { getEngineBreadcrumbs } from '../engine'; +import { EmptyState } from './components'; import { RESULT_SETTINGS_TITLE } from './constants'; import { ResultSettingsTable } from './result_settings_table'; import { SampleResponse } from './sample_response'; @@ -115,26 +108,7 @@ export const ResultSettings: React.FC = () => { ) : ( - - - {i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.resultSettings.noSchemaTitle', - { defaultMessage: 'Engine does not have a schema' } - )} - - } - body={i18n.translate( - 'xpack.enterpriseSearch.appSearch.engine.resultSettings.noSchemaDescription', - { - defaultMessage: - 'You need one! A schema is created for you after you index some documents.', - } - )} - /> - + )} ); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx index 6f1ccd1ae2b53..3a292792fbca0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/sample_engine_creation_cta/sample_engine_creation_cta.tsx @@ -23,10 +23,10 @@ export const SampleEngineCreationCta: React.FC = () => { const { createSampleEngine } = useActions(SampleEngineCreationCtaLogic); return ( - + - +

{SAMPLE_ENGINE_CREATION_CTA_TITLE}

diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/icons/engine_icon.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/engine_icon.tsx index 9e502b623ae43..13c948787c77f 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/icons/engine_icon.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/icons/engine_icon.tsx @@ -7,13 +7,14 @@ import React from 'react'; -export const EngineIcon: React.FC = () => ( +export const EngineIcon: React.FC = ({ ...props }) => (