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

Drilldown registration #59834

Merged
merged 2 commits into from
Mar 10, 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
49 changes: 6 additions & 43 deletions src/plugins/ui_actions/public/actions/action_definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,53 +17,16 @@
* under the License.
*/

import { UiComponent } from 'src/plugins/kibana_utils/common';
import { ActionType, ActionContextMapping } from '../types';
import { Presentable } from '../util/presentable';

export interface ActionDefinition<T extends ActionType> {
export interface ActionDefinition<T extends ActionType>
extends Partial<Presentable<ActionContextMapping[T]>> {
/**
* Determined the order when there is more than one action matched to a trigger.
* Higher numbers are displayed first.
* ID of the action factory for this action. Action factories are registered
* int X-Pack `ui_actions` plugin.
*/
order?: number;

/**
* A unique identifier for this action instance.
*/
id?: string;

/**
* The action type is what determines the context shape.
*/
readonly type: T;

/**
* Optional EUI icon type that can be displayed along with the title.
*/
getIconType?(context: ActionContextMapping[T]): string;

/**
* Returns a title to be displayed to the user.
* @param context
*/
getDisplayName?(context: ActionContextMapping[T]): string;

/**
* `UiComponent` to render when displaying this action as a context menu item.
* If not provided, `getDisplayName` will be used instead.
*/
MenuItem?: UiComponent<{ context: ActionContextMapping[T] }>;

/**
* Returns a promise that resolves to true if this action is compatible given the context,
* otherwise resolves to false.
*/
isCompatible?(context: ActionContextMapping[T]): Promise<boolean>;

/**
* If this returns something truthy, this is used in addition to the `execute` method when clicked.
*/
getHref?(context: ActionContextMapping[T]): string | undefined;
readonly type?: T;

/**
* Executes the action.
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/ui_actions/public/actions/create_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,5 @@ export function createAction<T extends ActionType>(action: ActionDefinition<T>):
getDisplayName: () => '',
getHref: () => undefined,
...action,
};
} as ActionByType<T>;
}
4 changes: 1 addition & 3 deletions src/plugins/ui_actions/public/util/presentable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,10 @@

import { UiComponent } from 'src/plugins/kibana_utils/common';

export type PresentableBaseContext = object;

/**
* Represents something that can be displayed to user in UI.
*/
export interface Presentable<Context extends PresentableBaseContext = PresentableBaseContext> {
export interface Presentable<Context extends object = object> {
/**
* ID that uniquely identifies this object.
*/
Expand Down
1 change: 1 addition & 0 deletions x-pack/.i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"xpack.beatsManagement": "legacy/plugins/beats_management",
"xpack.canvas": "legacy/plugins/canvas",
"xpack.crossClusterReplication": "legacy/plugins/cross_cluster_replication",
"xpack.dashboard": "plugins/dashboard_enhanced",
"xpack.dashboardMode": "legacy/plugins/dashboard_mode",
"xpack.data": "plugins/data_enhanced",
"xpack.drilldowns": "plugins/drilldowns",
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/advanced_ui_actions/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { AdvancedUiActionsSetup, AdvancedUiActionsStart } from './plugin';
export { ActionWizard } from './components';
export {
ActionFactoryDefinition as AdvancedUiActionsActionFactoryDefinition,
AnyActionFactoryDefinition as AdvancedUiActionsAnyActionFactoryDefinition,
ActionFactory as AdvancedUiActionsActionFactory,
AnyActionFactory as AdvancedUiActionsAnyActionFactory,
} from './services/action_factory_service';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

import { uiToReactComponent } from '../../../../../../src/plugins/kibana_react/public';
import {
UiActionsPresentable,
UiActionsActionDefinition,
UiActionsPresentable as Presentable,
UiActionsActionDefinition as ActionDefinition,
} from '../../../../../../src/plugins/ui_actions/public';
import {
AnyActionFactoryDefinition,
AFDConfig,
AFDFactoryContext,
AFDActionContext,
AFDConfig as Config,
AFDFactoryContext as FactoryContext,
AFDActionContext as ActionContext,
} from './action_factory_definition';
import { Configurable } from '../../util';

export class ActionFactory<D extends AnyActionFactoryDefinition>
implements UiActionsPresentable<AFDFactoryContext<D>>, Configurable<AFDConfig<D>> {
implements Presentable<FactoryContext<D>>, Configurable<Config<D>> {
constructor(public readonly definition: D) {}

public readonly id = this.definition.id;
Expand All @@ -31,28 +31,28 @@ export class ActionFactory<D extends AnyActionFactoryDefinition>
public readonly createConfig = this.definition.createConfig;
public readonly isConfigValid = this.definition.isConfigValid;

public getIconType(context: AFDFactoryContext<D>): string | undefined {
public getIconType(context: FactoryContext<D>): string | undefined {
if (!this.definition.getIconType) return undefined;
return this.definition.getIconType(context);
}

public getDisplayName(context: AFDFactoryContext<D>): string {
public getDisplayName(context: FactoryContext<D>): string {
if (!this.definition.getDisplayName) return '';
return this.definition.getDisplayName(context);
}

public async isCompatible(context: AFDFactoryContext<D>): Promise<boolean> {
public async isCompatible(context: FactoryContext<D>): Promise<boolean> {
if (!this.definition.isCompatible) return true;
return await this.definition.isCompatible(context);
}

public getHref(context: AFDFactoryContext<D>): string | undefined {
public getHref(context: FactoryContext<D>): string | undefined {
if (!this.definition.getHref) return undefined;
return this.definition.getHref(context);
}

public create(): UiActionsActionDefinition<AFDActionContext<D>> {
throw new Error('not implemented');
public create(config: Config<D>): ActionDefinition<ActionContext<D>> {
return this.definition.create(config);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
*/

import {
UiActionsPresentable,
UiActionsActionDefinition,
UiActionsPresentable as Presentable,
UiActionsActionDefinition as ActionDefinition,
} from '../../../../../../src/plugins/ui_actions/public';
import { Configurable } from '../../util';

Expand All @@ -17,7 +17,7 @@ export interface ActionFactoryDefinition<
Config extends object = object,
FactoryContext extends object = object,
ActionContext extends object = object
> extends Partial<UiActionsPresentable<FactoryContext>>, Configurable<Config> {
> extends Partial<Presentable<FactoryContext>>, Configurable<Config> {
/**
* Unique ID of the action factory. This ID is used to identify this action
* factory in the registry as well as to construct actions of this ID and
Expand All @@ -29,7 +29,7 @@ export interface ActionFactoryDefinition<
* This method should return a definition of a new action, normally used to
* register it in `ui_actions` registry.
*/
create(): UiActionsActionDefinition<ActionContext>;
create(config: Config): ActionDefinition<ActionContext>;
}

export type AnyActionFactoryDefinition = ActionFactoryDefinition<any, any, any>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class FlyoutCreateDrilldownAction implements ActionByType<typeof OPEN_FLY
constructor(protected readonly params: OpenFlyoutAddDrilldownParams) {}

public getDisplayName() {
return i18n.translate('xpack.drilldowns.FlyoutCreateDrilldownAction.displayName', {
return i18n.translate('xpack.dashboard.FlyoutCreateDrilldownAction.displayName', {
defaultMessage: 'Create drilldown',
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export interface FlyoutEditDrilldownParams {
drilldowns: () => Promise<DrilldownsStartContract>;
}

const displayName = i18n.translate('xpack.drilldowns.panel.openFlyoutEditDrilldown.displayName', {
const displayName = i18n.translate('xpack.dashboard.panel.openFlyoutEditDrilldown.displayName', {
defaultMessage: 'Manage drilldowns',
});

Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/drilldowns/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { CoreStart, CoreSetup, Plugin } from 'src/core/public';
import { UiActionsSetup, UiActionsStart } from '../../../../src/plugins/ui_actions/public';
import { AdvancedUiActionsSetup, AdvancedUiActionsStart } from '../../advanced_ui_actions/public';
import { DrilldownService, DrilldownServiceSetupContract } from './service';
import { DrilldownService, DrilldownServiceSetupContract } from './services';
import { createFlyoutManageDrilldowns } from './components/connected_flyout_manage_drilldowns';
import { Storage } from '../../../../src/plugins/kibana_utils/public';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
*/

import { CoreSetup } from 'src/core/public';
import {
AdvancedUiActionsSetup,
AdvancedUiActionsActionFactoryDefinition,
} from '../../../advanced_ui_actions/public';
import { AdvancedUiActionsSetup } from '../../../advanced_ui_actions/public';
import { Drilldown } from '../types';

// TODO: MOCK DATA
import {
Expand All @@ -25,20 +23,42 @@ export interface DrilldownServiceSetupContract {
/**
* Convenience method to register a drilldown.
*/
registerDrilldown: (drilldownFactory: AdvancedUiActionsActionFactoryDefinition<any>) => void;
registerDrilldown: (drilldown: Drilldown) => void;
}

export class DrilldownService {
setup(
core: CoreSetup,
{ advancedUiActions }: DrilldownServiceSetupDeps
): DrilldownServiceSetupContract {
const registerDrilldown: DrilldownServiceSetupContract['registerDrilldown'] = drilldownFactory => {
advancedUiActions.actionFactory.register(drilldownFactory);
const registerDrilldown: DrilldownServiceSetupContract['registerDrilldown'] = ({
id,
places,
CollectConfig,
createConfig,
isConfigValid,
getDisplayName,
getIconType,
execute,
}) => {
advancedUiActions.actionFactory.register({
id,
CollectConfig,
createConfig,
isConfigValid,
getDisplayName,
getIconType,
isCompatible: async ({ place }: any) => (!places ? true : places.indexOf(place) > -1),
create: config => ({
id: '',
type: id as any,
execute: async context => await execute(config, context),
}),
});
};

registerDrilldown(dashboardDrilldownActionFactory);
registerDrilldown(urlDrilldownActionFactory);
registerDrilldown({ ...dashboardDrilldownActionFactory, execute: () => {} } as any);
registerDrilldown({ ...urlDrilldownActionFactory, execute: () => {} } as any);

return {
registerDrilldown,
Expand Down
33 changes: 33 additions & 0 deletions x-pack/plugins/drilldowns/public/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* 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 { AdvancedUiActionsActionFactoryDefinition as ActionFactoryDefinition } from '../../advanced_ui_actions/public';

export interface Drilldown<
Config extends object = object,
FactoryContext extends object = object,
ExecutionContext extends object = object
>
extends Pick<
ActionFactoryDefinition<Config, FactoryContext, ExecutionContext>,
'id' | 'createConfig' | 'CollectConfig' | 'isConfigValid' | 'getIconType' | 'getDisplayName'
> {
/**
* List of places where this drilldown should be available, e.g "dashboard".
* If omitted, the drilldown will be show in all places.
*/
places?: string[];

/**
* Implements the "navigation" action when user clicks something in the UI and
* instance of this drilldown is triggered.
*
* @param config Config object that user configured this drilldown with.
* @param context Object that represents context in which the underlying
* `UIAction` of this drilldown is being executed in.
*/
execute(config: Config, context: ExecutionContext): void;
}