Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use "Apply_filter_trigger" in "explore underlying data" action #71445

Merged
merged 13 commits into from
Aug 1, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/plugins/embeddable/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"server": false,
"ui": true,
"requiredPlugins": [
"data",
"inspector",
"uiActions"
],
Expand Down
2 changes: 0 additions & 2 deletions src/plugins/embeddable/public/mocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,6 @@ const createStartContract = (): Start => {
getAttributeService: jest.fn(),
getEmbeddablePanel: jest.fn(),
getStateTransfer: jest.fn(() => createEmbeddableStateTransferMock() as EmbeddableStateTransfer),
filtersAndTimeRangeFromContext: jest.fn(),
filtersFromContext: jest.fn(),
};
return startContract;
};
Expand Down
60 changes: 1 addition & 59 deletions src/plugins/embeddable/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,7 @@
* under the License.
*/
import React from 'react';
import {
DataPublicPluginSetup,
DataPublicPluginStart,
Filter,
TimeRange,
esFilters,
} from '../../data/public';
import { DataPublicPluginSetup, DataPublicPluginStart } from '../../data/public';
import { getSavedObjectFinder } from '../../saved_objects/public';
import { UiActionsSetup, UiActionsStart } from '../../ui_actions/public';
import { Start as InspectorStart } from '../../inspector/public';
Expand All @@ -44,9 +38,6 @@ import {
IEmbeddable,
EmbeddablePanel,
SavedObjectEmbeddableInput,
ChartActionContext,
isRangeSelectTriggerContext,
isValueClickTriggerContext,
} from './lib';
import { EmbeddableFactoryDefinition } from './lib/embeddables/embeddable_factory_definition';
import { AttributeService } from './lib/embeddables/attribute_service';
Expand Down Expand Up @@ -92,18 +83,6 @@ export interface EmbeddableStart {
type: string
) => AttributeService<A, V, R>;

/**
* Given {@link ChartActionContext} returns a list of `data` plugin {@link Filter} entries.
*/
filtersFromContext: (context: ChartActionContext) => Promise<Filter[]>;

/**
* Returns possible time range and filters that can be constructed from {@link ChartActionContext} object.
*/
filtersAndTimeRangeFromContext: (
context: ChartActionContext
) => Promise<{ filters: Filter[]; timeRange?: TimeRange }>;

EmbeddablePanel: EmbeddablePanelHOC;
getEmbeddablePanel: (stateTransfer?: EmbeddableStateTransfer) => EmbeddablePanelHOC;
getStateTransfer: (history?: ScopedHistory) => EmbeddableStateTransfer;
Expand Down Expand Up @@ -155,41 +134,6 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
this.outgoingOnlyStateTransfer = new EmbeddableStateTransfer(core.application.navigateToApp);
this.isRegistryReady = true;

const filtersFromContext: EmbeddableStart['filtersFromContext'] = async (context) => {
try {
if (isRangeSelectTriggerContext(context))
return await data.actions.createFiltersFromRangeSelectAction(context.data);
if (isValueClickTriggerContext(context))
return await data.actions.createFiltersFromValueClickAction(context.data);
// eslint-disable-next-line no-console
console.warn("Can't extract filters from action.", context);
} catch (error) {
// eslint-disable-next-line no-console
console.warn('Error extracting filters from action. Returning empty filter list.', error);
}
return [];
};

const filtersAndTimeRangeFromContext: EmbeddableStart['filtersAndTimeRangeFromContext'] = async (
context
) => {
const filters = await filtersFromContext(context);

if (!context.data.timeFieldName) return { filters };

const { timeRangeFilter, restOfFilters } = esFilters.extractTimeFilter(
context.data.timeFieldName,
filters
);

return {
filters: restOfFilters,
timeRange: timeRangeFilter
? esFilters.convertRangeFilterToTimeRangeString(timeRangeFilter)
: undefined,
};
};

