mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
Use "Apply_filter_trigger" in "explore underlying data" action (#71445)
* use apply filter trigger for “expore underlying data” * disable for maps for now Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
01e6a4f1c0
commit
56e51bde7a
9 changed files with 72 additions and 134 deletions
|
@ -4,7 +4,6 @@
|
|||
"server": false,
|
||||
"ui": true,
|
||||
"requiredPlugins": [
|
||||
"data",
|
||||
"inspector",
|
||||
"uiActions"
|
||||
],
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
|
|
@ -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.',
|
||||
};
|
||||
|
|
|
@ -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';
|
||||
|
@ -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'];
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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', () => {
|
||||
|
@ -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: [
|
||||
{
|
||||
|
@ -274,8 +274,8 @@ describe('"Explore underlying data" panel action', () => {
|
|||
],
|
||||
indexPatternId: 'index-ptr-foo',
|
||||
timeRange: {
|
||||
from: 'from',
|
||||
to: 'to',
|
||||
from,
|
||||
to,
|
||||
},
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
@ -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> => {
|
||||
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
@ -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,
|
||||
|
|
|
@ -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';
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue