mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[App Search] Added a History tab to the Automated Curation detail view (#115090)
This commit is contained in:
parent
e9d6a072a8
commit
c2571c7faf
4 changed files with 140 additions and 9 deletions
|
@ -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';
|
||||
|
@ -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 = {
|
||||
|
@ -39,6 +41,7 @@ describe('AutomatedCuration', () => {
|
|||
suggestion: {
|
||||
status: 'applied',
|
||||
},
|
||||
queries: ['foo'],
|
||||
},
|
||||
activeQuery: 'query A',
|
||||
isAutomated: true,
|
||||
|
@ -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', () => {
|
||||
|
|
|
@ -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,
|
||||
|
@ -26,19 +29,25 @@ 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,
|
||||
|
@ -46,6 +55,16 @@ export const AutomatedCuration: React.FC = () => {
|
|||
isSelected: false,
|
||||
disabled: true,
|
||||
},
|
||||
{
|
||||
label: i18n.translate(
|
||||
'xpack.enterpriseSearch.appSearch.engine.curation.detail.historyButtonLabel',
|
||||
{
|
||||
defaultMessage: 'History',
|
||||
}
|
||||
),
|
||||
isSelected: selectedPageTab === HISTORY,
|
||||
onClick: () => setSelectedPageTab(HISTORY),
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -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'
|
||||
);
|
||||
});
|
||||
});
|
|
@ -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>
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue