Skip to content

Commit

Permalink
[Drilldowns] Trigger picker (elastic#74751)
Browse files Browse the repository at this point in the history
Drilldowns now support trigger picker. It allows to create a drilldown and specify which trigger it should be attached to.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
Dosant and elasticmachine committed Aug 18, 2020
1 parent 8ea2bb3 commit 832b952
Show file tree
Hide file tree
Showing 47 changed files with 942 additions and 150 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export class UiActionsExecutionService {
context,
trigger,
})),
title: tasks[0].trigger.title, // title of context menu is title of trigger which originated the chain
title: '', // intentionally don't have any title
closeMenu: () => {
tasks.forEach((t) => t.defer.resolve());
session.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@
* under the License.
*/

import { i18n } from '@kbn/i18n';
import { Trigger } from '.';

export const APPLY_FILTER_TRIGGER = 'FILTER_TRIGGER';
export const applyFilterTrigger: Trigger<'FILTER_TRIGGER'> = {
id: APPLY_FILTER_TRIGGER,
title: 'Apply filter',
description: 'Triggered when user applies filter to an embeddable.',
title: i18n.translate('uiActions.triggers.applyFilterTitle', {
defaultMessage: 'Apply filter',
}),
description: i18n.translate('uiActions.triggers.applyFilterDescription', {
defaultMessage: 'When kibana filter is applied. Could be a single value or a range filter.',
}),
};
11 changes: 7 additions & 4 deletions src/plugins/ui_actions/public/triggers/select_range_trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
* under the License.
*/

import { i18n } from '@kbn/i18n';
import { Trigger } from '.';

export const SELECT_RANGE_TRIGGER = 'SELECT_RANGE_TRIGGER';
export const selectRangeTrigger: Trigger<'SELECT_RANGE_TRIGGER'> = {
id: SELECT_RANGE_TRIGGER,
// This is empty string to hide title of ui_actions context menu that appears
// when this trigger is executed.
title: '',
description: 'Applies a range filter',
title: i18n.translate('uiActions.triggers.selectRangeTitle', {
defaultMessage: 'Range selection',
}),
description: i18n.translate('uiActions.triggers.selectRangeDescription', {
defaultMessage: 'Select a group of values',
}),
};
11 changes: 7 additions & 4 deletions src/plugins/ui_actions/public/triggers/value_click_trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,16 @@
* under the License.
*/

import { i18n } from '@kbn/i18n';
import { Trigger } from '.';

export const VALUE_CLICK_TRIGGER = 'VALUE_CLICK_TRIGGER';
export const valueClickTrigger: Trigger<'VALUE_CLICK_TRIGGER'> = {
id: VALUE_CLICK_TRIGGER,
// This is empty string to hide title of ui_actions context menu that appears
// when this trigger is executed.
title: '',
description: 'Value was clicked',
title: i18n.translate('uiActions.triggers.valueClickTitle', {
defaultMessage: 'Single click',
}),
description: i18n.translate('uiActions.triggers.valueClickDescription', {
defaultMessage: 'A single point clicked on a visualization',
}),
};
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { Vis } from '../vis';
import { getExpressions, getUiActions } from '../services';
import { VIS_EVENT_TO_TRIGGER } from './events';
import { VisualizeEmbeddableFactoryDeps } from './visualize_embeddable_factory';
import { TriggerId } from '../../../ui_actions/public';

const getKeys = <T extends {}>(o: T): Array<keyof T> => Object.keys(o) as Array<keyof T>;

Expand Down Expand Up @@ -393,7 +394,7 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
});
};

