Skip to content

Commit

Permalink
[App Search] Split Curation Detail views into tabs (#114117)
Browse files Browse the repository at this point in the history
  • Loading branch information
byronhulcher authored Oct 6, 2021
1 parent 6723fa5 commit 3135075
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ import React from 'react';

import { shallow, ShallowWrapper } from 'enzyme';

import { EuiBadge } from '@elastic/eui';
import { EuiBadge, EuiTab } from '@elastic/eui';

import { getPageHeaderActions, getPageTitle } from '../../../../test_helpers';
import { getPageHeaderActions, getPageHeaderTabs, getPageTitle } from '../../../../test_helpers';

jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() }));

Expand Down Expand Up @@ -60,6 +60,20 @@ describe('AutomatedCuration', () => {
expect(wrapper.find(OrganicDocuments)).toHaveLength(1);
});

it('includes a static tab group', () => {
const wrapper = shallow(<AutomatedCuration />);
const tabs = getPageHeaderTabs(wrapper).find(EuiTab);

expect(tabs).toHaveLength(2);

expect(tabs.at(0).prop('onClick')).toBeUndefined();
expect(tabs.at(0).prop('isSelected')).toBe(true);

expect(tabs.at(1).prop('onClick')).toBeUndefined();
expect(tabs.at(1).prop('isSelected')).toBe(false);
expect(tabs.at(1).prop('disabled')).toBe(true);
});

it('initializes CurationLogic with a curationId prop from URL param', () => {
mockUseParams.mockReturnValueOnce({ curationId: 'hello-world' });
shallow(<AutomatedCuration />);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import {
COVERT_TO_MANUAL_BUTTON_LABEL,
CONVERT_TO_MANUAL_CONFIRMATION,
} from '../constants';

import { getCurationsBreadcrumbs } from '../utils';

import { HIDDEN_DOCUMENTS_TITLE, PROMOTED_DOCUMENTS_TITLE } from './constants';
import { CurationLogic } from './curation_logic';
import { PromotedDocuments, OrganicDocuments } from './documents';

Expand All @@ -30,6 +32,19 @@ export const AutomatedCuration: React.FC = () => {
const { convertToManual } = useActions(logic);
const { activeQuery, dataLoading, queries } = useValues(logic);

// This tab group is meant to visually mirror the dynamic group of tags in the ManualCuration component
const pageTabs = [
{
label: PROMOTED_DOCUMENTS_TITLE,
isSelected: true,
},
{
label: HIDDEN_DOCUMENTS_TITLE,
isSelected: false,
disabled: true,
},
];

return (
<AppSearchPageTemplate
pageChrome={getCurationsBreadcrumbs([queries.join(', ')])}
Expand All @@ -54,6 +69,7 @@ export const AutomatedCuration: React.FC = () => {
{COVERT_TO_MANUAL_BUTTON_LABEL}
</EuiButton>,
],
tabs: pageTabs,
}}
isLoading={dataLoading}
>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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 { i18n } from '@kbn/i18n';

export const PROMOTED_DOCUMENTS_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.title',
{ defaultMessage: 'Promoted documents' }
);

export const HIDDEN_DOCUMENTS_TITLE = i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curations.hiddenDocuments.title',
{ defaultMessage: 'Hidden documents' }
);
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe('CurationLogic', () => {
hiddenIds: [],
hiddenDocumentsLoading: false,
isAutomated: false,
selectedPageTab: 'promoted',
};

beforeEach(() => {
Expand Down Expand Up @@ -264,6 +265,21 @@ describe('CurationLogic', () => {
});
});
});

describe('onSelectPageTab', () => {
it('should set the selected page tab', () => {
mount({
selectedPageTab: 'promoted',
});

CurationLogic.actions.onSelectPageTab('hidden');

expect(CurationLogic.values).toEqual({
...DEFAULT_VALUES,
selectedPageTab: 'hidden',
});
});
});
});

