mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
## Summary * Fix: disables dropping a new data provider provider on the timeline, deleting an existing data provider, or choosing an action from the data provider context menu while the timeline is loading data to prevent draggable errors, like the one pictured in the screenshot below:  * Fix: the timeline settings icon appears too close to the `Refresh` button: ### Before (Chrome)  ### After (Chrome) <img width="1679" alt="timeline-gear-after-chrome" src="https://user-images.githubusercontent.com/4459398/58997064-1ce4ce00-87b8-11e9-9ffb-0f412e0018ad.png"> ### After (Firefox) <img width="1672" alt="timeline-gear-after-firefox" src="https://user-images.githubusercontent.com/4459398/58997113-4f8ec680-87b8-11e9-9b52-dc8a13d51361.png"> ### After (Safari) <img width="1680" alt="timeline-gear-after-safari" src="https://user-images.githubusercontent.com/4459398/58997169-911f7180-87b8-11e9-8186-0ff31e41ad53.png"> ### After (IE 11) <img width="1354" alt="timeline-gear-after-ie11" src="https://user-images.githubusercontent.com/4459398/58997306-40f4df00-87b9-11e9-844d-b12c7e16f7cb.png"> * Fix: the `Open Timeline` modal is showing bulk-delete actions ### Before (Chrome)  ### After (Chrome) <img width="1008" alt="open-timeline-after" src="https://user-images.githubusercontent.com/4459398/58997381-9af5a480-87b9-11e9-9909-2d68bd5ff2c3.png"> * Fix: action icons on the `Timelines` page and `Open Timelines` modal are not aligned with the counts ### Before (Chrome) <img width="1552" alt="all-timelines-before" src="https://user-images.githubusercontent.com/4459398/58997554-659d8680-87ba-11e9-868c-d92ad72f44b8.png"> ### After (Chrome) <img width="1550" alt="all-timelines-after" src="https://user-images.githubusercontent.com/4459398/58997656-d8a6fd00-87ba-11e9-9038-c0ca464f8c4d.png"> * Fix: Changed the title text of the fields browser from `Select Fields` to `Customize Columns` ### Before (Chrome) <img width="910" alt="fields-browser-before" src="https://user-images.githubusercontent.com/4459398/58997616-a4334100-87ba-11e9-9cd8-02ed9d265bf2.png"> ### After (Chrome) <img width="910" alt="fields-browser-after" src="https://user-images.githubusercontent.com/4459398/58997691-fa07e900-87ba-11e9-8cd9-6412d2cef8f0.png"> https://github.com/elastic/ingest-dev/issues/471
This commit is contained in:
parent
e20d5b88ce
commit
5746d01ae0
12 changed files with 378 additions and 72 deletions
|
@ -91,7 +91,7 @@ const TitleRow = pure<{ onOutsideClick: () => void; onUpdateColumns: OnUpdateCol
|
|||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiTitle size="s">
|
||||
<h2>{i18n.SELECT_FIELDS}</h2>
|
||||
<h2>{i18n.CUSTOMIZE_COLUMNS}</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlexItem>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import { ActionCreator } from 'typescript-fsa';
|
||||
import { connect } from 'react-redux';
|
||||
import { EuiButton } from '@elastic/eui';
|
||||
import { EuiButton, EuiToolTip } from '@elastic/eui';
|
||||
import { noop } from 'lodash/fp';
|
||||
import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
@ -116,16 +116,18 @@ export class StatefulFieldsBrowserComponent extends React.PureComponent<
|
|||
return (
|
||||
<>
|
||||
<FieldsBrowserButtonContainer>
|
||||
<EuiButton
|
||||
color="primary"
|
||||
data-test-subj="show-field-browser"
|
||||
iconSide="right"
|
||||
iconType="arrowDown"
|
||||
onClick={this.toggleShow}
|
||||
size="s"
|
||||
>
|
||||
{i18n.FIELDS}
|
||||
</EuiButton>
|
||||
<EuiToolTip content={i18n.CUSTOMIZE_COLUMNS}>
|
||||
<EuiButton
|
||||
color="primary"
|
||||
data-test-subj="show-field-browser"
|
||||
iconSide="right"
|
||||
iconType="arrowDown"
|
||||
onClick={this.toggleShow}
|
||||
size="s"
|
||||
>
|
||||
{i18n.FIELDS}
|
||||
</EuiButton>
|
||||
</EuiToolTip>
|
||||
</FieldsBrowserButtonContainer>
|
||||
|
||||
{show && (
|
||||
|
|
|
@ -24,6 +24,10 @@ export const COPY_TO_CLIPBOARD = i18n.translate('xpack.siem.fieldBrowser.copyToC
|
|||
defaultMessage: 'Copy to Clipboard',
|
||||
});
|
||||
|
||||
export const CUSTOMIZE_COLUMNS = i18n.translate('xpack.siem.fieldBrowser.customizeColumnsTitle', {
|
||||
defaultMessage: 'Customize Columns',
|
||||
});
|
||||
|
||||
export const DESCRIPTION = i18n.translate('xpack.siem.fieldBrowser.descriptionLabel', {
|
||||
defaultMessage: 'Description',
|
||||
});
|
||||
|
@ -62,10 +66,6 @@ export const RESET_FIELDS = i18n.translate('xpack.siem.fieldBrowser.resetFieldsL
|
|||
defaultMessage: 'Reset Fields',
|
||||
});
|
||||
|
||||
export const SELECT_FIELDS = i18n.translate('xpack.siem.fieldBrowser.selectFieldsTitle', {
|
||||
defaultMessage: 'Select Fields',
|
||||
});
|
||||
|
||||
export const VIEW_CATEGORY = (categoryId: string) =>
|
||||
i18n.translate('xpack.siem.fieldBrowser.viewCategoryTooltip', {
|
||||
defaultMessage: 'View all {categoryId} fields',
|
||||
|
|
|
@ -185,7 +185,6 @@ export class StatefulOpenTimelineComponent extends React.PureComponent<
|
|||
isLoading={loading}
|
||||
itemIdToExpandedNotesRowMap={itemIdToExpandedNotesRowMap}
|
||||
onAddTimelinesToFavorites={undefined}
|
||||
onDeleteSelected={this.onDeleteSelected}
|
||||
onlyFavorites={onlyFavorites}
|
||||
onOpenTimeline={this.openTimeline}
|
||||
onQueryChange={this.onQueryChange}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { EuiIcon, EuiToolTip } from '@elastic/eui';
|
||||
import * as React from 'react';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { ACTION_COLUMN_WIDTH, PositionedIcon } from './common_styles';
|
||||
import { FavoriteTimelineResult, OpenTimelineResult } from '../types';
|
||||
|
@ -13,16 +14,25 @@ import { getNotesCount, getPinnedEventCount } from '../helpers';
|
|||
|
||||
import * as i18n from '../translations';
|
||||
|
||||
const PinnedIcon = styled(EuiIcon)`
|
||||
position: relative;
|
||||
left: -3px;
|
||||
`;
|
||||
|
||||
const CommentIcon = styled(EuiIcon)`
|
||||
position: relative;
|
||||
left: -2px;
|
||||
`;
|
||||
|
||||
/**
|
||||
* Returns the columns that have icon headers
|
||||
*/
|
||||
export const getIconHeaderColumns = () => [
|
||||
{
|
||||
align: 'center',
|
||||
field: 'pinnedEventIds',
|
||||
name: (
|
||||
<EuiToolTip content={i18n.PINNED_EVENTS}>
|
||||
<EuiIcon data-test-subj="pinned-event-header-icon" size="m" color="subdued" type="pin" />
|
||||
<PinnedIcon data-test-subj="pinned-event-header-icon" size="m" color="subdued" type="pin" />
|
||||
</EuiToolTip>
|
||||
),
|
||||
render: (_: Record<string, boolean> | null | undefined, timelineResult: OpenTimelineResult) => (
|
||||
|
@ -32,11 +42,10 @@ export const getIconHeaderColumns = () => [
|
|||
width: ACTION_COLUMN_WIDTH,
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
field: 'eventIdToNoteIds',
|
||||
name: (
|
||||
<EuiToolTip content={i18n.NOTES}>
|
||||
<EuiIcon
|
||||
<CommentIcon
|
||||
data-test-subj="notes-count-header-icon"
|
||||
size="m"
|
||||
color="subdued"
|
||||
|
@ -52,7 +61,6 @@ export const getIconHeaderColumns = () => [
|
|||
width: ACTION_COLUMN_WIDTH,
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
field: 'favorite',
|
||||
name: (
|
||||
<EuiToolTip content={i18n.FAVORITES}>
|
||||
|
|
|
@ -19,6 +19,7 @@ import {
|
|||
OnToggleDataProviderEnabled,
|
||||
OnToggleDataProviderExcluded,
|
||||
} from '../events';
|
||||
import { TimelineContext } from '../timeline_context';
|
||||
|
||||
import { DataProvider } from './data_provider';
|
||||
import { Empty } from './empty';
|
||||
|
@ -83,23 +84,27 @@ export const DataProviders = pure<Props>(
|
|||
show,
|
||||
}) => (
|
||||
<DropTargetDataProviders data-test-subj="dataProviders">
|
||||
<DroppableWrapper isDropDisabled={!show} droppableId={getDroppableId(id)}>
|
||||
{dataProviders != null && dataProviders.length ? (
|
||||
<Providers
|
||||
browserFields={browserFields}
|
||||
id={id}
|
||||
dataProviders={dataProviders}
|
||||
onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery}
|
||||
onChangeDroppableAndProvider={onChangeDroppableAndProvider}
|
||||
onDataProviderEdited={onDataProviderEdited}
|
||||
onDataProviderRemoved={onDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={onToggleDataProviderEnabled}
|
||||
onToggleDataProviderExcluded={onToggleDataProviderExcluded}
|
||||
/>
|
||||
) : (
|
||||
<Empty />
|
||||
<TimelineContext.Consumer>
|
||||
{({ isLoading }) => (
|
||||
<DroppableWrapper isDropDisabled={!show || isLoading} droppableId={getDroppableId(id)}>
|
||||
{dataProviders != null && dataProviders.length ? (
|
||||
<Providers
|
||||
browserFields={browserFields}
|
||||
id={id}
|
||||
dataProviders={dataProviders}
|
||||
onChangeDataProviderKqlQuery={onChangeDataProviderKqlQuery}
|
||||
onChangeDroppableAndProvider={onChangeDroppableAndProvider}
|
||||
onDataProviderEdited={onDataProviderEdited}
|
||||
onDataProviderRemoved={onDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={onToggleDataProviderEnabled}
|
||||
onToggleDataProviderExcluded={onToggleDataProviderExcluded}
|
||||
/>
|
||||
) : (
|
||||
<Empty />
|
||||
)}
|
||||
</DroppableWrapper>
|
||||
)}
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Consumer>
|
||||
</DropTargetDataProviders>
|
||||
)
|
||||
);
|
||||
|
|
|
@ -30,6 +30,7 @@ interface OwnProps {
|
|||
kqlQuery: string;
|
||||
isEnabled: boolean;
|
||||
isExcluded: boolean;
|
||||
isLoading: boolean;
|
||||
isOpen: boolean;
|
||||
onDataProviderEdited?: OnDataProviderEdited;
|
||||
operator: QueryOperator;
|
||||
|
@ -52,6 +53,7 @@ export const getProviderActions = ({
|
|||
field,
|
||||
isEnabled,
|
||||
isExcluded,
|
||||
isLoading,
|
||||
operator,
|
||||
onDataProviderEdited,
|
||||
onFilterForFieldPresent,
|
||||
|
@ -67,6 +69,7 @@ export const getProviderActions = ({
|
|||
field: string;
|
||||
isEnabled: boolean;
|
||||
isExcluded: boolean;
|
||||
isLoading: boolean;
|
||||
onDataProviderEdited?: OnDataProviderEdited;
|
||||
onFilterForFieldPresent: () => void;
|
||||
operator: QueryOperator;
|
||||
|
@ -81,30 +84,35 @@ export const getProviderActions = ({
|
|||
items: [
|
||||
{
|
||||
className: EDIT_CLASS_NAME,
|
||||
disabled: isLoading,
|
||||
icon: 'pencil',
|
||||
name: i18n.EDIT_MENU_ITEM,
|
||||
panel: 1,
|
||||
},
|
||||
{
|
||||
className: EXCLUDE_CLASS_NAME,
|
||||
disabled: isLoading,
|
||||
icon: `${isExcluded ? 'plusInCircle' : 'minusInCircle'}`,
|
||||
name: isExcluded ? i18n.INCLUDE_DATA_PROVIDER : i18n.EXCLUDE_DATA_PROVIDER,
|
||||
onClick: toggleExcluded,
|
||||
},
|
||||
{
|
||||
className: ENABLE_CLASS_NAME,
|
||||
disabled: isLoading,
|
||||
icon: `${isEnabled ? 'eyeClosed' : 'eye'}`,
|
||||
name: isEnabled ? i18n.TEMPORARILY_DISABLE_DATA_PROVIDER : i18n.RE_ENABLE_DATA_PROVIDER,
|
||||
onClick: toggleEnabled,
|
||||
},
|
||||
{
|
||||
className: FILTER_FOR_FIELD_PRESENT_CLASS_NAME,
|
||||
disabled: isLoading,
|
||||
icon: 'logstashFilter',
|
||||
name: i18n.FILTER_FOR_FIELD_PRESENT,
|
||||
onClick: onFilterForFieldPresent,
|
||||
},
|
||||
{
|
||||
className: DELETE_CLASS_NAME,
|
||||
disabled: isLoading,
|
||||
icon: 'trash',
|
||||
name: i18n.DELETE_DATA_PROVIDER,
|
||||
onClick: deleteItem,
|
||||
|
@ -143,6 +151,7 @@ export class ProviderItemActions extends React.PureComponent<OwnProps> {
|
|||
field,
|
||||
isEnabled,
|
||||
isExcluded,
|
||||
isLoading,
|
||||
isOpen,
|
||||
operator,
|
||||
providerId,
|
||||
|
@ -159,6 +168,7 @@ export class ProviderItemActions extends React.PureComponent<OwnProps> {
|
|||
field,
|
||||
isEnabled,
|
||||
isExcluded,
|
||||
isLoading,
|
||||
onDataProviderEdited: this.onDataProviderEdited,
|
||||
onFilterForFieldPresent: this.onFilterForFieldPresent,
|
||||
operator,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { noop } from 'lodash/fp';
|
||||
import React, { PureComponent } from 'react';
|
||||
|
||||
import { BrowserFields } from '../../../containers/source';
|
||||
|
@ -12,6 +13,7 @@ import { OnDataProviderEdited } from '../events';
|
|||
import { ProviderBadge } from './provider_badge';
|
||||
import { ProviderItemActions } from './provider_item_actions';
|
||||
import { QueryOperator } from './data_provider';
|
||||
import { TimelineContext } from '../timeline_context';
|
||||
|
||||
interface ProviderItemBadgeProps {
|
||||
andProviderId?: string;
|
||||
|
@ -55,40 +57,43 @@ export class ProviderItemBadge extends PureComponent<ProviderItemBadgeProps, Own
|
|||
val,
|
||||
} = this.props;
|
||||
|
||||
const badge = (
|
||||
<ProviderBadge
|
||||
deleteProvider={deleteProvider}
|
||||
field={field}
|
||||
kqlQuery={kqlQuery}
|
||||
isEnabled={isEnabled}
|
||||
isExcluded={isExcluded}
|
||||
providerId={providerId}
|
||||
togglePopover={this.togglePopover}
|
||||
val={val}
|
||||
operator={operator}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<ProviderItemActions
|
||||
andProviderId={andProviderId}
|
||||
browserFields={browserFields}
|
||||
button={badge}
|
||||
closePopover={this.closePopover}
|
||||
deleteProvider={deleteProvider}
|
||||
field={field}
|
||||
kqlQuery={kqlQuery}
|
||||
isEnabled={isEnabled}
|
||||
isExcluded={isExcluded}
|
||||
isOpen={this.state.isPopoverOpen}
|
||||
onDataProviderEdited={onDataProviderEdited}
|
||||
operator={operator}
|
||||
providerId={providerId}
|
||||
timelineId={timelineId}
|
||||
toggleEnabledProvider={this.toggleEnabledProvider}
|
||||
toggleExcludedProvider={this.toggleExcludedProvider}
|
||||
value={val}
|
||||
/>
|
||||
<TimelineContext.Consumer>
|
||||
{({ isLoading }) => (
|
||||
<ProviderItemActions
|
||||
andProviderId={andProviderId}
|
||||
browserFields={browserFields}
|
||||
button={
|
||||
<ProviderBadge
|
||||
deleteProvider={!isLoading ? deleteProvider : noop}
|
||||
field={field}
|
||||
kqlQuery={kqlQuery}
|
||||
isEnabled={isEnabled}
|
||||
isExcluded={isExcluded}
|
||||
providerId={providerId}
|
||||
togglePopover={this.togglePopover}
|
||||
val={val}
|
||||
operator={operator}
|
||||
/>
|
||||
}
|
||||
closePopover={this.closePopover}
|
||||
deleteProvider={deleteProvider}
|
||||
field={field}
|
||||
kqlQuery={kqlQuery}
|
||||
isEnabled={isEnabled}
|
||||
isExcluded={isExcluded}
|
||||
isLoading={isLoading}
|
||||
isOpen={this.state.isPopoverOpen}
|
||||
onDataProviderEdited={onDataProviderEdited}
|
||||
operator={operator}
|
||||
providerId={providerId}
|
||||
timelineId={timelineId}
|
||||
toggleEnabledProvider={this.toggleEnabledProvider}
|
||||
toggleExcludedProvider={this.toggleExcludedProvider}
|
||||
value={val}
|
||||
/>
|
||||
)}
|
||||
</TimelineContext.Consumer>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import * as React from 'react';
|
|||
|
||||
import { TestProviders } from '../../../mock/test_providers';
|
||||
import { DroppableWrapper } from '../../drag_and_drop/droppable_wrapper';
|
||||
import { TimelineContext } from '../timeline_context';
|
||||
|
||||
import { mockDataProviders } from './mock/mock_data_providers';
|
||||
import { getDraggableId, Providers } from './providers';
|
||||
|
@ -90,6 +91,36 @@ describe('Providers', () => {
|
|||
expect(mockOnDataProviderRemoved.mock.calls[0][0]).toEqual('id-Provider 1');
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onDataProviderRemoved callback when the close button is clicked', () => {
|
||||
const mockOnDataProviderRemoved = jest.fn();
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={mockDataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={mockOnDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={jest.fn()}
|
||||
onToggleDataProviderExcluded={jest.fn()}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"] svg')
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(mockOnDataProviderRemoved).not.toBeCalled();
|
||||
});
|
||||
|
||||
test('it invokes the onDataProviderRemoved callback when you click on the option "Delete" in the provider menu', () => {
|
||||
const mockOnDataProviderRemoved = jest.fn();
|
||||
const wrapper = mount(
|
||||
|
@ -113,13 +144,51 @@ describe('Providers', () => {
|
|||
.find('[data-test-subj="providerBadge"]')
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
wrapper
|
||||
.find(`[data-test-subj="providerActions"] .${DELETE_CLASS_NAME}`)
|
||||
.first()
|
||||
.simulate('click');
|
||||
expect(mockOnDataProviderRemoved.mock.calls[0][0]).toEqual('id-Provider 1');
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onDataProviderRemoved callback when you click on the option "Delete" in the provider menu', () => {
|
||||
const mockOnDataProviderRemoved = jest.fn();
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={mockDataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={mockOnDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={jest.fn()}
|
||||
onToggleDataProviderExcluded={jest.fn()}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
wrapper
|
||||
.find(`[data-test-subj="providerActions"] .${DELETE_CLASS_NAME}`)
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(mockOnDataProviderRemoved).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getDraggableId', () => {
|
||||
|
@ -150,6 +219,7 @@ describe('Providers', () => {
|
|||
</DroppableWrapper>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.first()
|
||||
|
@ -165,6 +235,42 @@ describe('Providers', () => {
|
|||
providerId: 'id-Provider 1',
|
||||
});
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onToggleDataProviderEnabled callback when you click on the option "Temporary disable" in the provider menu', () => {
|
||||
const mockOnToggleDataProviderEnabled = jest.fn();
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={mockDataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={jest.fn()}
|
||||
onToggleDataProviderEnabled={mockOnToggleDataProviderEnabled}
|
||||
onToggleDataProviderExcluded={jest.fn()}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.first()
|
||||
.simulate('click');
|
||||
wrapper.update();
|
||||
|
||||
wrapper
|
||||
.find(`[data-test-subj="providerActions"] .${ENABLE_CLASS_NAME}`)
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(mockOnToggleDataProviderEnabled).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#onToggleDataProviderExcluded', () => {
|
||||
|
@ -206,6 +312,44 @@ describe('Providers', () => {
|
|||
providerId: 'id-Provider 1',
|
||||
});
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onToggleDataProviderExcluded callback when you click on the option "Exclude results" in the provider menu', () => {
|
||||
const onToggleDataProviderExcluded = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={mockDataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={jest.fn()}
|
||||
onToggleDataProviderEnabled={jest.fn()}
|
||||
onToggleDataProviderExcluded={onToggleDataProviderExcluded}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
wrapper
|
||||
.find(`[data-test-subj="providerActions"] .${EXCLUDE_CLASS_NAME}`)
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(onToggleDataProviderExcluded).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#ProviderWithAndProvider', () => {
|
||||
|
@ -276,6 +420,43 @@ describe('Providers', () => {
|
|||
expect(mockOnDataProviderRemoved.mock.calls[0]).toEqual(['id-Provider 1', 'id-Provider 2']);
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onDataProviderRemoved callback when you click on the close button is clicked', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
dataProviders[0].and = mockDataProviders.slice(1, 3);
|
||||
const mockOnDataProviderRemoved = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={mockDataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={mockOnDataProviderRemoved}
|
||||
onToggleDataProviderEnabled={jest.fn()}
|
||||
onToggleDataProviderExcluded={jest.fn()}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.at(4)
|
||||
.find('svg')
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
expect(mockOnDataProviderRemoved).not.toBeCalled();
|
||||
});
|
||||
|
||||
test('it invokes the onToggleDataProviderEnabled callback when you click on the option "Temporary disable" in the provider menu', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
dataProviders[0].and = mockDataProviders.slice(1, 3);
|
||||
|
@ -318,6 +499,46 @@ describe('Providers', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onToggleDataProviderEnabled callback when you click on the option "Temporary disable" in the provider menu', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
dataProviders[0].and = mockDataProviders.slice(1, 3);
|
||||
const mockOnToggleDataProviderEnabled = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={dataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={jest.fn()}
|
||||
onToggleDataProviderEnabled={mockOnToggleDataProviderEnabled}
|
||||
onToggleDataProviderExcluded={jest.fn()}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.at(4)
|
||||
.simulate('click');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
wrapper
|
||||
.find(`[data-test-subj="providerActions"] .${ENABLE_CLASS_NAME}`)
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(mockOnToggleDataProviderEnabled).not.toBeCalled();
|
||||
});
|
||||
|
||||
test('it invokes the onToggleDataProviderExcluded callback when you click on the option "Exclude results" in the provider menu', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
dataProviders[0].and = mockDataProviders.slice(1, 3);
|
||||
|
@ -359,5 +580,45 @@ describe('Providers', () => {
|
|||
providerId: 'id-Provider 1',
|
||||
});
|
||||
});
|
||||
|
||||
test('while loading data, it does NOT invoke the onToggleDataProviderExcluded callback when you click on the option "Exclude results" in the provider menu', () => {
|
||||
const dataProviders = mockDataProviders.slice(0, 1);
|
||||
dataProviders[0].and = mockDataProviders.slice(1, 3);
|
||||
const mockOnToggleDataProviderExcluded = jest.fn();
|
||||
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<TimelineContext.Provider value={{ isLoading: true }}>
|
||||
<DroppableWrapper droppableId="unitTest">
|
||||
<Providers
|
||||
browserFields={{}}
|
||||
dataProviders={dataProviders}
|
||||
id="foo"
|
||||
onChangeDataProviderKqlQuery={jest.fn()}
|
||||
onChangeDroppableAndProvider={jest.fn()}
|
||||
onDataProviderEdited={jest.fn()}
|
||||
onDataProviderRemoved={jest.fn()}
|
||||
onToggleDataProviderEnabled={jest.fn()}
|
||||
onToggleDataProviderExcluded={mockOnToggleDataProviderExcluded}
|
||||
/>
|
||||
</DroppableWrapper>
|
||||
</TimelineContext.Provider>
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
wrapper
|
||||
.find('[data-test-subj="providerBadge"]')
|
||||
.at(4)
|
||||
.simulate('click');
|
||||
|
||||
wrapper.update();
|
||||
|
||||
wrapper
|
||||
.find(`[data-test-subj="providerActions"] .${EXCLUDE_CLASS_NAME}`)
|
||||
.first()
|
||||
.simulate('click');
|
||||
|
||||
expect(mockOnToggleDataProviderExcluded).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -59,6 +59,7 @@ const DescriptionPopoverMenuContainer = styled.div`
|
|||
`;
|
||||
|
||||
const SettingsIcon = styled(EuiIcon)`
|
||||
margin-left: 4px;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ import { StaticIndexPattern } from 'ui/index_patterns';
|
|||
import { BrowserFields } from '../../containers/source';
|
||||
import { TimelineQuery } from '../../containers/timeline';
|
||||
import { Direction } from '../../graphql/types';
|
||||
import { KqlMode } from '../../store/timeline/model';
|
||||
import { AutoSizer } from '../auto_sizer';
|
||||
|
||||
import { ColumnHeader } from './body/column_headers/column_header';
|
||||
|
@ -34,7 +35,7 @@ import { Footer, footerHeight } from './footer';
|
|||
import { TimelineHeader } from './header';
|
||||
import { calculateBodyHeight, combineQueries } from './helpers';
|
||||
import { TimelineRefetch } from './refetch_timeline';
|
||||
import { KqlMode } from '../../store/timeline/model';
|
||||
import { TimelineContext } from './timeline_context';
|
||||
|
||||
const WrappedByAutoSizer = styled.div`
|
||||
width: 100%;
|
||||
|
@ -150,6 +151,7 @@ export const Timeline = pure<Props>(
|
|||
>
|
||||
{({ events, loading, totalCount, pageInfo, loadMore, getUpdatedAt, refetch }) => (
|
||||
<TimelineRefetch loading={loading} id={id} refetch={refetch}>
|
||||
<TimelineContext.Provider value={{ isLoading: loading }} />
|
||||
<StatefulBody
|
||||
browserFields={browserFields}
|
||||
data={events}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
|
||||
export interface TimelineContextData {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export const TimelineContext = React.createContext<TimelineContextData>({ isLoading: false });
|
Loading…
Add table
Add a link
Reference in a new issue