Generalize dashboard panel actions to not be dashboard specific (#22775) (#22829)

This commit is contained in:
Stacey Gammon 2018-09-07 14:52:09 -04:00 committed by GitHub
parent e3865d5e93
commit 64db863761
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 72 additions and 75 deletions

View file

@ -48,7 +48,7 @@ import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery';
import * as filterActions from 'ui/doc_table/actions/filter';
import { FilterManagerProvider } from 'ui/filter_manager';
import { EmbeddableFactoriesRegistryProvider } from 'ui/embeddable/embeddable_factories_registry';
import { DashboardPanelActionsRegistryProvider } from 'ui/dashboard_panel_actions/dashboard_panel_actions_registry';
import { ContextMenuActionsRegistryProvider } from 'ui/embeddable';
import { VisTypesRegistryProvider } from 'ui/registry/vis_types';
import { timefilter } from 'ui/timefilter';
import { getUnhashableStatesProvider } from 'ui/state_management/state_hashing';
@ -84,7 +84,7 @@ app.directive('dashboardApp', function ($injector) {
const filterBar = Private(FilterBarQueryFilterProvider);
const docTitle = Private(DocTitleProvider);
const embeddableFactories = Private(EmbeddableFactoriesRegistryProvider);
const panelActionsRegistry = Private(DashboardPanelActionsRegistryProvider);
const panelActionsRegistry = Private(ContextMenuActionsRegistryProvider);
const getUnhashableStates = Private(getUnhashableStatesProvider);
panelActionsStore.initializeFromRegistry(panelActionsRegistry);

View file

@ -19,7 +19,7 @@
import { EuiIcon } from '@elastic/eui';
import React from 'react';
import { DashboardContextMenuPanel, DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContextMenuAction, ContextMenuPanel } from 'ui/embeddable';
import { DashboardViewMode } from '../../../dashboard_view_mode';
import { PanelOptionsMenuForm } from '../panel_options_menu_form';
@ -33,15 +33,15 @@ export function getCustomizePanelAction({
onUpdatePanelTitle: (title: string) => void;
closeContextMenu: () => void;
title?: string;
}): DashboardPanelAction {
return new DashboardPanelAction(
}): ContextMenuAction {
return new ContextMenuAction(
{
displayName: 'Customize panel',
id: 'customizePanel',
parentPanelId: 'mainMenu',
},
{
childContextMenuPanel: new DashboardContextMenuPanel(
childContextMenuPanel: new ContextMenuPanel(
{
id: 'panelSubOptionsMenu',
title: 'Customize panel',

View file

@ -21,15 +21,15 @@ import React from 'react';
import { EuiIcon } from '@elastic/eui';
import { DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContextMenuAction } from 'ui/embeddable';
import { DashboardViewMode } from '../../../dashboard_view_mode';
/**
*
* @return {DashboardPanelAction}
* @return {ContextMenuAction}
*/
export function getEditPanelAction() {
return new DashboardPanelAction(
return new ContextMenuAction(
{
displayName: 'Edit visualization',
id: 'editPanel',

View file

@ -21,7 +21,7 @@ import React from 'react';
import { EuiIcon } from '@elastic/eui';
import { DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContextMenuAction } from 'ui/embeddable';
import { Inspector } from 'ui/inspector';
/**
@ -29,7 +29,7 @@ import { Inspector } from 'ui/inspector';
* This will check if the embeddable inside the panel actually exposes inspector adapters
* via its embeddable.getInspectorAdapters() method. If so - and if an inspector
* could be shown for those adapters - the inspector icon will be visible.
* @return {DashboardPanelAction}
* @return {ContextMenuAction}
*/
export function getInspectorPanelAction({
closeContextMenu,
@ -38,7 +38,7 @@ export function getInspectorPanelAction({
closeContextMenu: () => void;
panelTitle?: string;
}) {
return new DashboardPanelAction(
return new ContextMenuAction(
{
id: 'openInspector',
displayName: 'Inspect',

View file

@ -20,16 +20,16 @@
import { EuiIcon } from '@elastic/eui';
import React from 'react';
import { DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContextMenuAction } from 'ui/embeddable';
import { DashboardViewMode } from '../../../dashboard_view_mode';
/**
*
* @param {function} onDeletePanel
* @return {DashboardPanelAction}
* @return {ContextMenuAction}
*/
export function getRemovePanelAction(onDeletePanel: () => void) {
return new DashboardPanelAction(
return new ContextMenuAction(
{
displayName: 'Delete from dashboard',
id: 'deletePanel',

View file

@ -20,13 +20,13 @@
import { EuiIcon } from '@elastic/eui';
import React from 'react';
import { DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContextMenuAction } from 'ui/embeddable';
/**
* Returns an action that toggles the panel into maximized or minimized state.
* @param {boolean} isExpanded
* @param {function} toggleExpandedPanel
* @return {DashboardPanelAction}
* @return {ContextMenuAction}
*/
export function getToggleExpandPanelAction({
isExpanded,
@ -35,7 +35,7 @@ export function getToggleExpandPanelAction({
isExpanded: boolean;
toggleExpandedPanel: () => void;
}) {
return new DashboardPanelAction(
return new ContextMenuAction(
{
displayName: isExpanded ? 'Minimize' : 'Full screen',
id: 'togglePanel',

View file

@ -19,7 +19,6 @@
export { getEditPanelAction } from './get_edit_panel_action';
export { getRemovePanelAction } from './get_remove_panel_action';
export { buildEuiContextMenuPanels } from './build_context_menu';
export { getCustomizePanelAction } from './get_customize_panel_action';
export { getToggleExpandPanelAction } from './get_toggle_expand_panel_action';
export { getInspectorPanelAction } from './get_inspector_panel_action';

View file

@ -19,10 +19,14 @@
import { EuiContextMenuPanelDescriptor } from '@elastic/eui';
import { connect } from 'react-redux';
import { ContainerState, Embeddable } from 'ui/embeddable';
import { panelActionsStore } from '../../store/panel_actions_store';
import {
buildEuiContextMenuPanels,
ContainerState,
ContextMenuPanel,
Embeddable,
} from 'ui/embeddable';
import { panelActionsStore } from '../../store/panel_actions_store';
import {
getCustomizePanelAction,
getEditPanelAction,
getInspectorPanelAction,
@ -42,7 +46,6 @@ import {
} from '../../actions';
import { Dispatch } from 'redux';
import { DashboardContextMenuPanel } from 'ui/dashboard_panel_actions';
import { CoreKibanaState } from '../../../selectors';
import { DashboardViewMode } from '../../dashboard_view_mode';
import {
@ -163,7 +166,7 @@ const mergeProps = (
// Don't build the panels if the pop over is not open, or this gets expensive - this function is called once for
// every panel, every time any state changes.
if (isPopoverOpen) {
const contextMenuPanel = new DashboardContextMenuPanel({
const contextMenuPanel = new ContextMenuPanel({
title: 'Options',
id: 'mainMenu',
});

View file

@ -17,16 +17,16 @@
* under the License.
*/
import { DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContextMenuAction } from 'ui/embeddable';
class PanelActionsStore {
public actions: DashboardPanelAction[] = [];
public actions: ContextMenuAction[] = [];
/**
*
* @type {IndexedArray} panelActionsRegistry
*/
public initializeFromRegistry(panelActionsRegistry: DashboardPanelAction[]) {
public initializeFromRegistry(panelActionsRegistry: ContextMenuAction[]) {
panelActionsRegistry.forEach(panelAction => {
this.actions.push(panelAction);
});

View file

@ -35,7 +35,7 @@ import 'uiExports/savedObjectTypes';
import 'uiExports/fieldFormats';
import 'uiExports/fieldFormatEditors';
import 'uiExports/navbarExtensions';
import 'uiExports/dashboardPanelActions';
import 'uiExports/contextMenuActions';
import 'uiExports/managementSections';
import 'uiExports/devTools';
import 'uiExports/docViews';

View file

@ -19,22 +19,20 @@
import { EuiContextMenuPanelDescriptor, EuiContextMenuPanelItemDescriptor } from '@elastic/eui';
import _ from 'lodash';
import { DashboardContextMenuPanel, DashboardPanelAction } from 'ui/dashboard_panel_actions';
import { ContainerState, Embeddable } from 'ui/embeddable';
import { PanelId } from '../../../selectors';
import { ContainerState, ContextMenuAction, ContextMenuPanel, Embeddable } from 'ui/embeddable';
/**
* Loops through allActions and extracts those that belong on the given contextMenuPanelId
* @param {string} contextMenuPanelId
* @param {Array.<DashboardPanelAction>} allActions
* @param {Array.<ContextMenuAction>} allActions
*/
function getActionsForPanel(contextMenuPanelId: PanelId, allActions: DashboardPanelAction[]) {
function getActionsForPanel(contextMenuPanelId: string, allActions: ContextMenuAction[]) {
return allActions.filter(action => action.parentPanelId === contextMenuPanelId);
}
/**
* @param {String} contextMenuPanelId
* @param {Array.<DashboardPanelAction>} actions
* @param {Array.<ContextMenuAction>} actions
* @param {Embeddable} embeddable
* @param {ContainerState} containerState
* @return {{
@ -50,8 +48,8 @@ function buildEuiContextMenuPanelItemsAndChildPanels({
embeddable,
containerState,
}: {
contextMenuPanelId: PanelId;
actions: DashboardPanelAction[];
contextMenuPanelId: string;
actions: ContextMenuAction[];
embeddable?: Embeddable;
containerState: ContainerState;
}) {
@ -90,8 +88,8 @@ function buildEuiContextMenuPanelItemsAndChildPanels({
/**
* Transforms a DashboardContextMenuPanel to the shape EuiContextMenuPanel expects, inserting any registered pluggable
* panel actions.
* @param {DashboardContextMenuPanel} contextMenuPanel
* @param {Array.<DashboardPanelAction>} actions to build the context menu with
* @param {ContextMenuPanel} contextMenuPanel
* @param {Array.<ContextMenuAction>} actions to build the context menu with
* @param {Embeddable} embeddable
* @param {ContainerState} containerState
* @return {EuiContextMenuPanelDescriptor[]} An array of context menu panels to be used in the eui react component.
@ -102,8 +100,8 @@ export function buildEuiContextMenuPanels({
embeddable,
containerState,
}: {
contextMenuPanel: DashboardContextMenuPanel;
actions: DashboardPanelAction[];
contextMenuPanel: ContextMenuPanel;
actions: ContextMenuAction[];
embeddable?: Embeddable;
containerState: ContainerState;
}): EuiContextMenuPanelDescriptor[] {
@ -128,7 +126,7 @@ export function buildEuiContextMenuPanels({
/**
*
* @param {DashboardPanelAction} action
* @param {ContextMenuAction} action
* @param {ContainerState} containerState
* @param {Embeddable} embeddable
* @return {EuiContextMenuPanelItemDescriptor}
@ -138,7 +136,7 @@ function convertPanelActionToContextMenuItem({
containerState,
embeddable,
}: {
action: DashboardPanelAction;
action: ContextMenuAction;
containerState: ContainerState;
embeddable?: Embeddable;
}): EuiContextMenuPanelItemDescriptor {

View file

@ -17,10 +17,10 @@
* under the License.
*/
import { EuiContextMenuItemIcon } from '@elastic/eui';
import { DashboardContextMenuPanel } from './dashboard_context_menu_panel';
import { ContextMenuPanel } from './context_menu_panel';
import { PanelActionAPI } from './types';
interface DashboardPanelActionOptions {
interface ContextMenuActionOptions {
/**
* An optional action to take when the action is clicked on. Either this or childContextMenuPanel should be
* given.
@ -30,7 +30,7 @@ interface DashboardPanelActionOptions {
/**
* An optional child context menu to display when the action is clicked.
*/
childContextMenuPanel?: DashboardContextMenuPanel;
childContextMenuPanel?: ContextMenuPanel;
/**
* Whether this action should be disabled based on the parameters given.
@ -47,7 +47,7 @@ interface DashboardPanelActionOptions {
isVisible?: (panelActionAPI: PanelActionAPI) => boolean;
/**
* Determines which DashboardContextMenuPanel this action is displayed on.
* Determines which ContextMenuPanel this action is displayed on.
*/
parentPanelId?: string;
@ -57,7 +57,7 @@ interface DashboardPanelActionOptions {
icon?: EuiContextMenuItemIcon;
}
interface DashboardPanelActionsConfig {
interface ContextMenuActionsConfig {
id: string;
/**
@ -66,12 +66,12 @@ interface DashboardPanelActionsConfig {
displayName: string;
/**
* Determines which DashboardContextMenuPanel this action is displayed on.
* Determines which ContextMenuPanel this action is displayed on.
*/
parentPanelId: string;
}
export class DashboardPanelAction {
export class ContextMenuAction {
public readonly id: string;
/**
@ -87,10 +87,10 @@ export class DashboardPanelAction {
/**
* Optional child context menu to open when the action is clicked.
*/
public readonly childContextMenuPanel?: DashboardContextMenuPanel;
public readonly childContextMenuPanel?: ContextMenuPanel;
/**
* Determines which DashboardContextMenuPanel this action is displayed on.
* Determines which ContextMenuPanel this action is displayed on.
*/
public readonly parentPanelId: string;
@ -100,15 +100,12 @@ export class DashboardPanelAction {
* @param {string} config.displayName
* @param {string} config.parentPanelId - set if this action belongs on a nested child panel
* @param {function} options.onClick
* @param {DashboardContextMenuPanel} options.childContextMenuPanel - optional child panel to open when clicked.
* @param {ContextMenuPanel} options.childContextMenuPanel - optional child panel to open when clicked.
* @param {function} options.isDisabled - optionally set a custom disabled function
* @param {function} options.isVisible - optionally set a custom isVisible function
* @param {Element} options.icon
*/
public constructor(
config: DashboardPanelActionsConfig,
options: DashboardPanelActionOptions = {}
) {
public constructor(config: ContextMenuActionsConfig, options: ContextMenuActionOptions = {}) {
this.id = config.id;
this.displayName = config.displayName;
this.parentPanelId = config.parentPanelId;

View file

@ -20,7 +20,7 @@
// @ts-ignore: implicit any for JS file
import { uiRegistry } from 'ui/registry/_registry';
export const DashboardPanelActionsRegistryProvider = uiRegistry({
export const ContextMenuActionsRegistryProvider = uiRegistry({
index: ['name'],
name: 'dashboardPanelActions',
name: 'ContextMenuActions',
});

View file

@ -20,23 +20,20 @@
import { ReactElement } from 'react';
import { PanelActionAPI } from './types';
interface DashboardContextMenuPanelOptions {
interface ContextMenuPanelOptions {
getContent?: (panelActionAPI: PanelActionAPI) => ReactElement<any> | HTMLElement | undefined;
}
interface DashboardContextMenuPanelConfig {
interface ContextMenuPanelConfig {
id: string;
title: string;
}
export class DashboardContextMenuPanel {
export class ContextMenuPanel {
public readonly id: string;
public readonly title: string;
constructor(
config: DashboardContextMenuPanelConfig,
options: DashboardContextMenuPanelOptions = {}
) {
constructor(config: ContextMenuPanelConfig, options: ContextMenuPanelOptions = {}) {
this.id = config.id;
this.title = config.title;

View file

@ -17,6 +17,7 @@
* under the License.
*/
export { DashboardContextMenuPanel } from './dashboard_context_menu_panel';
export { DashboardPanelAction } from './dashboard_panel_action';
export { DashboardPanelActionsRegistryProvider } from './dashboard_panel_actions_registry';
export { ContextMenuPanel } from './context_menu_panel';
export { ContextMenuAction } from './context_menu_action';
export { ContextMenuActionsRegistryProvider } from './context_menu_actions_registry';
export { buildEuiContextMenuPanels } from './build_eui_context_menu_panels';

View file

@ -19,5 +19,6 @@
export { EmbeddableFactory } from './embeddable_factory';
export * from './embeddable';
export * from './context_menu_actions';
export { EmbeddableFactoriesRegistryProvider } from './embeddable_factories_registry';
export { ContainerState, EmbeddableState, Query, Filters, TimeRange } from './types';

View file

@ -43,7 +43,7 @@ export {
inspectorViews,
chromeNavControls,
navbarExtensions,
dashboardPanelActions,
contextMenuActions,
managementSections,
devTools,
docViews,

View file

@ -40,7 +40,7 @@ export const visEditorTypes = appExtension;
export const autocompleteProviders = appExtension;
export const savedObjectTypes = appExtension;
export const embeddableFactories = appExtension;
export const dashboardPanelActions = appExtension;
export const contextMenuActions = appExtension;
export const fieldFormats = appExtension;
export const fieldFormatEditors = appExtension;
export const chromeNavControls = appExtension;

View file

@ -20,7 +20,7 @@
function samplePanelAction(kibana) {
return new kibana.Plugin({
uiExports: {
dashboardPanelActions: ['plugins/sample_panel_action/sample_panel_action'],
contextMenuActions: ['plugins/sample_panel_action/sample_panel_action'],
},
});
}

View file

@ -21,11 +21,11 @@ import React from 'react';
import { openFlyout } from 'ui/flyout';
import {
DashboardPanelAction,
DashboardPanelActionsRegistryProvider,
} from 'ui/dashboard_panel_actions';
ContextMenuAction,
ContextMenuActionsRegistryProvider,
} from 'ui/embeddable';
class SamplePanelAction extends DashboardPanelAction {
class SamplePanelAction extends ContextMenuAction {
constructor() {
super({
displayName: 'Sample Panel Action',
@ -52,4 +52,4 @@ class SamplePanelAction extends DashboardPanelAction {
}
}
DashboardPanelActionsRegistryProvider.register(() => new SamplePanelAction());
ContextMenuActionsRegistryProvider.register(() => new SamplePanelAction());

View file

@ -14,6 +14,7 @@ import routes from 'ui/routes';
import { uiModules } from 'ui/modules';
// import the uiExports that we want to "use"
import 'uiExports/contextMenuActions';
import 'uiExports/visTypes';
import 'uiExports/visResponseHandlers';
import 'uiExports/visRequestHandlers';