[8.x] [maps] lazy load map actions (#210252) (#210653)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[maps] lazy load map actions
(#210252)](https://github.com/elastic/kibana/pull/210252)

<!--- Backport version: 9.6.4 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Nathan
Reese","email":"reese.nathan@elastic.co"},"sourceCommit":{"committedDate":"2025-02-11T16:37:34Z","message":"[maps]
lazy load map actions (#210252)\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"8a30b862cc1c4aee11559f34f6c6c0c453a674e5","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Presentation","release_note:skip","backport:version","v9.1.0","v8.19.0"],"title":"[maps]
lazy load map
actions","number":210252,"url":"https://github.com/elastic/kibana/pull/210252","mergeCommit":{"message":"[maps]
lazy load map actions (#210252)\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"8a30b862cc1c4aee11559f34f6c6c0c453a674e5"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/210252","number":210252,"mergeCommit":{"message":"[maps]
lazy load map actions (#210252)\n\nCo-authored-by: kibanamachine
<42973632+kibanamachine@users.noreply.github.com>\r\nCo-authored-by:
Elastic Machine
<elasticmachine@users.noreply.github.com>","sha":"8a30b862cc1c4aee11559f34f6c6c0c453a674e5"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2025-02-11 12:30:08 -07:00 committed by GitHub
parent c17fc1c2d4
commit b28c80e5f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 220 additions and 187 deletions

View file

@ -105,7 +105,7 @@ pageLoadAssetSize:
logsShared: 281060
logstash: 53548
management: 46112
maps: 90000
maps: 46000
mapsEms: 26072
metricsDataAccess: 73287
ml: 85000

View file

@ -10,7 +10,7 @@ import { dynamic } from '@kbn/shared-ux-utility';
import type { Props } from './passive_map';
const Component = dynamic(async () => {
const { PassiveMap } = await import('./passive_map');
const { PassiveMap } = await import('../react_embeddable/embeddable_module');
return {
default: PassiveMap,
};

View file

@ -23,10 +23,8 @@ import { DEFAULT_APP_CATEGORIES } from '@kbn/core/public';
import type { HomePublicPluginSetup } from '@kbn/home-plugin/public';
import type { VisualizationsSetup, VisualizationsStart } from '@kbn/visualizations-plugin/public';
import type { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
import { ADD_PANEL_TRIGGER, VISUALIZE_GEO_FIELD_TRIGGER } from '@kbn/ui-actions-plugin/public';
import { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public';
import { EmbeddableEnhancedPluginStart } from '@kbn/embeddable-enhanced-plugin/public';
import { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
import type { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public';
import type { DataPublicPluginSetup, DataPublicPluginStart } from '@kbn/data-plugin/public';
@ -69,9 +67,6 @@ import {
suggestEMSTermJoinConfig,
} from './api';
import type { MapsXPackConfig, MapsConfigType } from '../server/config';
import { filterByMapExtentAction } from './trigger_actions/filter_by_map_extent/action';
import { synchronizeMovementAction } from './trigger_actions/synchronize_movement/action';
import { visualizeGeoFieldAction } from './trigger_actions/visualize_geo_field_action';
import { APP_NAME, APP_ICON_SOLUTION, APP_ID } from '../common/constants';
import { mapsVisTypeAlias } from './maps_vis_type_alias';
import { featureCatalogueEntry } from './feature_catalogue_entry';
@ -89,6 +84,7 @@ import { PassiveMapLazy, setupLensChoroplethChart } from './lens';
import { CONTENT_ID, LATEST_VERSION } from '../common/content_management';
import { setupMapEmbeddable } from './react_embeddable/setup_map_embeddable';
import { MapRendererLazy } from './react_embeddable/map_renderer/map_renderer_lazy';
import { registerUiActions } from './trigger_actions/register_ui_actions';
export interface MapsPluginSetupDependencies {
cloud?: CloudSetup;
@ -251,22 +247,7 @@ export class MapsPlugin
setLicensingPluginStart(plugins.licensing);
setStartServices(core, plugins);
if (core.application.capabilities.maps.show) {
plugins.uiActions.addTriggerAction(VISUALIZE_GEO_FIELD_TRIGGER, visualizeGeoFieldAction);
}
plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, filterByMapExtentAction);
plugins.uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, synchronizeMovementAction);
plugins.uiActions.registerActionAsync('addMapPanelAction', async () => {
const { getAddMapPanelAction } = await import('./trigger_actions/add_map_panel_action');
return getAddMapPanelAction(plugins);
});
plugins.uiActions.attachAction(ADD_PANEL_TRIGGER, 'addMapPanelAction');
if (plugins.uiActions.hasTrigger('ADD_CANVAS_ELEMENT_TRIGGER')) {
// Because Canvas is not enabled in Serverless, this trigger might not be registered - only attach
// the create action if the Canvas-specific trigger does indeed exist.
plugins.uiActions.attachAction('ADD_CANVAS_ELEMENT_TRIGGER', 'addMapPanelAction');
}
registerUiActions(core, plugins);
if (!core.application.capabilities.maps.save) {
plugins.visualizations.unRegisterAlias(APP_ID);

View file

@ -0,0 +1,10 @@
/*
* 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 { MapRenderer } from './map_renderer/map_renderer';
export { PassiveMap } from '../lens/passive_map';
export { mapEmbeddableFactory } from './map_react_embeddable';

View file

@ -10,7 +10,7 @@ import { dynamic } from '@kbn/shared-ux-utility';
import type { Props } from './map_renderer';
const Component = dynamic(async () => {
const { MapRenderer } = await import('./map_renderer');
const { MapRenderer } = await import('../embeddable_module');
return {
default: MapRenderer,
};

View file

@ -16,7 +16,7 @@ export function setupMapEmbeddable(embeddableSetup: EmbeddableSetup) {
const startServicesPromise = untilPluginStartServicesReady();
const [, { mapEmbeddableFactory }] = await Promise.all([
startServicesPromise,
import('./map_react_embeddable'),
import('./embeddable_module'),
]);
return mapEmbeddableFactory;

View file

@ -6,32 +6,30 @@
*/
import type { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public';
import { TimeRange } from '@kbn/es-query';
import { HasInspectorAdapters } from '@kbn/inspector-plugin/public';
import {
apiIsOfType,
apiPublishesTitle,
apiPublishesUnifiedSearch,
import type { TimeRange } from '@kbn/es-query';
import type { HasInspectorAdapters } from '@kbn/inspector-plugin/public';
import type {
HasEditCapabilities,
HasLibraryTransforms,
HasSupportedTriggers,
HasType,
PublishesDataLoading,
PublishesDataViews,
PublishesUnifiedSearch,
SerializedTitles,
} from '@kbn/presentation-publishing';
import { HasDynamicActions } from '@kbn/embeddable-enhanced-plugin/public';
import { DynamicActionsSerializedState } from '@kbn/embeddable-enhanced-plugin/public/plugin';
import { Observable } from 'rxjs';
import { MapAttributes } from '../../common/content_management';
import {
import type { HasDynamicActions } from '@kbn/embeddable-enhanced-plugin/public';
import type { DynamicActionsSerializedState } from '@kbn/embeddable-enhanced-plugin/public/plugin';
import type { Observable } from 'rxjs';
import type { MapAttributes } from '../../common/content_management';
import type {
LayerDescriptor,
MapCenterAndZoom,
MapExtent,
MapSettings,
} from '../../common/descriptor_types';
import { ILayer } from '../classes/layers/layer';
import { EventHandlers } from '../reducers/non_serializable_instances';
import type { ILayer } from '../classes/layers/layer';
import type { EventHandlers } from '../reducers/non_serializable_instances';
export type MapSerializedState = SerializedTitles &
Partial<DynamicActionsSerializedState> & {
@ -72,10 +70,6 @@ export type MapApi = DefaultEmbeddableApi<MapSerializedState> &
export const isMapApi = (api: unknown): api is MapApi => {
return Boolean(
api &&
apiIsOfType(api, 'map') &&
typeof (api as MapApi).getLayerList === 'function' &&
apiPublishesTitle(api) &&
apiPublishesUnifiedSearch(api)
api && (api as HasType)?.type === 'map' && typeof (api as MapApi).getLayerList === 'function'
);
};

View file

@ -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 { filterByMapExtentAction } from './filter_by_map_extent/action';
export { synchronizeMovementAction } from './synchronize_movement/action';

View file

@ -8,23 +8,23 @@
import { i18n } from '@kbn/i18n';
import {
type EmbeddableApiContext,
apiHasType,
apiIsOfType,
areTriggersDisabled,
HasParentApi,
HasType,
} from '@kbn/presentation-publishing';
import { createAction } from '@kbn/ui-actions-plugin/public';
import { apiHasVisualizeConfig } from '@kbn/visualizations-plugin/public';
import { type FilterByMapExtentActionApi } from './types';
import React, { Suspense, lazy } from 'react';
import { toMountPoint } from '@kbn/react-kibana-mount';
import { EuiModalBody, EuiSkeletonText } from '@elastic/eui';
import { MAP_SAVED_OBJECT_TYPE } from '../../../common/constants';
import { isLegacyMapApi } from '../../legacy_visualizations/is_legacy_map';
import { getCore } from '../../kibana_services';
import { FILTER_BY_MAP_EXTENT } from './constants';
export const FILTER_BY_MAP_EXTENT = 'FILTER_BY_MAP_EXTENT';
export const isApiCompatible = (api: unknown | null): api is FilterByMapExtentActionApi =>
Boolean(apiHasType(api));
function getContainerLabel(api: FilterByMapExtentActionApi | unknown) {
return isApiCompatible(api) && api.parentApi?.type === 'dashboard'
function getContainerLabel(api: unknown) {
return (api as Partial<HasParentApi<Partial<HasType>>>)?.parentApi?.type === 'dashboard'
? i18n.translate('xpack.maps.filterByMapExtentMenuItem.dashboardLabel', {
defaultMessage: 'dashboard',
})
@ -33,7 +33,7 @@ function getContainerLabel(api: FilterByMapExtentActionApi | unknown) {
});
}
function getDisplayName(api: FilterByMapExtentActionApi | unknown) {
function getDisplayName(api: unknown) {
return i18n.translate('xpack.maps.filterByMapExtentMenuItem.displayName', {
defaultMessage: 'Filter {containerLabel} by map bounds',
values: { containerLabel: getContainerLabel(api) },
@ -44,28 +44,42 @@ export const filterByMapExtentAction = createAction<EmbeddableApiContext>({
id: FILTER_BY_MAP_EXTENT,
type: FILTER_BY_MAP_EXTENT,
order: 20,
getDisplayName: ({ embeddable }: EmbeddableApiContext) => {
return getDisplayName(embeddable);
},
getDisplayNameTooltip: ({ embeddable }: EmbeddableApiContext) => {
return i18n.translate('xpack.maps.filterByMapExtentMenuItem.displayNameTooltip', {
getDisplayName: ({ embeddable }: EmbeddableApiContext) => getDisplayName(embeddable),
getDisplayNameTooltip: ({ embeddable }: EmbeddableApiContext) =>
i18n.translate('xpack.maps.filterByMapExtentMenuItem.displayNameTooltip', {
defaultMessage:
'As you zoom and pan the map, the {containerLabel} updates to display only the data visible in the map bounds.',
values: { containerLabel: getContainerLabel(embeddable) },
});
},
getIconType: () => {
return 'filter';
},
}),
getIconType: () => 'filter',
isCompatible: async ({ embeddable }: EmbeddableApiContext) => {
if (!isApiCompatible(embeddable) || areTriggersDisabled(embeddable)) return false;
return (
apiIsOfType(embeddable, MAP_SAVED_OBJECT_TYPE) ||
(apiHasVisualizeConfig(embeddable) && isLegacyMapApi(embeddable))
!areTriggersDisabled(embeddable) &&
(apiIsOfType(embeddable, MAP_SAVED_OBJECT_TYPE) ||
(apiHasVisualizeConfig(embeddable) && isLegacyMapApi(embeddable)))
);
},
execute: async ({ embeddable }: EmbeddableApiContext) => {
const { openModal } = await import('./modal');
openModal(getDisplayName(embeddable));
const core = getCore();
const LazyModal = lazy(async () => {
const { FilterByMapExtentModal } = await import('./modal');
return {
default: FilterByMapExtentModal,
};
});
const overlayRef = core.overlays.openModal(
toMountPoint(
<Suspense
fallback={
<EuiModalBody>
<EuiSkeletonText />
</EuiModalBody>
}
>
<LazyModal onClose={() => overlayRef.close()} title={getDisplayName(embeddable)} />
</Suspense>,
core
)
);
},
});

View file

@ -0,0 +1,8 @@
/*
* 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 const FILTER_BY_MAP_EXTENT = 'FILTER_BY_MAP_EXTENT';

View file

@ -14,23 +14,14 @@ import {
EuiSwitch,
EuiSwitchEvent,
} from '@elastic/eui';
import { createReactOverlays } from '@kbn/kibana-react-plugin/public';
import { mapEmbeddablesSingleton } from '../../react_embeddable/map_embeddables_singleton';
import { getCore } from '../../kibana_services';
export function openModal(title: string) {
const { openModal: reactOverlaysOpenModal } = createReactOverlays(getCore());
const modalSession = reactOverlaysOpenModal(
<FilterByMapExtentModal onClose={() => modalSession.close()} title={title} />
);
}
interface Props {
onClose: () => void;
title: string;
}
class FilterByMapExtentModal extends Component<Props> {
export class FilterByMapExtentModal extends Component<Props> {
_renderSwitches() {
return mapEmbeddablesSingleton.getMapPanels().map((mapPanel) => {
return (

View file

@ -1,12 +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 { HasDisableTriggers, HasParentApi, HasType } from '@kbn/presentation-publishing';
import type { HasVisualizeConfig } from '@kbn/visualizations-plugin/public';
export type FilterByMapExtentActionApi = HasType<'visualization' | 'map'> &
Partial<HasDisableTriggers & HasParentApi<HasType> & HasVisualizeConfig>;

View file

@ -0,0 +1,54 @@
/*
* 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 { CONTEXT_MENU_TRIGGER } from '@kbn/embeddable-plugin/public';
import {
ACTION_VISUALIZE_GEO_FIELD,
ADD_PANEL_TRIGGER,
VISUALIZE_GEO_FIELD_TRIGGER,
} from '@kbn/ui-actions-plugin/public';
import { CoreStart } from '@kbn/core/public';
import { FILTER_BY_MAP_EXTENT } from './filter_by_map_extent/constants';
import { SYNCHRONIZE_MOVEMENT_ACTION } from './synchronize_movement/constants';
import type { MapsPluginStartDependencies } from '../plugin';
export function registerUiActions(core: CoreStart, plugins: MapsPluginStartDependencies) {
if (core.application.capabilities.maps.show) {
plugins.uiActions.addTriggerActionAsync(
VISUALIZE_GEO_FIELD_TRIGGER,
ACTION_VISUALIZE_GEO_FIELD,
async () => {
const { visualizeGeoFieldAction } = await import('./visualize_geo_field_action');
return visualizeGeoFieldAction;
}
);
}
plugins.uiActions.registerActionAsync('addMapPanelAction', async () => {
const { getAddMapPanelAction } = await import('./add_map_panel_action');
return getAddMapPanelAction(plugins);
});
plugins.uiActions.attachAction(ADD_PANEL_TRIGGER, 'addMapPanelAction');
if (plugins.uiActions.hasTrigger('ADD_CANVAS_ELEMENT_TRIGGER')) {
// Because Canvas is not enabled in Serverless, this trigger might not be registered - only attach
// the create action if the Canvas-specific trigger does indeed exist.
plugins.uiActions.attachAction('ADD_CANVAS_ELEMENT_TRIGGER', 'addMapPanelAction');
}
plugins.uiActions.addTriggerActionAsync(CONTEXT_MENU_TRIGGER, FILTER_BY_MAP_EXTENT, async () => {
const { filterByMapExtentAction } = await import('./context_menu_actions_module');
return filterByMapExtentAction;
});
plugins.uiActions.addTriggerActionAsync(
CONTEXT_MENU_TRIGGER,
SYNCHRONIZE_MOVEMENT_ACTION,
async () => {
const { synchronizeMovementAction } = await import('./context_menu_actions_module');
return synchronizeMovementAction;
}
);
}

View file

@ -1,45 +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 { i18n } from '@kbn/i18n';
import { type EmbeddableApiContext, apiHasType } from '@kbn/presentation-publishing';
import { createAction } from '@kbn/ui-actions-plugin/public';
import type { SynchronizeMovementActionApi } from './types';
export const SYNCHRONIZE_MOVEMENT_ACTION = 'SYNCHRONIZE_MOVEMENT_ACTION';
export const isApiCompatible = (api: unknown | null): api is SynchronizeMovementActionApi =>
Boolean(apiHasType(api));
export const synchronizeMovementAction = createAction<EmbeddableApiContext>({
id: SYNCHRONIZE_MOVEMENT_ACTION,
type: SYNCHRONIZE_MOVEMENT_ACTION,
order: 21,
getDisplayName: () => {
return i18n.translate('xpack.maps.synchronizeMovementAction.title', {
defaultMessage: 'Synchronize map movement',
});
},
getDisplayNameTooltip: () => {
return i18n.translate('xpack.maps.synchronizeMovementAction.tooltipContent', {
defaultMessage:
'Synchronize maps, so that if you zoom and pan in one map, the movement is reflected in other maps',
});
},
getIconType: () => {
return 'crosshairs';
},
isCompatible: async ({ embeddable }: EmbeddableApiContext) => {
if (!isApiCompatible(embeddable)) return false;
const { isCompatible } = await import('./is_compatible');
return isCompatible(embeddable);
},
execute: async () => {
const { openModal } = await import('./modal');
openModal();
},
});

View file

@ -0,0 +1,69 @@
/*
* 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 { i18n } from '@kbn/i18n';
import { type EmbeddableApiContext, apiIsOfType } from '@kbn/presentation-publishing';
import { createAction } from '@kbn/ui-actions-plugin/public';
import { toMountPoint } from '@kbn/react-kibana-mount';
import { isLensApi } from '@kbn/lens-plugin/public';
import { apiHasVisualizeConfig } from '@kbn/visualizations-plugin/public';
import { Suspense, lazy } from 'react';
import { EuiModalBody, EuiSkeletonText } from '@elastic/eui';
import React from 'react';
import { getCore } from '../../kibana_services';
import { isLegacyMapApi } from '../../legacy_visualizations/is_legacy_map';
import { MAP_SAVED_OBJECT_TYPE } from '../../../common/constants';
import { mapEmbeddablesSingleton } from '../../react_embeddable/map_embeddables_singleton';
import { SYNCHRONIZE_MOVEMENT_ACTION } from './constants';
export const synchronizeMovementAction = createAction<EmbeddableApiContext>({
id: SYNCHRONIZE_MOVEMENT_ACTION,
type: SYNCHRONIZE_MOVEMENT_ACTION,
order: 21,
getDisplayName: () =>
i18n.translate('xpack.maps.synchronizeMovementAction.title', {
defaultMessage: 'Synchronize map movement',
}),
getDisplayNameTooltip: () =>
i18n.translate('xpack.maps.synchronizeMovementAction.tooltipContent', {
defaultMessage:
'Synchronize maps, so that if you zoom and pan in one map, the movement is reflected in other maps',
}),
getIconType: () => 'crosshairs',
isCompatible: async ({ embeddable }: EmbeddableApiContext) => {
return (
mapEmbeddablesSingleton.hasMultipleMaps() &&
(apiIsOfType(embeddable, MAP_SAVED_OBJECT_TYPE) ||
(isLensApi(embeddable) &&
embeddable.getSavedVis()?.visualizationType === 'lnsChoropleth') ||
(apiHasVisualizeConfig(embeddable) && isLegacyMapApi(embeddable)))
);
},
execute: async () => {
const core = getCore();
const LazyModal = lazy(async () => {
const { SynchronizeMovementModal } = await import('./modal');
return {
default: SynchronizeMovementModal,
};
});
const overlayRef = core.overlays.openModal(
toMountPoint(
<Suspense
fallback={
<EuiModalBody>
<EuiSkeletonText />
</EuiModalBody>
}
>
<LazyModal onClose={() => overlayRef.close()} />
</Suspense>,
core
)
);
},
});

View file

@ -0,0 +1,8 @@
/*
* 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 const SYNCHRONIZE_MOVEMENT_ACTION = 'SYNCHRONIZE_MOVEMENT_ACTION';

View file

@ -1,25 +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 { apiIsOfType } from '@kbn/presentation-publishing';
import { apiHasVisualizeConfig } from '@kbn/visualizations-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 '../../react_embeddable/map_embeddables_singleton';
import type { SynchronizeMovementActionApi } from './types';
export function isCompatible(api: SynchronizeMovementActionApi) {
if (!mapEmbeddablesSingleton.hasMultipleMaps()) {
return false;
}
return (
apiIsOfType(api, MAP_SAVED_OBJECT_TYPE) ||
(isLensApi(api) && api.getSavedVis()?.visualizationType === 'lnsChoropleth') ||
(apiHasVisualizeConfig(api) && isLegacyMapApi(api))
);
}

View file

@ -15,22 +15,13 @@ import {
EuiSwitch,
EuiSwitchEvent,
} from '@elastic/eui';
import { createReactOverlays } from '@kbn/kibana-react-plugin/public';
import { mapEmbeddablesSingleton } from '../../react_embeddable/map_embeddables_singleton';
import { getCore } from '../../kibana_services';
export function openModal() {
const { openModal: reactOverlaysOpenModal } = createReactOverlays(getCore());
const modalSession = reactOverlaysOpenModal(
<SynchronizeMovementModal onClose={() => modalSession.close()} />
);
}
interface Props {
onClose: () => void;
}
class SynchronizeMovementModal extends Component<Props> {
export class SynchronizeMovementModal extends Component<Props> {
_renderSwitches() {
const mapPanels = mapEmbeddablesSingleton.getMapPanels();

View file

@ -1,14 +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 } from '@kbn/presentation-publishing';
import type { LensApi } from '@kbn/lens-plugin/public';
import type { HasVisualizeConfig } from '@kbn/visualizations-plugin/public';
export type SynchronizeMovementActionApi =
| HasType<'map' | 'visualization' | 'lens'>
| Partial<LensApi | HasVisualizeConfig>;

View file

@ -14,6 +14,7 @@ import {
} from '@kbn/ui-actions-plugin/public';
import { getUsageCollection } from '../kibana_services';
import { APP_ID } from '../../common/constants';
import { getMapsLink } from './get_maps_link';
import { getVisualizeCapabilities, getCore } from '../kibana_services';
@ -28,7 +29,6 @@ export const visualizeGeoFieldAction = createAction<VisualizeFieldContext>({
return Boolean(!!getVisualizeCapabilities().show && context.dataViewSpec && context.fieldName);
},
getHref: async (context) => {
const { getMapsLink } = await import('./get_maps_link');
const { app, path } = await getMapsLink(context);
return getCore().application.getUrlForApp(app, {
@ -37,7 +37,6 @@ export const visualizeGeoFieldAction = createAction<VisualizeFieldContext>({
});
},
execute: async (context) => {
const { getMapsLink } = await import('./get_maps_link');
const { app, path, state } = await getMapsLink(context);
const usageCollection = getUsageCollection();

View file

@ -90,7 +90,8 @@
"@kbn/embeddable-enhanced-plugin",
"@kbn/presentation-containers",
"@kbn/field-utils",
"@kbn/react-hooks"
"@kbn/react-hooks",
"@kbn/react-kibana-mount",
],
"exclude": [
"target/**/*",