const getEmbeddablePanelHoc = (stateTransfer?: EmbeddableStateTransfer) => ({
embeddable,
hideHeader,
Expand All @@ -216,8 +160,6 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
getEmbeddableFactory: this.getEmbeddableFactory,
getEmbeddableFactories: this.getEmbeddableFactories,
getAttributeService: (type: string) => new AttributeService(type, core.savedObjects.client),
filtersFromContext,
filtersAndTimeRangeFromContext,
getStateTransfer: (history?: ScopedHistory) => {
return history
? new EmbeddableStateTransfer(core.application.navigateToApp, history)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ import { Trigger } from '.';
export const APPLY_FILTER_TRIGGER = 'FILTER_TRIGGER';
export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'> = {
id: APPLY_FILTER_TRIGGER,
title: 'Filter click',
title: 'Apply filter',
description: 'Triggered when user applies filter to an embeddable.',
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import { i18n } from '@kbn/i18n';
import { DiscoverStart } from '../../../../../../src/plugins/discover/public';
import { EmbeddableStart } from '../../../../../../src/plugins/embeddable/public';
import { ViewMode, IEmbeddable } from '../../../../../../src/plugins/embeddable/public';
import { StartServicesGetter } from '../../../../../../src/plugins/kibana_utils/public';
import { KibanaLegacyStart } from '../../../../../../src/plugins/kibana_legacy/public';
Expand All @@ -18,7 +17,6 @@ export const ACTION_EXPLORE_DATA = 'ACTION_EXPLORE_DATA';

export interface PluginDeps {
discover: Pick<DiscoverStart, 'urlGenerator'>;
embeddable: Pick<EmbeddableStart, 'filtersAndTimeRangeFromContext'>;
kibanaLegacy?: {
dashboardConfig: {
getHideWriteControls: KibanaLegacyStart['dashboardConfig']['getHideWriteControls'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,14 @@ import { ExploreDataChartAction } from './explore_data_chart_action';
import { Params, PluginDeps } from './abstract_explore_data_action';
import { coreMock } from '../../../../../../src/core/public/mocks';
import { UrlGeneratorContract } from '../../../../../../src/plugins/share/public';
import {
EmbeddableStart,
RangeSelectContext,
ValueClickContext,
ChartActionContext,
} from '../../../../../../src/plugins/embeddable/public';
import { ExploreDataChartActionContext } from './explore_data_chart_action';
import { i18n } from '@kbn/i18n';
import {
VisualizeEmbeddableContract,
VISUALIZE_EMBEDDABLE_TYPE,
} from '../../../../../../src/plugins/visualizations/public';
import { ViewMode } from '../../../../../../src/plugins/embeddable/public';
import { Filter, TimeRange } from '../../../../../../src/plugins/data/public';
import { Filter, RangeFilter } from '../../../../../../src/plugins/data/public';

const i18nTranslateSpy = (i18n.translate as unknown) as jest.SpyInstance;

Expand All @@ -34,10 +29,19 @@ afterEach(() => {
i18nTranslateSpy.mockClear();
});

const setup = ({
useRangeEvent = false,
dashboardOnlyMode = false,
}: { useRangeEvent?: boolean; dashboardOnlyMode?: boolean } = {}) => {
const setup = (
{
useRangeEvent = false,
timeFieldName,
filters = [],
dashboardOnlyMode = false,
}: {
useRangeEvent?: boolean;
filters?: Filter[];
timeFieldName?: string;
dashboardOnlyMode?: boolean;
} = { filters: [] }
) => {
type UrlGenerator = UrlGeneratorContract<'DISCOVER_APP_URL_GENERATOR'>;

const core = coreMock.createStart();
Expand All @@ -46,17 +50,10 @@ const setup = ({
createUrl: jest.fn(() => Promise.resolve('/xyz/app/discover/foo#bar')),
} as unknown) as UrlGenerator;

const filtersAndTimeRangeFromContext = jest.fn((async () => ({
filters: [],
})) as EmbeddableStart['filtersAndTimeRangeFromContext']);

const plugins: PluginDeps = {
discover: {
urlGenerator,
},
embeddable: {
filtersAndTimeRangeFromContext,
},
kibanaLegacy: {
dashboardConfig: {
getHideWriteControls: () => dashboardOnlyMode,
Expand Down Expand Up @@ -91,19 +88,13 @@ const setup = ({
getOutput: () => output,
} as unknown) as VisualizeEmbeddableContract;

const data: ChartActionContext<typeof embeddable>['data'] = {
...(useRangeEvent
? ({ range: {} } as RangeSelectContext['data'])
: ({ data: [] } as ValueClickContext['data'])),
timeFieldName: 'order_date',
};

const context = {
filters,
timeFieldName,
embeddable,
data,
} as ChartActionContext<typeof embeddable>;
} as ExploreDataChartActionContext;

return { core, plugins, urlGenerator, params, action, input, output, embeddable, data, context };
return { core, plugins, urlGenerator, params, action, input, output, embeddable, context };
};

describe('"Explore underlying data" panel action', () => {
Expand Down Expand Up @@ -236,32 +227,41 @@ describe('"Explore underlying data" panel action', () => {
});

test('applies chart event filters', async () => {
const { action, context, urlGenerator, plugins } = setup();

((plugins.embeddable
.filtersAndTimeRangeFromContext as unknown) as jest.SpyInstance).mockImplementation(() => {
const filters: Filter[] = [
{
meta: {
alias: 'alias',
disabled: false,
negate: false,
const timeFieldName = 'timeField';
const from = '2020-07-13T13:40:43.583Z';
const to = '2020-07-13T13:44:43.583Z';
const filters: Array<Filter | RangeFilter> = [
{
meta: {
alias: 'alias',
disabled: false,
negate: false,
},
},
{
meta: {
alias: 'alias',
disabled: false,
negate: false,
field: timeFieldName,
params: {
gte: from,
lte: to,
},
},
];
const timeRange: TimeRange = {
from: 'from',
to: 'to',
};
return { filters, timeRange };
});
range: {
[timeFieldName]: {
gte: from,
lte: to,
},
},
},
];

expect(plugins.embeddable.filtersAndTimeRangeFromContext).toHaveBeenCalledTimes(0);
const { action, context, urlGenerator } = setup({ filters, timeFieldName });

await action.getHref(context);

expect(plugins.embeddable.filtersAndTimeRangeFromContext).toHaveBeenCalledTimes(1);
expect(plugins.embeddable.filtersAndTimeRangeFromContext).toHaveBeenCalledWith(context);
expect(urlGenerator.createUrl).toHaveBeenCalledWith({
filters: [
{
Expand All @@ -274,8 +274,8 @@ describe('"Explore underlying data" panel action', () => {
],
indexPatternId: 'index-ptr-foo',
timeRange: {
from: 'from',
to: 'to',
from,
to,
},
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@
*/

import { Action } from '../../../../../../src/plugins/ui_actions/public';
import {
ValueClickContext,
RangeSelectContext,
} from '../../../../../../src/plugins/embeddable/public';
import { DiscoverUrlGeneratorState } from '../../../../../../src/plugins/discover/public';
import { isTimeRange, isQuery, isFilters } from '../../../../../../src/plugins/data/public';
import {
isTimeRange,
isQuery,
isFilters,
ApplyGlobalFilterActionContext,
esFilters,
} from '../../../../../../src/plugins/data/public';
import { KibanaURL } from './kibana_url';
import * as shared from './shared';
import { AbstractExploreDataAction } from './abstract_explore_data_action';

export type ExploreDataChartActionContext = ValueClickContext | RangeSelectContext;
export type ExploreDataChartActionContext = ApplyGlobalFilterActionContext;

export const ACTION_EXPLORE_DATA_CHART = 'ACTION_EXPLORE_DATA_CHART';

Expand All @@ -31,6 +33,11 @@ export class ExploreDataChartAction extends AbstractExploreDataAction<ExploreDat

public readonly order = 200;

public async isCompatible(context: ExploreDataChartActionContext): Promise<boolean> {
if (context.embeddable?.type === 'map') return false; // TODO: https://github.com/elastic/kibana/issues/73043
return super.isCompatible(context);
}

protected readonly getUrl = async (
context: ExploreDataChartActionContext
): Promise<KibanaURL> => {
Expand All @@ -42,7 +49,11 @@ export class ExploreDataChartAction extends AbstractExploreDataAction<ExploreDat
}

const { embeddable } = context;
const { filters, timeRange } = await plugins.embeddable.filtersAndTimeRangeFromContext(context);
const { restOfFilters: filters, timeRange } = esFilters.extractTimeRange(
context.filters,
context.timeFieldName
);

const state: DiscoverUrlGeneratorState = {
filters,
timeRange,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ExploreDataContextMenuAction } from './explore_data_context_menu_action
import { Params, PluginDeps } from './abstract_explore_data_action';
import { coreMock } from '../../../../../../src/core/public/mocks';
import { UrlGeneratorContract } from '../../../../../../src/plugins/share/public';
import { EmbeddableStart } from '../../../../../../src/plugins/embeddable/public';
import { i18n } from '@kbn/i18n';
import {
VisualizeEmbeddableContract,
Expand Down Expand Up @@ -37,17 +36,10 @@ const setup = ({ dashboardOnlyMode = false }: { dashboardOnlyMode?: boolean } =
createUrl: jest.fn(() => Promise.resolve('/xyz/app/discover/foo#bar')),
} as unknown) as UrlGenerator;

const filtersAndTimeRangeFromContext = jest.fn((async () => ({
filters: [],
})) as EmbeddableStart['filtersAndTimeRangeFromContext']);

const plugins: PluginDeps = {
discover: {
urlGenerator,
},
embeddable: {
filtersAndTimeRangeFromContext,
},
kibanaLegacy: {
dashboardConfig: {
getHideWriteControls: () => dashboardOnlyMode,
Expand Down
6 changes: 2 additions & 4 deletions x-pack/plugins/discover_enhanced/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { PluginInitializerContext } from 'kibana/public';
import {
UiActionsSetup,
UiActionsStart,
SELECT_RANGE_TRIGGER,
VALUE_CLICK_TRIGGER,
APPLY_FILTER_TRIGGER,
} from '../../../../src/plugins/ui_actions/public';
import { createStartServicesGetter } from '../../../../src/plugins/kibana_utils/public';
import { DiscoverSetup, DiscoverStart } from '../../../../src/plugins/discover/public';
Expand Down Expand Up @@ -77,8 +76,7 @@ export class DiscoverEnhancedPlugin

if (this.config.actions.exploreDataInChart.enabled) {
const exploreDataChartAction = new ExploreDataChartAction(params);
uiActions.addTriggerAction(SELECT_RANGE_TRIGGER, exploreDataChartAction);
uiActions.addTriggerAction(VALUE_CLICK_TRIGGER, exploreDataChartAction);
uiActions.addTriggerAction(APPLY_FILTER_TRIGGER, exploreDataChartAction);
}
}
}
Expand Down