diff --git a/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_api.ts b/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_api.ts index 42915c0aa3979..ad9a32d31f861 100644 --- a/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_api.ts +++ b/src/plugins/dashboard/public/dashboard_container/external_api/dashboard_api.ts @@ -8,12 +8,24 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import { CanDuplicatePanels, CanExpandPanels, TracksOverlays } from '@kbn/presentation-containers'; -import { HasTypeDisplayName, PublishesSavedObjectId } from '@kbn/presentation-publishing'; +import { + HasType, + HasTypeDisplayName, + PublishesLocalUnifiedSearch, + PublishesPanelTitle, + PublishesSavedObjectId, +} from '@kbn/presentation-publishing'; import { DashboardPanelState } from '../../../common'; import { DashboardContainer } from '../embeddable/dashboard_container'; // TODO lock down DashboardAPI -export type DashboardAPI = DashboardContainer; +export type DashboardAPI = DashboardContainer & + Partial< + HasType<'dashboard'> & + PublishesLocalUnifiedSearch & + PublishesPanelTitle & + PublishesSavedObjectId + >; export type AwaitingDashboardAPI = DashboardAPI | null; export const buildApiFromDashboardContainer = (container?: DashboardContainer) => container ?? null; diff --git a/x-pack/plugins/lens/public/embeddable/index.ts b/x-pack/plugins/lens/public/embeddable/index.ts index 37bd92c53a9a3..50ee0f582a2ff 100644 --- a/x-pack/plugins/lens/public/embeddable/index.ts +++ b/x-pack/plugins/lens/public/embeddable/index.ts @@ -7,4 +7,4 @@ export * from './embeddable'; -export { type HasLensConfig, apiHasLensConfig } from './interfaces/has_lens_config'; +export { type LensApi, isLensApi } from './interfaces/lens_api'; diff --git a/x-pack/plugins/lens/public/embeddable/interfaces/has_lens_config.ts b/x-pack/plugins/lens/public/embeddable/interfaces/has_lens_config.ts deleted file mode 100644 index 9e3f9c4b026e0..0000000000000 --- a/x-pack/plugins/lens/public/embeddable/interfaces/has_lens_config.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 { type HasType, apiIsOfType } from '@kbn/presentation-publishing'; -import { LensSavedObjectAttributes } from '../embeddable'; - -export type HasLensConfig = HasType<'lens'> & { - getSavedVis: () => Readonly; -}; - -export const apiHasLensConfig = (api: unknown): api is HasLensConfig => { - return Boolean( - api && apiIsOfType(api, 'lens') && typeof (api as HasLensConfig).getSavedVis === 'function' - ); -}; diff --git a/x-pack/plugins/lens/public/embeddable/interfaces/lens_api.ts b/x-pack/plugins/lens/public/embeddable/interfaces/lens_api.ts new file mode 100644 index 0000000000000..32e1ac52085a2 --- /dev/null +++ b/x-pack/plugins/lens/public/embeddable/interfaces/lens_api.ts @@ -0,0 +1,38 @@ +/* + * 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 type { + HasParentApi, + HasType, + PublishesLocalUnifiedSearch, + PublishesPanelTitle, +} from '@kbn/presentation-publishing'; +import { + apiIsOfType, + apiPublishesLocalUnifiedSearch, + apiPublishesPanelTitle, +} from '@kbn/presentation-publishing'; +import { LensSavedObjectAttributes } from '../embeddable'; + +export type HasLensConfig = HasType<'lens'> & { + getSavedVis: () => Readonly; +}; + +export type LensApi = HasLensConfig & + PublishesPanelTitle & + PublishesLocalUnifiedSearch & + Partial>; + +export const isLensApi = (api: unknown): api is LensApi => { + return Boolean( + api && + apiIsOfType(api, 'lens') && + typeof (api as HasLensConfig).getSavedVis === 'function' && + apiPublishesPanelTitle(api) && + apiPublishesLocalUnifiedSearch(api) + ); +}; diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index 2bf09422986e9..0088e434cb72d 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -7,7 +7,7 @@ import { LensPlugin } from './plugin'; -export { apiHasLensConfig } from './embeddable/interfaces/has_lens_config'; +export { isLensApi } from './embeddable/interfaces/lens_api'; export type { EmbeddableComponentProps, EmbeddableComponent, @@ -110,7 +110,7 @@ export type { export type { InlineEditLensEmbeddableContext } from './trigger_actions/open_lens_config/in_app_embeddable_edit/types'; export type { - HasLensConfig, + LensApi, LensEmbeddableInput, LensSavedObjectAttributes, Embeddable, diff --git a/x-pack/plugins/maps/public/embeddable/map_api.ts b/x-pack/plugins/maps/public/embeddable/map_api.ts new file mode 100644 index 0000000000000..171816289a8af --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/map_api.ts @@ -0,0 +1,37 @@ +/* + * 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 type { + HasParentApi, + HasType, + PublishesDataViews, + PublishesPanelTitle, + PublishesLocalUnifiedSearch, +} from '@kbn/presentation-publishing'; +import { + apiIsOfType, + apiPublishesLocalUnifiedSearch, + apiPublishesPanelTitle, +} from '@kbn/presentation-publishing'; +import type { ILayer } from '../classes/layers/layer'; + +export type MapApi = HasType<'map'> & { + getLayerList: () => ILayer[]; +} & PublishesDataViews & + PublishesPanelTitle & + PublishesLocalUnifiedSearch & + Partial>; + +export const isMapApi = (api: unknown): api is MapApi => { + return Boolean( + api && + apiIsOfType(api, 'map') && + typeof (api as MapApi).getLayerList === 'function' && + apiPublishesPanelTitle(api) && + apiPublishesLocalUnifiedSearch(api) + ); +}; diff --git a/x-pack/plugins/maps/public/index.ts b/x-pack/plugins/maps/public/index.ts index 72806e7579dc6..d0281537e7a02 100644 --- a/x-pack/plugins/maps/public/index.ts +++ b/x-pack/plugins/maps/public/index.ts @@ -28,6 +28,7 @@ export type { export type { MapsSetupApi, MapsStartApi } from './api'; export type { MapEmbeddable, MapEmbeddableInput, MapEmbeddableOutput } from './embeddable'; +export { type MapApi, isMapApi } from './embeddable/map_api'; export type { EMSTermJoinConfig, SampleValuesConfig } from './ems_autosuggest'; diff --git a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/is_compatible.ts b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/is_compatible.ts index bd31feb04f00e..520ed2e1cc92e 100644 --- a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/is_compatible.ts +++ b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/is_compatible.ts @@ -7,7 +7,7 @@ import { apiIsOfType } from '@kbn/presentation-publishing'; import { apiHasVisualizeConfig } from '@kbn/visualizations-plugin/public'; -import { apiHasLensConfig } from '@kbn/lens-plugin/public'; +import { isLensApi } from '@kbn/lens-plugin/public'; import { MAP_SAVED_OBJECT_TYPE } from '../../../common/constants'; import { isLegacyMapApi } from '../../legacy_visualizations/is_legacy_map'; import { mapEmbeddablesSingleton } from '../../embeddable/map_embeddables_singleton'; @@ -19,7 +19,7 @@ export function isCompatible(api: SynchronizeMovementActionApi) { } return ( apiIsOfType(api, MAP_SAVED_OBJECT_TYPE) || - (apiHasLensConfig(api) && api.getSavedVis()?.visualizationType === 'lnsChoropleth') || + (isLensApi(api) && api.getSavedVis()?.visualizationType === 'lnsChoropleth') || (apiHasVisualizeConfig(api) && isLegacyMapApi(api)) ); } diff --git a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/types.ts b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/types.ts index 4b9e48e19c2d0..f171e39a2ad25 100644 --- a/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/types.ts +++ b/x-pack/plugins/maps/public/trigger_actions/synchronize_movement/types.ts @@ -6,9 +6,9 @@ */ import type { HasType } from '@kbn/presentation-publishing'; -import type { HasLensConfig } from '@kbn/lens-plugin/public'; +import type { LensApi } from '@kbn/lens-plugin/public'; import type { HasVisualizeConfig } from '@kbn/visualizations-plugin/public'; export type SynchronizeMovementActionApi = | HasType<'map' | 'visualization' | 'lens'> - | Partial; + | Partial; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/index.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/index.ts index 37e7eb83d5720..60fa45bfae44e 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/index.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/index.ts @@ -5,5 +5,5 @@ * 2.0. */ -export { QuickJobCreatorBase, isLensEmbeddable, isMapEmbeddable } from './quick_create_job_base'; +export { QuickJobCreatorBase } from './quick_create_job_base'; export type { CreateState } from './quick_create_job_base'; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/quick_create_job_base.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/quick_create_job_base.ts index f3b986d352777..d6bfc450a4cfa 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/quick_create_job_base.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_dashboard/quick_create_job_base.ts @@ -11,11 +11,14 @@ import type { IUiSettingsClient } from '@kbn/core/public'; import type { TimefilterContract } from '@kbn/data-plugin/public'; import { firstValueFrom } from 'rxjs'; import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -import type { DashboardLocatorParams, DashboardStart } from '@kbn/dashboard-plugin/public'; +import type { + DashboardAPI, + DashboardLocatorParams, + DashboardStart, +} from '@kbn/dashboard-plugin/public'; +import { getPanelTitle } from '@kbn/presentation-publishing'; import type { Filter, Query, DataViewBase } from '@kbn/es-query'; import { FilterStateStore } from '@kbn/es-query'; -import type { Embeddable } from '@kbn/lens-plugin/public'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; import type { ErrorType } from '@kbn/ml-error-utils'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import type { MlApiServices } from '../../../services/ml_api_service'; @@ -25,16 +28,6 @@ import type { CREATED_BY_LABEL } from '../../../../../common/constants/new_job'; import { createQueries } from '../utils/new_job_utils'; import { createDatafeedId } from '../../../../../common/util/job_utils'; -export function isLensEmbeddable(arg: any): arg is Embeddable { - return arg.hasOwnProperty('type') && arg.type === 'lens'; -} - -export function isMapEmbeddable(arg: any): arg is MapEmbeddable { - return arg.hasOwnProperty('type') && arg.type === 'map'; -} - -export type Dashboard = Embeddable['parent']; - interface CreationState { success: boolean; error?: ErrorType; @@ -85,7 +78,7 @@ export class QuickJobCreatorBase { end: number | undefined; startJob: boolean; runInRealTime: boolean; - dashboard?: Dashboard; + dashboard?: DashboardAPI; }) { const datafeedId = createDatafeedId(jobId); const datafeed = { ...datafeedConfig, job_id: jobId, datafeed_id: datafeedId }; @@ -232,23 +225,14 @@ export class QuickJobCreatorBase { return mergedQueries; } - private async createDashboardLink(dashboard: Dashboard, datafeedConfig: estypes.MlDatafeed) { - const dashboardTitle = dashboard?.getTitle(); - if (dashboardTitle === undefined || dashboardTitle === '') { - // embeddable may have not been in a dashboard - // and my not have been given a title as it is unsaved. - return null; - } - - const findDashboardsService = await this.dashboardService.findDashboardsService(); - // find the dashboard from the dashboard service as the dashboard passed in may not have the correct id - const foundDashboard = await findDashboardsService.findByTitle(dashboardTitle); - if (foundDashboard === undefined) { + private async createDashboardLink(dashboard: DashboardAPI, datafeedConfig: estypes.MlDatafeed) { + const savedObjectId = dashboard.savedObjectId?.value; + if (!savedObjectId) { return null; } const params: DashboardLocatorParams = { - dashboardId: foundDashboard.id, + dashboardId: savedObjectId, timeRange: { from: '$earliest$', to: '$latest$', @@ -270,13 +254,13 @@ export class QuickJobCreatorBase { const url = `${location.app}${location.path}`; const urlName = i18n.translate('xpack.ml.newJob.fromLens.createJob.namedUrlDashboard', { defaultMessage: 'Open {dashboardTitle}', - values: { dashboardTitle }, + values: { dashboardTitle: getPanelTitle(dashboard) ?? 'dashboard' }, }); return { url_name: urlName, url_value: url, time_range: 'auto' }; } - private async getCustomUrls(dashboard: Dashboard, datafeedConfig: estypes.MlDatafeed) { + private async getCustomUrls(dashboard: DashboardAPI, datafeedConfig: estypes.MlDatafeed) { const customUrls = await this.createDashboardLink(dashboard, datafeedConfig); return dashboard !== undefined && customUrls !== null ? { custom_urls: [customUrls] } : {}; } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/index.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/index.ts index 25f4fc16c7f25..ccb24599a9c7e 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/index.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/index.ts @@ -13,4 +13,5 @@ export { getJobsItemsFromEmbeddable, isCompatibleVisualizationType, redirectToADJobWizards, + getChartInfoFromVisualization, } from './utils'; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts index 0860f8c9f4d86..88ad820c059f2 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/quick_create_job.ts @@ -8,7 +8,6 @@ import { i18n } from '@kbn/i18n'; import type { ChartInfo, - Embeddable, LensPublicStart, LensSavedObjectAttributes, } from '@kbn/lens-plugin/public'; @@ -17,7 +16,7 @@ import type { TimefilterContract } from '@kbn/data-plugin/public'; import type { DataViewsContract } from '@kbn/data-views-plugin/public'; import type { Filter, Query } from '@kbn/es-query'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; - +import type { LensApi } from '@kbn/lens-plugin/public'; import type { JobCreatorType } from '../common/job_creator'; import { createEmptyJob, createEmptyDatafeed } from '../common/job_creator/util/default_configs'; import { stashJobForCloning } from '../common/job_creator/util/general'; @@ -51,7 +50,7 @@ export class QuickLensJobCreator extends QuickJobCreatorBase { public async createAndSaveJob( jobId: string, bucketSpan: string, - embeddable: Embeddable, + embeddable: LensApi, startJob: boolean, runInRealTime: boolean, layerIndex: number diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts index 88e66aab91933..e8d6d890a0a0c 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/utils.ts @@ -7,18 +7,20 @@ import { i18n } from '@kbn/i18n'; import type { - Embeddable, LensPublicStart, DataType, ChartInfo, LensSavedObjectAttributes, } from '@kbn/lens-plugin/public'; +import type { Query } from '@kbn/es-query'; +import { apiIsOfType } from '@kbn/presentation-publishing'; import type { SerializableRecord } from '@kbn/utility-types'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import { layerTypes } from '@kbn/lens-plugin/public'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { ML_JOB_AGGREGATION } from '@kbn/ml-anomaly-utils'; - +import type { LensApi } from '@kbn/lens-plugin/public'; +import type { DashboardAPI } from '@kbn/dashboard-plugin/public'; import { ML_PAGES, ML_APP_LOCATOR } from '../../../../../common/constants/locator'; export const COMPATIBLE_SERIES_TYPES = [ @@ -43,7 +45,7 @@ export const COMPATIBLE_SPLIT_FIELD_TYPES: DataType[] = [ ]; export async function redirectToADJobWizards( - embeddable: Embeddable, + embeddable: LensApi, layerIndex: number, share: SharePluginStart, lens: LensPublicStart @@ -66,7 +68,7 @@ export async function redirectToADJobWizards( window.open(url, '_blank'); } -export async function getJobsItemsFromEmbeddable(embeddable: Embeddable, lens?: LensPublicStart) { +export async function getJobsItemsFromEmbeddable(embeddable: LensApi, lens?: LensPublicStart) { if (!lens) { throw Error( i18n.translate('xpack.ml.newJob.fromLens.createJob.error.lensNotFound', { @@ -75,9 +77,11 @@ export async function getJobsItemsFromEmbeddable(embeddable: Embeddable, lens?: ); } - const { filters, timeRange, ...input } = embeddable.getInput(); - const query = input.query === undefined ? { query: '', language: 'kuery' } : input.query; + const dashboardApi = apiIsOfType(embeddable.parentApi, 'dashboard') + ? (embeddable.parentApi as DashboardAPI) + : undefined; + const timeRange = embeddable.localTimeRange?.value ?? dashboardApi?.localTimeRange?.value; if (timeRange === undefined) { throw Error( i18n.translate('xpack.ml.newJob.fromLens.createJob.error.noTimeRange', { @@ -85,8 +89,6 @@ export async function getJobsItemsFromEmbeddable(embeddable: Embeddable, lens?: }) ); } - const { to, from } = timeRange; - const vis = embeddable.getSavedVis(); if (vis === undefined) { @@ -97,17 +99,14 @@ export async function getJobsItemsFromEmbeddable(embeddable: Embeddable, lens?: ); } - const chartInfo = await getChartInfoFromVisualization(lens, vis); - const dashboard = embeddable.parent?.type === 'dashboard' ? embeddable.parent : undefined; - return { vis, - chartInfo, - from, - to, - query, - filters, - dashboard, + chartInfo: await getChartInfoFromVisualization(lens, vis), + from: timeRange.from, + to: timeRange.to, + query: (dashboardApi?.localQuery?.value as Query) ?? { query: '', language: 'kuery' }, + filters: dashboardApi?.localFilters?.value ?? [], + dashboard: dashboardApi, }; } @@ -238,7 +237,7 @@ export function createDetectors( export async function getChartInfoFromVisualization( lens: LensPublicStart, vis: LensSavedObjectAttributes -) { +): Promise { const chartInfo = await (await (await lens.stateHelperApi()).chartInfo).getChartInfo(vis); if (!chartInfo) { throw new Error('Cannot create job, chart info is undefined'); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts index 4552123184f5c..3883558d7652d 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_lens/visualization_extractor.ts @@ -5,12 +5,11 @@ * 2.0. */ -import type { Embeddable, LensPublicStart, ChartInfo } from '@kbn/lens-plugin/public'; +import type { LensPublicStart, ChartInfo } from '@kbn/lens-plugin/public'; import { layerTypes } from '@kbn/lens-plugin/public'; - import { i18n } from '@kbn/i18n'; - import type { ErrorType } from '@kbn/ml-error-utils'; +import type { LensApi } from '@kbn/lens-plugin/public'; import { JOB_TYPE } from '../../../../../common/constants/new_job'; import { getVisTypeFactory, @@ -39,7 +38,7 @@ export class VisualizationExtractor { constructor() {} public async getResultLayersFromEmbeddable( - embeddable: Embeddable, + embeddable: LensApi, lens: LensPublicStart ): Promise { const { chartInfo } = await getJobsItemsFromEmbeddable(embeddable, lens); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/quick_create_job.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/quick_create_job.ts index dae30d13b877b..cf4d4a35545ae 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/quick_create_job.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/quick_create_job.ts @@ -6,13 +6,12 @@ */ import { i18n } from '@kbn/i18n'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; import type { IUiSettingsClient } from '@kbn/core/public'; import type { TimefilterContract } from '@kbn/data-plugin/public'; import type { Filter, Query } from '@kbn/es-query'; import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; - +import type { MapApi } from '@kbn/maps-plugin/public'; import type { MlApiServices } from '../../../services/ml_api_service'; import { CREATED_BY_LABEL, @@ -63,7 +62,7 @@ export class QuickGeoJobCreator extends QuickJobCreatorBase { }: { jobId: string; bucketSpan: string; - embeddable: MapEmbeddable; + embeddable: MapApi; startJob: boolean; runInRealTime: boolean; dataViewId?: string; @@ -81,8 +80,8 @@ export class QuickGeoJobCreator extends QuickJobCreatorBase { } = await getJobsItemsFromEmbeddable(embeddable); // Map level stuff - const embeddableQuery = (await embeddable.getQuery()) ?? getDefaultQuery(); - const embeddableFilters = (await embeddable.getFilters()) ?? []; + const embeddableQuery = (embeddable.localQuery?.value as Query) ?? getDefaultQuery(); + const embeddableFilters = embeddable.localFilters?.value ?? []; if (dashboardQuery === undefined || dashboardFilters === undefined) { throw new Error('Cannot create job, query and filters are undefined'); diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/utils.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/utils.ts index 5a3985aa0dc36..5fe0c3bc0846e 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/utils.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/utils.ts @@ -7,12 +7,14 @@ import { i18n } from '@kbn/i18n'; import type { Query } from '@kbn/es-query'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; +import { apiIsOfType } from '@kbn/presentation-publishing'; import type { SharePluginStart } from '@kbn/share-plugin/public'; +import type { MapApi } from '@kbn/maps-plugin/public'; +import type { DashboardAPI } from '@kbn/dashboard-plugin/public'; import { ML_PAGES, ML_APP_LOCATOR } from '../../../../../common/constants/locator'; export async function redirectToGeoJobWizard( - embeddable: MapEmbeddable, + embeddable: MapApi, dataViewId: string, geoField: string, layerQuery: Query | null, @@ -20,8 +22,8 @@ export async function redirectToGeoJobWizard( share: SharePluginStart ) { const { query, filters, to, from } = await getJobsItemsFromEmbeddable(embeddable); - const embeddableQuery = await embeddable.getQuery(); - const embeddableFilters = await embeddable.getFilters(); + const embeddableQuery = embeddable.localQuery?.value; + const embeddableFilters = embeddable.localFilters?.value ?? []; const locator = share.url.locators.get(ML_APP_LOCATOR); const pageState = { @@ -43,21 +45,17 @@ export async function redirectToGeoJobWizard( window.open(url, '_blank'); } -export function isCompatibleMapVisualization(embeddable: MapEmbeddable) { - return embeddable.getLayerList().some((layer) => { - const geoField = layer.getGeoFieldNames().length ? layer.getGeoFieldNames()[0] : undefined; - const dataViewId = layer.getIndexPatternIds().length - ? layer.getIndexPatternIds()[0] - : undefined; - return geoField && dataViewId; +export function isCompatibleMapVisualization(api: MapApi) { + return api.getLayerList().some((layer) => { + return layer.getGeoFieldNames().length && layer.getIndexPatternIds().length; }); } -export async function getJobsItemsFromEmbeddable(embeddable: MapEmbeddable) { - // Get dashboard level query/filters - const { filters, timeRange, ...input } = embeddable.getInput(); - const query = input.query === undefined ? { query: '', language: 'kuery' } : input.query; - +export async function getJobsItemsFromEmbeddable(embeddable: MapApi) { + const dashboardApi = apiIsOfType(embeddable.parentApi, 'dashboard') + ? (embeddable.parentApi as DashboardAPI) + : undefined; + const timeRange = embeddable.localTimeRange?.value ?? dashboardApi?.localTimeRange?.value; if (timeRange === undefined) { throw Error( i18n.translate('xpack.ml.newJob.fromGeo.createJob.error.noTimeRange', { @@ -65,14 +63,11 @@ export async function getJobsItemsFromEmbeddable(embeddable: MapEmbeddable) { }) ); } - const { to, from } = timeRange; - const dashboard = embeddable.parent?.type === 'dashboard' ? embeddable.parent : undefined; - return { - from, - to, - query, - filters, - dashboard, + from: timeRange.from, + to: timeRange.to, + query: (dashboardApi?.localQuery?.value as Query) ?? { query: '', language: 'kuery' }, + filters: dashboardApi?.localFilters?.value ?? [], + dashboard: dashboardApi, }; } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/visualization_extractor.ts b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/visualization_extractor.ts index 26972a454ff8b..ab319fab9f34a 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/visualization_extractor.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/job_from_map/visualization_extractor.ts @@ -6,11 +6,11 @@ */ import { asyncForEach } from '@kbn/std'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; +import type { PublishesDataViews } from '@kbn/presentation-publishing'; +import { type MapApi } from '@kbn/maps-plugin/public'; import type { EuiComboBoxOptionOption } from '@elastic/eui'; import type { DataView } from '@kbn/data-views-plugin/common'; import type { Query } from '@kbn/es-query'; -import type { DashboardAPI } from '@kbn/dashboard-plugin/public'; import { categoryFieldTypes } from '../../../../../common/util/fields_utils'; export interface LayerResult { @@ -26,9 +26,11 @@ export interface LayerResult { export class VisualizationExtractor { constructor() {} - public async getResultLayersFromEmbeddable(embeddable: MapEmbeddable): Promise { + public async getResultLayersFromEmbeddable( + embeddable: MapApi & Partial + ): Promise { const layers: LayerResult[] = []; - const dataViews: DataView[] = (embeddable.getRoot() as DashboardAPI)?.getAllDataViews() ?? []; + const dataViews: DataView[] = embeddable.dataViews?.value ?? []; // Keep track of geoFields for layers as they can be repeated const layerGeoFields: Record = {}; @@ -39,8 +41,8 @@ export class VisualizationExtractor { ? layer.getIndexPatternIds()[0] : undefined; const layerDisplayName = await layer.getDisplayName(); - const layerId = await layer.getId(); - const query = await layer.getQuery(); + const layerId = layer.getId(); + const query = layer.getQuery(); if (geoField && dataViewId && layerGeoFields[geoField] === undefined) { layerGeoFields[geoField] = true; diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/aiops/flyout/create_job.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/aiops/flyout/create_job.tsx index 7a440794092bb..df5048d7261ad 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/aiops/flyout/create_job.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/aiops/flyout/create_job.tsx @@ -147,7 +147,6 @@ export const CreateJob: FC = ({ dataView, field, query, timeRange }) => { Promise; layer?: LayerResult; layerIndex: number; - embeddable: Embeddable | MapEmbeddable | undefined; timeRange: TimeRange | undefined; incomingCreateError?: { text: string; errorText: string }; outerFormComplete?: boolean; @@ -78,7 +73,6 @@ export const JobDetails: FC = ({ createADJob, layer, layerIndex, - embeddable, timeRange, incomingCreateError, outerFormComplete, @@ -112,7 +106,6 @@ export const JobDetails: FC = ({ const result = await createADJob({ jobId, bucketSpan, - embeddable, startJob, runInRealTime, }); diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/flyout.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/flyout.tsx index e9705b85278f8..8e0b4178b5a1f 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/flyout.tsx @@ -7,7 +7,6 @@ import type { FC } from 'react'; import React, { useState, useEffect } from 'react'; -import type { Embeddable } from '@kbn/lens-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiFlyoutFooter, @@ -20,14 +19,15 @@ import { EuiSpacer, EuiText, } from '@elastic/eui'; - +import { getPanelTitle } from '@kbn/presentation-publishing'; +import type { LensApi } from '@kbn/lens-plugin/public'; import { Layer } from './layer'; import type { LayerResult } from '../../../../application/jobs/new_job/job_from_lens'; import { VisualizationExtractor } from '../../../../application/jobs/new_job/job_from_lens'; import { useMlFromLensKibanaContext } from '../../common/context'; interface Props { - embeddable: Embeddable; + embeddable: LensApi; onClose: () => void; } @@ -67,7 +67,7 @@ export const LensLayerSelectionFlyout: FC = ({ onClose, embeddable }) => diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx index 041abd7aaab5e..3c9eefd47370a 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/compatible_layer.tsx @@ -8,10 +8,8 @@ import type { FC } from 'react'; import React, { useMemo } from 'react'; // useCallback import { FormattedMessage } from '@kbn/i18n-react'; -import type { Embeddable } from '@kbn/lens-plugin/public'; - import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiText } from '@elastic/eui'; - +import type { LensApi } from '@kbn/lens-plugin/public'; import { redirectToADJobWizards, QuickLensJobCreator, @@ -25,7 +23,7 @@ import { JobDetails } from '../../../common/job_details'; interface Props { layer: LayerResult; layerIndex: number; - embeddable: Embeddable; + embeddable: LensApi; } export const CompatibleLayer: FC = ({ layer, layerIndex, embeddable }) => { @@ -58,17 +56,11 @@ export const CompatibleLayer: FC = ({ layer, layerIndex, embeddable }) => redirectToADJobWizards(embeddable, layerIndex, share, lens); } - async function createADJob({ - jobId, - bucketSpan, - embeddable: lensEmbeddable, - startJob, - runInRealTime, - }: CreateADJobParams) { + async function createADJob({ jobId, bucketSpan, startJob, runInRealTime }: CreateADJobParams) { const result = await quickJobCreator.createAndSaveJob( jobId, bucketSpan, - lensEmbeddable as Embeddable, + embeddable, startJob, runInRealTime, layerIndex @@ -81,8 +73,7 @@ export const CompatibleLayer: FC = ({ layer, layerIndex, embeddable }) => diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/layer.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/layer.tsx index 073a38383f748..03f862e7bf672 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/layer.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/lens/lens_vis_layer_selection_flyout/layer/layer.tsx @@ -7,7 +7,6 @@ import type { FC } from 'react'; import React from 'react'; -import type { Embeddable } from '@kbn/lens-plugin/public'; import { EuiFlexGroup, EuiFlexItem, @@ -17,6 +16,7 @@ import { EuiSplitPanel, EuiHorizontalRule, } from '@elastic/eui'; +import type { LensApi } from '@kbn/lens-plugin/public'; import type { LayerResult } from '../../../../../application/jobs/new_job/job_from_lens'; import { CompatibleLayer } from './compatible_layer'; import { IncompatibleLayer } from './incompatible_layer'; @@ -24,7 +24,7 @@ import { IncompatibleLayer } from './incompatible_layer'; interface Props { layer: LayerResult; layerIndex: number; - embeddable: Embeddable; + embeddable: LensApi; } export const Layer: FC = ({ layer, layerIndex, embeddable }) => { diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/lens/show_flyout.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/lens/show_flyout.tsx index 4a0f87c48a080..949d0a3183314 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/lens/show_flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/lens/show_flyout.tsx @@ -7,17 +7,17 @@ import type { FC } from 'react'; import React from 'react'; -import type { Embeddable } from '@kbn/lens-plugin/public'; import type { CoreStart } from '@kbn/core/public'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; +import type { LensApi } from '@kbn/lens-plugin/public'; import { createFlyout, type FlyoutComponentProps } from '../common/create_flyout'; import { LensLayerSelectionFlyout } from './lens_vis_layer_selection_flyout'; export async function showLensVisToADJobFlyout( - embeddable: Embeddable, + embeddable: LensApi, coreStart: CoreStart, share: SharePluginStart, data: DataPublicPluginStart, diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/map/flyout.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/map/flyout.tsx index 80e43a0f682b2..a10ed011f7e84 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/map/flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/map/flyout.tsx @@ -7,7 +7,6 @@ import type { FC } from 'react'; import React, { useEffect, useState } from 'react'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiFlyoutFooter, @@ -21,12 +20,14 @@ import { EuiTitle, useEuiTheme, } from '@elastic/eui'; +import { getPanelTitle } from '@kbn/presentation-publishing'; +import type { MapApi } from '@kbn/maps-plugin/public'; import { Layer } from './map_vis_layer_selection_flyout/layer'; import type { LayerResult } from '../../../application/jobs/new_job/job_from_map'; import { VisualizationExtractor } from '../../../application/jobs/new_job/job_from_map'; interface Props { - embeddable: MapEmbeddable; + embeddable: MapApi; onClose: () => void; } @@ -62,7 +63,7 @@ export const GeoJobFlyout: FC = ({ onClose, embeddable }) => { diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/compatible_layer.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/compatible_layer.tsx index ba7216e802528..c5b8c69e72be3 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/compatible_layer.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/compatible_layer.tsx @@ -20,7 +20,7 @@ import { EuiText, } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; +import type { MapApi } from '@kbn/maps-plugin/public'; import { type LayerResult, QuickGeoJobCreator, @@ -36,7 +36,7 @@ interface DropDownLabel { } interface Props { - embeddable: MapEmbeddable; + embeddable: MapApi; layer: LayerResult; layerIndex: number; } @@ -81,18 +81,12 @@ export const CompatibleLayer: FC = ({ embeddable, layer, layerIndex }) => }, [layer?.dataView?.id, embeddable, selectedSplitField]); const createGeoJob = useCallback( - async ({ - jobId, - bucketSpan, - embeddable: mapEmbeddable, - startJob, - runInRealTime, - }: CreateADJobParams) => { + async ({ jobId, bucketSpan, startJob, runInRealTime }: CreateADJobParams) => { try { const result = await quickJobCreator.createAndSaveGeoJob({ jobId, bucketSpan, - embeddable: mapEmbeddable as MapEmbeddable, + embeddable, startJob, runInRealTime, sourceDataView: layer.dataView, @@ -149,8 +143,7 @@ export const CompatibleLayer: FC = ({ embeddable, layer, layerIndex }) => layerIndex={layerIndex} createADJob={createGeoJob} createADJobInWizard={createGeoJobInWizard} - embeddable={embeddable} - timeRange={embeddable.getInput().timeRange} + timeRange={embeddable.localTimeRange?.value} incomingCreateError={createError} > <> diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/layer.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/layer.tsx index 1d519cb739fcd..3d31438246769 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/layer.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/map/map_vis_layer_selection_flyout/layer/layer.tsx @@ -7,7 +7,6 @@ import type { FC } from 'react'; import React from 'react'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; import { EuiFlexGroup, EuiFlexItem, @@ -17,6 +16,7 @@ import { EuiSplitPanel, EuiHorizontalRule, } from '@elastic/eui'; +import type { MapApi } from '@kbn/maps-plugin/public'; import type { LayerResult } from '../../../../../application/jobs/new_job/job_from_map'; import { CompatibleLayer } from './compatible_layer'; import { IncompatibleLayer } from './incompatible_layer'; @@ -24,7 +24,7 @@ import { IncompatibleLayer } from './incompatible_layer'; interface Props { layer: LayerResult; layerIndex: number; - embeddable: MapEmbeddable; + embeddable: MapApi; } export const Layer: FC = ({ layer, layerIndex, embeddable }) => ( diff --git a/x-pack/plugins/ml/public/embeddables/job_creation/map/show_flyout.tsx b/x-pack/plugins/ml/public/embeddables/job_creation/map/show_flyout.tsx index 3c29b5b4dd5bf..0f98fd5a29779 100644 --- a/x-pack/plugins/ml/public/embeddables/job_creation/map/show_flyout.tsx +++ b/x-pack/plugins/ml/public/embeddables/job_creation/map/show_flyout.tsx @@ -10,14 +10,13 @@ import React from 'react'; import type { CoreStart } from '@kbn/core/public'; import type { SharePluginStart } from '@kbn/share-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; import type { DashboardStart } from '@kbn/dashboard-plugin/public'; - +import type { MapApi } from '@kbn/maps-plugin/public'; import { GeoJobFlyout } from './flyout'; import { createFlyout, type FlyoutComponentProps } from '../common/create_flyout'; export async function showMapVisToADJobFlyout( - embeddable: MapEmbeddable, + embeddable: MapApi, coreStart: CoreStart, share: SharePluginStart, data: DataPublicPluginStart, diff --git a/x-pack/plugins/ml/public/ui_actions/open_vis_in_ml_action.tsx b/x-pack/plugins/ml/public/ui_actions/open_vis_in_ml_action.tsx index ce62db4587462..e4ce56e8f5a54 100644 --- a/x-pack/plugins/ml/public/ui_actions/open_vis_in_ml_action.tsx +++ b/x-pack/plugins/ml/public/ui_actions/open_vis_in_ml_action.tsx @@ -6,17 +6,20 @@ */ import { i18n } from '@kbn/i18n'; -import type { Embeddable } from '@kbn/lens-plugin/public'; -import type { MapEmbeddable } from '@kbn/maps-plugin/public'; +import { type EmbeddableApiContext, apiHasType, apiIsOfType } from '@kbn/presentation-publishing'; import type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public'; +import { isLensApi } from '@kbn/lens-plugin/public'; +import { isMapApi } from '@kbn/maps-plugin/public'; +import type { ActionApi } from './types'; import type { MlCoreSetup } from '../plugin'; -import { isLensEmbeddable, isMapEmbeddable } from '../application/jobs/new_job/job_from_dashboard'; export const CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION = 'createMLADJobAction'; +export const isApiCompatible = (api: unknown | null): api is ActionApi => apiHasType(api); + export function createVisToADJobAction( getStartServices: MlCoreSetup['getStartServices'] -): UiActionsActionDefinition<{ embeddable: Embeddable | MapEmbeddable }> { +): UiActionsActionDefinition { return { id: 'create-ml-ad-job-action', type: CREATE_LENS_VIS_TO_ML_AD_JOB_ACTION, @@ -27,20 +30,20 @@ export function createVisToADJobAction( i18n.translate('xpack.ml.actions.createADJobFromLens', { defaultMessage: 'Create anomaly detection job', }), - async execute({ embeddable }) { + async execute({ embeddable }: EmbeddableApiContext) { if (!embeddable) { throw new Error('Not possible to execute an action without the embeddable context'); } try { - if (isLensEmbeddable(embeddable)) { + if (isLensApi(embeddable)) { const [{ showLensVisToADJobFlyout }, [coreStart, { share, data, lens, dashboard }]] = await Promise.all([import('../embeddables/job_creation/lens'), getStartServices()]); if (lens === undefined) { return; } await showLensVisToADJobFlyout(embeddable, coreStart, share, data, dashboard, lens); - } else if (isMapEmbeddable(embeddable)) { + } else if (isMapApi(embeddable)) { const [{ showMapVisToADJobFlyout }, [coreStart, { share, data, dashboard }]] = await Promise.all([import('../embeddables/job_creation/map'), getStartServices()]); await showMapVisToADJobFlyout(embeddable, coreStart, share, data, dashboard); @@ -49,19 +52,20 @@ export function createVisToADJobAction( return Promise.reject(); } }, - async isCompatible(context: { embeddable: Embeddable }) { - const embeddableType = context.embeddable.type; - if (embeddableType !== 'map') { - if (embeddableType !== 'lens' || !context.embeddable.getSavedVis()) { - return false; - } - } + async isCompatible({ embeddable }: EmbeddableApiContext) { + if ( + !isApiCompatible(embeddable) || + !(apiIsOfType(embeddable, 'lens') || apiIsOfType(embeddable, 'map')) + ) + return false; - const [{ getJobsItemsFromEmbeddable, isCompatibleVisualizationType }, [coreStart, { lens }]] = - await Promise.all([ - import('../application/jobs/new_job/job_from_lens'), - getStartServices(), - ]); + const [ + { getChartInfoFromVisualization, isCompatibleVisualizationType }, + [coreStart, { lens }], + ] = await Promise.all([ + import('../application/jobs/new_job/job_from_lens'), + getStartServices(), + ]); const { isCompatibleMapVisualization } = await import( '../application/jobs/new_job/job_from_map' ); @@ -74,13 +78,17 @@ export function createVisToADJobAction( } try { - if (embeddableType === 'lens' && lens) { - const { chartInfo } = await getJobsItemsFromEmbeddable(context.embeddable, lens); - return isCompatibleVisualizationType(chartInfo!); - } else if (isMapEmbeddable(context.embeddable)) { - return isCompatibleMapVisualization(context.embeddable); + if (isLensApi(embeddable) && lens) { + const vis = embeddable.getSavedVis(); + if (!vis) { + return false; + } + const chartInfo = await getChartInfoFromVisualization(lens, vis); + return isCompatibleVisualizationType(chartInfo); + } else if (isMapApi(embeddable)) { + return isCompatibleMapVisualization(embeddable); } - return true; + return false; } catch (error) { // eslint-disable-next-line no-console console.error('Error attempting to check for ML job compatibility', error); diff --git a/x-pack/plugins/ml/public/ui_actions/types.ts b/x-pack/plugins/ml/public/ui_actions/types.ts new file mode 100644 index 0000000000000..24459c48bde24 --- /dev/null +++ b/x-pack/plugins/ml/public/ui_actions/types.ts @@ -0,0 +1,11 @@ +/* + * 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 type { LensApi } from '@kbn/lens-plugin/public'; +import type { MapApi } from '@kbn/maps-plugin/public'; + +export type ActionApi = MapApi | LensApi; diff --git a/x-pack/plugins/ml/tsconfig.json b/x-pack/plugins/ml/tsconfig.json index 0f30e96a0be2f..79391f2c156fa 100644 --- a/x-pack/plugins/ml/tsconfig.json +++ b/x-pack/plugins/ml/tsconfig.json @@ -115,6 +115,7 @@ "@kbn/ml-creation-wizard-utils", "@kbn/deeplinks-management", "@kbn/code-editor", + "@kbn/presentation-publishing", "@kbn/core-elasticsearch-server", "@kbn/core-elasticsearch-client-server-mocks", ],