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

Enable "Explore underlying data" actions for Lens visualizations #70047

Merged
merged 30 commits into from
Jul 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
4e180aa
refactor: 💡 rename folder to "explore_data"
streamich Jun 18, 2020
428bbab
style: 💄 check for "share" plugin in more semantic way
streamich Jun 18, 2020
11c6b64
refactor: 💡 move KibanaURL to a separate file
streamich Jun 18, 2020
795bfbb
feat: 🎸 add "Explore underlying data" in-chart action
streamich Jun 18, 2020
64ce4c4
fix: 🐛 fix imports after refactor
streamich Jun 18, 2020
55992da
feat: 🎸 add start.filtersFromContext to embeddable plugin
streamich Jun 18, 2020
a730c55
feat: 🎸 add type checkers to data plugin
streamich Jun 18, 2020
00a7aa3
feat: 🎸 better handle empty filters in Discover URL generator
streamich Jun 18, 2020
088feb1
feat: 🎸 implement .getUrl() method of explore data in-chart act
streamich Jun 18, 2020
302702f
feat: 🎸 add embeddable.filtersAndTimeRangeFromContext()
streamich Jun 18, 2020
5217996
feat: 🎸 improve getUrl() method of explore data action
streamich Jun 18, 2020
ec890c6
test: 💍 update test mock
streamich Jun 18, 2020
45f4cc4
Merge remote-tracking branch 'upstream/master' into chart-underlying-…
streamich Jun 23, 2020
9b5739a
fix possible stale hashHistory.location in discover
Dosant Jun 24, 2020
d2747a7
chore: 🤖 merge master
streamich Jun 25, 2020
eb61452
style: 💄 ensureHashHistoryLocation -> syncHistoryLocations
streamich Jun 25, 2020
406e02d
docs: ✏️ update autogenerated docs
streamich Jun 25, 2020
599382b
test: 💍 add in-chart "Explore underlying data" unit tests
streamich Jun 25, 2020
4ceefdd
test: 💍 add in-chart "Explore underlying data" functional tests
streamich Jun 25, 2020
0e29de3
test: 💍 clean-up custom time range after panel action tests
streamich Jun 25, 2020
424414f
chore: 🤖 fix embeddable plugin mocks
streamich Jun 25, 2020
dcef452
chore: 🤖 fix another mock
streamich Jun 25, 2020
905f0bc
test: 💍 add support for new action to pie chart service
streamich Jun 25, 2020
b567eb2
Merge remote-tracking branch 'upstream/master' into chart-underlying-…
streamich Jun 26, 2020
8c2e4e3
feat: 🎸 enable "Explore underlying data" action for Lens vis
streamich Jun 26, 2020
06b7743
test: 💍 make tests green again
streamich Jun 26, 2020
98a1c5c
Merge remote-tracking branch 'upstream/master' into enable-explore-da…
streamich Jun 26, 2020
eb08d0e
refactor: 💡 rename trigger contexts
streamich Jun 26, 2020
54f84b5
chore: 🤖 fix TypeScript errors
streamich Jun 26, 2020
a844cc3
Merge branch 'master' into enable-explore-data-for-lens
elasticmachine Jun 29, 2020
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import moment from 'moment';
import { esFilters, IFieldType, RangeFilterParams } from '../../../public';
import { getIndexPatterns } from '../../../public/services';
import { deserializeAggConfig } from '../../search/expressions/utils';
import { RangeSelectTriggerContext } from '../../../../embeddable/public';
import { RangeSelectContext } from '../../../../embeddable/public';