public supportedTriggers() {
public supportedTriggers(): TriggerId[] {
return this.vis.type.getSupportedTriggers?.() ?? [];
}
}
2 changes: 1 addition & 1 deletion x-pack/examples/ui_actions_enhanced_examples/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"configPath": ["ui_actions_enhanced_examples"],
"server": false,
"ui": true,
"requiredPlugins": ["uiActionsEnhanced", "data", "discover"],
"requiredPlugins": ["uiActions","uiActionsEnhanced", "data", "discover"],
"optionalPlugins": [],
"requiredBundles": [
"kibanaUtils",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/publ
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import { ChartActionContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps } from '../../../../../src/plugins/kibana_utils/public';
import {
SELECT_RANGE_TRIGGER,
VALUE_CLICK_TRIGGER,
} from '../../../../../src/plugins/ui_actions/public';

export type ActionContext = ChartActionContext;

Expand All @@ -19,7 +23,8 @@ export interface Config {

const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN = 'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN';

export class DashboardHelloWorldDrilldown implements Drilldown<Config, ActionContext> {
export class DashboardHelloWorldDrilldown
implements Drilldown<Config, typeof VALUE_CLICK_TRIGGER | typeof SELECT_RANGE_TRIGGER> {
public readonly id = SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN;

public readonly order = 6;
Expand All @@ -28,9 +33,14 @@ export class DashboardHelloWorldDrilldown implements Drilldown<Config, ActionCon

public readonly euiIcon = 'cheer';

supportedTriggers(): Array<typeof VALUE_CLICK_TRIGGER | typeof SELECT_RANGE_TRIGGER> {
return [VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER];
}

private readonly ReactCollectConfig: React.FC<CollectConfigProps<Config>> = ({
config,
onConfig,
context,
}) => (
<EuiFormRow label="Enter your name" fullWidth>
<EuiFieldText
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This folder contains a one-file example of the most basic drilldown implementation which support only RANGE_SELECT_TRIGGER.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 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 { RangeSelectContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps } from '../../../../../src/plugins/kibana_utils/public';
import { SELECT_RANGE_TRIGGER } from '../../../../../src/plugins/ui_actions/public';

export interface Config {
name: string;
}

const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT =
'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT';

export class DashboardHelloWorldOnlyRangeSelectDrilldown
implements Drilldown<Config, typeof SELECT_RANGE_TRIGGER> {
public readonly id = SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN_ONLY_RANGE_SELECT;

public readonly order = 7;

public readonly getDisplayName = () => 'Say hello only for range select';

public readonly euiIcon = 'cheer';

supportedTriggers(): Array<typeof SELECT_RANGE_TRIGGER> {
return [SELECT_RANGE_TRIGGER];
}

private readonly ReactCollectConfig: React.FC<CollectConfigProps<Config>> = ({
config,
onConfig,
}) => (
<EuiFormRow label="Enter your name" fullWidth>
<EuiFieldText
fullWidth
value={config.name}
onChange={(event) => onConfig({ ...config, name: event.target.value })}
/>
</EuiFormRow>
);

public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);

public readonly createConfig = () => ({
name: '',
});

public readonly isConfigValid = (config: Config): config is Config => {
return !!config.name;
};

public readonly execute = async (config: Config, context: RangeSelectContext) => {
alert(`Hello, ${config.name}, your selected range: ${JSON.stringify(context.data.range)}`);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { CollectConfigContainer } from './collect_config_container';
import { SAMPLE_DASHBOARD_TO_DISCOVER_DRILLDOWN } from './constants';
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import { txtGoToDiscover } from './i18n';
import { APPLY_FILTER_TRIGGER } from '../../../../../src/plugins/ui_actions/public';

const isOutputWithIndexPatterns = (
output: unknown
Expand All @@ -25,7 +26,8 @@ export interface Params {
start: StartServicesGetter<Pick<Start, 'data' | 'discover'>>;
}

export class DashboardToDiscoverDrilldown implements Drilldown<Config, ActionContext> {
export class DashboardToDiscoverDrilldown
implements Drilldown<Config, typeof APPLY_FILTER_TRIGGER> {
constructor(protected readonly params: Params) {}

public readonly id = SAMPLE_DASHBOARD_TO_DISCOVER_DRILLDOWN;
Expand All @@ -36,6 +38,10 @@ export class DashboardToDiscoverDrilldown implements Drilldown<Config, ActionCon

public readonly euiIcon = 'discoverApp';

public supportedTriggers(): Array<typeof APPLY_FILTER_TRIGGER> {
return [APPLY_FILTER_TRIGGER];
}

private readonly ReactCollectConfig: React.FC<CollectConfigProps> = (props) => (
<CollectConfigContainer {...props} params={this.params} />
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ChartActionContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps as CollectConfigPropsBase } from '../../../../../src/plugins/kibana_utils/public';
import { ApplyGlobalFilterActionContext } from '../../../../../src/plugins/data/public';

export type ActionContext = ChartActionContext;
export type ActionContext = ApplyGlobalFilterActionContext;

export interface Config {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
*/

import React from 'react';
import { EuiFormRow, EuiSwitch, EuiFieldText, EuiCallOut, EuiSpacer } from '@elastic/eui';
import { EuiCallOut, EuiFieldText, EuiFormRow, EuiSpacer, EuiSwitch } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/public';
import { UiActionsEnhancedDrilldownDefinition as Drilldown } from '../../../../plugins/ui_actions_enhanced/public';
import { ChartActionContext } from '../../../../../src/plugins/embeddable/public';
import { CollectConfigProps as CollectConfigPropsBase } from '../../../../../src/plugins/kibana_utils/public';
import {
SELECT_RANGE_TRIGGER,
VALUE_CLICK_TRIGGER,
} from '../../../../../src/plugins/ui_actions/public';
import { ActionExecutionContext } from '../../../../../src/plugins/ui_actions/public';

function isValidUrl(url: string) {
Expand All @@ -28,11 +32,13 @@ export interface Config {
openInNewTab: boolean;
}

export type CollectConfigProps = CollectConfigPropsBase<Config>;
type UrlTrigger = typeof VALUE_CLICK_TRIGGER | typeof SELECT_RANGE_TRIGGER;

export type CollectConfigProps = CollectConfigPropsBase<Config, { triggers: UrlTrigger[] }>;

const SAMPLE_DASHBOARD_TO_URL_DRILLDOWN = 'SAMPLE_DASHBOARD_TO_URL_DRILLDOWN';

export class DashboardToUrlDrilldown implements Drilldown<Config, ActionContext> {
export class DashboardToUrlDrilldown implements Drilldown<Config, UrlTrigger> {
public readonly id = SAMPLE_DASHBOARD_TO_URL_DRILLDOWN;

public readonly order = 8;
Expand All @@ -43,7 +49,15 @@ export class DashboardToUrlDrilldown implements Drilldown<Config, ActionContext>

public readonly euiIcon = 'link';

private readonly ReactCollectConfig: React.FC<CollectConfigProps> = ({ config, onConfig }) => (
supportedTriggers(): UrlTrigger[] {
return [VALUE_CLICK_TRIGGER, SELECT_RANGE_TRIGGER];
}

private readonly ReactCollectConfig: React.FC<CollectConfigProps> = ({
config,
onConfig,
context,
}) => (
<>
<EuiCallOut title="Example warning!" color="warning" iconType="help">
<p>
Expand Down Expand Up @@ -79,6 +93,11 @@ export class DashboardToUrlDrilldown implements Drilldown<Config, ActionContext>
onChange={() => onConfig({ ...config, openInNewTab: !config.openInNewTab })}
/>
</EuiFormRow>
<EuiSpacer size="xl" />
<EuiCallOut>
{/* just demo how can access selected triggers*/}
<p>Will be attached to triggers: {JSON.stringify(context.triggers)}</p>
</EuiCallOut>
</>
);

Expand Down
2 changes: 2 additions & 0 deletions x-pack/examples/ui_actions_enhanced_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DashboardToUrlDrilldown } from './dashboard_to_url_drilldown';
import { DashboardToDiscoverDrilldown } from './dashboard_to_discover_drilldown';
import { createStartServicesGetter } from '../../../../src/plugins/kibana_utils/public';
import { DiscoverSetup, DiscoverStart } from '../../../../src/plugins/discover/public';
import { DashboardHelloWorldOnlyRangeSelectDrilldown } from './dashboard_hello_world_only_range_select_drilldown';

export interface SetupDependencies {
data: DataPublicPluginSetup;
Expand All @@ -37,6 +38,7 @@ export class UiActionsEnhancedExamplesPlugin
const start = createStartServicesGetter(core.getStartServices);

uiActions.registerDrilldown(new DashboardHelloWorldDrilldown());
uiActions.registerDrilldown(new DashboardHelloWorldOnlyRangeSelectDrilldown());
uiActions.registerDrilldown(new DashboardToUrlDrilldown());
uiActions.registerDrilldown(new DashboardToDiscoverDrilldown({ start }));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 {
APPLY_FILTER_TRIGGER,
SELECT_RANGE_TRIGGER,
TriggerId,
VALUE_CLICK_TRIGGER,
} from '../../../../../../../src/plugins/ui_actions/public';

/**
* We know that VALUE_CLICK_TRIGGER and SELECT_RANGE_TRIGGER are also triggering APPLY_FILTER_TRIGGER
* This function appends APPLY_FILTER_TRIGGER to list of triggers if VALUE_CLICK_TRIGGER or SELECT_RANGE_TRIGGER
*
* TODO: this probably should be part of uiActions infrastructure,
* but dynamic implementation of nested trigger doesn't allow to statically express such relations
*
* @param triggers
*/
export function ensureNestedTriggers(triggers: TriggerId[]): TriggerId[] {
if (
!triggers.includes(APPLY_FILTER_TRIGGER) &&
(triggers.includes(VALUE_CLICK_TRIGGER) || triggers.includes(SELECT_RANGE_TRIGGER))
) {
return [...triggers, APPLY_FILTER_TRIGGER];
}

return triggers;
}
Loading

0 comments on commit 832b952

Please sign in to comment.