describe('selectors', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import { EngineLogic, generateEnginePath } from '../../engine';
import { Curation } from '../types';
import { addDocument, removeDocument } from '../utils';

type CurationPageTabs = 'promoted' | 'hidden';

interface CurationValues {
dataLoading: boolean;
curation: Curation;
Expand All @@ -28,6 +30,7 @@ interface CurationValues {
hiddenIds: string[];
hiddenDocumentsLoading: boolean;
isAutomated: boolean;
selectedPageTab: CurationPageTabs;
}

interface CurationActions {
Expand All @@ -46,6 +49,7 @@ interface CurationActions {
removeHiddenId(id: string): { id: string };
clearHiddenIds(): void;
resetCuration(): void;
onSelectPageTab(pageTab: CurationPageTabs): { pageTab: CurationPageTabs };
}

interface CurationProps {
Expand All @@ -70,6 +74,7 @@ export const CurationLogic = kea<MakeLogicType<CurationValues, CurationActions,
removeHiddenId: (id) => ({ id }),
clearHiddenIds: true,
resetCuration: true,
onSelectPageTab: (pageTab) => ({ pageTab }),
}),
reducers: () => ({
dataLoading: [
Expand Down Expand Up @@ -164,6 +169,12 @@ export const CurationLogic = kea<MakeLogicType<CurationValues, CurationActions,
onCurationError: () => false,
},
],
selectedPageTab: [
'promoted',
{
onSelectPageTab: (_, { pageTab }) => pageTab,
},
],
}),
selectors: ({ selectors }) => ({
isAutomated: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { i18n } from '@kbn/i18n';
import { DataPanel } from '../../../data_panel';

import { SHOW_DOCUMENT_ACTION } from '../../constants';
import { HIDDEN_DOCUMENTS_TITLE } from '../constants';
import { CurationLogic } from '../curation_logic';
import { AddResultButton, CurationResult, convertToResultFormat } from '../results';

Expand All @@ -29,14 +30,7 @@ export const HiddenDocuments: React.FC = () => {
<DataPanel
filled
iconType="eyeClosed"
title={
<h2>
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curations.hiddenDocuments.title',
{ defaultMessage: 'Hidden documents' }
)}
</h2>
}
title={<h2>{HIDDEN_DOCUMENTS_TITLE}</h2>}
subtitle={i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curations.hiddenDocuments.description',
{ defaultMessage: 'Hidden documents will not appear in organic results.' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { DataPanel } from '../../../data_panel';

import { DEMOTE_DOCUMENT_ACTION } from '../../constants';
import { PROMOTED_DOCUMENTS_TITLE } from '../constants';
import { CurationLogic } from '../curation_logic';
import { AddResultButton, CurationResult, convertToResultFormat } from '../results';

Expand All @@ -46,14 +47,7 @@ export const PromotedDocuments: React.FC = () => {
<DataPanel
filled
iconType="starFilled"
title={
<h2>
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curations.promotedDocuments.title',
{ defaultMessage: 'Promoted documents' }
)}
</h2>
}
title={<h2>{PROMOTED_DOCUMENTS_TITLE}</h2>}
subtitle={
isAutomated ? (
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ import React from 'react';

import { shallow, ShallowWrapper } from 'enzyme';

import { getPageTitle, getPageHeaderActions } from '../../../../test_helpers';
import { EuiTab } from '@elastic/eui';

import { getPageTitle, getPageHeaderActions, getPageHeaderTabs } from '../../../../test_helpers';

jest.mock('./curation_logic', () => ({ CurationLogic: jest.fn() }));
import { CurationLogic } from './curation_logic';

import { PromotedDocuments, HiddenDocuments } from './documents';
import { ManualCuration } from './manual_curation';
import { AddResultFlyout } from './results';
import { SuggestedDocumentsCallout } from './suggested_documents_callout';
Expand All @@ -28,9 +31,11 @@ describe('ManualCuration', () => {
dataLoading: false,
queries: ['query A', 'query B'],
isFlyoutOpen: false,
selectedPageTab: 'promoted',
};
const actions = {
resetCuration: jest.fn(),
onSelectPageTab: jest.fn(),
};

beforeEach(() => {
Expand All @@ -39,7 +44,7 @@ describe('ManualCuration', () => {
setMockActions(actions);
});

it('renders', () => {
it('renders a view for managing a curation', () => {
const wrapper = shallow(<ManualCuration />);

expect(getPageTitle(wrapper)).toEqual('Manage curation');
Expand All @@ -51,12 +56,44 @@ describe('ManualCuration', () => {
]);
});

it('contains a suggested documents callout', () => {
it('includes set of tabs in the page header', () => {
const wrapper = shallow(<ManualCuration />);

const tabs = getPageHeaderTabs(wrapper).find(EuiTab);

tabs.at(0).simulate('click');
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(1, 'promoted');

tabs.at(1).simulate('click');
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(2, 'hidden');
});

it('contains a suggested documents callout when the selectedPageTab is ', () => {
const wrapper = shallow(<ManualCuration />);

expect(wrapper.find(SuggestedDocumentsCallout)).toHaveLength(1);
});

it('renders promoted documents when that tab is selected', () => {
setMockValues({ ...values, selectedPageTab: 'promoted' });
const wrapper = shallow(<ManualCuration />);
const tabs = getPageHeaderTabs(wrapper).find(EuiTab);

expect(tabs.at(0).prop('isSelected')).toEqual(true);

expect(wrapper.find(PromotedDocuments)).toHaveLength(1);
});

it('renders hidden documents when that tab is selected', () => {
setMockValues({ ...values, selectedPageTab: 'hidden' });
const wrapper = shallow(<ManualCuration />);
const tabs = getPageHeaderTabs(wrapper).find(EuiTab);

expect(tabs.at(1).prop('isSelected')).toEqual(true);

expect(wrapper.find(HiddenDocuments)).toHaveLength(1);
});

it('renders the add result flyout when open', () => {
setMockValues({ ...values, isFlyoutOpen: true });
const wrapper = shallow(<ManualCuration />);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { AppSearchPageTemplate } from '../../layout';
import { MANAGE_CURATION_TITLE, RESTORE_CONFIRMATION } from '../constants';
import { getCurationsBreadcrumbs } from '../utils';

import { PROMOTED_DOCUMENTS_TITLE, HIDDEN_DOCUMENTS_TITLE } from './constants';
import { CurationLogic } from './curation_logic';
import { PromotedDocuments, OrganicDocuments, HiddenDocuments } from './documents';
import { ActiveQuerySelect, ManageQueriesModal } from './queries';
Expand All @@ -25,10 +26,23 @@ import { SuggestedDocumentsCallout } from './suggested_documents_callout';

export const ManualCuration: React.FC = () => {
const { curationId } = useParams() as { curationId: string };
const { resetCuration } = useActions(CurationLogic({ curationId }));
const { dataLoading, queries } = useValues(CurationLogic({ curationId }));
const { onSelectPageTab, resetCuration } = useActions(CurationLogic({ curationId }));
const { dataLoading, queries, selectedPageTab } = useValues(CurationLogic({ curationId }));
const { isFlyoutOpen } = useValues(AddResultLogic);

const pageTabs = [
{
label: PROMOTED_DOCUMENTS_TITLE,
isSelected: selectedPageTab === 'promoted',
onClick: () => onSelectPageTab('promoted'),
},
{
label: HIDDEN_DOCUMENTS_TITLE,
isSelected: selectedPageTab === 'hidden',
onClick: () => onSelectPageTab('hidden'),
},
];

return (
<AppSearchPageTemplate
pageChrome={getCurationsBreadcrumbs([queries.join(', ')])}
Expand All @@ -44,6 +58,7 @@ export const ManualCuration: React.FC = () => {
{RESTORE_DEFAULTS_BUTTON_LABEL}
</EuiButton>,
],
tabs: pageTabs,
}}
isLoading={dataLoading}
>
Expand All @@ -57,12 +72,10 @@ export const ManualCuration: React.FC = () => {
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="xl" />

<PromotedDocuments />
{selectedPageTab === 'promoted' && <PromotedDocuments />}
{selectedPageTab === 'hidden' && <HiddenDocuments />}
<EuiSpacer />
<OrganicDocuments />
<EuiSpacer />
<HiddenDocuments />

{isFlyoutOpen && <AddResultFlyout />}
</AppSearchPageTemplate>
Expand Down

0 comments on commit 3135075

Please sign in to comment.