diff --git a/src/plugins/maps_legacy/public/get_service_settings.ts b/src/plugins/maps_legacy/public/get_service_settings.ts new file mode 100644 index 0000000000000..8d0656237976d --- /dev/null +++ b/src/plugins/maps_legacy/public/get_service_settings.ts @@ -0,0 +1,39 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { lazyLoadMapsLegacyModules } from './lazy_load_bundle'; +// @ts-expect-error +import { getMapsLegacyConfig } from './kibana_services'; +import { IServiceSettings } from './map/service_settings_types'; + +let loadPromise: Promise; + +export async function getServiceSettings(): Promise { + if (typeof loadPromise !== 'undefined') { + return loadPromise; + } + + loadPromise = new Promise(async (resolve) => { + const modules = await lazyLoadMapsLegacyModules(); + const config = getMapsLegacyConfig(); + // @ts-expect-error + resolve(new modules.ServiceSettings(config, config.tilemap)); + }); + return loadPromise; +} diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 8f14cd1b15e2c..d31f23f4bc4a6 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -19,8 +19,6 @@ // @ts-ignore import { PluginInitializerContext } from 'kibana/public'; -// @ts-ignore -import { L } from './leaflet'; import { MapsLegacyPlugin } from './plugin'; // @ts-ignore import * as colorUtil from './map/color_util'; @@ -29,14 +27,14 @@ import { KibanaMapLayer } from './map/kibana_map_layer'; // @ts-ignore import { convertToGeoJson } from './map/convert_to_geojson'; // @ts-ignore -import { scaleBounds, getPrecision, geoContains } from './map/decode_geo_hash'; +import { getPrecision, geoContains } from './map/decode_geo_hash'; import { VectorLayer, FileLayerField, FileLayer, TmsLayer, IServiceSettings, -} from './map/service_settings'; +} from './map/service_settings_types'; // @ts-ignore import { mapTooltipProvider } from './tooltip_provider'; @@ -48,7 +46,6 @@ export function plugin(initializerContext: PluginInitializerContext) { /** @public */ export { - scaleBounds, getPrecision, geoContains, colorUtil, @@ -60,7 +57,6 @@ export { FileLayer, TmsLayer, mapTooltipProvider, - L, }; export * from './common/types'; @@ -68,5 +64,7 @@ export { ORIGIN } from './common/constants/origin'; export { WmsOptions } from './components/wms_options'; +export { lazyLoadMapsLegacyModules } from './lazy_load_bundle'; + export type MapsLegacyPluginSetup = ReturnType; export type MapsLegacyPluginStart = ReturnType; diff --git a/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts b/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts new file mode 100644 index 0000000000000..292949503a616 --- /dev/null +++ b/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts @@ -0,0 +1,43 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +let loadModulesPromise: Promise; + +interface LazyLoadedMapsLegacyModules { + KibanaMap: unknown; + L: unknown; + ServiceSettings: unknown; +} + +export async function lazyLoadMapsLegacyModules(): Promise { + if (typeof loadModulesPromise !== 'undefined') { + return loadModulesPromise; + } + + loadModulesPromise = new Promise(async (resolve) => { + const { KibanaMap, L, ServiceSettings } = await import('./lazy'); + + resolve({ + KibanaMap, + L, + ServiceSettings, + }); + }); + return loadModulesPromise; +} diff --git a/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts b/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts new file mode 100644 index 0000000000000..5031b29e74b9a --- /dev/null +++ b/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts @@ -0,0 +1,25 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-expect-error +export { KibanaMap } from '../../map/kibana_map'; +// @ts-expect-error +export { ServiceSettings } from '../../map/service_settings'; +// @ts-expect-error +export { L } from '../../leaflet'; diff --git a/src/plugins/maps_legacy/public/map/base_maps_visualization.js b/src/plugins/maps_legacy/public/map/base_maps_visualization.js index 2d78fdc246e19..406dae43c9b5e 100644 --- a/src/plugins/maps_legacy/public/map/base_maps_visualization.js +++ b/src/plugins/maps_legacy/public/map/base_maps_visualization.js @@ -17,25 +17,22 @@ * under the License. */ -import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import * as Rx from 'rxjs'; import { filter, first } from 'rxjs/operators'; import { getEmsTileLayerId, getUiSettings, getToasts } from '../kibana_services'; +import { lazyLoadMapsLegacyModules } from '../lazy_load_bundle'; +import { getServiceSettings } from '../get_service_settings'; const WMS_MINZOOM = 0; const WMS_MAXZOOM = 22; //increase this to 22. Better for WMS -export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) { +export function BaseMapsVisualizationProvider() { /** * Abstract base class for a visualization consisting of a map with a single baselayer. * @class BaseMapsVisualization * @constructor */ - - const serviceSettings = mapServiceSettings; - const toastService = getToasts(); - return class BaseMapsVisualization { constructor(element, vis) { this.vis = vis; @@ -95,9 +92,9 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) const centerFromUIState = uiState.get('mapCenter'); options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.params.mapZoom; options.center = centerFromUIState ? centerFromUIState : this.vis.params.mapCenter; - const services = { toastService }; - this._kibanaMap = getKibanaMap(this._container, options, services); + const modules = await lazyLoadMapsLegacyModules(); + this._kibanaMap = new modules.KibanaMap(this._container, options); this._kibanaMap.setMinZoom(WMS_MINZOOM); //use a default this._kibanaMap.setMaxZoom(WMS_MAXZOOM); //use a default @@ -138,6 +135,7 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) const mapParams = this._getMapsParams(); if (!this._tmsConfigured()) { try { + const serviceSettings = await getServiceSettings(); const tmsServices = await serviceSettings.getTMSServices(); const userConfiguredTmsLayer = tmsServices[0]; const initBasemapLayer = userConfiguredTmsLayer @@ -147,7 +145,7 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) this._setTmsLayer(initBasemapLayer); } } catch (e) { - toastService.addWarning(e.message); + getToasts().addWarning(e.message); return; } return; @@ -174,7 +172,7 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) this._setTmsLayer(selectedTmsLayer); } } catch (tmsLoadingError) { - toastService.addWarning(tmsLoadingError.message); + getToasts().addWarning(tmsLoadingError.message); } } @@ -189,13 +187,14 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) isDesaturated = true; } const isDarkMode = getUiSettings().get('theme:darkMode'); + const serviceSettings = await getServiceSettings(); const meta = await serviceSettings.getAttributesForTMSLayer( tmsLayer, isDesaturated, isDarkMode ); const showZoomMessage = serviceSettings.shouldShowZoomMessage(tmsLayer); - const options = _.cloneDeep(tmsLayer); + const options = { ...tmsLayer }; delete options.id; delete options.subdomains; this._kibanaMap.setBaseLayer({ @@ -228,12 +227,11 @@ export function BaseMapsVisualizationProvider(getKibanaMap, mapServiceSettings) } _getMapsParams() { - return _.assign( - {}, - this.vis.type.visConfig.defaults, - { type: this.vis.type.name }, - this._params - ); + return { + ...this.vis.type.visConfig.defaults, + type: this.vis.type.name, + ...this._params, + }; } _whenBaseLayerIsLoaded() { diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts index 8c39ada03a46b..65184a8244777 100644 --- a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts @@ -17,8 +17,6 @@ * under the License. */ -import _ from 'lodash'; - interface DecodedGeoHash { latitude: number[]; longitude: number[]; @@ -101,33 +99,6 @@ interface GeoBoundingBox { bottom_right: GeoBoundingBoxCoordinate; } -export function scaleBounds(bounds: GeoBoundingBox): GeoBoundingBox { - const scale = 0.5; // scale bounds by 50% - - const topLeft = bounds.top_left; - const bottomRight = bounds.bottom_right; - let latDiff = _.round(Math.abs(topLeft.lat - bottomRight.lat), 5); - const lonDiff = _.round(Math.abs(bottomRight.lon - topLeft.lon), 5); - // map height can be zero when vis is first created - if (latDiff === 0) latDiff = lonDiff; - - const latDelta = latDiff * scale; - let topLeftLat = _.round(topLeft.lat, 5) + latDelta; - if (topLeftLat > 90) topLeftLat = 90; - let bottomRightLat = _.round(bottomRight.lat, 5) - latDelta; - if (bottomRightLat < -90) bottomRightLat = -90; - const lonDelta = lonDiff * scale; - let topLeftLon = _.round(topLeft.lon, 5) - lonDelta; - if (topLeftLon < -180) topLeftLon = -180; - let bottomRightLon = _.round(bottomRight.lon, 5) + lonDelta; - if (bottomRightLon > 180) bottomRightLon = 180; - - return { - top_left: { lat: topLeftLat, lon: topLeftLon }, - bottom_right: { lat: bottomRightLat, lon: bottomRightLon }, - }; -} - export function geoContains(collar?: GeoBoundingBox, bounds?: GeoBoundingBox) { if (!bounds || !collar) return false; // test if bounds top_left is outside collar diff --git a/src/plugins/maps_legacy/public/map/grid_dimensions.js b/src/plugins/maps_legacy/public/map/grid_dimensions.js index d146adf2ca67f..0f84e972104ba 100644 --- a/src/plugins/maps_legacy/public/map/grid_dimensions.js +++ b/src/plugins/maps_legacy/public/map/grid_dimensions.js @@ -17,8 +17,6 @@ * under the License. */ -import _ from 'lodash'; - // geohash precision mapping of geohash grid cell dimensions (width x height, in meters) at equator. // https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator const gridAtEquator = { @@ -37,5 +35,5 @@ const gridAtEquator = { }; export function gridDimensions(precision) { - return _.get(gridAtEquator, precision); + return gridAtEquator[precision]; } diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index ad5d2c089b875..3948692e55676 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -20,7 +20,7 @@ import { EventEmitter } from 'events'; import { createZoomWarningMsg } from './map_messages'; import $ from 'jquery'; -import _ from 'lodash'; +import { get, isEqual, escape } from 'lodash'; import { zoomToPrecision } from './zoom_to_precision'; import { i18n } from '@kbn/i18n'; import { ORIGIN } from '../common/constants/origin'; @@ -380,7 +380,7 @@ export class KibanaMap extends EventEmitter { const distanceX = latLngC.distanceTo(latLngX); // calculate distance between c and x (latitude) const distanceY = latLngC.distanceTo(latLngY); // calculate distance between c and y (longitude) - return _.min([distanceX, distanceY]); + return Math.min(distanceX, distanceY); } _getLeafletBounds(resizeOnFail) { @@ -544,7 +544,7 @@ export class KibanaMap extends EventEmitter { } setBaseLayer(settings) { - if (_.isEqual(settings, this._baseLayerSettings)) { + if (isEqual(settings, this._baseLayerSettings)) { return; } @@ -567,7 +567,7 @@ export class KibanaMap extends EventEmitter { let baseLayer; if (settings.baseLayerType === 'wms') { //This is user-input that is rendered with the Leaflet attribution control. Needs to be sanitized. - this._baseLayerSettings.options.attribution = _.escape(settings.options.attribution); + this._baseLayerSettings.options.attribution = escape(settings.options.attribution); baseLayer = this._getWMSBaseLayer(settings.options); } else if (settings.baseLayerType === 'tms') { baseLayer = this._getTMSBaseLayer(settings.options); @@ -661,7 +661,7 @@ export class KibanaMap extends EventEmitter { _updateDesaturation() { const tiles = $('img.leaflet-tile-loaded'); // Don't apply client-side styling to EMS basemaps - if (_.get(this._baseLayerSettings, 'options.origin') === ORIGIN.EMS) { + if (get(this._baseLayerSettings, 'options.origin') === ORIGIN.EMS) { tiles.addClass('filters-off'); } else { if (this._baseLayerIsDesaturated) { diff --git a/src/plugins/maps_legacy/public/map/service_settings.d.ts b/src/plugins/maps_legacy/public/map/service_settings_types.ts similarity index 100% rename from src/plugins/maps_legacy/public/map/service_settings.d.ts rename to src/plugins/maps_legacy/public/map/service_settings_types.ts diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index 8c9f1e9cef194..17cee226cb70c 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -22,15 +22,12 @@ import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/p // @ts-ignore import { setToasts, setUiSettings, setKibanaVersion, setMapsLegacyConfig } from './kibana_services'; // @ts-ignore -import { ServiceSettings } from './map/service_settings'; -// @ts-ignore import { getPrecision, getZoomPrecision } from './map/precision'; -// @ts-ignore -import { KibanaMap } from './map/kibana_map'; import { MapsLegacyPluginSetup, MapsLegacyPluginStart } from './index'; import { MapsLegacyConfig } from '../config'; // @ts-ignore import { BaseMapsVisualizationProvider } from './map/base_maps_visualization'; +import { getServiceSettings } from './get_service_settings'; /** * These are the interfaces with your public contracts. You should export these @@ -67,17 +64,13 @@ export class MapsLegacyPlugin implements Plugin new KibanaMap(...args); - const getBaseMapsVis = () => - new BaseMapsVisualizationProvider(getKibanaMapFactoryProvider, serviceSettings); + const getBaseMapsVis = () => new BaseMapsVisualizationProvider(); return { - serviceSettings, + getServiceSettings, getZoomPrecision, getPrecision, config, - getKibanaMapFactoryProvider, getBaseMapsVis, }; } diff --git a/src/plugins/region_map/public/choropleth_layer.js b/src/plugins/region_map/public/choropleth_layer.js index 30fa8b544cdec..14a91e189e0d5 100644 --- a/src/plugins/region_map/public/choropleth_layer.js +++ b/src/plugins/region_map/public/choropleth_layer.js @@ -33,7 +33,7 @@ const EMPTY_STYLE = { fillOpacity: 0, }; -export default class ChoroplethLayer extends KibanaMapLayer { +export class ChoroplethLayer extends KibanaMapLayer { static _doInnerJoin(sortedMetrics, sortedGeojsonFeatures, joinField) { let j = 0; for (let i = 0; i < sortedGeojsonFeatures.length; i++) { @@ -71,7 +71,16 @@ export default class ChoroplethLayer extends KibanaMapLayer { } } - constructor(name, attribution, format, showAllShapes, meta, layerConfig, serviceSettings) { + constructor( + name, + attribution, + format, + showAllShapes, + meta, + layerConfig, + serviceSettings, + leaflet + ) { super(); this._serviceSettings = serviceSettings; this._metrics = null; @@ -84,9 +93,10 @@ export default class ChoroplethLayer extends KibanaMapLayer { this._showAllShapes = showAllShapes; this._layerName = name; this._layerConfig = layerConfig; + this._leaflet = leaflet; // eslint-disable-next-line no-undef - this._leafletLayer = L.geoJson(null, { + this._leafletLayer = this._leaflet.geoJson(null, { onEachFeature: (feature, layer) => { layer.on('click', () => { this.emit('select', feature.properties[this._joinField]); @@ -97,7 +107,7 @@ export default class ChoroplethLayer extends KibanaMapLayer { const tooltipContents = this._tooltipFormatter(feature); if (!location) { // eslint-disable-next-line no-undef - const leafletGeojson = L.geoJson(feature); + const leafletGeojson = this._leaflet.geoJson(feature); location = leafletGeojson.getBounds().getCenter(); } this.emit('showTooltip', { @@ -425,7 +435,7 @@ CORS configuration of the server permits requests from the Kibana application on const { min, max } = getMinMax(this._metrics); // eslint-disable-next-line no-undef - const boundsOfAllFeatures = new L.LatLngBounds(); + const boundsOfAllFeatures = new this._leaflet.LatLngBounds(); return { leafletStyleFunction: (geojsonFeature) => { const match = geojsonFeature.__kbnJoinedMetric; @@ -433,7 +443,7 @@ CORS configuration of the server permits requests from the Kibana application on return emptyStyle(); } // eslint-disable-next-line no-undef - const boundsOfFeature = L.geoJson(geojsonFeature).getBounds(); + const boundsOfFeature = this._leaflet.geoJson(geojsonFeature).getBounds(); boundsOfAllFeatures.extend(boundsOfFeature); return { diff --git a/src/plugins/region_map/public/components/region_map_options.tsx b/src/plugins/region_map/public/components/region_map_options.tsx index be3d7fe86ab3f..4d564d7347a1e 100644 --- a/src/plugins/region_map/public/components/region_map_options.tsx +++ b/src/plugins/region_map/public/components/region_map_options.tsx @@ -37,11 +37,11 @@ const mapFieldForOption = ({ description, name }: FileLayerField) => ({ }); export type RegionMapOptionsProps = { - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; } & VisOptionsProps; function RegionMapOptions(props: RegionMapOptionsProps) { - const { serviceSettings, stateParams, vis, setValue } = props; + const { getServiceSettings, stateParams, vis, setValue } = props; const { vectorLayers } = vis.type.editorConfig.collections; const vectorLayerOptions = useMemo(() => vectorLayers.map(mapLayerForOption), [vectorLayers]); const fieldOptions = useMemo( @@ -54,10 +54,11 @@ function RegionMapOptions(props: RegionMapOptionsProps) { const setEmsHotLink = useCallback( async (layer: VectorLayer) => { + const serviceSettings = await getServiceSettings(); const emsHotLink = await serviceSettings.getEMSHotLink(layer); setValue('emsHotLink', emsHotLink); }, - [setValue, serviceSettings] + [setValue, getServiceSettings] ); const setLayer = useCallback( diff --git a/src/plugins/region_map/public/plugin.ts b/src/plugins/region_map/public/plugin.ts index ec9ee94310578..c641c16a8112b 100644 --- a/src/plugins/region_map/public/plugin.ts +++ b/src/plugins/region_map/public/plugin.ts @@ -41,7 +41,7 @@ import { KibanaLegacyStart } from '../../kibana_legacy/public'; interface RegionMapVisualizationDependencies { uiSettings: IUiSettingsClient; regionmapsConfig: RegionMapsConfig; - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; BaseMapsVisualization: any; } @@ -93,7 +93,7 @@ export class RegionMapPlugin implements Plugin = { uiSettings: core.uiSettings, regionmapsConfig: config as RegionMapsConfig, - serviceSettings: mapsLegacy.serviceSettings, + getServiceSettings: mapsLegacy.getServiceSettings, BaseMapsVisualization: mapsLegacy.getBaseMapsVis(), }; diff --git a/src/plugins/region_map/public/region_map_type.js b/src/plugins/region_map/public/region_map_type.js index def95950e6151..036726f6a4a9e 100644 --- a/src/plugins/region_map/public/region_map_type.js +++ b/src/plugins/region_map/public/region_map_type.js @@ -26,7 +26,7 @@ import { Schemas } from '../../vis_default_editor/public'; import { ORIGIN } from '../../maps_legacy/public'; export function createRegionMapTypeDefinition(dependencies) { - const { uiSettings, regionmapsConfig, serviceSettings } = dependencies; + const { uiSettings, regionmapsConfig, getServiceSettings } = dependencies; const visualization = createRegionMapVisualization(dependencies); return { @@ -54,7 +54,9 @@ provided base maps, or add your own. Darker colors represent higher values.', }, visualization, editorConfig: { - optionsTemplate: (props) => , + optionsTemplate: (props) => ( + + ), collections: { colorSchemas: truncatedColorSchemas, vectorLayers: [], @@ -97,6 +99,7 @@ provided base maps, or add your own. Darker colors represent higher values.', ]), }, setup: async (vis) => { + const serviceSettings = await getServiceSettings(); const tmsLayers = await serviceSettings.getTMSServices(); vis.type.editorConfig.collections.tmsLayers = tmsLayers; if (!vis.params.wms.selectedTmsLayer && tmsLayers.length) { diff --git a/src/plugins/region_map/public/region_map_visualization.js b/src/plugins/region_map/public/region_map_visualization.js index 43959c367558f..9b20a35630c86 100644 --- a/src/plugins/region_map/public/region_map_visualization.js +++ b/src/plugins/region_map/public/region_map_visualization.js @@ -18,18 +18,16 @@ */ import { i18n } from '@kbn/i18n'; -import ChoroplethLayer from './choropleth_layer'; import { getFormatService, getNotifications, getKibanaLegacy } from './kibana_services'; import { truncatedColorMaps } from '../../charts/public'; import { tooltipFormatter } from './tooltip_formatter'; -import { mapTooltipProvider, ORIGIN } from '../../maps_legacy/public'; -import _ from 'lodash'; +import { mapTooltipProvider, ORIGIN, lazyLoadMapsLegacyModules } from '../../maps_legacy/public'; export function createRegionMapVisualization({ regionmapsConfig, - serviceSettings, uiSettings, BaseMapsVisualization, + getServiceSettings, }) { return class RegionMapsVisualization extends BaseMapsVisualization { constructor(container, vis) { @@ -71,7 +69,7 @@ export function createRegionMapVisualization({ return; } - this._updateChoroplethLayerForNewMetrics( + await this._updateChoroplethLayerForNewMetrics( selectedLayer.name, selectedLayer.attribution, this._params.showAllShapes, @@ -98,10 +96,13 @@ export function createRegionMapVisualization({ // Do not use the selectedLayer from the visState. // These settings are stored in the URL and can be used to inject dirty display content. + const { escape } = await import('lodash'); + if ( fileLayerConfig.isEMS || //Hosted by EMS. Metadata needs to be resolved through EMS (fileLayerConfig.layerId && fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`)) //fallback for older saved objects ) { + const serviceSettings = await getServiceSettings(); return await serviceSettings.loadFileLayerConfig(fileLayerConfig); } @@ -113,7 +114,7 @@ export function createRegionMapVisualization({ if (configuredLayer) { return { ...configuredLayer, - attribution: _.escape(configuredLayer.attribution ? configuredLayer.attribution : ''), + attribution: escape(configuredLayer.attribution ? configuredLayer.attribution : ''), }; } @@ -133,7 +134,7 @@ export function createRegionMapVisualization({ return; } - this._updateChoroplethLayerForNewProperties( + await this._updateChoroplethLayerForNewProperties( selectedLayer.name, selectedLayer.attribution, this._params.showAllShapes @@ -151,24 +152,24 @@ export function createRegionMapVisualization({ ); } - _updateChoroplethLayerForNewMetrics(name, attribution, showAllData, newMetrics) { + async _updateChoroplethLayerForNewMetrics(name, attribution, showAllData, newMetrics) { if ( this._choroplethLayer && this._choroplethLayer.canReuseInstanceForNewMetrics(name, showAllData, newMetrics) ) { return; } - return this._recreateChoroplethLayer(name, attribution, showAllData); + await this._recreateChoroplethLayer(name, attribution, showAllData); } - _updateChoroplethLayerForNewProperties(name, attribution, showAllData) { + async _updateChoroplethLayerForNewProperties(name, attribution, showAllData) { if (this._choroplethLayer && this._choroplethLayer.canReuseInstance(name, showAllData)) { return; } - return this._recreateChoroplethLayer(name, attribution, showAllData); + await this._recreateChoroplethLayer(name, attribution, showAllData); } - _recreateChoroplethLayer(name, attribution, showAllData) { + async _recreateChoroplethLayer(name, attribution, showAllData) { this._kibanaMap.removeLayer(this._choroplethLayer); if (this._choroplethLayer) { @@ -179,9 +180,10 @@ export function createRegionMapVisualization({ showAllData, this._params.selectedLayer.meta, this._params.selectedLayer, - serviceSettings + await getServiceSettings() ); } else { + const { ChoroplethLayer } = await import('./choropleth_layer'); this._choroplethLayer = new ChoroplethLayer( name, attribution, @@ -189,7 +191,8 @@ export function createRegionMapVisualization({ showAllData, this._params.selectedLayer.meta, this._params.selectedLayer, - serviceSettings + await getServiceSettings(), + (await lazyLoadMapsLegacyModules()).L ); } diff --git a/src/plugins/tile_map/public/geohash_layer.js b/src/plugins/tile_map/public/geohash_layer.js index ca2f49a1f31e0..ca992a0d09ec9 100644 --- a/src/plugins/tile_map/public/geohash_layer.js +++ b/src/plugins/tile_map/public/geohash_layer.js @@ -19,14 +19,14 @@ import { min, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { L, KibanaMapLayer, MapTypes } from '../../maps_legacy/public'; +import { KibanaMapLayer, MapTypes } from '../../maps_legacy/public'; import { HeatmapMarkers } from './markers/heatmap'; import { ScaledCirclesMarkers } from './markers/scaled_circles'; import { ShadedCirclesMarkers } from './markers/shaded_circles'; import { GeohashGridMarkers } from './markers/geohash_grid'; export class GeohashLayer extends KibanaMapLayer { - constructor(featureCollection, featureCollectionMetaData, options, zoom, kibanaMap) { + constructor(featureCollection, featureCollectionMetaData, options, zoom, kibanaMap, leaflet) { super(); this._featureCollection = featureCollection; @@ -35,7 +35,8 @@ export class GeohashLayer extends KibanaMapLayer { this._geohashOptions = options; this._zoom = zoom; this._kibanaMap = kibanaMap; - const geojson = L.geoJson(this._featureCollection); + this._leaflet = leaflet; + const geojson = this._leaflet.geoJson(this._featureCollection); this._bounds = geojson.getBounds(); this._createGeohashMarkers(); this._lastBounds = null; @@ -56,7 +57,8 @@ export class GeohashLayer extends KibanaMapLayer { this._featureCollectionMetaData, markerOptions, this._zoom, - this._kibanaMap + this._kibanaMap, + this._leaflet ); break; case MapTypes.ShadedCircleMarkers: @@ -65,7 +67,8 @@ export class GeohashLayer extends KibanaMapLayer { this._featureCollectionMetaData, markerOptions, this._zoom, - this._kibanaMap + this._kibanaMap, + this._leaflet ); break; case MapTypes.ShadedGeohashGrid: @@ -74,7 +77,8 @@ export class GeohashLayer extends KibanaMapLayer { this._featureCollectionMetaData, markerOptions, this._zoom, - this._kibanaMap + this._kibanaMap, + this._leaflet ); break; case MapTypes.Heatmap: @@ -95,7 +99,8 @@ export class GeohashLayer extends KibanaMapLayer { tooltipFormatter: this._geohashOptions.tooltipFormatter, }, this._zoom, - this._featureCollectionMetaData.max + this._featureCollectionMetaData.max, + this._leaflet ); break; default: @@ -126,9 +131,15 @@ export class GeohashLayer extends KibanaMapLayer { if (this._geohashOptions.fetchBounds) { const geoHashBounds = await this._geohashOptions.fetchBounds(); if (geoHashBounds) { - const northEast = L.latLng(geoHashBounds.top_left.lat, geoHashBounds.bottom_right.lon); - const southWest = L.latLng(geoHashBounds.bottom_right.lat, geoHashBounds.top_left.lon); - return L.latLngBounds(southWest, northEast); + const northEast = this._leaflet.latLng( + geoHashBounds.top_left.lat, + geoHashBounds.bottom_right.lon + ); + const southWest = this._leaflet.latLng( + geoHashBounds.bottom_right.lat, + geoHashBounds.top_left.lon + ); + return this._leaflet.latLngBounds(southWest, northEast); } } diff --git a/src/plugins/tile_map/public/markers/geohash_grid.js b/src/plugins/tile_map/public/markers/geohash_grid.js index 46e7987c601f5..d81e435a6dd5d 100644 --- a/src/plugins/tile_map/public/markers/geohash_grid.js +++ b/src/plugins/tile_map/public/markers/geohash_grid.js @@ -18,11 +18,10 @@ */ import { ScaledCirclesMarkers } from './scaled_circles'; -import { L } from '../../../maps_legacy/public'; export class GeohashGridMarkers extends ScaledCirclesMarkers { getMarkerFunction() { - return function (feature) { + return (feature) => { const geohashRect = feature.properties.geohash_meta.rectangle; // get bounds from northEast[3] and southWest[1] // corners in geohash rectangle @@ -30,7 +29,7 @@ export class GeohashGridMarkers extends ScaledCirclesMarkers { [geohashRect[3][0], geohashRect[3][1]], [geohashRect[1][0], geohashRect[1][1]], ]; - return L.rectangle(corners); + return this._leaflet.rectangle(corners); }; } } diff --git a/src/plugins/tile_map/public/markers/heatmap.js b/src/plugins/tile_map/public/markers/heatmap.js index f2d014797bce0..79bbee16548ac 100644 --- a/src/plugins/tile_map/public/markers/heatmap.js +++ b/src/plugins/tile_map/public/markers/heatmap.js @@ -20,7 +20,6 @@ import _ from 'lodash'; import d3 from 'd3'; import { EventEmitter } from 'events'; -import { L } from '../../../maps_legacy/public'; /** * Map overlay: canvas layer with leaflet.heat plugin @@ -30,17 +29,17 @@ import { L } from '../../../maps_legacy/public'; * @param params {Object} */ export class HeatmapMarkers extends EventEmitter { - constructor(featureCollection, options, zoom, max) { + constructor(featureCollection, options, zoom, max, leaflet) { super(); this._geojsonFeatureCollection = featureCollection; const points = dataToHeatArray(featureCollection, max); - this._leafletLayer = new L.HeatLayer(points, options); + this._leafletLayer = new leaflet.HeatLayer(points, options); this._tooltipFormatter = options.tooltipFormatter; this._zoom = zoom; this._disableTooltips = false; this._getLatLng = _.memoize( function (feature) { - return L.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); + return leaflet.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); }, function (feature) { // turn coords into a string for the memoize cache diff --git a/src/plugins/tile_map/public/markers/scaled_circles.js b/src/plugins/tile_map/public/markers/scaled_circles.js index cb111107f6fe3..4a5f1b452580b 100644 --- a/src/plugins/tile_map/public/markers/scaled_circles.js +++ b/src/plugins/tile_map/public/markers/scaled_circles.js @@ -21,7 +21,7 @@ import _ from 'lodash'; import d3 from 'd3'; import $ from 'jquery'; import { EventEmitter } from 'events'; -import { L, colorUtil } from '../../../maps_legacy/public'; +import { colorUtil } from '../../../maps_legacy/public'; import { truncatedColorMaps } from '../../../charts/public'; export class ScaledCirclesMarkers extends EventEmitter { @@ -31,14 +31,13 @@ export class ScaledCirclesMarkers extends EventEmitter { options, targetZoom, kibanaMap, - metricAgg + leaflet ) { super(); this._featureCollection = featureCollection; this._featureCollectionMetaData = featureCollectionMetaData; this._zoom = targetZoom; - this._metricAgg = metricAgg; this._valueFormatter = options.valueFormatter || @@ -55,6 +54,7 @@ export class ScaledCirclesMarkers extends EventEmitter { this._legendColors = null; this._legendQuantizer = null; + this._leaflet = leaflet; this._popups = []; @@ -72,7 +72,7 @@ export class ScaledCirclesMarkers extends EventEmitter { return kibanaMap.isInside(bucketRectBounds); }; } - this._leafletLayer = L.geoJson(null, layerOptions); + this._leafletLayer = this._leaflet.geoJson(null, layerOptions); this._leafletLayer.addData(this._featureCollection); } @@ -143,7 +143,7 @@ export class ScaledCirclesMarkers extends EventEmitter { mouseover: (e) => { const layer = e.target; // bring layer to front if not older browser - if (!L.Browser.ie && !L.Browser.opera) { + if (!this._leaflet.Browser.ie && !this._leaflet.Browser.opera) { layer.bringToFront(); } this._showTooltip(feature); @@ -170,7 +170,10 @@ export class ScaledCirclesMarkers extends EventEmitter { return; } - const latLng = L.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); + const latLng = this._leaflet.latLng( + feature.geometry.coordinates[1], + feature.geometry.coordinates[0] + ); this.emit('showTooltip', { content: content, position: latLng, @@ -182,7 +185,7 @@ export class ScaledCirclesMarkers extends EventEmitter { return (feature, latlng) => { const value = feature.properties.value; const scaledRadius = this._radiusScale(value) * scaleFactor; - return L.circleMarker(latlng).setRadius(scaledRadius); + return this._leaflet.circleMarker(latlng).setRadius(scaledRadius); }; } diff --git a/src/plugins/tile_map/public/markers/shaded_circles.js b/src/plugins/tile_map/public/markers/shaded_circles.js index 745d0422856c6..3468cab7d8b75 100644 --- a/src/plugins/tile_map/public/markers/shaded_circles.js +++ b/src/plugins/tile_map/public/markers/shaded_circles.js @@ -19,7 +19,6 @@ import _ from 'lodash'; import { ScaledCirclesMarkers } from './scaled_circles'; -import { L } from '../../../maps_legacy/public'; export class ShadedCirclesMarkers extends ScaledCirclesMarkers { getMarkerFunction() { @@ -27,7 +26,7 @@ export class ShadedCirclesMarkers extends ScaledCirclesMarkers { const scaleFactor = 0.8; return (feature, latlng) => { const radius = this._geohashMinDistance(feature) * scaleFactor; - return L.circle(latlng, radius); + return this._leaflet.circle(latlng, radius); }; } @@ -49,12 +48,12 @@ export class ShadedCirclesMarkers extends ScaledCirclesMarkers { // clockwise, each value being an array of [lat, lng] // center lat and southeast lng - const east = L.latLng([centerPoint[0], geohashRect[2][1]]); + const east = this._leaflet.latLng([centerPoint[0], geohashRect[2][1]]); // southwest lat and center lng - const north = L.latLng([geohashRect[3][0], centerPoint[1]]); + const north = this._leaflet.latLng([geohashRect[3][0], centerPoint[1]]); // get latLng of geohash center point - const center = L.latLng([centerPoint[0], centerPoint[1]]); + const center = this._leaflet.latLng([centerPoint[0], centerPoint[1]]); // get smallest radius at center of geohash grid rectangle const eastRadius = Math.floor(center.distanceTo(east)); diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts index 9a164f8a303f8..07add6901fb49 100644 --- a/src/plugins/tile_map/public/plugin.ts +++ b/src/plugins/tile_map/public/plugin.ts @@ -47,7 +47,7 @@ interface TileMapVisualizationDependencies { getZoomPrecision: any; getPrecision: any; BaseMapsVisualization: any; - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; } /** @internal */ @@ -81,13 +81,13 @@ export class TileMapPlugin implements Plugin = { getZoomPrecision, getPrecision, BaseMapsVisualization: mapsLegacy.getBaseMapsVis(), uiSettings: core.uiSettings, - serviceSettings, + getServiceSettings, }; expressions.registerFunction(() => createTileMapFn(visualizationDependencies)); diff --git a/src/plugins/tile_map/public/tile_map_type.js b/src/plugins/tile_map/public/tile_map_type.js index f76da26022a77..2b23f345f012e 100644 --- a/src/plugins/tile_map/public/tile_map_type.js +++ b/src/plugins/tile_map/public/tile_map_type.js @@ -28,7 +28,7 @@ import { truncatedColorSchemas } from '../../charts/public'; export function createTileMapTypeDefinition(dependencies) { const CoordinateMapsVisualization = createTileMapVisualization(dependencies); - const { uiSettings, serviceSettings } = dependencies; + const { uiSettings, getServiceSettings } = dependencies; return { name: 'tile_map', @@ -142,6 +142,7 @@ export function createTileMapTypeDefinition(dependencies) { let tmsLayers; try { + const serviceSettings = await getServiceSettings(); tmsLayers = await serviceSettings.getTMSServices(); } catch (e) { return vis; diff --git a/src/plugins/tile_map/public/tile_map_visualization.js b/src/plugins/tile_map/public/tile_map_visualization.js index 2ebb76d05c219..b09a2f3bac48f 100644 --- a/src/plugins/tile_map/public/tile_map_visualization.js +++ b/src/plugins/tile_map/public/tile_map_visualization.js @@ -17,12 +17,42 @@ * under the License. */ -import { get } from 'lodash'; -import { GeohashLayer } from './geohash_layer'; +import { get, round } from 'lodash'; import { getFormatService, getQueryService, getKibanaLegacy } from './services'; -import { scaleBounds, geoContains, mapTooltipProvider } from '../../maps_legacy/public'; +import { + geoContains, + mapTooltipProvider, + lazyLoadMapsLegacyModules, +} from '../../maps_legacy/public'; import { tooltipFormatter } from './tooltip_formatter'; +function scaleBounds(bounds) { + const scale = 0.5; // scale bounds by 50% + + const topLeft = bounds.top_left; + const bottomRight = bounds.bottom_right; + let latDiff = round(Math.abs(topLeft.lat - bottomRight.lat), 5); + const lonDiff = round(Math.abs(bottomRight.lon - topLeft.lon), 5); + // map height can be zero when vis is first created + if (latDiff === 0) latDiff = lonDiff; + + const latDelta = latDiff * scale; + let topLeftLat = round(topLeft.lat, 5) + latDelta; + if (topLeftLat > 90) topLeftLat = 90; + let bottomRightLat = round(bottomRight.lat, 5) - latDelta; + if (bottomRightLat < -90) bottomRightLat = -90; + const lonDelta = lonDiff * scale; + let topLeftLon = round(topLeft.lon, 5) - lonDelta; + if (topLeftLon < -180) topLeftLon = -180; + let bottomRightLon = round(bottomRight.lon, 5) + lonDelta; + if (bottomRightLon > 180) bottomRightLon = 180; + + return { + top_left: { lat: topLeftLat, lon: topLeftLon }, + bottom_right: { lat: bottomRightLat, lon: bottomRightLon }, + }; +} + export const createTileMapVisualization = (dependencies) => { const { getZoomPrecision, getPrecision, BaseMapsVisualization } = dependencies; @@ -147,7 +177,9 @@ export const createTileMapVisualization = (dependencies) => { this._recreateGeohashLayer(); } - _recreateGeohashLayer() { + async _recreateGeohashLayer() { + const { GeohashLayer } = await import('./geohash_layer'); + if (this._geohashLayer) { this._kibanaMap.removeLayer(this._geohashLayer); this._geohashLayer = null; @@ -158,7 +190,8 @@ export const createTileMapVisualization = (dependencies) => { this._geoJsonFeatureCollectionAndMeta.meta, geohashOptions, this._kibanaMap.getZoomLevel(), - this._kibanaMap + this._kibanaMap, + (await lazyLoadMapsLegacyModules()).L ); this._kibanaMap.addLayer(this._geohashLayer); } diff --git a/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js b/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js index 4883a8129903a..5c7656efe925b 100644 --- a/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js +++ b/src/plugins/vis_type_vega/public/data_model/vega_parser.test.js @@ -162,12 +162,15 @@ describe('VegaParser._resolveEsQueries', () => { function check(spec, expected, warnCount) { return async () => { - const vp = new VegaParser(spec, searchApiStub, 0, 0, { - getFileLayers: async () => [{ name: 'file1', url: 'url1' }], - getUrlForRegionLayer: async (layer) => { - return layer.url; - }, - }); + const mockGetServiceSettings = async () => { + return { + getFileLayers: async () => [{ name: 'file1', url: 'url1' }], + getUrlForRegionLayer: async (layer) => { + return layer.url; + }, + }; + }; + const vp = new VegaParser(spec, searchApiStub, 0, 0, mockGetServiceSettings); await vp._resolveDataUrls(); expect(vp.spec).toEqual(expected); diff --git a/src/plugins/vis_type_vega/public/data_model/vega_parser.ts b/src/plugins/vis_type_vega/public/data_model/vega_parser.ts index b3fb2d54cb266..ccb89207e222f 100644 --- a/src/plugins/vis_type_vega/public/data_model/vega_parser.ts +++ b/src/plugins/vis_type_vega/public/data_model/vega_parser.ts @@ -65,7 +65,7 @@ export class VegaParser { hideWarnings: boolean; error?: string; warnings: string[]; - _urlParsers: UrlParserConfig; + _urlParsers: UrlParserConfig | undefined; isVegaLite?: boolean; useHover?: boolean; _config?: VegaConfig; @@ -80,13 +80,16 @@ export class VegaParser { containerDir?: ControlsLocation | ControlsDirection; controlsDir?: ControlsLocation; searchAPI: SearchAPI; + getServiceSettings: () => Promise; + filters: Bool; + timeCache: TimeCache; constructor( spec: VegaSpec | string, searchAPI: SearchAPI, timeCache: TimeCache, filters: Bool, - serviceSettings: IServiceSettings + getServiceSettings: () => Promise ) { this.spec = spec as VegaSpec; this.hideWarnings = false; @@ -94,13 +97,9 @@ export class VegaParser { this.error = undefined; this.warnings = []; this.searchAPI = searchAPI; - - const onWarn = this._onWarning.bind(this); - this._urlParsers = { - elasticsearch: new EsQueryParser(timeCache, this.searchAPI, filters, onWarn), - emsfile: new EmsFileParser(serviceSettings), - url: new UrlParser(onWarn), - }; + this.getServiceSettings = getServiceSettings; + this.filters = filters; + this.timeCache = timeCache; } async parseAsync() { @@ -123,7 +122,7 @@ export class VegaParser { throw new Error( i18n.translate('visTypeVega.vegaParser.inputSpecDoesNotSpecifySchemaErrorMessage', { defaultMessage: `Your specification requires a {schemaParam} field with a valid URL for -Vega (see {vegaSchemaUrl}) or +Vega (see {vegaSchemaUrl}) or Vega-Lite (see {vegaLiteSchemaUrl}). The URL is an identifier only. Kibana and your browser will never access this URL.`, values: { @@ -547,6 +546,15 @@ The URL is an identifier only. Kibana and your browser will never access this UR * @private */ async _resolveDataUrls() { + if (!this._urlParsers) { + const serviceSettings = await this.getServiceSettings(); + const onWarn = this._onWarning.bind(this); + this._urlParsers = { + elasticsearch: new EsQueryParser(this.timeCache, this.searchAPI, this.filters, onWarn), + emsfile: new EmsFileParser(serviceSettings), + url: new UrlParser(onWarn), + }; + } const pending: PendingType = {}; this.searchAPI.resetSearchStats(); @@ -560,7 +568,7 @@ The URL is an identifier only. Kibana and your browser will never access this UR type = DEFAULT_PARSER; } - const parser = this._urlParsers[type]; + const parser = this._urlParsers![type]; if (parser === undefined) { throw new Error( i18n.translate('visTypeVega.vegaParser.notSupportedUrlTypeErrorMessage', { @@ -584,7 +592,7 @@ The URL is an identifier only. Kibana and your browser will never access this UR if (pendingParsers.length > 0) { // let each parser populate its data in parallel await Promise.all( - pendingParsers.map((type) => this._urlParsers[type].populateData(pending[type])) + pendingParsers.map((type) => this._urlParsers![type].populateData(pending[type])) ); } } diff --git a/src/plugins/vis_type_vega/public/plugin.ts b/src/plugins/vis_type_vega/public/plugin.ts index 4b8ff8e2cb43a..ce5c5130961c6 100644 --- a/src/plugins/vis_type_vega/public/plugin.ts +++ b/src/plugins/vis_type_vega/public/plugin.ts @@ -28,7 +28,6 @@ import { setSavedObjects, setInjectedVars, setUISettings, - setKibanaMapFactory, setMapsLegacyConfig, setInjectedMetadata, } from './services'; @@ -47,7 +46,7 @@ export interface VegaVisualizationDependencies { plugins: { data: DataPublicPluginSetup; }; - serviceSettings: IServiceSettings; + getServiceSettings: () => Promise; } /** @internal */ @@ -81,7 +80,6 @@ export class VegaPlugin implements Plugin, void> { emsTileLayerId: core.injectedMetadata.getInjectedVar('emsTileLayerId', true), }); setUISettings(core.uiSettings); - setKibanaMapFactory(mapsLegacy.getKibanaMapFactoryProvider); setMapsLegacyConfig(mapsLegacy.config); const visualizationDependencies: Readonly = { @@ -89,7 +87,7 @@ export class VegaPlugin implements Plugin, void> { plugins: { data, }, - serviceSettings: mapsLegacy.serviceSettings, + getServiceSettings: mapsLegacy.getServiceSettings, }; inspector.registerView(getVegaInspectorView({ uiSettings: core.uiSettings })); diff --git a/src/plugins/vis_type_vega/public/services.ts b/src/plugins/vis_type_vega/public/services.ts index dfb2c96e9f894..455fe67dbc423 100644 --- a/src/plugins/vis_type_vega/public/services.ts +++ b/src/plugins/vis_type_vega/public/services.ts @@ -33,9 +33,6 @@ export const [getData, setData] = createGetterSetter('Dat export const [getNotifications, setNotifications] = createGetterSetter( 'Notifications' ); -export const [getKibanaMapFactory, setKibanaMapFactory] = createGetterSetter( - 'KibanaMapFactory' -); export const [getUISettings, setUISettings] = createGetterSetter('UISettings'); diff --git a/src/plugins/vis_type_vega/public/vega_request_handler.ts b/src/plugins/vis_type_vega/public/vega_request_handler.ts index c09a9466df602..f48b61ed70822 100644 --- a/src/plugins/vis_type_vega/public/vega_request_handler.ts +++ b/src/plugins/vis_type_vega/public/vega_request_handler.ts @@ -40,7 +40,7 @@ interface VegaRequestHandlerContext { } export function createVegaRequestHandler( - { plugins: { data }, core: { uiSettings }, serviceSettings }: VegaVisualizationDependencies, + { plugins: { data }, core: { uiSettings }, getServiceSettings }: VegaVisualizationDependencies, context: VegaRequestHandlerContext = {} ) { let searchAPI: SearchAPI; @@ -70,7 +70,7 @@ export function createVegaRequestHandler( const esQueryConfigs = esQuery.getEsQueryConfig(uiSettings); const filtersDsl = esQuery.buildEsQuery(undefined, query, filters, esQueryConfigs); const { VegaParser } = await import('./data_model/vega_parser'); - const vp = new VegaParser(visParams.spec, searchAPI, timeCache, filtersDsl, serviceSettings); + const vp = new VegaParser(visParams.spec, searchAPI, timeCache, filtersDsl, getServiceSettings); return await vp.parseAsync(); }; diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_map_layer.js b/src/plugins/vis_type_vega/public/vega_view/vega_map_layer.js index bc1cb4e4734c7..ec4959a51d741 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_map_layer.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_map_layer.js @@ -17,16 +17,16 @@ * under the License. */ -import { KibanaMapLayer, L } from '../../../maps_legacy/public'; +import { KibanaMapLayer } from '../../../maps_legacy/public'; export class VegaMapLayer extends KibanaMapLayer { - constructor(spec, options) { + constructor(spec, options, leaflet) { super(); // Used by super.getAttributions() this._attribution = options.attribution; delete options.attribution; - this._leafletLayer = L.vega(spec, options); + this._leafletLayer = leaflet.vega(spec, options); } getVegaView() { diff --git a/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js b/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js index 78ae2efdbdda5..d925aaeeced66 100644 --- a/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js +++ b/src/plugins/vis_type_vega/public/vega_view/vega_map_view.js @@ -21,7 +21,8 @@ import { i18n } from '@kbn/i18n'; import { vega } from '../lib/vega'; import { VegaBaseView } from './vega_base_view'; import { VegaMapLayer } from './vega_map_layer'; -import { getEmsTileLayerId, getUISettings, getKibanaMapFactory } from '../services'; +import { getEmsTileLayerId, getUISettings } from '../services'; +import { lazyLoadMapsLegacyModules } from '../../../maps_legacy/public'; export class VegaMapView extends VegaBaseView { constructor(opts) { @@ -106,7 +107,9 @@ export class VegaMapView extends VegaBaseView { // maxBounds = L.latLngBounds(L.latLng(b[1], b[0]), L.latLng(b[3], b[2])); // } - this._kibanaMap = getKibanaMapFactory()(this._$container.get(0), { + const modules = await lazyLoadMapsLegacyModules(); + + this._kibanaMap = new modules.KibanaMap(this._$container.get(0), { zoom, minZoom, maxZoom, @@ -122,14 +125,18 @@ export class VegaMapView extends VegaBaseView { }); } - const vegaMapLayer = new VegaMapLayer(this._parser.spec, { - vega, - bindingsContainer: this._$controls.get(0), - delayRepaint: mapConfig.delayRepaint, - viewConfig: this._vegaViewConfig, - onWarning: this.onWarn.bind(this), - onError: this.onError.bind(this), - }); + const vegaMapLayer = new VegaMapLayer( + this._parser.spec, + { + vega, + bindingsContainer: this._$controls.get(0), + delayRepaint: mapConfig.delayRepaint, + viewConfig: this._vegaViewConfig, + onWarning: this.onWarn.bind(this), + onError: this.onError.bind(this), + }, + modules.L + ); this._kibanaMap.addLayer(vegaMapLayer); diff --git a/src/plugins/vis_type_vega/public/vega_visualization.js b/src/plugins/vis_type_vega/public/vega_visualization.js index d6db0f9ea239f..2d58e9cda60cd 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.js @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n'; import { getNotifications, getData, getSavedObjects } from './services'; -export const createVegaVisualization = ({ serviceSettings }) => +export const createVegaVisualization = ({ getServiceSettings }) => class VegaVisualization { constructor(el, vis) { this._el = el; @@ -102,6 +102,7 @@ export const createVegaVisualization = ({ serviceSettings }) => this._vegaView = null; } + const serviceSettings = await getServiceSettings(); const { filterManager } = this.dataPlugin.query; const { timefilter } = this.dataPlugin.query.timefilter; const vegaViewParams = { diff --git a/src/plugins/vis_type_vega/public/vega_visualization.test.js b/src/plugins/vis_type_vega/public/vega_visualization.test.js index 1bf625af76207..dcf1722768075 100644 --- a/src/plugins/vis_type_vega/public/vega_visualization.test.js +++ b/src/plugins/vis_type_vega/public/vega_visualization.test.js @@ -32,16 +32,9 @@ import { SearchAPI } from './data_model/search_api'; import { createVegaTypeDefinition } from './vega_type'; -import { - setInjectedVars, - setData, - setSavedObjects, - setNotifications, - setKibanaMapFactory, -} from './services'; +import { setInjectedVars, setData, setSavedObjects, setNotifications } from './services'; import { coreMock } from '../../../core/public/mocks'; import { dataPluginMock } from '../../data/public/mocks'; -import { KibanaMap } from '../../maps_legacy/public/map/kibana_map'; jest.mock('./default_spec', () => ({ getDefaultSpec: () => jest.requireActual('./test_utils/default.spec.json'), @@ -77,8 +70,11 @@ describe('VegaVisualizations', () => { mockHeight = jest.spyOn($.prototype, 'height').mockImplementation(() => mockedHeightValue); }; + const mockGetServiceSettings = async () => { + return {}; + }; + beforeEach(() => { - setKibanaMapFactory((...args) => new KibanaMap(...args)); setInjectedVars({ emsTileLayerId: {}, enableExternalUrls: true, @@ -92,6 +88,7 @@ describe('VegaVisualizations', () => { plugins: { data: dataPluginMock.createSetupContract(), }, + getServiceSettings: mockGetServiceSettings, }; vegaVisType = createVegaTypeDefinition(vegaVisualizationDependencies); @@ -128,7 +125,10 @@ describe('VegaVisualizations', () => { search: dataPluginStart.search, uiSettings: coreStart.uiSettings, injectedMetadata: coreStart.injectedMetadata, - }) + }), + 0, + 0, + mockGetServiceSettings ); await vegaParser.parseAsync(); await vegaVis.render(vegaParser); @@ -155,7 +155,10 @@ describe('VegaVisualizations', () => { search: dataPluginStart.search, uiSettings: coreStart.uiSettings, injectedMetadata: coreStart.injectedMetadata, - }) + }), + 0, + 0, + mockGetServiceSettings ); await vegaParser.parseAsync(); @@ -176,7 +179,10 @@ describe('VegaVisualizations', () => { search: dataPluginStart.search, uiSettings: coreStart.uiSettings, injectedMetadata: coreStart.injectedMetadata, - }) + }), + 0, + 0, + mockGetServiceSettings ); await vegaParser.parseAsync(); diff --git a/x-pack/plugins/maps_legacy_licensing/public/plugin.ts b/x-pack/plugins/maps_legacy_licensing/public/plugin.ts index eaf527f856bc5..ed7321b2c0e74 100644 --- a/x-pack/plugins/maps_legacy_licensing/public/plugin.ts +++ b/x-pack/plugins/maps_legacy_licensing/public/plugin.ts @@ -26,12 +26,10 @@ export type MapsLegacyLicensingStart = ReturnType; export class MapsLegacyLicensing implements Plugin { public setup(core: CoreSetup, plugins: MapsLegacyLicensingSetupDependencies) { - const { - licensing, - mapsLegacy: { serviceSettings }, - } = plugins; + const { licensing, mapsLegacy } = plugins; if (licensing) { - licensing.license$.subscribe((license: ILicense) => { + licensing.license$.subscribe(async (license: ILicense) => { + const serviceSettings = await mapsLegacy.getServiceSettings(); const { uid, isActive } = license; if (isActive && license.hasAtLeast('basic')) { serviceSettings.setQueryParams({ license: uid });