diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx index 944d8315452b..309924e99f60 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.test.tsx @@ -49,6 +49,7 @@ describe('AutomatedCuration', () => { const actions = { convertToManual: jest.fn(), + onSelectPageTab: jest.fn(), }; beforeEach(() => { @@ -62,48 +63,41 @@ describe('AutomatedCuration', () => { const wrapper = shallow(); expect(wrapper.is(AppSearchPageTemplate)); - expect(wrapper.find(PromotedDocuments)).toHaveLength(1); - expect(wrapper.find(OrganicDocuments)).toHaveLength(1); - expect(wrapper.find(History)).toHaveLength(0); }); - it('includes tabs', () => { + it('includes set of tabs in the page header', () => { const wrapper = shallow(); - let tabs = getPageHeaderTabs(wrapper).find(EuiTab); - expect(tabs).toHaveLength(3); + const tabs = getPageHeaderTabs(wrapper).find(EuiTab); - expect(tabs.at(0).prop('isSelected')).toBe(true); + tabs.at(0).simulate('click'); + expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(1, 'promoted'); - expect(tabs.at(1).prop('onClick')).toBeUndefined(); - expect(tabs.at(1).prop('isSelected')).toBe(false); expect(tabs.at(1).prop('disabled')).toBe(true); - expect(tabs.at(2).prop('isSelected')).toBe(false); - - // Clicking on the History tab shows the history view tabs.at(2).simulate('click'); + expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(2, 'history'); + }); - tabs = getPageHeaderTabs(wrapper).find(EuiTab); + it('renders promoted and organic documents when the promoted tab is selected', () => { + setMockValues({ ...values, selectedPageTab: 'promoted' }); + const wrapper = shallow(); + const tabs = getPageHeaderTabs(wrapper).find(EuiTab); - expect(tabs.at(0).prop('isSelected')).toBe(false); - expect(tabs.at(2).prop('isSelected')).toBe(true); - - expect(wrapper.find(PromotedDocuments)).toHaveLength(0); - expect(wrapper.find(OrganicDocuments)).toHaveLength(0); - expect(wrapper.find(History)).toHaveLength(1); - - // Clicking back to the Promoted tab shows promoted documents - tabs.at(0).simulate('click'); - - tabs = getPageHeaderTabs(wrapper).find(EuiTab); - - expect(tabs.at(0).prop('isSelected')).toBe(true); - expect(tabs.at(2).prop('isSelected')).toBe(false); + expect(tabs.at(0).prop('isSelected')).toEqual(true); expect(wrapper.find(PromotedDocuments)).toHaveLength(1); expect(wrapper.find(OrganicDocuments)).toHaveLength(1); - expect(wrapper.find(History)).toHaveLength(0); + }); + + it('renders curation history when the history tab is selected', () => { + setMockValues({ ...values, selectedPageTab: 'history' }); + const wrapper = shallow(); + const tabs = getPageHeaderTabs(wrapper).find(EuiTab); + + expect(tabs.at(2).prop('isSelected')).toEqual(true); + + expect(wrapper.find(History)).toHaveLength(1); }); it('initializes CurationLogic with a curationId prop from URL param', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx index 276b40ba8867..eefe012cd8a2 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/automated_curation.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { useState } from 'react'; +import React from 'react'; import { useParams } from 'react-router-dom'; import { useValues, useActions } from 'kea'; @@ -31,23 +31,19 @@ import { DeleteCurationButton } from './delete_curation_button'; import { PromotedDocuments, OrganicDocuments } from './documents'; import { History } from './history'; -const PROMOTED = 'promoted'; -const HISTORY = 'history'; - export const AutomatedCuration: React.FC = () => { const { curationId } = useParams<{ curationId: string }>(); const logic = CurationLogic({ curationId }); - const { convertToManual } = useActions(logic); - const { activeQuery, dataLoading, queries, curation } = useValues(logic); + const { convertToManual, onSelectPageTab } = useActions(logic); + const { activeQuery, dataLoading, queries, curation, selectedPageTab } = useValues(logic); const { engineName } = useValues(EngineLogic); - const [selectedPageTab, setSelectedPageTab] = useState(PROMOTED); const pageTabs = [ { label: PROMOTED_DOCUMENTS_TITLE, append: {curation.promoted.length}, - isSelected: selectedPageTab === PROMOTED, - onClick: () => setSelectedPageTab(PROMOTED), + isSelected: selectedPageTab === 'promoted', + onClick: () => onSelectPageTab('promoted'), }, { label: HIDDEN_DOCUMENTS_TITLE, @@ -62,8 +58,8 @@ export const AutomatedCuration: React.FC = () => { defaultMessage: 'History', } ), - isSelected: selectedPageTab === HISTORY, - onClick: () => setSelectedPageTab(HISTORY), + isSelected: selectedPageTab === 'history', + onClick: () => onSelectPageTab('history'), }, ]; @@ -102,9 +98,9 @@ export const AutomatedCuration: React.FC = () => { }} isLoading={dataLoading} > - {selectedPageTab === PROMOTED && } - {selectedPageTab === PROMOTED && } - {selectedPageTab === HISTORY && ( + {selectedPageTab === 'promoted' && } + {selectedPageTab === 'promoted' && } + {selectedPageTab === 'history' && ( )} diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts index 5c3ac6d700de..b1f16944c985 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.test.ts @@ -250,7 +250,7 @@ describe('CurationLogic', () => { }); describe('onSelectPageTab', () => { - it('should set the selected page tab', () => { + it('should set the selected page tab and clears flash messages', () => { mount({ selectedPageTab: 'promoted', }); @@ -261,6 +261,7 @@ describe('CurationLogic', () => { ...DEFAULT_VALUES, selectedPageTab: 'hidden', }); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts index 7b617dd89e96..6393ccf97422 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/curation_logic.ts @@ -21,7 +21,7 @@ import { DELETE_SUCCESS_MESSAGE } from '../constants'; import { Curation } from '../types'; import { addDocument, removeDocument } from '../utils'; -type CurationPageTabs = 'promoted' | 'hidden'; +type CurationPageTabs = 'promoted' | 'history' | 'hidden'; interface CurationValues { dataLoading: boolean; @@ -271,6 +271,9 @@ export const CurationLogic = kea { + clearFlashMessages(); + }, setActiveQuery: () => actions.updateCuration(), setPromotedIds: () => actions.updateCuration(), addPromotedId: () => actions.updateCuration(), diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx index 103d7be37535..d739eae55040 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.test.tsx @@ -22,7 +22,7 @@ jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() })); import { CurationLogic } from './curation_logic'; import { DeleteCurationButton } from './delete_curation_button'; -import { PromotedDocuments, HiddenDocuments } from './documents'; +import { PromotedDocuments, HiddenDocuments, OrganicDocuments } from './documents'; import { ManualCuration } from './manual_curation'; import { ActiveQuerySelect, ManageQueriesModal } from './queries'; import { AddResultFlyout } from './results'; @@ -74,13 +74,13 @@ describe('ManualCuration', () => { expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(2, 'hidden'); }); - it('contains a suggested documents callout when the selectedPageTab is ', () => { + it('contains a suggested documents callout', () => { const wrapper = shallow(); expect(wrapper.find(SuggestedDocumentsCallout)).toHaveLength(1); }); - it('renders promoted documents when that tab is selected', () => { + it('renders promoted and organic documents when the promoted tab is selected', () => { setMockValues({ ...values, selectedPageTab: 'promoted' }); const wrapper = shallow(); const tabs = getPageHeaderTabs(wrapper).find(EuiTab); @@ -88,9 +88,10 @@ describe('ManualCuration', () => { expect(tabs.at(0).prop('isSelected')).toEqual(true); expect(wrapper.find(PromotedDocuments)).toHaveLength(1); + expect(wrapper.find(OrganicDocuments)).toHaveLength(1); }); - it('renders hidden documents when that tab is selected', () => { + it('renders hidden documents when the hidden tab is selected', () => { setMockValues({ ...values, selectedPageTab: 'hidden' }); const wrapper = shallow(); const tabs = getPageHeaderTabs(wrapper).find(EuiTab); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx index 3aee306e3d2f..e78a80a5878b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curation/manual_curation.tsx @@ -26,10 +26,10 @@ import { SuggestedDocumentsCallout } from './suggested_documents_callout'; export const ManualCuration: React.FC = () => { const { curationId } = useParams() as { curationId: string }; - const { onSelectPageTab } = useActions(CurationLogic({ curationId })); - const { dataLoading, queries, selectedPageTab, curation } = useValues( - CurationLogic({ curationId }) - ); + const logic = CurationLogic({ curationId }); + const { onSelectPageTab } = useActions(logic); + const { dataLoading, queries, selectedPageTab, curation } = useValues(logic); + const { isFlyoutOpen } = useValues(AddResultLogic); const pageTabs = [ diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.test.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.test.ts index 42c3985e4dcf..44ff66e5f46e 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.test.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.test.ts @@ -92,7 +92,7 @@ describe('CurationsLogic', () => { }); describe('onSelectPageTab', () => { - it('should set the selected page tab', () => { + it('should set the selected page tab and clear flash messages', () => { mount(); CurationsLogic.actions.onSelectPageTab('settings'); @@ -101,6 +101,7 @@ describe('CurationsLogic', () => { ...DEFAULT_VALUES, selectedPageTab: 'settings', }); + expect(clearFlashMessages).toHaveBeenCalled(); }); }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts index 4419603efddf..487072584583 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_logic.ts @@ -126,5 +126,8 @@ export const CurationsLogic = kea { + clearFlashMessages(); + }, }), }); diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx index a0fd778ac7dd..c0278c765e85 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/curations_router.test.tsx @@ -94,7 +94,7 @@ describe('CurationsRouter', () => { expect(MOCK_ACTIONS.loadCurationsSettings).toHaveBeenCalledTimes(1); }); - it('skips loading curation settings when log retention is enabled', () => { + it('skips loading curation settings when log retention is disabled', () => { setMockValues({ ...MOCK_VALUES, logRetention: { diff --git a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts index b206c0c79ed2..8e6c3a9c6a6a 100644 --- a/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/app_search/components/curations/views/curation_suggestion/curation_suggestion_logic.ts @@ -137,7 +137,7 @@ export const CurationSuggestionLogic = kea< setQueuedSuccessMessage( i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.successfullyAppliedMessage', - { defaultMessage: 'Suggestion was succefully applied.' } + { defaultMessage: 'Suggestion was successfully applied.' } ) ); if (suggestion!.operation === 'delete') { @@ -177,7 +177,7 @@ export const CurationSuggestionLogic = kea< 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.successfullyAutomatedMessage', { defaultMessage: - 'Suggestion was succefully applied and all future suggestions for the query "{query}" will be automatically applied.', + 'Suggestion was successfully applied and all future suggestions for the query "{query}" will be automatically applied.', values: { query: suggestion!.query }, } ) @@ -208,7 +208,7 @@ export const CurationSuggestionLogic = kea< i18n.translate( 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.successfullyRejectedMessage', { - defaultMessage: 'Suggestion was succefully rejected.', + defaultMessage: 'Suggestion was successfully rejected.', } ) ); @@ -230,7 +230,7 @@ export const CurationSuggestionLogic = kea< 'xpack.enterpriseSearch.appSearch.engine.curations.suggestedCuration.successfullyDisabledMessage', { defaultMessage: - 'Suggestion was succefully rejected and you will no longer receive suggestions for the query "{query}".', + 'Suggestion was successfully rejected and you will no longer receive suggestions for the query "{query}".', values: { query: suggestion!.query }, } ) 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 aacabf0ac730..f446438d83d9 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 @@ -47,6 +47,10 @@ describe('Curations', () => { }, }, selectedPageTab: 'overview', + // CurationsSettingsLogic + curationsSettings: { + enabled: true, + }, // LicensingLogic hasPlatinumLicense: true, }; @@ -78,8 +82,6 @@ describe('Curations', () => { tabs.at(2).simulate('click'); expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(3, 'settings'); - // The settings tab should NOT have an icon next to it - expect(tabs.at(2).prop('prepend')).toBeUndefined(); }); it('renders less tabs when less than platinum license', () => { @@ -90,8 +92,47 @@ describe('Curations', () => { const tabs = getPageHeaderTabs(wrapper).find(EuiTab); expect(tabs.length).toBe(2); - // The settings tab should have an icon next to it - expect(tabs.at(1).prop('prepend')).not.toBeUndefined(); + }); + + it('renders a New! badge when less than platinum license', () => { + setMockValues({ ...values, hasPlatinumLicense: false }); + const wrapper = shallow(); + + expect(getPageTitle(wrapper)).toEqual('Curated results'); + + const tabs = getPageHeaderTabs(wrapper).find(EuiTab); + expect(tabs.at(1).prop('append')).not.toBeUndefined(); + }); + + it('renders a New! badge when suggestions are disabled', () => { + setMockValues({ + ...values, + curationsSettings: { + enabled: false, + }, + }); + const wrapper = shallow(); + + expect(getPageTitle(wrapper)).toEqual('Curated results'); + + const tabs = getPageHeaderTabs(wrapper).find(EuiTab); + expect(tabs.at(2).prop('append')).not.toBeUndefined(); + }); + + it('hides the badge when suggestions are enabled and the user has a platinum license', () => { + setMockValues({ + ...values, + hasPlatinumLicense: true, + curationsSettings: { + enabled: true, + }, + }); + const wrapper = shallow(); + + expect(getPageTitle(wrapper)).toEqual('Curated results'); + + const tabs = getPageHeaderTabs(wrapper).find(EuiTab); + expect(tabs.at(2).prop('append')).toBeUndefined(); }); it('renders an overview view', () => { 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 3d4751fcb343..e5b064e649af 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,7 +9,7 @@ import React, { useEffect } from 'react'; import { useValues, useActions } from 'kea'; -import { EuiIcon } from '@elastic/eui'; +import { EuiBadge } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { LicensingLogic } from '../../../../shared/licensing'; @@ -31,7 +31,12 @@ export const Curations: React.FC = () => { const { dataLoading: curationsDataLoading, meta, selectedPageTab } = useValues(CurationsLogic); const { loadCurations, onSelectPageTab } = useActions(CurationsLogic); const { hasPlatinumLicense } = useValues(LicensingLogic); - const { dataLoading: curationsSettingsDataLoading } = useValues(CurationsSettingsLogic); + const { + dataLoading: curationsSettingsDataLoading, + curationsSettings: { enabled: curationsSettingsEnabled }, + } = useValues(CurationsSettingsLogic); + + const suggestionsEnabled = hasPlatinumLicense && curationsSettingsEnabled; const OVERVIEW_TAB = { label: i18n.translate( @@ -61,17 +66,18 @@ export const Curations: React.FC = () => { ), isSelected: selectedPageTab === 'settings', onClick: () => onSelectPageTab('settings'), + append: suggestionsEnabled ? undefined : ( + + {i18n.translate('xpack.enterpriseSearch.appSearch.engine.curations.newBadgeLabel', { + defaultMessage: 'New!', + })} + + ), }; const pageTabs = hasPlatinumLicense ? [OVERVIEW_TAB, HISTORY_TAB, SETTINGS_TAB] - : [ - OVERVIEW_TAB, - { - ...SETTINGS_TAB, - prepend: , - }, - ]; + : [OVERVIEW_TAB, SETTINGS_TAB]; useEffect(() => { loadCurations();