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

[uiActions] Support emitting nested triggers and actions #70602

Merged
merged 16 commits into from
Jul 15, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) &gt; [embeddable](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md)

## ApplyGlobalFilterActionContext.embeddable property

<b>Signature:</b>

```typescript
embeddable?: IEmbeddable;
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) &gt; [filters](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md)

## ApplyGlobalFilterActionContext.filters property

<b>Signature:</b>

```typescript
filters: Filter[];
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md)

## ApplyGlobalFilterActionContext interface

<b>Signature:</b>

```typescript
export interface ApplyGlobalFilterActionContext
```

## Properties

| Property | Type | Description |
| --- | --- | --- |
| [embeddable](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.embeddable.md) | <code>IEmbeddable</code> | |
| [filters](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.filters.md) | <code>Filter[]</code> | |
| [timeFieldName](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md) | <code>string</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) &gt; [timeFieldName](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.timefieldname.md)

## ApplyGlobalFilterActionContext.timeFieldName property

<b>Signature:</b>

```typescript
timeFieldName?: string;
```
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
| Interface | Description |
| --- | --- |
| [AggParamOption](./kibana-plugin-plugins-data-public.aggparamoption.md) | |
| [ApplyGlobalFilterActionContext](./kibana-plugin-plugins-data-public.applyglobalfilteractioncontext.md) | |
| [DataPublicPluginSetup](./kibana-plugin-plugins-data-public.datapublicpluginsetup.md) | |
| [DataPublicPluginStart](./kibana-plugin-plugins-data-public.datapublicpluginstart.md) | |
| [EsQueryConfig](./kibana-plugin-plugins-data-public.esqueryconfig.md) | |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
<b>Signature:</b>

```typescript
setup(core: CoreSetup, { expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
setup(core: CoreSetup<DataStartDependencies, DataPublicPluginStart>, { expressions, uiActions, usageCollection }: DataSetupDependencies): DataPublicPluginSetup;
```

## Parameters

| Parameter | Type | Description |
| --- | --- | --- |
| core | <code>CoreSetup</code> | |
| core | <code>CoreSetup&lt;DataStartDependencies, DataPublicPluginStart&gt;</code> | |
| { expressions, uiActions, usageCollection } | <code>DataSetupDependencies</code> | |

<b>Returns:</b>
Expand Down
16 changes: 5 additions & 11 deletions examples/ui_actions_explorer/public/actions/actions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const ACTION_VIEW_IN_MAPS = 'ACTION_VIEW_IN_MAPS';
export const ACTION_TRAVEL_GUIDE = 'ACTION_TRAVEL_GUIDE';
export const ACTION_CALL_PHONE_NUMBER = 'ACTION_CALL_PHONE_NUMBER';
export const ACTION_EDIT_USER = 'ACTION_EDIT_USER';
export const ACTION_PHONE_USER = 'ACTION_PHONE_USER';
export const ACTION_TRIGGER_PHONE_USER = 'ACTION_TRIGGER_PHONE_USER';
export const ACTION_SHOWCASE_PLUGGABILITY = 'ACTION_SHOWCASE_PLUGGABILITY';

