Skip to content

Commit

Permalink
[App Search] Added a History tab to the Automated Curation detail view (
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonStoltz authored and byronhulcher committed Oct 19, 2021
1 parent a12a4d2 commit 7d66193
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import '../../../../__mocks__/shallow_useeffect.mock';
import { setMockActions, setMockValues } from '../../../../__mocks__/kea_logic';
import { mockUseParams } from '../../../../__mocks__/react_router';

import '../../../__mocks__/engine_logic.mock';

import React from 'react';
Expand All @@ -27,6 +28,7 @@ import { CurationLogic } from './curation_logic';

import { DeleteCurationButton } from './delete_curation_button';
import { PromotedDocuments, OrganicDocuments } from './documents';
import { History } from './history';

describe('AutomatedCuration', () => {
const values = {
Expand All @@ -39,6 +41,7 @@ describe('AutomatedCuration', () => {
suggestion: {
status: 'applied',
},
queries: ['foo'],
},
activeQuery: 'query A',
isAutomated: true,
Expand All @@ -61,20 +64,46 @@ describe('AutomatedCuration', () => {
expect(wrapper.is(AppSearchPageTemplate));
expect(wrapper.find(PromotedDocuments)).toHaveLength(1);
expect(wrapper.find(OrganicDocuments)).toHaveLength(1);
expect(wrapper.find(History)).toHaveLength(0);
});

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

expect(tabs).toHaveLength(2);
expect(tabs).toHaveLength(3);

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);

expect(tabs.at(2).prop('isSelected')).toBe(false);

// Clicking on the History tab shows the history view
tabs.at(2).simulate('click');

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(wrapper.find(PromotedDocuments)).toHaveLength(1);
expect(wrapper.find(OrganicDocuments)).toHaveLength(1);
expect(wrapper.find(History)).toHaveLength(0);
});

it('initializes CurationLogic with a curationId prop from URL param', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,18 @@
* 2.0.
*/

import React from 'react';
import React, { useState } from 'react';
import { useParams } from 'react-router-dom';

import { useValues, useActions } from 'kea';

import { EuiButton, EuiBadge, EuiLoadingSpinner, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { i18n } from '@kbn/i18n';

import { EngineLogic } from '../../engine';
import { AppSearchPageTemplate } from '../../layout';
import { AutomatedIcon } from '../components/automated_icon';

import {
AUTOMATED_LABEL,
COVERT_TO_MANUAL_BUTTON_LABEL,
Expand All @@ -26,26 +29,42 @@ import { HIDDEN_DOCUMENTS_TITLE, PROMOTED_DOCUMENTS_TITLE } from './constants';
import { CurationLogic } from './curation_logic';
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 { engineName } = useValues(EngineLogic);
const [selectedPageTab, setSelectedPageTab] = useState(PROMOTED);

// This tab group is meant to visually mirror the dynamic group of tags in the ManualCuration component
const pageTabs = [
{
label: PROMOTED_DOCUMENTS_TITLE,
append: <EuiBadge>{curation.promoted.length}</EuiBadge>,
isSelected: true,
isSelected: selectedPageTab === PROMOTED,
onClick: () => setSelectedPageTab(PROMOTED),
},
{
label: HIDDEN_DOCUMENTS_TITLE,
append: <EuiBadge isDisabled>0</EuiBadge>,
isSelected: false,
disabled: true,
},
{
label: i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curation.detail.historyButtonLabel',
{
defaultMessage: 'History',
}
),
isSelected: selectedPageTab === HISTORY,
onClick: () => setSelectedPageTab(HISTORY),
},
];

return (
Expand Down Expand Up @@ -83,8 +102,11 @@ export const AutomatedCuration: React.FC = () => {
}}
isLoading={dataLoading}
>
<PromotedDocuments />
<OrganicDocuments />
{selectedPageTab === PROMOTED && <PromotedDocuments />}
{selectedPageTab === PROMOTED && <OrganicDocuments />}
{selectedPageTab === HISTORY && (
<History query={curation.queries[0]} engineName={engineName} />
)}
</AppSearchPageTemplate>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 { EntSearchLogStream } from '../../../../shared/log_stream';

import { History } from './history';

describe('History', () => {
it('renders', () => {
const wrapper = shallow(<History engineName="foo" query="some text" />);
expect(wrapper.find(EntSearchLogStream).prop('query')).toEqual(
'appsearch.search_relevance_suggestions.query: some text and event.kind: event and event.dataset: search-relevance-suggestions and appsearch.search_relevance_suggestions.engine: foo and event.action: curation_suggestion'
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 { i18n } from '@kbn/i18n';

import { EntSearchLogStream } from '../../../../shared/log_stream';
import { DataPanel } from '../../data_panel';

interface Props {
query: string;
engineName: string;
}

export const History: React.FC<Props> = ({ query, engineName }) => {
const filters = [
`appsearch.search_relevance_suggestions.query: ${query}`,
'event.kind: event',
'event.dataset: search-relevance-suggestions',
`appsearch.search_relevance_suggestions.engine: ${engineName}`,
'event.action: curation_suggestion',
];

return (
<DataPanel
iconType="tableDensityNormal"
title={
<h2>
{i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curation.detail.historyTableTitle',
{
defaultMessage: 'Automated curation changes',
}
)}
</h2>
}
subtitle={i18n.translate(
'xpack.enterpriseSearch.appSearch.engine.curation.detail.historyTableDescription',
{
defaultMessage: 'A detailed log of recent changes to your automated curation.',
}
)}
hasBorder
>
<EntSearchLogStream
hoursAgo={720}
query={filters.join(' and ')}
columns={[{ type: 'timestamp' }, { type: 'message' }]}
/>
</DataPanel>
);
};

0 comments on commit 7d66193

Please sign in to comment.