[App Search] Static Curations History Tab (#113481)
This commit is contained in:
parent
8d1c96cd7e
commit
a532ea5c05
13 changed files with 278 additions and 3 deletions
|
@ -23,7 +23,7 @@ import { EngineLogic, generateEnginePath } from '../engine';
|
||||||
import { DELETE_CONFIRMATION_MESSAGE, DELETE_SUCCESS_MESSAGE } from './constants';
|
import { DELETE_CONFIRMATION_MESSAGE, DELETE_SUCCESS_MESSAGE } from './constants';
|
||||||
import { Curation, CurationsAPIResponse } from './types';
|
import { Curation, CurationsAPIResponse } from './types';
|
||||||
|
|
||||||
type CurationsPageTabs = 'overview' | 'settings';
|
type CurationsPageTabs = 'overview' | 'settings' | 'history';
|
||||||
|
|
||||||
interface CurationsValues {
|
interface CurationsValues {
|
||||||
dataLoading: boolean;
|
dataLoading: boolean;
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { EuiTab } from '@elastic/eui';
|
||||||
import { getPageHeaderTabs, getPageTitle } from '../../../../test_helpers';
|
import { getPageHeaderTabs, getPageTitle } from '../../../../test_helpers';
|
||||||
|
|
||||||
import { Curations } from './curations';
|
import { Curations } from './curations';
|
||||||
|
import { CurationsHistory } from './curations_history/curations_history';
|
||||||
import { CurationsOverview } from './curations_overview';
|
import { CurationsOverview } from './curations_overview';
|
||||||
import { CurationsSettings } from './curations_settings';
|
import { CurationsSettings } from './curations_settings';
|
||||||
|
|
||||||
|
@ -70,7 +71,10 @@ describe('Curations', () => {
|
||||||
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(1, 'overview');
|
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(1, 'overview');
|
||||||
|
|
||||||
tabs.at(1).simulate('click');
|
tabs.at(1).simulate('click');
|
||||||
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(2, 'settings');
|
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(2, 'history');
|
||||||
|
|
||||||
|
tabs.at(2).simulate('click');
|
||||||
|
expect(actions.onSelectPageTab).toHaveBeenNthCalledWith(3, 'settings');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders an overview view', () => {
|
it('renders an overview view', () => {
|
||||||
|
@ -83,12 +87,22 @@ describe('Curations', () => {
|
||||||
expect(wrapper.find(CurationsOverview)).toHaveLength(1);
|
expect(wrapper.find(CurationsOverview)).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders a history view', () => {
|
||||||
|
setMockValues({ ...values, selectedPageTab: 'history' });
|
||||||
|
const wrapper = shallow(<Curations />);
|
||||||
|
const tabs = getPageHeaderTabs(wrapper).find(EuiTab);
|
||||||
|
|
||||||
|
expect(tabs.at(1).prop('isSelected')).toEqual(true);
|
||||||
|
|
||||||
|
expect(wrapper.find(CurationsHistory)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
it('renders a settings view', () => {
|
it('renders a settings view', () => {
|
||||||
setMockValues({ ...values, selectedPageTab: 'settings' });
|
setMockValues({ ...values, selectedPageTab: 'settings' });
|
||||||
const wrapper = shallow(<Curations />);
|
const wrapper = shallow(<Curations />);
|
||||||
const tabs = getPageHeaderTabs(wrapper).find(EuiTab);
|
const tabs = getPageHeaderTabs(wrapper).find(EuiTab);
|
||||||
|
|
||||||
expect(tabs.at(1).prop('isSelected')).toEqual(true);
|
expect(tabs.at(2).prop('isSelected')).toEqual(true);
|
||||||
|
|
||||||
expect(wrapper.find(CurationsSettings)).toHaveLength(1);
|
expect(wrapper.find(CurationsSettings)).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { CURATIONS_OVERVIEW_TITLE, CREATE_NEW_CURATION_TITLE } from '../constant
|
||||||
import { CurationsLogic } from '../curations_logic';
|
import { CurationsLogic } from '../curations_logic';
|
||||||
import { getCurationsBreadcrumbs } from '../utils';
|
import { getCurationsBreadcrumbs } from '../utils';
|
||||||
|
|
||||||
|
import { CurationsHistory } from './curations_history/curations_history';
|
||||||
import { CurationsOverview } from './curations_overview';
|
import { CurationsOverview } from './curations_overview';
|
||||||
import { CurationsSettings } from './curations_settings';
|
import { CurationsSettings } from './curations_settings';
|
||||||
|
|
||||||
|
@ -39,6 +40,16 @@ export const Curations: React.FC = () => {
|
||||||
isSelected: selectedPageTab === 'overview',
|
isSelected: selectedPageTab === 'overview',
|
||||||
onClick: () => onSelectPageTab('overview'),
|
onClick: () => onSelectPageTab('overview'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: i18n.translate(
|
||||||
|
'xpack.enterpriseSearch.appSearch.engine.curations.historyPageTabLabel',
|
||||||
|
{
|
||||||
|
defaultMessage: 'History',
|
||||||
|
}
|
||||||
|
),
|
||||||
|
isSelected: selectedPageTab === 'history',
|
||||||
|
onClick: () => onSelectPageTab('history'),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: i18n.translate(
|
label: i18n.translate(
|
||||||
'xpack.enterpriseSearch.appSearch.engine.curations.settingsPageTabLabel',
|
'xpack.enterpriseSearch.appSearch.engine.curations.settingsPageTabLabel',
|
||||||
|
@ -74,6 +85,7 @@ export const Curations: React.FC = () => {
|
||||||
isLoading={dataLoading && !curations.length}
|
isLoading={dataLoading && !curations.length}
|
||||||
>
|
>
|
||||||
{selectedPageTab === 'overview' && <CurationsOverview />}
|
{selectedPageTab === 'overview' && <CurationsOverview />}
|
||||||
|
{selectedPageTab === 'history' && <CurationsHistory />}
|
||||||
{selectedPageTab === 'settings' && <CurationsSettings />}
|
{selectedPageTab === 'settings' && <CurationsSettings />}
|
||||||
</AppSearchPageTemplate>
|
</AppSearchPageTemplate>
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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 { DataPanel } from '../../../../data_panel';
|
||||||
|
|
||||||
|
import { CurationChangesPanel } from './curation_changes_panel';
|
||||||
|
|
||||||
|
describe('CurationChangesPanel', () => {
|
||||||
|
it('renders', () => {
|
||||||
|
const wrapper = shallow(<CurationChangesPanel />);
|
||||||
|
|
||||||
|
expect(wrapper.is(DataPanel)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -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 { DataPanel } from '../../../../data_panel';
|
||||||
|
|
||||||
|
export const CurationChangesPanel: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<DataPanel
|
||||||
|
title={<h2>Automated curation changes</h2>}
|
||||||
|
subtitle={<span>A detailed log of recent changes to your automated curations</span>}
|
||||||
|
iconType="visTable"
|
||||||
|
hasBorder
|
||||||
|
>
|
||||||
|
Embedded logs view goes here...
|
||||||
|
</DataPanel>
|
||||||
|
);
|
||||||
|
};
|
|
@ -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 { EuiBasicTable } from '@elastic/eui';
|
||||||
|
|
||||||
|
import { DataPanel } from '../../../../data_panel';
|
||||||
|
|
||||||
|
import { IgnoredSuggestionsPanel } from './ignored_suggestions_panel';
|
||||||
|
|
||||||
|
describe('IgnoredSuggestionsPanel', () => {
|
||||||
|
it('renders', () => {
|
||||||
|
const wrapper = shallow(<IgnoredSuggestionsPanel />);
|
||||||
|
|
||||||
|
expect(wrapper.is(DataPanel)).toBe(true);
|
||||||
|
expect(wrapper.find(EuiBasicTable)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* 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 { CustomItemAction, EuiBasicTable, EuiBasicTableColumn, EuiLink } from '@elastic/eui';
|
||||||
|
|
||||||
|
import { DataPanel } from '../../../../data_panel';
|
||||||
|
import { CurationSuggestion } from '../../../types';
|
||||||
|
|
||||||
|
export const IgnoredSuggestionsPanel: React.FC = () => {
|
||||||
|
const ignoredSuggestions: CurationSuggestion[] = [];
|
||||||
|
|
||||||
|
const allowSuggestion = (query: string) => alert(query);
|
||||||
|
|
||||||
|
const actions: Array<CustomItemAction<CurationSuggestion>> = [
|
||||||
|
{
|
||||||
|
render: (item: CurationSuggestion) => {
|
||||||
|
return (
|
||||||
|
<EuiLink onClick={() => allowSuggestion(item.query)} color="primary">
|
||||||
|
Allow
|
||||||
|
</EuiLink>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const columns: Array<EuiBasicTableColumn<CurationSuggestion>> = [
|
||||||
|
{
|
||||||
|
field: 'query',
|
||||||
|
name: 'Query',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
actions,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<DataPanel
|
||||||
|
title={<h2>Ignored queries</h2>}
|
||||||
|
subtitle={<span>You won’t be notified about suggestions for these queries</span>}
|
||||||
|
iconType="eyeClosed"
|
||||||
|
hasBorder
|
||||||
|
>
|
||||||
|
<EuiBasicTable items={ignoredSuggestions} itemId="query" columns={columns} />
|
||||||
|
</DataPanel>
|
||||||
|
);
|
||||||
|
};
|
|
@ -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 { CurationChangesPanel } from './curation_changes_panel';
|
||||||
|
export { IgnoredSuggestionsPanel } from './ignored_suggestions_panel';
|
||||||
|
export { RejectedCurationsPanel } from './rejected_curations_panel';
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* 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 { DataPanel } from '../../../../data_panel';
|
||||||
|
|
||||||
|
import { RejectedCurationsPanel } from './rejected_curations_panel';
|
||||||
|
|
||||||
|
describe('RejectedCurationsPanel', () => {
|
||||||
|
it('renders', () => {
|
||||||
|
const wrapper = shallow(<RejectedCurationsPanel />);
|
||||||
|
|
||||||
|
expect(wrapper.is(DataPanel)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
|
@ -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 { DataPanel } from '../../../../data_panel';
|
||||||
|
|
||||||
|
export const RejectedCurationsPanel: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<DataPanel
|
||||||
|
title={<h2>Rececntly rejected sugggestions</h2>}
|
||||||
|
subtitle={<span>Recent suggestions that are still valid can be re-enabled from here</span>}
|
||||||
|
iconType="crossInACircleFilled"
|
||||||
|
hasBorder
|
||||||
|
>
|
||||||
|
Embedded logs view goes here...
|
||||||
|
</DataPanel>
|
||||||
|
);
|
||||||
|
};
|
|
@ -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 {
|
||||||
|
CurationChangesPanel,
|
||||||
|
IgnoredSuggestionsPanel,
|
||||||
|
RejectedCurationsPanel,
|
||||||
|
} from './components';
|
||||||
|
import { CurationsHistory } from './curations_history';
|
||||||
|
|
||||||
|
describe('CurationsHistory', () => {
|
||||||
|
it('renders', () => {
|
||||||
|
const wrapper = shallow(<CurationsHistory />);
|
||||||
|
|
||||||
|
expect(wrapper.find(CurationChangesPanel)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(RejectedCurationsPanel)).toHaveLength(1);
|
||||||
|
expect(wrapper.find(IgnoredSuggestionsPanel)).toHaveLength(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* 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 { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||||
|
|
||||||
|
import {
|
||||||
|
CurationChangesPanel,
|
||||||
|
IgnoredSuggestionsPanel,
|
||||||
|
RejectedCurationsPanel,
|
||||||
|
} from './components';
|
||||||
|
|
||||||
|
export const CurationsHistory: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<EuiFlexGroup>
|
||||||
|
<EuiFlexItem grow={2}>
|
||||||
|
<EuiFlexGroup direction="column">
|
||||||
|
<EuiFlexItem>
|
||||||
|
<CurationChangesPanel />
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem>
|
||||||
|
<RejectedCurationsPanel />
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
</EuiFlexItem>
|
||||||
|
<EuiFlexItem grow={1}>
|
||||||
|
<IgnoredSuggestionsPanel />
|
||||||
|
</EuiFlexItem>
|
||||||
|
</EuiFlexGroup>
|
||||||
|
);
|
||||||
|
};
|
|
@ -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 { CurationsHistory } from './curations_history';
|
Loading…
Reference in a new issue