export async function createFiltersFromRangeSelectAction(event: RangeSelectTriggerContext['data']) {
export async function createFiltersFromRangeSelectAction(event: RangeSelectContext['data']) {
const column: Record<string, any> = event.table.columns[event.column];

if (!column || !column.meta) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { dataPluginMock } from '../../../public/mocks';
import { setIndexPatterns } from '../../../public/services';
import { mockDataServices } from '../../../public/search/aggs/test_helpers';
import { createFiltersFromValueClickAction } from './create_filters_from_value_click';
import { ValueClickTriggerContext } from '../../../../embeddable/public';
import { ValueClickContext } from '../../../../embeddable/public';

const mockField = {
name: 'bytes',
Expand All @@ -39,7 +39,7 @@ const mockField = {
};

describe('createFiltersFromValueClick', () => {
let dataPoints: ValueClickTriggerContext['data']['data'];
let dataPoints: ValueClickContext['data']['data'];

beforeEach(() => {
dataPoints = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { KibanaDatatable } from '../../../../../plugins/expressions/public';
import { deserializeAggConfig } from '../../search/expressions';
import { esFilters, Filter } from '../../../public';
import { getIndexPatterns } from '../../../public/services';
import { ValueClickTriggerContext } from '../../../../embeddable/public';
import { ValueClickContext } from '../../../../embeddable/public';

/**
* For terms aggregations on `__other__` buckets, this assembles a list of applicable filter
Expand Down Expand Up @@ -114,7 +114,7 @@ const createFilter = async (
export const createFiltersFromValueClickAction = async ({
data,
negate,
}: ValueClickTriggerContext['data']) => {
}: ValueClickContext['data']) => {
const filters: Filter[] = [];

await Promise.all(
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/public/actions/select_range_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ import {
ActionByType,
} from '../../../../plugins/ui_actions/public';
import { createFiltersFromRangeSelectAction } from './filters/create_filters_from_range_select';
import { RangeSelectTriggerContext } from '../../../embeddable/public';
import { RangeSelectContext } from '../../../embeddable/public';
import { FilterManager, TimefilterContract, esFilters } from '..';

export const ACTION_SELECT_RANGE = 'ACTION_SELECT_RANGE';

export type SelectRangeActionContext = RangeSelectTriggerContext;
export type SelectRangeActionContext = RangeSelectContext;

async function isCompatible(context: SelectRangeActionContext) {
try {
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/data/public/actions/value_click_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ import {
import { getOverlays, getIndexPatterns } from '../services';
import { applyFiltersPopover } from '../ui/apply_filters';
import { createFiltersFromValueClickAction } from './filters/create_filters_from_value_click';
import { ValueClickTriggerContext } from '../../../embeddable/public';
import { ValueClickContext } from '../../../embeddable/public';
import { Filter, FilterManager, TimefilterContract, esFilters } from '..';

export const ACTION_VALUE_CLICK = 'ACTION_VALUE_CLICK';

export type ValueClickActionContext = ValueClickTriggerContext;
export type ValueClickActionContext = ValueClickContext;

async function isCompatible(context: ValueClickActionContext) {
try {
Expand Down
4 changes: 2 additions & 2 deletions src/plugins/embeddable/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export {
EmbeddableOutput,
EmbeddablePanel,
EmbeddableRoot,
ValueClickTriggerContext,
RangeSelectTriggerContext,
ValueClickContext,
RangeSelectContext,
ErrorEmbeddable,
IContainer,
IEmbeddable,
Expand Down
12 changes: 6 additions & 6 deletions src/plugins/embeddable/public/lib/triggers/triggers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface EmbeddableContext {
embeddable: IEmbeddable;
}

export interface ValueClickTriggerContext<T extends IEmbeddable = IEmbeddable> {
export interface ValueClickContext<T extends IEmbeddable = IEmbeddable> {
embeddable?: T;
data: {
data: Array<{
Expand All @@ -39,7 +39,7 @@ export interface ValueClickTriggerContext<T extends IEmbeddable = IEmbeddable> {
};
}

export interface RangeSelectTriggerContext<T extends IEmbeddable = IEmbeddable> {
export interface RangeSelectContext<T extends IEmbeddable = IEmbeddable> {
embeddable?: T;
data: {
table: KibanaDatatable;
Expand All @@ -50,16 +50,16 @@ export interface RangeSelectTriggerContext<T extends IEmbeddable = IEmbeddable>
}

export type ChartActionContext<T extends IEmbeddable = IEmbeddable> =
| ValueClickTriggerContext<T>
| RangeSelectTriggerContext<T>;
| ValueClickContext<T>
| RangeSelectContext<T>;

export const isValueClickTriggerContext = (
context: ChartActionContext
): context is ValueClickTriggerContext => context.data && 'data' in context.data;
): context is ValueClickContext => context.data && 'data' in context.data;

export const isRangeSelectTriggerContext = (
context: ChartActionContext
): context is RangeSelectTriggerContext => context.data && 'range' in context.data;
): context is RangeSelectContext => context.data && 'range' in context.data;

export const CONTEXT_MENU_TRIGGER = 'CONTEXT_MENU_TRIGGER';
export const contextMenuTrigger: Trigger<'CONTEXT_MENU_TRIGGER'> = {
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/ui_actions/public/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { TriggerInternal } from './triggers/trigger_internal';
import { Filter } from '../../data/public';
import { SELECT_RANGE_TRIGGER, VALUE_CLICK_TRIGGER, APPLY_FILTER_TRIGGER } from './triggers';
import { IEmbeddable } from '../../embeddable/public';
import { RangeSelectTriggerContext, ValueClickTriggerContext } from '../../embeddable/public';
import { RangeSelectContext, ValueClickContext } from '../../embeddable/public';

export type TriggerRegistry = Map<TriggerId, TriggerInternal<any>>;
export type ActionRegistry = Map<string, ActionInternal>;
Expand All @@ -37,8 +37,8 @@ export type TriggerContext = BaseContext;

export interface TriggerContextMapping {
[DEFAULT_TRIGGER]: TriggerContext;
[SELECT_RANGE_TRIGGER]: RangeSelectTriggerContext;
[VALUE_CLICK_TRIGGER]: ValueClickTriggerContext;
[SELECT_RANGE_TRIGGER]: RangeSelectContext;
[VALUE_CLICK_TRIGGER]: ValueClickContext;
[APPLY_FILTER_TRIGGER]: {
embeddable: IEmbeddable;
filters: Filter[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@ import React from 'react';
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/public';
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import {
RangeSelectTriggerContext,
ValueClickTriggerContext,
} from '../../../../../src/plugins/embeddable/public';
import { ChartActionContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps } from '../../../../../src/plugins/kibana_utils/public';

export type ActionContext = RangeSelectTriggerContext | ValueClickTriggerContext;
export type ActionContext = ChartActionContext;

export interface Config {
name: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import {
RangeSelectTriggerContext,
ValueClickTriggerContext,
} from '../../../../../src/plugins/embeddable/public';
import { ChartActionContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps as CollectConfigPropsBase } from '../../../../../src/plugins/kibana_utils/public';

export type ActionContext = RangeSelectTriggerContext | ValueClickTriggerContext;
export type ActionContext = ChartActionContext;

export interface Config {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import React from 'react';
import { EuiFormRow, EuiSwitch, EuiFieldText, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/public';
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import {
RangeSelectTriggerContext,
ValueClickTriggerContext,
} from '../../../../../src/plugins/embeddable/public';
import { ChartActionContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps as CollectConfigPropsBase } from '../../../../../src/plugins/kibana_utils/public';

function isValidUrl(url: string) {
Expand All @@ -23,7 +20,7 @@ function isValidUrl(url: string) {
}
}

export type ActionContext = RangeSelectTriggerContext | ValueClickTriggerContext;
export type ActionContext = ChartActionContext;

export interface Config {
url: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ import { createDashboardUrlGenerator } from '../../../../../../../src/plugins/da
import { UrlGeneratorsService } from '../../../../../../../src/plugins/share/public/url_generators';
import { VisualizeEmbeddableContract } from '../../../../../../../src/plugins/visualizations/public';
import {
RangeSelectTriggerContext,
ValueClickTriggerContext,
RangeSelectContext,
ValueClickContext,
} from '../../../../../../../src/plugins/embeddable/public';
import { StartDependencies } from '../../../plugin';
import { SavedObjectLoader } from '../../../../../../../src/plugins/saved_objects/public';
Expand Down Expand Up @@ -136,8 +136,8 @@ describe('.execute() & getHref', () => {
const context = ({
data: {
...(useRangeEvent
? ({ range: {} } as RangeSelectTriggerContext['data'])
: ({ data: [] } as ValueClickTriggerContext['data'])),
? ({ range: {} } as RangeSelectContext['data'])
: ({ data: [] } as ValueClickContext['data'])),
timeFieldName: 'order_date',
},
embeddable: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
*/

import {
ValueClickTriggerContext,
RangeSelectTriggerContext,
ValueClickContext,
RangeSelectContext,
IEmbeddable,
} from '../../../../../../../src/plugins/embeddable/public';

export type ActionContext<T extends IEmbeddable = IEmbeddable> =
| ValueClickTriggerContext<T>
| RangeSelectTriggerContext<T>;
| ValueClickContext<T>
| RangeSelectContext<T>;

export interface Config {
dashboardId?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,13 @@ export abstract class AbstractExploreDataAction<Context extends { embeddable?: I
public async isCompatible({ embeddable }: Context): Promise<boolean> {
if (!embeddable) return false;
if (!this.params.start().plugins.discover.urlGenerator) return false;
if (!shared.isVisualizeEmbeddable(embeddable)) return false;
if (!shared.getIndexPattern(embeddable)) return false;
if (!shared.hasExactlyOneIndexPattern(embeddable)) return false;
if (embeddable.getInput().viewMode !== ViewMode.VIEW) return false;
return true;
}

public async execute(context: Context): Promise<void> {
if (!shared.isVisualizeEmbeddable(context.embeddable)) return;
if (!shared.hasExactlyOneIndexPattern(context.embeddable)) return;

const { core } = this.params.start();
const { appName, appPath } = await this.getUrl(context);
Expand All @@ -63,7 +62,7 @@ export abstract class AbstractExploreDataAction<Context extends { embeddable?: I
public async getHref(context: Context): Promise<string> {
const { embeddable } = context;

if (!shared.isVisualizeEmbeddable(embeddable)) {
if (!shared.hasExactlyOneIndexPattern(embeddable)) {
throw new Error(`Embeddable not supported for "${this.getDisplayName(context)}" action.`);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { coreMock } from '../../../../../../src/core/public/mocks';
import { UrlGeneratorContract } from '../../../../../../src/plugins/share/public';
import {
EmbeddableStart,
RangeSelectTriggerContext,
ValueClickTriggerContext,
RangeSelectContext,
ValueClickContext,
ChartActionContext,
} from '../../../../../../src/plugins/embeddable/public';
import { i18n } from '@kbn/i18n';
Expand Down Expand Up @@ -85,8 +85,8 @@ const setup = ({ useRangeEvent = false }: { useRangeEvent?: boolean } = {}) => {

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

Expand Down Expand Up @@ -139,9 +139,16 @@ describe('"Explore underlying data" panel action', () => {
expect(isCompatible).toBe(false);
});

test('returns false if embeddable is not Visualize embeddable', async () => {
const { action, embeddable, context } = setup();
(embeddable as any).type = 'NOT_VISUALIZE_EMBEDDABLE';
test('returns false if embeddable has more than one index pattern', async () => {
const { action, output, context } = setup();
output.indexPatterns = [
{
id: 'index-ptr-foo',
},
{
id: 'index-ptr-bar',
},
];

const isCompatible = await action.isCompatible(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@

import { Action } from '../../../../../../src/plugins/ui_actions/public';
import {
ValueClickTriggerContext,
RangeSelectTriggerContext,
ValueClickContext,
RangeSelectContext,
} from '../../../../../../src/plugins/embeddable/public';
import { DiscoverUrlGeneratorState } from '../../../../../../src/plugins/discover/public';
import { isTimeRange, isQuery, isFilters } 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 = ValueClickTriggerContext | RangeSelectTriggerContext;
export type ExploreDataChartActionContext = ValueClickContext | RangeSelectContext;

export const ACTION_EXPLORE_DATA_CHART = 'ACTION_EXPLORE_DATA_CHART';

Expand Down Expand Up @@ -49,7 +49,7 @@ export class ExploreDataChartAction extends AbstractExploreDataAction<ExploreDat
};

if (embeddable) {
state.indexPatternId = shared.getIndexPattern(embeddable) || undefined;
state.indexPatternId = shared.getIndexPatterns(embeddable)[0] || undefined;

const input = embeddable.getInput();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,16 @@ describe('"Explore underlying data" panel action', () => {
expect(isCompatible).toBe(false);
});

test('returns false if embeddable is not Visualize embeddable', async () => {
const { action, embeddable, context } = setup();
(embeddable as any).type = 'NOT_VISUALIZE_EMBEDDABLE';
test('returns false if embeddable has more than one index pattern', async () => {
const { action, output, context } = setup();
output.indexPatterns = [
{
id: 'index-ptr-foo',
},
{
id: 'index-ptr-bar',
},
];

const isCompatible = await action.isCompatible(context);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export class ExploreDataContextMenuAction extends AbstractExploreDataAction<Embe
const state: DiscoverUrlGeneratorState = {};

if (embeddable) {
state.indexPatternId = shared.getIndexPattern(embeddable) || undefined;
state.indexPatternId = shared.getIndexPatterns(embeddable)[0] || undefined;

const input = embeddable.getInput();

Expand Down
Loading