Skip to content

Commit

Permalink
Drilldown registration (#59834)
Browse files Browse the repository at this point in the history
* feat: 🎸 improve drilldown registration method

* fix: πŸ› set up translations for dashboard_enhanced plugin
  • Loading branch information
streamich authored Mar 10, 2020
1 parent 140c5dc commit b8cf696
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 75 deletions.
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;
}

0 comments on commit b8cf696

Please sign in to comment.