diff --git a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx index 8a46a16c1bf0c..effbf8ce980d7 100644 --- a/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx +++ b/src/plugins/dashboard/public/application/top_nav/editor_menu.tsx @@ -231,7 +231,7 @@ export const EditorMenu = ({ dashboardContainer, createNewVisType }: Props) => { +
+ +
+ +`; + +exports[`Storyshots components/WorkpadHeader/EditorMenu default 1`] = ` +
+
+ +
+
+`; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx new file mode 100644 index 0000000000000..01048bc0af301 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/__stories__/editor_menu.stories.tsx @@ -0,0 +1,107 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { storiesOf } from '@storybook/react'; +import { action } from '@storybook/addon-actions'; +import React from 'react'; +import { EmbeddableFactoryDefinition, IEmbeddable } from 'src/plugins/embeddable/public'; +import { BaseVisType, VisTypeAlias } from 'src/plugins/visualizations/public'; +import { EditorMenu } from '../editor_menu.component'; + +const testFactories: EmbeddableFactoryDefinition[] = [ + { + type: 'ml_anomaly_swimlane', + getDisplayName: () => 'Anomaly swimlane', + getIconType: () => '', + getDescription: () => 'Description for anomaly swimlane', + isEditable: () => Promise.resolve(true), + create: () => Promise.resolve({ id: 'swimlane_embeddable' } as IEmbeddable), + grouping: [ + { + id: 'ml', + getDisplayName: () => 'machine learning', + getIconType: () => 'machineLearningApp', + }, + ], + }, + { + type: 'ml_anomaly_chart', + getDisplayName: () => 'Anomaly chart', + getIconType: () => '', + getDescription: () => 'Description for anomaly chart', + isEditable: () => Promise.resolve(true), + create: () => Promise.resolve({ id: 'anomaly_chart_embeddable' } as IEmbeddable), + grouping: [ + { + id: 'ml', + getDisplayName: () => 'machine learning', + getIconType: () => 'machineLearningApp', + }, + ], + }, + { + type: 'log_stream', + getDisplayName: () => 'Log stream', + getIconType: () => '', + getDescription: () => 'Description for log stream', + isEditable: () => Promise.resolve(true), + create: () => Promise.resolve({ id: 'anomaly_chart_embeddable' } as IEmbeddable), + }, +]; + +const testVisTypes: BaseVisType[] = [ + { title: 'TSVB', icon: '', description: 'Description of TSVB', name: 'tsvb' } as BaseVisType, + { + titleInWizard: 'Custom visualization', + title: 'Vega', + icon: '', + description: 'Description of Vega', + name: 'vega', + } as BaseVisType, +]; + +const testVisTypeAliases: VisTypeAlias[] = [ + { + title: 'Lens', + aliasApp: 'lens', + aliasPath: 'path/to/lens', + icon: 'lensApp', + name: 'lens', + description: 'Description of Lens app', + stage: 'production', + }, + { + title: 'Maps', + aliasApp: 'maps', + aliasPath: 'path/to/maps', + icon: 'gisApp', + name: 'maps', + description: 'Description of Maps app', + stage: 'production', + }, +]; + +storiesOf('components/WorkpadHeader/EditorMenu', module) + .add('default', () => ( + action('createNewVisType')} + createNewEmbeddable={() => action('createNewEmbeddable')} + /> + )) + .add('dark mode', () => ( + action('createNewVisType')} + createNewEmbeddable={() => action('createNewEmbeddable')} + /> + )); diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx new file mode 100644 index 0000000000000..e8f762f9731a1 --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.component.tsx @@ -0,0 +1,170 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { + EuiContextMenu, + EuiContextMenuPanelItemDescriptor, + EuiContextMenuItemIcon, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { EmbeddableFactoryDefinition } from '../../../../../../../src/plugins/embeddable/public'; +import { BaseVisType, VisTypeAlias } from '../../../../../../../src/plugins/visualizations/public'; +import { SolutionToolbarPopover } from '../../../../../../../src/plugins/presentation_util/public'; + +const strings = { + getEditorMenuButtonLabel: () => + i18n.translate('xpack.canvas.solutionToolbar.editorMenuButtonLabel', { + defaultMessage: 'Select type', + }), +}; + +interface FactoryGroup { + id: string; + appName: string; + icon: EuiContextMenuItemIcon; + panelId: number; + factories: EmbeddableFactoryDefinition[]; +} + +interface Props { + factories: EmbeddableFactoryDefinition[]; + isDarkThemeEnabled?: boolean; + promotedVisTypes: BaseVisType[]; + visTypeAliases: VisTypeAlias[]; + createNewVisType: (visType?: BaseVisType | VisTypeAlias) => () => void; + createNewEmbeddable: (factory: EmbeddableFactoryDefinition) => () => void; +} + +export const EditorMenu: FC = ({ + factories, + isDarkThemeEnabled, + promotedVisTypes, + visTypeAliases, + createNewVisType, + createNewEmbeddable, +}: Props) => { + const factoryGroupMap: Record = {}; + const ungroupedFactories: EmbeddableFactoryDefinition[] = []; + + let panelCount = 1; + + // Maps factories with a group to create nested context menus for each group type + // and pushes ungrouped factories into a separate array + factories.forEach((factory: EmbeddableFactoryDefinition, index) => { + const { grouping } = factory; + + if (grouping) { + grouping.forEach((group) => { + if (factoryGroupMap[group.id]) { + factoryGroupMap[group.id].factories.push(factory); + } else { + factoryGroupMap[group.id] = { + id: group.id, + appName: group.getDisplayName ? group.getDisplayName({}) : group.id, + icon: (group.getIconType ? group.getIconType({}) : 'empty') as EuiContextMenuItemIcon, + factories: [factory], + panelId: panelCount, + }; + + panelCount++; + } + }); + } else { + ungroupedFactories.push(factory); + } + }); + + const getVisTypeMenuItem = (visType: BaseVisType): EuiContextMenuPanelItemDescriptor => { + const { name, title, titleInWizard, description, icon = 'empty' } = visType; + return { + name: titleInWizard || title, + icon: icon as string, + onClick: createNewVisType(visType), + 'data-test-subj': `visType-${name}`, + toolTipContent: description, + }; + }; + + const getVisTypeAliasMenuItem = ( + visTypeAlias: VisTypeAlias + ): EuiContextMenuPanelItemDescriptor => { + const { name, title, description, icon = 'empty' } = visTypeAlias; + + return { + name: title, + icon, + onClick: createNewVisType(visTypeAlias), + 'data-test-subj': `visType-${name}`, + toolTipContent: description, + }; + }; + + const getEmbeddableFactoryMenuItem = ( + factory: EmbeddableFactoryDefinition + ): EuiContextMenuPanelItemDescriptor => { + const icon = factory?.getIconType ? factory.getIconType() : 'empty'; + + const toolTipContent = factory?.getDescription ? factory.getDescription() : undefined; + + return { + name: factory.getDisplayName(), + icon, + toolTipContent, + onClick: createNewEmbeddable(factory), + 'data-test-subj': `createNew-${factory.type}`, + }; + }; + + const editorMenuPanels = [ + { + id: 0, + items: [ + ...visTypeAliases.map(getVisTypeAliasMenuItem), + ...Object.values(factoryGroupMap).map(({ id, appName, icon, panelId }) => ({ + name: appName, + icon, + panel: panelId, + 'data-test-subj': `canvasEditorMenu-${id}Group`, + })), + ...ungroupedFactories.map(getEmbeddableFactoryMenuItem), + ...promotedVisTypes.map(getVisTypeMenuItem), + ], + }, + ...Object.values(factoryGroupMap).map( + ({ appName, panelId, factories: groupFactories }: FactoryGroup) => ({ + id: panelId, + title: appName, + items: groupFactories.map(getEmbeddableFactoryMenuItem), + }) + ), + ]; + + return ( + + {() => ( + + )} + + ); +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx new file mode 100644 index 0000000000000..dad34e6983c5d --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/editor_menu.tsx @@ -0,0 +1,147 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC, useCallback } from 'react'; +import { useLocation } from 'react-router-dom'; +import { trackCanvasUiMetric, METRIC_TYPE } from '../../../../public/lib/ui_metric'; +import { + useEmbeddablesService, + usePlatformService, + useVisualizationsService, +} from '../../../services'; +import { + BaseVisType, + VisGroups, + VisTypeAlias, +} from '../../../../../../../src/plugins/visualizations/public'; +import { + EmbeddableFactoryDefinition, + EmbeddableInput, +} from '../../../../../../../src/plugins/embeddable/public'; +import { CANVAS_APP } from '../../../../common/lib'; +import { encode } from '../../../../common/lib/embeddable_dataurl'; +import { ElementSpec } from '../../../../types'; +import { EditorMenu as Component } from './editor_menu.component'; + +interface Props { + /** + * Handler for adding a selected element to the workpad + */ + addElement: (element: Partial) => void; +} + +export const EditorMenu: FC = ({ addElement }) => { + const embeddablesService = useEmbeddablesService(); + const { pathname, search } = useLocation(); + const platformService = usePlatformService(); + const stateTransferService = embeddablesService.getStateTransfer(); + const visualizationsService = useVisualizationsService(); + const IS_DARK_THEME = platformService.getUISetting('theme:darkMode'); + + const createNewVisType = useCallback( + (visType?: BaseVisType | VisTypeAlias) => () => { + let path = ''; + let appId = ''; + + if (visType) { + if (trackCanvasUiMetric) { + trackCanvasUiMetric(METRIC_TYPE.CLICK, `${visType.name}:create`); + } + + if ('aliasPath' in visType) { + appId = visType.aliasApp; + path = visType.aliasPath; + } else { + appId = 'visualize'; + path = `#/create?type=${encodeURIComponent(visType.name)}`; + } + } else { + appId = 'visualize'; + path = '#/create?'; + } + + stateTransferService.navigateToEditor(appId, { + path, + state: { + originatingApp: CANVAS_APP, + originatingPath: `#/${pathname}${search}`, + }, + }); + }, + [stateTransferService, pathname, search] + ); + + const createNewEmbeddable = useCallback( + (factory: EmbeddableFactoryDefinition) => async () => { + if (trackCanvasUiMetric) { + trackCanvasUiMetric(METRIC_TYPE.CLICK, factory.type); + } + let embeddableInput; + if (factory.getExplicitInput) { + embeddableInput = await factory.getExplicitInput(); + } else { + const newEmbeddable = await factory.create({} as EmbeddableInput); + embeddableInput = newEmbeddable?.getInput(); + } + + if (embeddableInput) { + const config = encode(embeddableInput); + const expression = `embeddable config="${config}" + type="${factory.type}" +| render`; + + addElement({ expression }); + } + }, + [addElement] + ); + + const getVisTypesByGroup = (group: VisGroups): BaseVisType[] => + visualizationsService + .getByGroup(group) + .sort(({ name: a }: BaseVisType | VisTypeAlias, { name: b }: BaseVisType | VisTypeAlias) => { + if (a < b) { + return -1; + } + if (a > b) { + return 1; + } + return 0; + }) + .filter(({ hidden }: BaseVisType) => !hidden); + + const visTypeAliases = visualizationsService + .getAliases() + .sort(({ promotion: a = false }: VisTypeAlias, { promotion: b = false }: VisTypeAlias) => + a === b ? 0 : a ? -1 : 1 + ); + + const factories = embeddablesService + ? Array.from(embeddablesService.getEmbeddableFactories()).filter( + ({ type, isEditable, canCreateNew, isContainerType }) => + isEditable() && + !isContainerType && + canCreateNew() && + !['visualization', 'ml'].some((factoryType) => { + return type.includes(factoryType); + }) + ) + : []; + + const promotedVisTypes = getVisTypesByGroup(VisGroups.PROMOTED); + + return ( + + ); +}; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/index.ts new file mode 100644 index 0000000000000..0f903b1bbbe2e --- /dev/null +++ b/x-pack/plugins/canvas/public/components/workpad_header/editor_menu/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { EditorMenu } from './editor_menu'; +export { EditorMenu as EditorMenuComponent } from './editor_menu.component'; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx index a48a6e35a4a37..9d37873bcae0a 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/__stories__/element_menu.stories.tsx @@ -130,9 +130,5 @@ You can use standard Markdown in here, but you can also access your piped-in dat }; storiesOf('components/WorkpadHeader/ElementMenu', module).add('default', () => ( - + )); diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx index 024c71c7a8dfc..1cfab236d9a9c 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.component.tsx @@ -12,13 +12,12 @@ import { EuiContextMenu, EuiIcon, EuiContextMenuPanelItemDescriptor } from '@ela import { i18n } from '@kbn/i18n'; import { PrimaryActionPopover } from '../../../../../../../src/plugins/presentation_util/public'; import { getId } from '../../../lib/get_id'; -import { ClosePopoverFn } from '../../popover'; import { CONTEXT_MENU_TOP_BORDER_CLASSNAME } from '../../../../common/lib'; import { ElementSpec } from '../../../../types'; import { flattenPanelTree } from '../../../lib/flatten_panel_tree'; import { AssetManager } from '../../asset_manager'; +import { ClosePopoverFn } from '../../popover'; import { SavedElementsModal } from '../../saved_elements_modal'; -import { useLabsService } from '../../../services'; interface CategorizedElementLists { [key: string]: ElementSpec[]; @@ -122,19 +121,9 @@ export interface Props { * Handler for adding a selected element to the workpad */ addElement: (element: Partial) => void; - /** - * Crete new embeddable - */ - createNewEmbeddable: () => void; } -export const ElementMenu: FunctionComponent = ({ - elements, - addElement, - createNewEmbeddable, -}) => { - const labsService = useLabsService(); - const isByValueEnabled = labsService.isProjectEnabled('labs:canvas:byValueEmbeddable'); +export const ElementMenu: FunctionComponent = ({ elements, addElement }) => { const [isAssetModalVisible, setAssetModalVisible] = useState(false); const [isSavedElementsModalVisible, setSavedElementsModalVisible] = useState(false); @@ -210,18 +199,6 @@ export const ElementMenu: FunctionComponent = ({ closePopover(); }, }, - // TODO: Remove this menu option. This is a temporary menu options just for testing, - // will be removed once toolbar is implemented - isByValueEnabled - ? { - name: 'Lens', - icon: , - onClick: () => { - createNewEmbeddable(); - closePopover(); - }, - } - : {}, ], }; }; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx index b4f28df9e9a11..d43d13a65a5d7 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/element_menu.tsx @@ -5,34 +5,4 @@ * 2.0. */ -import React, { FC, useCallback } from 'react'; -import { useLocation } from 'react-router-dom'; -import { trackCanvasUiMetric, METRIC_TYPE } from '../../../../public/lib/ui_metric'; -import { CANVAS_APP } from '../../../../common/lib'; -import { ElementMenu as Component, Props } from './element_menu.component'; -import { useEmbeddablesService } from '../../../services'; - -export const ElementMenu: FC> = (props) => { - const embeddablesService = useEmbeddablesService(); - const stateTransferService = embeddablesService.getStateTransfer(); - const { pathname, search } = useLocation(); - - const createNewEmbeddable = useCallback(() => { - const path = '#/'; - const appId = 'lens'; - - if (trackCanvasUiMetric) { - trackCanvasUiMetric(METRIC_TYPE.CLICK, `${appId}:create`); - } - - stateTransferService.navigateToEditor(appId, { - path, - state: { - originatingApp: CANVAS_APP, - originatingPath: `#/${pathname}${search}`, - }, - }); - }, [pathname, search, stateTransferService]); - - return ; -}; +export * from './element_menu.component'; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts index 52c8daece7690..037bb84b0cdba 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts +++ b/x-pack/plugins/canvas/public/components/workpad_header/element_menu/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export { ElementMenu } from './element_menu'; -export { ElementMenu as ElementMenuComponent } from './element_menu.component'; +export { ElementMenu } from './element_menu.component'; diff --git a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx index f031d7c263199..b84e4faf2925e 100644 --- a/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx +++ b/x-pack/plugins/canvas/public/components/workpad_header/workpad_header.component.tsx @@ -27,6 +27,7 @@ import { ElementMenu } from './element_menu'; import { ShareMenu } from './share_menu'; import { ViewMenu } from './view_menu'; import { LabsControl } from './labs_control'; +import { EditorMenu } from './editor_menu'; const strings = { getFullScreenButtonAriaLabel: () => @@ -160,24 +161,22 @@ export const WorkpadHeader: FC = ({ + {isWriteable && ( + + + {{ + primaryActionButton: , + quickButtonGroup: , + addFromLibraryButton: , + extraButtons: [], + }} + + + )} - {isWriteable && ( - - - {{ - primaryActionButton: ( - - ), - quickButtonGroup: , - addFromLibraryButton: , - }} - - - )} @@ -192,6 +191,7 @@ export const WorkpadHeader: FC = ({ + diff --git a/x-pack/plugins/canvas/public/plugin.tsx b/x-pack/plugins/canvas/public/plugin.tsx index afaa750c124bf..912055dd47a62 100644 --- a/x-pack/plugins/canvas/public/plugin.tsx +++ b/x-pack/plugins/canvas/public/plugin.tsx @@ -8,6 +8,7 @@ import { BehaviorSubject } from 'rxjs'; import type { SharePluginSetup } from 'src/plugins/share/public'; import { ChartsPluginSetup, ChartsPluginStart } from 'src/plugins/charts/public'; +import { VisualizationsStart } from 'src/plugins/visualizations/public'; import { ReportingStart } from '../../reporting/public'; import { CoreSetup, @@ -63,6 +64,7 @@ export interface CanvasStartDeps { charts: ChartsPluginStart; data: DataPublicPluginStart; presentationUtil: PresentationUtilPluginStart; + visualizations: VisualizationsStart; spaces?: SpacesPluginStart; } diff --git a/x-pack/plugins/canvas/public/services/index.ts b/x-pack/plugins/canvas/public/services/index.ts index f4292810b8089..ed55f919e4c76 100644 --- a/x-pack/plugins/canvas/public/services/index.ts +++ b/x-pack/plugins/canvas/public/services/index.ts @@ -17,6 +17,7 @@ import { CanvasNavLinkService } from './nav_link'; import { CanvasNotifyService } from './notify'; import { CanvasPlatformService } from './platform'; import { CanvasReportingService } from './reporting'; +import { CanvasVisualizationsService } from './visualizations'; import { CanvasWorkpadService } from './workpad'; export interface CanvasPluginServices { @@ -28,6 +29,7 @@ export interface CanvasPluginServices { notify: CanvasNotifyService; platform: CanvasPlatformService; reporting: CanvasReportingService; + visualizations: CanvasVisualizationsService; workpad: CanvasWorkpadService; } @@ -44,4 +46,6 @@ export const useNavLinkService = () => (() => pluginServices.getHooks().navLink. export const useNotifyService = () => (() => pluginServices.getHooks().notify.useService())(); export const usePlatformService = () => (() => pluginServices.getHooks().platform.useService())(); export const useReportingService = () => (() => pluginServices.getHooks().reporting.useService())(); +export const useVisualizationsService = () => + (() => pluginServices.getHooks().visualizations.useService())(); export const useWorkpadService = () => (() => pluginServices.getHooks().workpad.useService())(); diff --git a/x-pack/plugins/canvas/public/services/kibana/index.ts b/x-pack/plugins/canvas/public/services/kibana/index.ts index 1eb010e8d6f9d..91767947bc0a6 100644 --- a/x-pack/plugins/canvas/public/services/kibana/index.ts +++ b/x-pack/plugins/canvas/public/services/kibana/index.ts @@ -22,6 +22,7 @@ import { navLinkServiceFactory } from './nav_link'; import { notifyServiceFactory } from './notify'; import { platformServiceFactory } from './platform'; import { reportingServiceFactory } from './reporting'; +import { visualizationsServiceFactory } from './visualizations'; import { workpadServiceFactory } from './workpad'; export { customElementServiceFactory } from './custom_element'; @@ -31,6 +32,7 @@ export { labsServiceFactory } from './labs'; export { notifyServiceFactory } from './notify'; export { platformServiceFactory } from './platform'; export { reportingServiceFactory } from './reporting'; +export { visualizationsServiceFactory } from './visualizations'; export { workpadServiceFactory } from './workpad'; export const pluginServiceProviders: PluginServiceProviders< @@ -45,6 +47,7 @@ export const pluginServiceProviders: PluginServiceProviders< notify: new PluginServiceProvider(notifyServiceFactory), platform: new PluginServiceProvider(platformServiceFactory), reporting: new PluginServiceProvider(reportingServiceFactory), + visualizations: new PluginServiceProvider(visualizationsServiceFactory), workpad: new PluginServiceProvider(workpadServiceFactory), }; diff --git a/x-pack/plugins/canvas/public/services/kibana/visualizations.ts b/x-pack/plugins/canvas/public/services/kibana/visualizations.ts new file mode 100644 index 0000000000000..e319ec1c1f427 --- /dev/null +++ b/x-pack/plugins/canvas/public/services/kibana/visualizations.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KibanaPluginServiceFactory } from '../../../../../../src/plugins/presentation_util/public'; +import { CanvasStartDeps } from '../../plugin'; +import { CanvasVisualizationsService } from '../visualizations'; + +export type VisualizationsServiceFactory = KibanaPluginServiceFactory< + CanvasVisualizationsService, + CanvasStartDeps +>; + +export const visualizationsServiceFactory: VisualizationsServiceFactory = ({ startPlugins }) => ({ + showNewVisModal: startPlugins.visualizations.showNewVisModal, + getByGroup: startPlugins.visualizations.getByGroup, + getAliases: startPlugins.visualizations.getAliases, +}); diff --git a/x-pack/plugins/canvas/public/services/stubs/index.ts b/x-pack/plugins/canvas/public/services/stubs/index.ts index 06a5ff49e9c04..2216013a29c12 100644 --- a/x-pack/plugins/canvas/public/services/stubs/index.ts +++ b/x-pack/plugins/canvas/public/services/stubs/index.ts @@ -22,6 +22,7 @@ import { navLinkServiceFactory } from './nav_link'; import { notifyServiceFactory } from './notify'; import { platformServiceFactory } from './platform'; import { reportingServiceFactory } from './reporting'; +import { visualizationsServiceFactory } from './visualizations'; import { workpadServiceFactory } from './workpad'; export { customElementServiceFactory } from './custom_element'; @@ -31,6 +32,7 @@ export { navLinkServiceFactory } from './nav_link'; export { notifyServiceFactory } from './notify'; export { platformServiceFactory } from './platform'; export { reportingServiceFactory } from './reporting'; +export { visualizationsServiceFactory } from './visualizations'; export { workpadServiceFactory } from './workpad'; export const pluginServiceProviders: PluginServiceProviders = { @@ -42,6 +44,7 @@ export const pluginServiceProviders: PluginServiceProviders; + +const noop = (..._args: any[]): any => {}; + +export const visualizationsServiceFactory: VisualizationsServiceFactory = () => ({ + showNewVisModal: noop, + getByGroup: noop, + getAliases: noop, +}); diff --git a/x-pack/plugins/canvas/public/services/visualizations.ts b/x-pack/plugins/canvas/public/services/visualizations.ts new file mode 100644 index 0000000000000..c602b1dd39f3d --- /dev/null +++ b/x-pack/plugins/canvas/public/services/visualizations.ts @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { VisualizationsStart } from '../../../../../src/plugins/visualizations/public'; + +export interface CanvasVisualizationsService { + showNewVisModal: VisualizationsStart['showNewVisModal']; + getByGroup: VisualizationsStart['getByGroup']; + getAliases: VisualizationsStart['getAliases']; +}