export const showcasePluggability = createAction<typeof ACTION_SHOWCASE_PLUGGABILITY>({
Expand Down Expand Up @@ -120,19 +120,13 @@ export interface UserContext {
update: (user: User) => void;
}

export const createPhoneUserAction = (getUiActionsApi: () => Promise<UiActionsStart>) =>
createAction<typeof ACTION_PHONE_USER>({
type: ACTION_PHONE_USER,
export const createTriggerPhoneTriggerAction = (getUiActionsApi: () => Promise<UiActionsStart>) =>
createAction<typeof ACTION_TRIGGER_PHONE_USER>({
type: ACTION_TRIGGER_PHONE_USER,
getDisplayName: () => 'Call phone number',
shouldAutoExecute: async () => true,
isCompatible: async ({ user }) => user.phone !== undefined,
execute: async ({ user }) => {
// One option - execute the more specific action directly.
// makePhoneCallAction.execute({ phone: user.phone });

// Another option - emit the trigger and automatically get *all* the actions attached
// to the phone number trigger.
// TODO: we need to figure out the best way to handle these nested actions however, since
// we don't want multiple context menu's to pop up.
if (user.phone !== undefined) {
(await getUiActionsApi()).executeTriggerActions(PHONE_TRIGGER, { phone: user.phone });
}
Expand Down
8 changes: 4 additions & 4 deletions examples/ui_actions_explorer/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
PHONE_TRIGGER,
USER_TRIGGER,
COUNTRY_TRIGGER,
createPhoneUserAction,
lookUpWeatherAction,
viewInMapsAction,
createEditUserAction,
Expand All @@ -37,7 +36,8 @@ import {
ACTION_CALL_PHONE_NUMBER,
ACTION_TRAVEL_GUIDE,
ACTION_VIEW_IN_MAPS,
ACTION_PHONE_USER,
ACTION_TRIGGER_PHONE_USER,
createTriggerPhoneTriggerAction,
} from './actions/actions';
import { DeveloperExamplesSetup } from '../../developer_examples/public';
import image from './ui_actions.png';
Expand All @@ -64,7 +64,7 @@ declare module '../../../src/plugins/ui_actions/public' {
[ACTION_CALL_PHONE_NUMBER]: PhoneContext;
[ACTION_TRAVEL_GUIDE]: CountryContext;
[ACTION_VIEW_IN_MAPS]: CountryContext;
[ACTION_PHONE_USER]: UserContext;
[ACTION_TRIGGER_PHONE_USER]: UserContext;
}
}

Expand All @@ -84,7 +84,7 @@ export class UiActionsExplorerPlugin implements Plugin<void, void, {}, StartDeps

deps.uiActions.addTriggerAction(
USER_TRIGGER,
createPhoneUserAction(async () => (await startServices)[1].uiActions)
createTriggerPhoneTriggerAction(async () => (await startServices)[1].uiActions)
);
deps.uiActions.addTriggerAction(
USER_TRIGGER,
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/data/public/actions/apply_filter_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ import { toMountPoint } from '../../../kibana_react/public';
import { ActionByType, createAction, IncompatibleActionError } from '../../../ui_actions/public';
import { getOverlays, getIndexPatterns } from '../services';
import { applyFiltersPopover } from '../ui/apply_filters';
import type { IEmbeddable } from '../../../embeddable/public';
import { Filter, FilterManager, TimefilterContract, esFilters } from '..';

export const ACTION_GLOBAL_APPLY_FILTER = 'ACTION_GLOBAL_APPLY_FILTER';

export interface ApplyGlobalFilterActionContext {
filters: Filter[];
timeFieldName?: string;
embeddable?: IEmbeddable;
}

async function isCompatible(context: ApplyGlobalFilterActionContext) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import moment from 'moment';
import { esFilters, IFieldType, RangeFilterParams } from '../../../public';
import { getIndexPatterns } from '../../../public/services';
import { deserializeAggConfig } from '../../search/expressions/utils';
import { RangeSelectContext } from '../../../../embeddable/public';
import type { RangeSelectContext } from '../../../../embeddable/public';
Dosant marked this conversation as resolved.
Show resolved Hide resolved

export async function createFiltersFromRangeSelectAction(event: RangeSelectContext['data']) {
const column: Record<string, any> = event.table.columns[event.column];
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 { ValueClickContext } from '../../../../embeddable/public';
import type { ValueClickContext } from '../../../../embeddable/public';

/**
* For terms aggregations on `__other__` buckets, this assembles a list of applicable filter
Expand Down
10 changes: 7 additions & 3 deletions src/plugins/data/public/actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
* under the License.
*/

export { ACTION_GLOBAL_APPLY_FILTER, createFilterAction } from './apply_filter_action';
export {
ACTION_GLOBAL_APPLY_FILTER,
createFilterAction,
ApplyGlobalFilterActionContext,
} from './apply_filter_action';
export { createFiltersFromValueClickAction } from './filters/create_filters_from_value_click';
export { createFiltersFromRangeSelectAction } from './filters/create_filters_from_range_select';
export { selectRangeAction } from './select_range_action';
export { valueClickAction } from './value_click_action';
export * from './select_range_action';
export * from './value_click_action';
61 changes: 20 additions & 41 deletions src/plugins/data/public/actions/select_range_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,60 +17,39 @@
* under the License.
*/

import { i18n } from '@kbn/i18n';
import {
createAction,
IncompatibleActionError,
ActionByType,
APPLY_FILTER_TRIGGER,
createAction,
UiActionsStart,
} from '../../../../plugins/ui_actions/public';
import { createFiltersFromRangeSelectAction } from './filters/create_filters_from_range_select';
import { RangeSelectContext } from '../../../embeddable/public';
import { FilterManager, TimefilterContract, esFilters } from '..';

export const ACTION_SELECT_RANGE = 'ACTION_SELECT_RANGE';
import type { RangeSelectContext } from '../../../embeddable/public';

export type SelectRangeActionContext = RangeSelectContext;

async function isCompatible(context: SelectRangeActionContext) {
try {
return Boolean(await createFiltersFromRangeSelectAction(context.data));
} catch {
return false;
}
}
export const ACTION_SELECT_RANGE = 'ACTION_SELECT_RANGE';

export function selectRangeAction(
filterManager: FilterManager,
timeFilter: TimefilterContract
export function createSelectRangeAction(
getStartServices: () => { uiActions: UiActionsStart }
): ActionByType<typeof ACTION_SELECT_RANGE> {
return createAction<typeof ACTION_SELECT_RANGE>({
type: ACTION_SELECT_RANGE,
id: ACTION_SELECT_RANGE,
getIconType: () => 'filter',
getDisplayName: () => {
return i18n.translate('data.filter.applyFilterActionTitle', {
defaultMessage: 'Apply filter to current view',
});
},
isCompatible,
execute: async ({ data }: SelectRangeActionContext) => {
if (!(await isCompatible({ data }))) {
throw new IncompatibleActionError();
}

const selectedFilters = await createFiltersFromRangeSelectAction(data);

if (data.timeFieldName) {
Dosant marked this conversation as resolved.
Show resolved Hide resolved
const { timeRangeFilter, restOfFilters } = esFilters.extractTimeFilter(
data.timeFieldName,
selectedFilters
);
filterManager.addFilters(restOfFilters);
if (timeRangeFilter) {
esFilters.changeTimeFilter(timeFilter, timeRangeFilter);
shouldAutoExecute: async () => true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, can this be

Suggested change
shouldAutoExecute: async () => true,
autoExecute: true,

? I.e. does it have to by async?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No use case now, but I thought of having it as flexible as possible from that start (doesn't add much burden). Recently had to change getHref: () => string to getHref: () => Promise<string>

execute: async (context: SelectRangeActionContext) => {
try {
const filters = await createFiltersFromRangeSelectAction(context.data);
if (filters.length > 0) {
await getStartServices().uiActions.getTrigger(APPLY_FILTER_TRIGGER).exec({
filters,
embeddable: context.embeddable,
timeFieldName: context.data.timeFieldName,
});
}
} else {
filterManager.addFilters(selectedFilters);
} catch (e) {
// eslint-disable-next-line no-console
console.warn(`Error [ACTION_SELECT_RANGE]: can\'t extract filters from action context`);
}
},
});
Expand Down
Loading