diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts b/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts index 92d92dfbd142da..7edc51d9d78b30 100644 --- a/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts +++ b/x-pack/plugins/maps/public/connected_components/gis_map/index.d.ts @@ -9,7 +9,11 @@ import { Filter } from 'src/plugins/data/public'; import { RenderToolTipContent } from '../../layers/tooltips/tooltip_property'; -export const GisMap: React.ComponentType<{ +declare const GisMap: React.ComponentType<{ addFilters: ((filters: Filter[]) => void) | null; renderTooltipContent?: RenderToolTipContent; }>; + +export { GisMap }; +// eslint-disable-next-line import/no-default-export +export default GisMap; diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/index.js b/x-pack/plugins/maps/public/connected_components/gis_map/index.js index f8769d0bb898ad..78944fd470c0d4 100644 --- a/x-pack/plugins/maps/public/connected_components/gis_map/index.js +++ b/x-pack/plugins/maps/public/connected_components/gis_map/index.js @@ -5,7 +5,7 @@ */ import { connect } from 'react-redux'; -import { GisMap } from './view'; +import { GisMap as UnconnectedGisMap } from './view'; import { exitFullScreen } from '../../actions/ui_actions'; import { getFlyoutDisplay, getIsFullScreen } from '../../selectors/ui_selectors'; import { triggerRefreshTimer, cancelAllInFlightRequests } from '../../actions/map_actions'; @@ -42,5 +42,6 @@ function mapDispatchToProps(dispatch) { }; } -const connectedGisMap = connect(mapStateToProps, mapDispatchToProps)(GisMap); -export { connectedGisMap as GisMap }; +const connectedGisMap = connect(mapStateToProps, mapDispatchToProps)(UnconnectedGisMap); +export { connectedGisMap as GisMap }; // GisMap is pulled in by name by the Maps-app itself +export default connectedGisMap; //lazy-loading in the embeddable requires default export diff --git a/x-pack/plugins/maps/public/connected_components/gis_map/view.js b/x-pack/plugins/maps/public/connected_components/gis_map/view.js index 6eb173a001d018..ca4b062ee7273f 100644 --- a/x-pack/plugins/maps/public/connected_components/gis_map/view.js +++ b/x-pack/plugins/maps/public/connected_components/gis_map/view.js @@ -22,6 +22,7 @@ import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; import { FLYOUT_STATE } from '../../reducers/ui'; import { MapSettingsPanel } from '../map_settings_panel'; +import { registerLayerWizards } from '../../layers/load_layer_wizards'; const RENDER_COMPLETE_EVENT = 'renderComplete'; @@ -36,6 +37,7 @@ export class GisMap extends Component { this._isMounted = true; this._isInitalLoadRenderTimerStarted = false; this._setRefreshTimer(); + registerLayerWizards(); } componentDidUpdate() { diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/index.js b/x-pack/plugins/maps/public/connected_components/map/mb/index.js index f8daf0804265b2..e560e95b71f321 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/index.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/index.js @@ -40,7 +40,6 @@ function mapStateToProps(state = {}) { scrollZoom: getScrollZoom(state), disableInteractive: isInteractiveDisabled(state), disableTooltipControl: isTooltipControlDisabled(state), - disableTooltipControl: isTooltipControlDisabled(state), hideViewControl: isViewControlHidden(state), }; } diff --git a/x-pack/plugins/maps/public/embeddable/lazy/index.ts b/x-pack/plugins/maps/public/embeddable/lazy/index.ts new file mode 100644 index 00000000000000..7475d56ee076f7 --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/lazy/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// These are map-dependencies of the embeddable. +// By lazy-loading these, the Maps-app can register the embeddable when the plugin mounts, without actually pulling all the code. + +// @ts-ignore +export * from '../../angular/services/gis_map_saved_object_loader'; +export * from '../map_embeddable'; +export * from '../../kibana_services'; +export * from '../../reducers/store'; +export * from '../../actions/map_actions'; +export * from '../../selectors/map_selectors'; +export * from '../../angular/get_initial_layers'; +export * from './../merge_input_with_saved_map'; diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 467cf4727edb78..c3937ba4cdcbb9 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -5,16 +5,16 @@ */ import _ from 'lodash'; -import React from 'react'; +import React, { Suspense, lazy } from 'react'; import { Provider } from 'react-redux'; import { render, unmountComponentAtNode } from 'react-dom'; import 'mapbox-gl/dist/mapbox-gl.css'; import { Subscription } from 'rxjs'; import { Unsubscribe } from 'redux'; +import { EuiLoadingSpinner } from '@elastic/eui'; import { Embeddable, IContainer, - EmbeddableInput, EmbeddableOutput, } from '../../../../../src/plugins/embeddable/public'; import { APPLY_FILTER_TRIGGER } from '../../../../../src/plugins/ui_actions/public'; @@ -26,7 +26,6 @@ import { Query, RefreshInterval, } from '../../../../../src/plugins/data/public'; -import { GisMap } from '../connected_components/gis_map'; import { createMapStore, MapStore } from '../reducers/store'; import { MapSettings } from '../reducers/map'; import { @@ -43,7 +42,6 @@ import { setHiddenLayers, setMapSettings, } from '../actions/map_actions'; -import { MapCenterAndZoom } from '../../common/descriptor_types'; import { setReadOnly, setIsLayerTOCOpen, setOpenTOCDetails } from '../actions/ui_actions'; import { getIsLayerTOCOpen, getOpenTOCDetails } from '../selectors/ui_selectors'; import { @@ -56,36 +54,14 @@ import { MAP_SAVED_OBJECT_TYPE } from '../../common/constants'; import { RenderToolTipContent } from '../layers/tooltips/tooltip_property'; import { getUiActions, getCoreI18n } from '../kibana_services'; -interface MapEmbeddableConfig { - editUrl?: string; - indexPatterns: IIndexPattern[]; - editable: boolean; - title?: string; - layerList: unknown[]; - settings?: MapSettings; -} - -export interface MapEmbeddableInput extends EmbeddableInput { - timeRange?: TimeRange; - filters: Filter[]; - query?: Query; - refreshConfig: RefreshInterval; - isLayerTOCOpen: boolean; - openTOCDetails?: string[]; - disableTooltipControl?: boolean; - disableInteractive?: boolean; - hideToolbarOverlay?: boolean; - hideLayerControl?: boolean; - hideViewControl?: boolean; - mapCenter?: MapCenterAndZoom; - hiddenLayers?: string[]; - hideFilterActions?: boolean; -} +import { MapEmbeddableInput, MapEmbeddableConfig } from './types'; +export { MapEmbeddableInput, MapEmbeddableConfig }; export interface MapEmbeddableOutput extends EmbeddableOutput { indexPatterns: IIndexPattern[]; } +const GisMap = lazy(() => import('../connected_components/gis_map')); export class MapEmbeddable extends Embeddable { type = MAP_SAVED_OBJECT_TYPE; @@ -254,10 +230,12 @@ export class MapEmbeddable extends Embeddable - + }> + + , this._domNode diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts b/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts index abfaba80c33d11..7e3a8387bed116 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable_factory.ts @@ -6,24 +6,67 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; +import { AnyAction } from 'redux'; import { IIndexPattern } from 'src/plugins/data/public'; -// @ts-ignore -import { getMapsSavedObjectLoader } from '../angular/services/gis_map_saved_object_loader'; -import { MapEmbeddable, MapEmbeddableInput } from './map_embeddable'; -import { getIndexPatternService, getHttp, getMapsCapabilities } from '../kibana_services'; import { + Embeddable, EmbeddableFactoryDefinition, IContainer, } from '../../../../../src/plugins/embeddable/public'; - +import '../index.scss'; import { createMapPath, MAP_SAVED_OBJECT_TYPE, APP_ICON } from '../../common/constants'; +import { MapStore, MapStoreState } from '../reducers/store'; +import { MapEmbeddableConfig, MapEmbeddableInput } from './types'; +import { MapEmbeddableOutput } from './map_embeddable'; +import { RenderToolTipContent } from '../layers/tooltips/tooltip_property'; +import { EventHandlers } from '../reducers/non_serializable_instances'; + +let whenModulesLoadedPromise: Promise; + +let getMapsSavedObjectLoader: any; +let MapEmbeddable: new ( + config: MapEmbeddableConfig, + initialInput: MapEmbeddableInput, + parent?: IContainer, + renderTooltipContent?: RenderToolTipContent, + eventHandlers?: EventHandlers +) => Embeddable; + +let getIndexPatternService: () => { + get: (id: string) => IIndexPattern | undefined; +}; +let getHttp: () => any; +let getMapsCapabilities: () => any; +let createMapStore: () => MapStore; +let addLayerWithoutDataSync: (layerDescriptor: unknown) => AnyAction; +let getQueryableUniqueIndexPatternIds: (state: MapStoreState) => string[]; +let getInitialLayers: (layerListJSON?: string, initialLayers?: unknown[]) => unknown[]; +let mergeInputWithSavedMap: any; + +async function waitForMapDependencies(): Promise { + if (typeof whenModulesLoadedPromise !== 'undefined') { + return whenModulesLoadedPromise; + } -import { createMapStore } from '../reducers/store'; -import { addLayerWithoutDataSync } from '../actions/map_actions'; -import { getQueryableUniqueIndexPatternIds } from '../selectors/map_selectors'; -import { getInitialLayers } from '../angular/get_initial_layers'; -import { mergeInputWithSavedMap } from './merge_input_with_saved_map'; -import '../index.scss'; + whenModulesLoadedPromise = new Promise(async resolve => { + ({ + // @ts-ignore + getMapsSavedObjectLoader, + getQueryableUniqueIndexPatternIds, + MapEmbeddable, + getIndexPatternService, + getHttp, + getMapsCapabilities, + createMapStore, + addLayerWithoutDataSync, + getInitialLayers, + mergeInputWithSavedMap, + } = await import('./lazy')); + + resolve(true); + }); + return whenModulesLoadedPromise; +} export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { type = MAP_SAVED_OBJECT_TYPE; @@ -36,6 +79,7 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { }; async isEditable() { + await waitForMapDependencies(); return getMapsCapabilities().save as boolean; } @@ -53,7 +97,7 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { async _getIndexPatterns(layerList: unknown[]): Promise { // Need to extract layerList from store to get queryable index pattern ids const store = createMapStore(); - let queryableIndexPatternIds; + let queryableIndexPatternIds: string[]; try { layerList.forEach((layerDescriptor: unknown) => { store.dispatch(addLayerWithoutDataSync(layerDescriptor)); @@ -69,6 +113,7 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { const promises = queryableIndexPatternIds.map(async indexPatternId => { try { + // @ts-ignore return await getIndexPatternService().get(indexPatternId); } catch (error) { // Unable to load index pattern, better to not throw error so map embeddable can render @@ -90,6 +135,7 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { input: MapEmbeddableInput, parent?: IContainer ) => { + await waitForMapDependencies(); const savedMap = await this._fetchSavedMap(savedObjectId); const layerList = getInitialLayers(savedMap.layerListJSON); const indexPatterns = await this._getIndexPatterns(layerList); @@ -129,6 +175,7 @@ export class MapEmbeddableFactory implements EmbeddableFactoryDefinition { }; create = async (input: MapEmbeddableInput, parent?: IContainer) => { + await waitForMapDependencies(); const layerList = getInitialLayers(); const indexPatterns = await this._getIndexPatterns(layerList); diff --git a/x-pack/plugins/maps/public/embeddable/types.ts b/x-pack/plugins/maps/public/embeddable/types.ts new file mode 100644 index 00000000000000..d287c431e50c29 --- /dev/null +++ b/x-pack/plugins/maps/public/embeddable/types.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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IIndexPattern } from '../../../../../src/plugins/data/common/index_patterns'; +import { MapSettings } from '../reducers/map'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { EmbeddableInput } from '../../../../../src/plugins/embeddable/public/lib/embeddables'; +import { Filter, Query, RefreshInterval, TimeRange } from '../../../../../src/plugins/data/common'; +import { MapCenterAndZoom } from '../../common/descriptor_types'; + +export interface MapEmbeddableConfig { + editUrl?: string; + indexPatterns: IIndexPattern[]; + editable: boolean; + title?: string; + layerList: unknown[]; + settings?: MapSettings; +} + +export interface MapEmbeddableInput extends EmbeddableInput { + timeRange?: TimeRange; + filters: Filter[]; + query?: Query; + refreshConfig: RefreshInterval; + isLayerTOCOpen: boolean; + openTOCDetails?: string[]; + disableTooltipControl?: boolean; + disableInteractive?: boolean; + hideToolbarOverlay?: boolean; + hideLayerControl?: boolean; + hideViewControl?: boolean; + mapCenter?: MapCenterAndZoom; + hiddenLayers?: string[]; + hideFilterActions?: boolean; +} diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 7a22653f504c8f..21bff95731580f 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -38,9 +38,8 @@ import { featureCatalogueEntry } from './feature_catalogue_entry'; import { getMapsVisTypeAlias } from './maps_vis_type_alias'; import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { VisualizationsSetup } from '../../../../src/plugins/visualizations/public'; -import { registerLayerWizards } from './layers/load_layer_wizards'; import { MAP_SAVED_OBJECT_TYPE } from '../common/constants'; -import { MapEmbeddableFactory } from './embeddable'; +import { MapEmbeddableFactory } from './embeddable/map_embeddable_factory'; import { EmbeddableSetup } from '../../../../src/plugins/embeddable/public'; export interface MapsPluginSetupDependencies { @@ -85,7 +84,6 @@ export const bindStartCoreAndPlugins = (core: CoreStart, plugins: any) => { setUiActions(plugins.uiActions); setNavigation(plugins.navigation); setCoreI18n(core.i18n); - registerLayerWizards(); }; /**