diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d116b1d3a41fc..b47c3b09cce30 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -178,12 +178,8 @@ /x-pack/test/visual_regression/tests/maps/index.js @elastic/kibana-gis /x-pack/plugins/stack_alerts/server/alert_types/geo_containment @elastic/kibana-gis /x-pack/plugins/stack_alerts/public/alert_types/geo_containment @elastic/kibana-gis -#CC# /src/plugins/maps_legacy/ @elastic/kibana-gis -/src/plugins/maps_legacy/ @elastic/kibana-gis #CC# /x-pack/plugins/file_upload @elastic/kibana-gis /x-pack/plugins/file_upload @elastic/kibana-gis -/src/plugins/tile_map/ @elastic/kibana-gis -/src/plugins/region_map/ @elastic/kibana-gis /packages/kbn-mapbox-gl @elastic/kibana-gis # Operations diff --git a/.i18nrc.json b/.i18nrc.json index 235b65d7502f4..6ebfd23bebf02 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -32,7 +32,6 @@ "kbnDocViews": "src/legacy/core_plugins/kbn_doc_views", "lists": "packages/kbn-securitysolution-list-utils/src", "management": ["src/legacy/core_plugins/management", "src/plugins/management"], - "maps_legacy": "src/plugins/maps_legacy", "monaco": "packages/kbn-monaco/src", "esQuery": "packages/kbn-es-query/src", "presentationUtil": "src/plugins/presentation_util", @@ -48,14 +47,12 @@ "kibana_utils": "src/plugins/kibana_utils", "navigation": "src/plugins/navigation", "newsfeed": "src/plugins/newsfeed", - "regionMap": "src/plugins/region_map", "savedObjects": "src/plugins/saved_objects", "savedObjectsManagement": "src/plugins/saved_objects_management", "security": "src/plugins/security_oss", "server": "src/legacy/server", "statusPage": "src/legacy/core_plugins/status_page", "telemetry": ["src/plugins/telemetry", "src/plugins/telemetry_management_section"], - "tileMap": "src/plugins/tile_map", "timelion": ["src/plugins/timelion", "src/plugins/vis_type_timelion"], "uiActions": "src/plugins/ui_actions", "visDefaultEditor": "src/plugins/vis_default_editor", diff --git a/docs/developer/plugin-list.asciidoc b/docs/developer/plugin-list.asciidoc index dc410f2e5f2a5..6431d85ac1a51 100644 --- a/docs/developer/plugin-list.asciidoc +++ b/docs/developer/plugin-list.asciidoc @@ -182,10 +182,6 @@ management section itself. |Configuration of kibana-wide EMS settings and some higher level utilities. -|{kib-repo}blob/{branch}/src/plugins/maps_legacy/README.md[mapsLegacy] -|Internal objects used by the Coordinate, Region, and Vega visualizations. - - |{kib-repo}blob/{branch}/src/plugins/navigation/README.md[navigation] |The navigation plugins exports the TopNavMenu component. It also provides a stateful version of it on the start contract. @@ -200,10 +196,6 @@ Content is fetched from the remote (https://feeds.elastic.co and https://feeds-s |The Presentation Utility Plugin is a set of common, shared components and toolkits for solutions within the Presentation space, (e.g. Dashboards, Canvas). -|{kib-repo}blob/{branch}/src/plugins/region_map/README.md[regionMap] -|Create choropleth maps. Display the results of a term-aggregation as e.g. countries, zip-codes, states. - - |{kib-repo}blob/{branch}/src/plugins/saved_objects/README.md[savedObjects] |NOTE: This plugin is deprecated and will be removed in 8.0. See https://github.com/elastic/kibana/issues/46435 for more information. @@ -247,10 +239,6 @@ generating deep links to other apps, and creating short URLs. |This plugin adds the Advanced Settings section for the Usage and Security Data collection (aka Telemetry). -|{kib-repo}blob/{branch}/src/plugins/tile_map/README.md[tileMap] -|Create a coordinate map. Display the results of a geohash_tile aggregation as bubbles, rectangles, or heatmap color blobs. - - |{kib-repo}blob/{branch}/src/plugins/timelion/README.md[timelion] |Contains the deprecated timelion application. For the timelion visualization, which also contains the timelion APIs and backend, look at the vis_type_timelion plugin. diff --git a/docs/management/advanced-options.asciidoc b/docs/management/advanced-options.asciidoc index 23f79c1bbb480..a5bdad16fa98f 100644 --- a/docs/management/advanced-options.asciidoc +++ b/docs/management/advanced-options.asciidoc @@ -534,17 +534,6 @@ of the chart. Use numbers between 0 and 1. The lower the number, the more the hi [[visualization-heatmap-maxbuckets]]`visualization:heatmap:maxBuckets`:: The maximum number of buckets a datasource can return. High numbers can have a negative impact on your browser rendering performance. -[[visualization-regionmap-showwarnings]]`visualization:regionmap:showWarnings`:: -Shows a warning in a region map when terms cannot be joined to a shape. - -[[visualization-tilemap-wmsdefaults]]`visualization:tileMap:WMSdefaults`:: -The default properties for the WMS map server supported in the coordinate map. - -[[visualization-tilemap-maxprecision]]`visualization:tileMap:maxPrecision`:: -The maximum geoHash precision displayed in tile maps. 7 is high, 10 is very high, -and 12 is the maximum. For more information, refer to -{ref}/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator[Cell dimensions at the equator]. - [[visualization-visualize-chartslibrary]]`visualization:visualize:legacyChartsLibrary`:: **The legacy XY charts are deprecated and will not be supported as of 7.16.** The visualize editor uses a new XY charts library with improved performance, color palettes, fill capacity, and more. Enable this option if you prefer to use the legacy charts library. @@ -563,4 +552,4 @@ only production-ready visualizations are available to users. [horizontal] [[telemetry-enabled-advanced-setting]]`telemetry:enabled`:: When enabled, helps improve the Elastic Stack by providing usage statistics for -basic features. This data will not be shared outside of Elastic. +basic features. This data will not be shared outside of Elastic. \ No newline at end of file diff --git a/package.json b/package.json index 205685cd5389c..8d3133de1e944 100644 --- a/package.json +++ b/package.json @@ -280,10 +280,6 @@ "jsonwebtoken": "^8.5.1", "jsts": "^1.6.2", "kea": "^2.4.2", - "leaflet": "1.5.1", - "leaflet-draw": "0.4.14", - "leaflet-responsive-popup": "0.6.4", - "leaflet.heat": "0.2.0", "less": "npm:@elastic/less@2.7.3-kibana", "load-json-file": "^6.2.0", "loader-utils": "^1.2.3", diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index 48130a7bfcf5b..b11458d6539e8 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -50,15 +50,13 @@ pageLoadAssetSize: lists: 22900 logstash: 53548 management: 46112 - maps: 80000 - mapsLegacy: 87859 + maps: 90000 ml: 82187 monitoring: 80000 navigation: 37269 newsfeed: 42228 observability: 89709 painlessLab: 179748 - regionMap: 66098 remoteClusters: 51327 reporting: 183418 rollup: 97204 @@ -75,7 +73,6 @@ pageLoadAssetSize: spaces: 57868 telemetry: 51957 telemetryManagementSection: 38586 - tileMap: 65337 timelion: 29920 transform: 41007 triggersActionsUi: 100000 diff --git a/src/core/server/ui_settings/saved_objects/migrations.test.ts b/src/core/server/ui_settings/saved_objects/migrations.test.ts index cb10f9c7fd981..c454338f44c79 100644 --- a/src/core/server/ui_settings/saved_objects/migrations.test.ts +++ b/src/core/server/ui_settings/saved_objects/migrations.test.ts @@ -128,3 +128,38 @@ describe('ui_settings 7.13.0 migrations', () => { }); }); }); + +describe('ui_settings 8.0.0 migrations', () => { + const migration = migrations['8.0.0']; + + test('returns doc on empty object', () => { + expect(migration({} as SavedObjectUnsanitizedDoc)).toEqual({ + references: [], + }); + }); + test('removes ui_settings from deleted region_map and tile_map plugins', () => { + const doc = { + type: 'config', + id: '8.0.0', + attributes: { + buildNum: 9007199254740991, + 'visualization:regionmap:showWarnings': false, + 'visualization:tileMap:WMSdefaults': '{}', + 'visualization:tileMap:maxPrecision': 10, + }, + references: [], + updated_at: '2020-06-09T20:18:20.349Z', + migrationVersion: {}, + }; + expect(migration(doc)).toEqual({ + type: 'config', + id: '8.0.0', + attributes: { + buildNum: 9007199254740991, + }, + references: [], + updated_at: '2020-06-09T20:18:20.349Z', + migrationVersion: {}, + }); + }); +}); diff --git a/src/core/server/ui_settings/saved_objects/migrations.ts b/src/core/server/ui_settings/saved_objects/migrations.ts index b187c5f86dab0..e5d1a6bd1aa25 100644 --- a/src/core/server/ui_settings/saved_objects/migrations.ts +++ b/src/core/server/ui_settings/saved_objects/migrations.ts @@ -75,4 +75,27 @@ export const migrations = { }), references: doc.references || [], }), + '8.0.0': (doc: SavedObjectUnsanitizedDoc): SavedObjectSanitizedDoc => ({ + ...doc, + ...(doc.attributes && { + // owner: Team:Geo + attributes: Object.keys(doc.attributes).reduce( + (acc, key) => + [ + 'visualization:regionmap:showWarnings', + 'visualization:tileMap:WMSdefaults', + 'visualization:tileMap:maxPrecision', + ].includes(key) + ? { + ...acc, + } + : { + ...acc, + [key]: doc.attributes[key], + }, + {} + ), + }), + references: doc.references || [], + }), }; diff --git a/src/plugins/maps_legacy/README.md b/src/plugins/maps_legacy/README.md deleted file mode 100644 index 4a870e4f7492d..0000000000000 --- a/src/plugins/maps_legacy/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# Maps legacy - -Internal objects used by the Coordinate, Region, and Vega visualizations. - -It exports the default Leaflet-based map and exposes the connection to the Elastic Maps service. - -This plugin is targeted for removal in 8.0. \ No newline at end of file diff --git a/src/plugins/maps_legacy/config.ts b/src/plugins/maps_legacy/config.ts deleted file mode 100644 index 41387a07d27cb..0000000000000 --- a/src/plugins/maps_legacy/config.ts +++ /dev/null @@ -1,13 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { schema, TypeOf } from '@kbn/config-schema'; - -export const configSchema = schema.object({}); - -export type MapsLegacyConfig = TypeOf; diff --git a/src/plugins/maps_legacy/jest.config.js b/src/plugins/maps_legacy/jest.config.js deleted file mode 100644 index cbdcdf0905777..0000000000000 --- a/src/plugins/maps_legacy/jest.config.js +++ /dev/null @@ -1,13 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/src/plugins/maps_legacy'], -}; diff --git a/src/plugins/maps_legacy/kibana.json b/src/plugins/maps_legacy/kibana.json deleted file mode 100644 index fde5ad7b7adf5..0000000000000 --- a/src/plugins/maps_legacy/kibana.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "id": "mapsLegacy", - "owner": { - "name": "GIS", - "githubTeam": "kibana-gis" - }, - "version": "8.0.0", - "kibanaVersion": "kibana", - "ui": true, - "server": true, - "requiredPlugins": ["mapsEms"], - "requiredBundles": ["visDefaultEditor", "mapsEms"] -} diff --git a/src/plugins/maps_legacy/public/common/types.ts b/src/plugins/maps_legacy/public/common/types.ts deleted file mode 100644 index 8ff1753b56c31..0000000000000 --- a/src/plugins/maps_legacy/public/common/types.ts +++ /dev/null @@ -1,23 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { TmsLayer } from '../../../maps_ems/public'; - -export interface WMSOptions { - selectedTmsLayer?: TmsLayer; - enabled: boolean; - url?: string; - options: { - version?: string; - layers?: string; - format: string; - transparent: boolean; - attribution?: string; - styles?: string; - }; -} diff --git a/src/plugins/maps_legacy/public/components/legacy_map_deprecation_message.tsx b/src/plugins/maps_legacy/public/components/legacy_map_deprecation_message.tsx deleted file mode 100644 index 513a3562c3d8f..0000000000000 --- a/src/plugins/maps_legacy/public/components/legacy_map_deprecation_message.tsx +++ /dev/null @@ -1,68 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { EuiButton, EuiCallOut, EuiLink } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { i18n } from '@kbn/i18n'; - -interface Props { - isMapsAvailable: boolean; - onClick: (e: React.MouseEvent) => Promise; - visualizationLabel: string; -} - -export function LegacyMapDeprecationMessage(props: Props) { - const getMapsMessage = !props.isMapsAvailable ? ( - - default distribution - - ), - }} - /> - ) : null; - - const button = props.isMapsAvailable ? ( -
- - - -
- ) : null; - - return ( - -

- -

- {button} -
- ); -} diff --git a/src/plugins/maps_legacy/public/components/wms_internal_options.tsx b/src/plugins/maps_legacy/public/components/wms_internal_options.tsx deleted file mode 100644 index d666a97489b62..0000000000000 --- a/src/plugins/maps_legacy/public/components/wms_internal_options.tsx +++ /dev/null @@ -1,205 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import { EuiLink, EuiSpacer, EuiText, EuiScreenReaderOnly } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n/react'; - -import { TextInputOption } from '../../../vis_default_editor/public'; -import { WMSOptions } from '../common/types'; - -interface WmsInternalOptions { - wms: WMSOptions; - setValue: (paramName: T, value: WMSOptions[T]) => void; -} - -function WmsInternalOptions({ wms, setValue }: WmsInternalOptions) { - const wmsLink = ( - - - - ); - const footnoteText = ( - <> - - - - ); - const footnote = ( - -

{footnoteText}

-
- ); - - const setOptions = ( - paramName: T, - value: WMSOptions['options'][T] - ) => - setValue('options', { - ...wms.options, - [paramName]: value, - }); - - return ( - <> - - - - - - - - - - - } - helpText={ - <> - - {footnote} - - } - paramName="url" - value={wms.url} - setValue={setValue} - /> - - - - - - } - helpText={ - <> - - {footnote} - - } - paramName="layers" - value={wms.options.layers} - setValue={setOptions} - /> - - - - - - } - helpText={ - <> - - {footnote} - - } - paramName="version" - value={wms.options.version} - setValue={setOptions} - /> - - - - - - } - helpText={ - <> - - {footnote} - - } - paramName="format" - value={wms.options.format} - setValue={setOptions} - /> - - - } - helpText={ - - } - paramName="attribution" - value={wms.options.attribution} - setValue={setOptions} - /> - - - - - - } - helpText={ - <> - - {footnote} - - } - paramName="styles" - value={wms.options.styles} - setValue={setOptions} - /> - - - - - - ); -} - -export { WmsInternalOptions }; diff --git a/src/plugins/maps_legacy/public/components/wms_options.tsx b/src/plugins/maps_legacy/public/components/wms_options.tsx deleted file mode 100644 index 8f63d205406e9..0000000000000 --- a/src/plugins/maps_legacy/public/components/wms_options.tsx +++ /dev/null @@ -1,88 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useMemo } from 'react'; -import { EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { TmsLayer } from '../../../maps_ems/public'; -import { SelectOption, SwitchOption } from '../../../vis_default_editor/public'; -import { WmsInternalOptions } from './wms_internal_options'; -import { WMSOptions } from '../common/types'; - -interface Props { - stateParams: K; - setValue: (title: 'wms', options: WMSOptions) => void; - tmsLayers: TmsLayer[]; -} - -const mapLayerForOption = ({ id }: TmsLayer) => ({ text: id, value: id }); - -function WmsOptions({ stateParams, setValue, tmsLayers }: Props) { - const { wms } = stateParams; - const tmsLayerOptions = useMemo(() => tmsLayers.map(mapLayerForOption), [tmsLayers]); - - const setWmsOption = (paramName: T, value: WMSOptions[T]) => - setValue('wms', { - ...wms, - [paramName]: value, - }); - - const selectTmsLayer = (id: string) => { - const layer = tmsLayers.find((l: TmsLayer) => l.id === id); - if (layer) { - setWmsOption('selectedTmsLayer', layer); - } - }; - - return ( - - -

- -

-
- - - - - {!wms.enabled && ( - <> - - selectTmsLayer(value)} - /> - - )} - - {wms.enabled && } -
- ); -} - -export { WmsOptions }; diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts deleted file mode 100644 index c21aabcf743b9..0000000000000 --- a/src/plugins/maps_legacy/public/index.ts +++ /dev/null @@ -1,31 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { PluginInitializerContext } from 'kibana/public'; -import { MapsLegacyPlugin } from './plugin'; -import * as colorUtil from './map/color_util'; -import { KibanaMapLayer } from './map/kibana_map_layer'; -import { mapTooltipProvider } from './tooltip_provider'; - -import './map/index.scss'; - -export function plugin(initializerContext: PluginInitializerContext) { - return new MapsLegacyPlugin(initializerContext); -} - -/** @public */ -export { colorUtil, KibanaMapLayer, mapTooltipProvider }; - -export { WMSOptions } from './common/types'; -export { WmsOptions } from './components/wms_options'; -export { LegacyMapDeprecationMessage } from './components/legacy_map_deprecation_message'; - -export { lazyLoadMapsLegacyModules } from './lazy_load_bundle'; - -export type MapsLegacyPluginSetup = ReturnType; -export type MapsLegacyPluginStart = ReturnType; diff --git a/src/plugins/maps_legacy/public/kibana_services.ts b/src/plugins/maps_legacy/public/kibana_services.ts deleted file mode 100644 index 1cf02ee06db88..0000000000000 --- a/src/plugins/maps_legacy/public/kibana_services.ts +++ /dev/null @@ -1,29 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { IUiSettingsClient, ToastsSetup } from 'kibana/public'; -import type { MapsEmsConfig, IServiceSettings } from '../../maps_ems/public'; - -let toast: ToastsSetup; -export const setToasts = (notificationToast: ToastsSetup) => (toast = notificationToast); -export const getToasts = () => toast; - -let uiSettings: IUiSettingsClient; -export const setUiSettings = (coreUiSettings: IUiSettingsClient) => (uiSettings = coreUiSettings); -export const getUiSettings = () => uiSettings; - -let mapsEmsConfig: MapsEmsConfig; -export const setMapsEmsConfig = (config: MapsEmsConfig) => (mapsEmsConfig = config); -export const getEmsTileLayerId = () => mapsEmsConfig.emsTileLayerId; - -let getServiceSettingsFunction: () => Promise; -export const setGetServiceSettings = (getSS: () => Promise) => - (getServiceSettingsFunction = getSS); -export const getServiceSettings = async (): Promise => { - return await getServiceSettingsFunction(); -}; diff --git a/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts b/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts deleted file mode 100644 index b1509c4effa7a..0000000000000 --- a/src/plugins/maps_legacy/public/lazy_load_bundle/index.ts +++ /dev/null @@ -1,30 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -let loadModulesPromise: Promise; - -interface LazyLoadedMapsLegacyModules { - KibanaMap: unknown; - L: unknown; -} - -export async function lazyLoadMapsLegacyModules(): Promise { - if (typeof loadModulesPromise !== 'undefined') { - return loadModulesPromise; - } - - loadModulesPromise = new Promise(async (resolve) => { - const { KibanaMap, L } = await import('./lazy'); - - resolve({ - KibanaMap, - L, - }); - }); - 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 deleted file mode 100644 index 5fb53c1a4f524..0000000000000 --- a/src/plugins/maps_legacy/public/lazy_load_bundle/lazy/index.ts +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// @ts-expect-error -export { KibanaMap } from '../../map/kibana_map'; -// @ts-expect-error -export { L } from '../../leaflet'; diff --git a/src/plugins/maps_legacy/public/leaflet.js b/src/plugins/maps_legacy/public/leaflet.js deleted file mode 100644 index fd02f83d72823..0000000000000 --- a/src/plugins/maps_legacy/public/leaflet.js +++ /dev/null @@ -1,22 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -if (!window.hasOwnProperty('L')) { - require('leaflet/dist/leaflet.css'); - window.L = require('leaflet/dist/leaflet.js'); - window.L.Browser.touch = false; - window.L.Browser.pointer = false; - - require('leaflet.heat/dist/leaflet-heat.js'); - require('leaflet-draw/dist/leaflet.draw.css'); - require('leaflet-draw/dist/leaflet.draw.js'); - require('leaflet-responsive-popup/leaflet.responsive.popup.css'); - require('leaflet-responsive-popup/leaflet.responsive.popup.js'); -} - -export const L = window.L; diff --git a/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss b/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss deleted file mode 100644 index c688a8c9b518c..0000000000000 --- a/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss +++ /dev/null @@ -1,158 +0,0 @@ -// stylelint-disable selector-no-qualifying-type -// SASSTODO: Create these tooltip variables in EUI -// And/Or create a tooltip mixin -$tempEUITooltipBackground: tintOrShade($euiColorFullShade, 25%, 90%); -$tempEUITooltipText: $euiColorGhost; - -// Converted leaflet icon sprite into background svg for custom coloring (dark mode) -$visMapLeafletSprite: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 600 60' height='60' width='600'%3E%3Cg fill='#{hexToRGB($euiTextColor)}'%3E%3Cg%3E%3Cpath d='M18 36v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M36 18v6h6v-6h-6zm4 4h-2v-2h2v2z'/%3E%3Cpath d='M23.142 39.145l-2.285-2.29 16-15.998 2.285 2.285z'/%3E%3C/g%3E%3Cpath d='M100 24.565l-2.096 14.83L83.07 42 76 28.773 86.463 18z'/%3E%3Cpath d='M140 20h20v20h-20z'/%3E%3Cpath d='M221 30c0 6.078-4.926 11-11 11s-11-4.922-11-11c0-6.074 4.926-11 11-11s11 4.926 11 11z'/%3E%3Cpath d='M270,19c-4.971,0-9,4.029-9,9c0,4.971,5.001,12,9,14c4.001-2,9-9.029,9-14C279,23.029,274.971,19,270,19z M270,31.5c-2.484,0-4.5-2.014-4.5-4.5c0-2.484,2.016-4.5,4.5-4.5c2.485,0,4.5,2.016,4.5,4.5C274.5,29.486,272.485,31.5,270,31.5z'/%3E%3Cg%3E%3Cpath d='M337,30.156v0.407v5.604c0,1.658-1.344,3-3,3h-10c-1.655,0-3-1.342-3-3v-10c0-1.657,1.345-3,3-3h6.345 l3.19-3.17H324c-3.313,0-6,2.687-6,6v10c0,3.313,2.687,6,6,6h10c3.314,0,6-2.687,6-6v-8.809L337,30.156'/%3E%3Cpath d='M338.72 24.637l-8.892 8.892H327V30.7l8.89-8.89z'/%3E%3Cpath d='M338.697 17.826h4v4h-4z' transform='rotate(-134.99 340.703 19.817)'/%3E%3C/g%3E%3Cg%3E%3Cpath d='M381 42h18V24h-18v18zm14-16h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26zm-4 0h2v14h-2V26z'/%3E%3Cpath d='M395 20v-4h-10v4h-6v2h22v-2h-6zm-2 0h-6v-2h6v2z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E%0A"; - -.leaflet-touch .leaflet-bar, -.leaflet-draw-actions { - @include euiBottomShadowMedium($color: $euiShadowColorLarge, $opacity: .2); - border: none; -} - -.leaflet-container { - background: $euiColorEmptyShade; - - //the heatmap layer plugin logs an error to the console when the map is in a 0-sized container - min-width: 1px !important; - min-height: 1px !important; -} - -.leaflet-clickable { - &:hover { - stroke-width: $euiSizeS; - stroke-opacity: .8; - } -} - -/** - * 1. Since Leaflet is an external library, we also have to provide EUI variables - * to non-override colors for darkmode. - */ - -.leaflet-draw-actions, -.leaflet-control { - a { - background-color: lightOrDarkTheme($euiColorEmptyShade, $euiColorLightShade); /* 1 */ - border-color: lightOrDarkTheme($euiColorLightShade, $euiColorMediumShade) !important; /* 1 */ - color: $euiTextColor !important; /* 1 */ - - &:hover { - background-color: $euiColorLightestShade; - } - } -} - -.leaflet-touch .leaflet-bar a:first-child { - border-top-left-radius: $euiBorderRadius; - border-top-right-radius: $euiBorderRadius; -} - -.leaflet-touch .leaflet-bar a:last-child { - border-bottom-left-radius: $euiBorderRadius; - border-bottom-right-radius: $euiBorderRadius; -} - -.leaflet-retina .leaflet-draw-toolbar a { - background-image: url($visMapLeafletSprite); /* 1 */ -} - -.leaflet-control-layers-expanded { - padding: 0; - margin: 0; - @include fontSize(11px); - font-family: $euiFontFamily; - font-weight: $euiFontWeightMedium; - line-height: $euiLineHeight; - - label { - font-weight: $euiFontWeightMedium; - margin: 0; - padding: 0; - } -} - -/* over-rides leaflet popup styles to look like kibana tooltip */ -.leaflet-popup-content-wrapper { - margin: 0; - padding: 0; - background: $tempEUITooltipBackground; - color: $tempEUITooltipText; - border-radius: $euiBorderRadius !important; // Override all positions the popup might be at -} - -.leaflet-popup { - pointer-events: none; -} - -.leaflet-popup-content { - margin: 0; - @include euiFontSizeS; - font-weight: $euiFontWeightRegular; - word-wrap: break-word; - overflow: hidden; - pointer-events: none; - - > * { - margin: $euiSizeS $euiSizeS 0; - } - - > :last-child { - margin-bottom: $euiSizeS; - } - - table { - td,th { - padding: $euiSizeXS; - } - } -} - -.leaflet-popup-tip-container, -.leaflet-popup-close-button, -.leaflet-draw-tooltip { - display: none !important; -} - -.leaflet-container .leaflet-control-attribution { - background-color: transparentize($euiColorEmptyShade, .7); - color: $euiColorDarkShade; - - // attributions are appended in blocks of

tags, this will allow them to display in one line - p { - display: inline; - } -} - -.leaflet-touch .leaflet-control-zoom-in, -.leaflet-touch .leaflet-control-zoom-out { - text-indent: -10000px; - background-repeat: no-repeat; - background-position: center; -} - -// Custom SVG as background for zoom controls based off of EUI glyphs plusInCircleFilled and minusInCircleFilled -.leaflet-touch .leaflet-control-zoom-in { - background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='15px' viewBox='0 0 15 15' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='#{hexToRGB($euiTextColor)}' d='M8,7 L8,3.5 C8,3.22385763 7.77614237,3 7.5,3 C7.22385763,3 7,3.22385763 7,3.5 L7,7 L3.5,7 C3.22385763,7 3,7.22385763 3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L7,8 L7,11.5 C7,11.7761424 7.22385763,12 7.5,12 C7.77614237,12 8,11.7761424 8,11.5 L8,8 L11.5,8 C11.7761424,8 12,7.77614237 12,7.5 C12,7.22385763 11.7761424,7 11.5,7 L8,7 Z M7.5,15 C3.35786438,15 0,11.6421356 0,7.5 C0,3.35786438 3.35786438,0 7.5,0 C11.6421356,0 15,3.35786438 15,7.5 C15,11.6421356 11.6421356,15 7.5,15 Z' /%3E%3C/svg%3E"); -} - -.leaflet-touch .leaflet-control-zoom-out { - background-image: url("data:image/svg+xml,%0A%3Csvg width='15px' height='15px' viewBox='0 0 15 15' version='1.1' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='#{hexToRGB($euiTextColor)}' d='M7.5,0 C11.6355882,0 15,3.36441176 15,7.5 C15,11.6355882 11.6355882,15 7.5,15 C3.36441176,15 0,11.6355882 0,7.5 C0,3.36441176 3.36441176,0 7.5,0 Z M3.5,7 C3.22385763,7 3,7.22385763 3,7.5 C3,7.77614237 3.22385763,8 3.5,8 L11.5,8 C11.7761424,8 12,7.77614237 12,7.5 C12,7.22385763 11.7761424,7 11.5,7 L3.5,7 Z' /%3E%3C/svg%3E"); -} - -// Filter to desaturate mapquest tiles - -img.leaflet-tile { - @if (lightness($euiTextColor) < 50) { - filter: brightness(1.03) grayscale(.73); - } @else { - filter: invert(1) brightness(1.75) grayscale(1); - } -} - -img.leaflet-tile.filters-off { - filter: none; -} diff --git a/src/plugins/maps_legacy/public/map/_legend.scss b/src/plugins/maps_legacy/public/map/_legend.scss deleted file mode 100644 index 27016840cfabf..0000000000000 --- a/src/plugins/maps_legacy/public/map/_legend.scss +++ /dev/null @@ -1,33 +0,0 @@ -.visMapLegend { - @include fontSize(11px); - @include euiBottomShadowMedium($color: $euiShadowColorLarge); - font-family: $euiFontFamily; - font-weight: $euiFontWeightMedium; - line-height: $euiLineHeight; - color: $euiColorDarkShade; - padding: $euiSizeS; - background: transparentize($euiColorEmptyShade, .2); - border-radius: $euiBorderRadius; - - i { - @include size($euiSizeS + 2px); - display: inline-block; - margin: 3px $euiSizeXS 0 0; - border-radius: 50%; - border: 1px solid $euiColorDarkShade; - background: $euiColorDarkShade; - } -} - -.visMapLegend__title { - font-weight: $euiFontWeightBold; -} - -// Wrapper/Position - -// top left needs some more styles -.leaflet-top.leaflet-left .visMapLegend__wrapper { - position: absolute; - left: $euiSizeXXL; - white-space: nowrap; -} diff --git a/src/plugins/maps_legacy/public/map/base_maps_visualization.js b/src/plugins/maps_legacy/public/map/base_maps_visualization.js deleted file mode 100644 index a261bcf6edd80..0000000000000 --- a/src/plugins/maps_legacy/public/map/base_maps_visualization.js +++ /dev/null @@ -1,244 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import * as Rx from 'rxjs'; -import { filter, first } from 'rxjs/operators'; -import { - getEmsTileLayerId, - getUiSettings, - getToasts, - getServiceSettings, -} from '../kibana_services'; -import { lazyLoadMapsLegacyModules } from '../lazy_load_bundle'; - -const WMS_MINZOOM = 0; -const WMS_MAXZOOM = 22; //increase this to 22. Better for WMS - -export function BaseMapsVisualizationProvider() { - /** - * Abstract base class for a visualization consisting of a map with a single baselayer. - * @class BaseMapsVisualization - * @constructor - */ - return class BaseMapsVisualization { - constructor(element, handlers, initialVisParams) { - this.handlers = handlers; - this._params = initialVisParams; - this._container = element; - this._kibanaMap = null; - this._chartData = null; //reference to data currently on the map. - this._baseLayerDirty = true; - this._mapIsLoaded = this._makeKibanaMap(); - } - - isLoaded() { - return this._mapIsLoaded; - } - - destroy() { - if (this._kibanaMap) { - this._kibanaMap.destroy(); - this._kibanaMap = null; - } - } - - /** - * Implementation of Visualization#render. - * Child-classes can extend this method if the render-complete function requires more time until rendering has completed. - * @param esResponse - * @param status - * @return {Promise} - */ - async render(esResponse = this._esResponse, visParams = this._params) { - await this._mapIsLoaded; - - if (!this._kibanaMap) { - //the visualization has been destroyed; - return; - } - - this.resize(); - this._params = visParams; - await this._updateParams(); - - if (this._hasESResponseChanged(esResponse)) { - this._esResponse = esResponse; - await this._updateData(esResponse); - } - this._kibanaMap.useUiStateFromVisualization(this.handlers.uiState); - - await this._whenBaseLayerIsLoaded(); - } - - resize() { - this._kibanaMap?.resize(); - } - - /** - * Creates an instance of a kibana-map with a single baselayer and assigns it to the this._kibanaMap property. - * Clients can override this method to customize the initialization. - * @private - */ - async _makeKibanaMap() { - const options = {}; - const zoomFromUiState = parseInt(this.handlers.uiState?.get('mapZoom')); - const centerFromUIState = this.handlers.uiState?.get('mapCenter'); - const { mapZoom, mapCenter } = this._getMapsParams(); - options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : mapZoom; - options.center = centerFromUIState ? centerFromUIState : mapCenter; - - 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 - - this._kibanaMap.addLegendControl(); - this._kibanaMap.addFitControl(); - this._kibanaMap.persistUiStateForVisualization(this.handlers.uiState); - - this._kibanaMap.on('baseLayer:loaded', () => { - this._baseLayerDirty = false; - }); - this._kibanaMap.on('baseLayer:loading', () => { - this._baseLayerDirty = true; - }); - await this._updateBaseLayer(); - } - - _tmsConfigured() { - const { wms } = this._getMapsParams(); - const hasTmsBaseLayer = wms && !!wms.selectedTmsLayer; - - return hasTmsBaseLayer; - } - - _wmsConfigured() { - const { wms } = this._getMapsParams(); - const hasWmsBaseLayer = wms && !!wms.enabled; - - return hasWmsBaseLayer; - } - - async _updateBaseLayer() { - const emsTileLayerId = getEmsTileLayerId(); - - if (!this._kibanaMap) { - return; - } - - const mapParams = this._getMapsParams(); - if (!this._tmsConfigured()) { - try { - const serviceSettings = await getServiceSettings(); - const tmsServices = await serviceSettings.getTMSServices(); - const userConfiguredTmsLayer = tmsServices[0]; - const initBasemapLayer = userConfiguredTmsLayer - ? userConfiguredTmsLayer - : tmsServices.find((s) => s.id === emsTileLayerId.bright); - if (initBasemapLayer) { - this._setTmsLayer(initBasemapLayer); - } - } catch (e) { - getToasts().addWarning(e.message); - return; - } - return; - } - - try { - if (this._wmsConfigured()) { - if (WMS_MINZOOM > this._kibanaMap.getMaxZoomLevel()) { - this._kibanaMap.setMinZoom(WMS_MINZOOM); - this._kibanaMap.setMaxZoom(WMS_MAXZOOM); - } - - this._kibanaMap.setBaseLayer({ - baseLayerType: 'wms', - options: { - minZoom: WMS_MINZOOM, - maxZoom: WMS_MAXZOOM, - url: mapParams.wms.url, - ...mapParams.wms.options, - }, - }); - } else if (this._tmsConfigured()) { - const selectedTmsLayer = mapParams.wms.selectedTmsLayer; - this._setTmsLayer(selectedTmsLayer); - } - } catch (tmsLoadingError) { - getToasts().addWarning(tmsLoadingError.message); - } - } - - async _setTmsLayer(tmsLayer) { - this._kibanaMap.setMinZoom(tmsLayer.minZoom); - this._kibanaMap.setMaxZoom(tmsLayer.maxZoom); - if (this._kibanaMap.getZoomLevel() > tmsLayer.maxZoom) { - this._kibanaMap.setZoomLevel(tmsLayer.maxZoom); - } - let isDesaturated = this._getMapsParams().isDesaturated; - if (typeof isDesaturated !== 'boolean') { - isDesaturated = true; - } - const isDarkMode = getUiSettings().get('theme:darkMode'); - const serviceSettings = await getServiceSettings(); - const meta = await serviceSettings.getAttributesForTMSLayer( - tmsLayer, - isDesaturated, - isDarkMode - ); - const options = { ...tmsLayer }; - delete options.id; - delete options.subdomains; - this._kibanaMap.setBaseLayer({ - baseLayerType: 'tms', - options: { ...options, ...meta }, - }); - } - - async _updateData() { - throw new Error( - i18n.translate('maps_legacy.baseMapsVisualization.childShouldImplementMethodErrorMessage', { - defaultMessage: 'Child should implement this method to respond to data-update', - }) - ); - } - - _hasESResponseChanged(data) { - return this._esResponse !== data; - } - - /** - * called on options change (vis.params change) - */ - async _updateParams() { - const mapParams = this._getMapsParams(); - await this._updateBaseLayer(); - this._kibanaMap.setLegendPosition(mapParams.legendPosition); - this._kibanaMap.setShowTooltip(mapParams.addTooltip); - this._kibanaMap.useUiStateFromVisualization(this.handlers.uiState); - } - - _getMapsParams() { - return this._params; - } - - _whenBaseLayerIsLoaded() { - if (!this._tmsConfigured()) { - return true; - } - - const maxTimeForBaseLayer = 10000; - const interval$ = Rx.interval(10).pipe(filter(() => !this._baseLayerDirty)); - const timer$ = Rx.timer(maxTimeForBaseLayer); - - return Rx.race(interval$, timer$).pipe(first()).toPromise(); - } - }; -} diff --git a/src/plugins/maps_legacy/public/map/color_util.d.ts b/src/plugins/maps_legacy/public/map/color_util.d.ts deleted file mode 100644 index 8ab753e529518..0000000000000 --- a/src/plugins/maps_legacy/public/map/color_util.d.ts +++ /dev/null @@ -1,11 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export function getLegendColors(colorRamp: unknown, numLegendColors?: number): string[]; - -export function getColor(colorRamp: unknown, i: number): string; diff --git a/src/plugins/maps_legacy/public/map/color_util.js b/src/plugins/maps_legacy/public/map/color_util.js deleted file mode 100644 index 64e4cedd7616c..0000000000000 --- a/src/plugins/maps_legacy/public/map/color_util.js +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export function getLegendColors(colorRamp, numLegendColors = 4) { - const colors = []; - colors[0] = getColor(colorRamp, 0); - for (let i = 1; i < numLegendColors - 1; i++) { - colors[i] = getColor(colorRamp, Math.floor((colorRamp.length * i) / numLegendColors)); - } - colors[numLegendColors - 1] = getColor(colorRamp, colorRamp.length - 1); - return colors; -} - -export function getColor(colorRamp, i) { - const color = colorRamp[i][1]; - const red = Math.floor(color[0] * 255); - const green = Math.floor(color[1] * 255); - const blue = Math.floor(color[2] * 255); - return `rgb(${red},${green},${blue})`; -} diff --git a/src/plugins/maps_legacy/public/map/geohash_columns.test.ts b/src/plugins/maps_legacy/public/map/geohash_columns.test.ts deleted file mode 100644 index e1da8ec506d9c..0000000000000 --- a/src/plugins/maps_legacy/public/map/geohash_columns.test.ts +++ /dev/null @@ -1,16 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { geohashColumns } from './geohash_columns'; - -test('geohashColumns', () => { - expect(geohashColumns(1)).toBe(8); - expect(geohashColumns(2)).toBe(8 * 4); - expect(geohashColumns(3)).toBe(8 * 4 * 8); - expect(geohashColumns(4)).toBe(8 * 4 * 8 * 4); -}); diff --git a/src/plugins/maps_legacy/public/map/geohash_columns.ts b/src/plugins/maps_legacy/public/map/geohash_columns.ts deleted file mode 100644 index 2140b4ea3d054..0000000000000 --- a/src/plugins/maps_legacy/public/map/geohash_columns.ts +++ /dev/null @@ -1,27 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export function geohashColumns(precision: number): number { - return geohashCells(precision, 0); -} - -/** - * Get the number of geohash cells for a given precision - * - * @param {number} precision the geohash precision (1<=precision<=12). - * @param {number} axis constant for the axis 0=lengthwise (ie. columns, along longitude), 1=heightwise (ie. rows, along latitude). - * @returns {number} Number of geohash cells (rows or columns) at that precision - */ -function geohashCells(precision: number, axis: number) { - let cells = 1; - for (let i = 1; i <= precision; i += 1) { - /* On odd precisions, rows divide by 4 and columns by 8. Vice-versa on even precisions */ - cells *= i % 2 === axis ? 4 : 8; - } - return cells; -} diff --git a/src/plugins/maps_legacy/public/map/index.scss b/src/plugins/maps_legacy/public/map/index.scss deleted file mode 100644 index f9fc841b9f868..0000000000000 --- a/src/plugins/maps_legacy/public/map/index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './leaflet_overrides'; -@import './legend'; diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js deleted file mode 100644 index 62dbbda2588a5..0000000000000 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ /dev/null @@ -1,683 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { EventEmitter } from 'events'; -import $ from 'jquery'; -import { get, isEqual, escape } from 'lodash'; -import { zoomToPrecision } from './zoom_to_precision'; -import { i18n } from '@kbn/i18n'; -import { ORIGIN } from '../../../maps_ems/common'; -import { L } from '../leaflet'; - -function makeFitControl(fitContainer, kibanaMap) { - // eslint-disable-next-line no-undef - const FitControl = L.Control.extend({ - options: { - position: 'topleft', - }, - initialize: function (fitContainer, kibanaMap) { - this._fitContainer = fitContainer; - this._kibanaMap = kibanaMap; - this._leafletMap = null; - }, - onAdd: function (leafletMap) { - this._leafletMap = leafletMap; - const fitDatBoundsLabel = i18n.translate( - 'maps_legacy.kibanaMap.leaflet.fitDataBoundsAriaLabel', - { defaultMessage: 'Fit Data Bounds' } - ); - $(this._fitContainer) - .html( - `` - ) - .on('click', (e) => { - e.preventDefault(); - this._kibanaMap.fitToData(); - }); - - return this._fitContainer; - }, - onRemove: function () { - $(this._fitContainer).off('click'); - }, - }); - - return new FitControl(fitContainer, kibanaMap); -} - -function makeLegendControl(container, kibanaMap, position) { - // eslint-disable-next-line no-undef - const LegendControl = L.Control.extend({ - options: { - position: 'topright', - }, - - initialize: function (container, kibanaMap, position) { - this._legendContainer = container; - this._kibanaMap = kibanaMap; - this.options.position = position; - }, - - updateContents() { - this._legendContainer.empty(); - const $div = $('

').addClass('visMapLegend'); - this._legendContainer.append($div); - const layers = this._kibanaMap.getLayers(); - layers.forEach((layer) => layer.appendLegendContents($div)); - }, - - onAdd: function () { - this._layerUpdateHandle = () => this.updateContents(); - this._kibanaMap.on('layers:update', this._layerUpdateHandle); - this.updateContents(); - return this._legendContainer.get(0); - }, - onRemove: function () { - this._kibanaMap.removeListener('layers:update', this._layerUpdateHandle); - this._legendContainer.empty(); - }, - }); - - return new LegendControl(container, kibanaMap, position); -} - -/** - * Collects map functionality required for Kibana. - * Serves as simple abstraction for leaflet as well. - */ -export class KibanaMap extends EventEmitter { - constructor(containerNode, options) { - super(); - this._containerNode = containerNode; - this._leafletBaseLayer = null; - this._baseLayerSettings = null; - this._baseLayerIsDesaturated = true; - - this._leafletDrawControl = null; - this._leafletFitControl = null; - this._leafletLegendControl = null; - this._legendPosition = 'topright'; - - this._layers = []; - this._listeners = []; - this._showTooltip = false; - - const leafletOptions = { - minZoom: options.minZoom, - maxZoom: options.maxZoom, - center: options.center ? options.center : [0, 0], - zoom: options.zoom ? options.zoom : 2, - // eslint-disable-next-line no-undef - renderer: L.canvas(), - zoomAnimation: false, // Desaturate map tiles causes animation rendering artifacts - zoomControl: options.zoomControl === undefined ? true : options.zoomControl, - }; - - // eslint-disable-next-line no-undef - this._leafletMap = L.map(containerNode, leafletOptions); - this._leafletMap.attributionControl.setPrefix(''); - - if (!options.scrollWheelZoom) { - this._leafletMap.scrollWheelZoom.disable(); - } - - let previousZoom = this._leafletMap.getZoom(); - this._leafletMap.on('zoomend', () => { - if (previousZoom !== this._leafletMap.getZoom()) { - previousZoom = this._leafletMap.getZoom(); - this.emit('zoomchange'); - } - }); - this._leafletMap.on('zoomend', () => this.emit('zoomend')); - this._leafletMap.on('dragend', () => this.emit('dragend')); - - this._leafletMap.on('zoomend', () => this._updateExtent()); - this._leafletMap.on('dragend', () => this._updateExtent()); - - this._leafletMap.on('mousemove', (e) => - this._layers.forEach((layer) => layer.movePointer('mousemove', e)) - ); - this._leafletMap.on('mouseout', (e) => - this._layers.forEach((layer) => layer.movePointer('mouseout', e)) - ); - this._leafletMap.on('mousedown', (e) => - this._layers.forEach((layer) => layer.movePointer('mousedown', e)) - ); - this._leafletMap.on('mouseup', (e) => - this._layers.forEach((layer) => layer.movePointer('mouseup', e)) - ); - this._leafletMap.on('draw:created', (event) => { - const drawType = event.layerType; - if (drawType === 'rectangle') { - const bounds = event.layer.getBounds(); - - const southEast = bounds.getSouthEast(); - const northWest = bounds.getNorthWest(); - let southEastLng = southEast.lng; - if (southEastLng > 180) { - southEastLng -= 360; - } - let northWestLng = northWest.lng; - if (northWestLng < -180) { - northWestLng += 360; - } - - const southEastLat = southEast.lat; - const northWestLat = northWest.lat; - - //Bounds cannot be created unless they form a box with larger than 0 dimensions - //Invalid areas are rejected by ES. - if (southEastLat === northWestLat || southEastLng === northWestLng) { - return; - } - - this.emit('drawCreated:rectangle', { - bounds: { - bottom_right: { - lat: southEastLat, - lon: southEastLng, - }, - top_left: { - lat: northWestLat, - lon: northWestLng, - }, - }, - }); - } else if (drawType === 'polygon') { - const latLongs = event.layer.getLatLngs()[0]; - this.emit('drawCreated:polygon', { - points: latLongs.map((leafletLatLng) => { - return { - lat: leafletLatLng.lat, - lon: leafletLatLng.lng, - }; - }), - }); - } - }); - - this.resize(); - } - - setShowTooltip(showTooltip) { - this._showTooltip = showTooltip; - } - - getLayers() { - return this._layers.slice(); - } - - addLayer(kibanaLayer) { - const onshowTooltip = (event) => { - if (!this._showTooltip) { - return; - } - - if (!this._popup) { - // eslint-disable-next-line no-undef - this._popup = new L.ResponsivePopup({ autoPan: false }); - this._popup.setLatLng(event.position); - this._popup.setContent(event.content); - this._leafletMap.openPopup(this._popup); - } else { - if (!this._popup.getLatLng().equals(event.position)) { - this._popup.setLatLng(event.position); - } - if (this._popup.getContent() !== event.content) { - this._popup.setContent(event.content); - } - } - }; - - kibanaLayer.on('showTooltip', onshowTooltip); - this._listeners.push({ name: 'showTooltip', handle: onshowTooltip, layer: kibanaLayer }); - - const onHideTooltip = () => { - this._leafletMap.closePopup(); - this._popup = null; - }; - kibanaLayer.on('hideTooltip', onHideTooltip); - this._listeners.push({ name: 'hideTooltip', handle: onHideTooltip, layer: kibanaLayer }); - - const onStyleChanged = () => { - if (this._leafletLegendControl) { - this._leafletLegendControl.updateContents(); - } - }; - kibanaLayer.on('styleChanged', onStyleChanged); - this._listeners.push({ name: 'styleChanged', handle: onStyleChanged, layer: kibanaLayer }); - - this._layers.push(kibanaLayer); - kibanaLayer.addToLeafletMap(this._leafletMap); - this.emit('layers:update'); - - this._addAttributions(kibanaLayer.getAttributions()); - } - - removeLayer(kibanaLayer) { - if (!kibanaLayer) { - return; - } - - this._removeAttributions(kibanaLayer.getAttributions()); - const index = this._layers.indexOf(kibanaLayer); - if (index >= 0) { - this._layers.splice(index, 1); - kibanaLayer.removeFromLeafletMap(this._leafletMap); - } - this._listeners.forEach((listener) => { - if (listener.layer === kibanaLayer) { - listener.layer.removeListener(listener.name, listener.handle); - } - }); - - //must readd all attributions, because we might have removed dupes - this._layers.forEach((layer) => this._addAttributions(layer.getAttributions())); - if (this._baseLayerSettings) { - this._addAttributions(this._baseLayerSettings.options.attribution); - } - } - - _addAttributions(attribution) { - const attributions = getAttributionArray(attribution); - attributions.forEach((attribution) => { - this._leafletMap.attributionControl.removeAttribution(attribution); //this ensures we do not add duplicates - this._leafletMap.attributionControl.addAttribution(attribution); - }); - } - - _removeAttributions(attribution) { - const attributions = getAttributionArray(attribution); - attributions.forEach((attribution) => { - this._leafletMap.attributionControl.removeAttribution(attribution); //this ensures we do not add duplicates - }); - } - - destroy() { - if (this._leafletFitControl) { - this._leafletMap.removeControl(this._leafletFitControl); - } - if (this._leafletDrawControl) { - this._leafletMap.removeControl(this._leafletDrawControl); - } - if (this._leafletLegendControl) { - this._leafletMap.removeControl(this._leafletLegendControl); - } - this.setBaseLayer(null); - let layer; - while (this._layers.length) { - layer = this._layers.pop(); - layer.removeFromLeafletMap(this._leafletMap); - } - this._leafletMap.remove(); - this._containerNode.innerHTML = ''; - this._listeners.forEach((listener) => - listener.layer.removeListener(listener.name, listener.handle) - ); - } - - getCenter() { - const center = this._leafletMap.getCenter(); - return { lon: center.lng, lat: center.lat }; - } - - setCenter(latitude, longitude) { - // eslint-disable-next-line no-undef - const latLong = L.latLng(latitude, longitude); - if (latLong.equals && !latLong.equals(this._leafletMap.getCenter())) { - this._leafletMap.setView(latLong); - } - } - - setZoomLevel(zoomLevel) { - if (this._leafletMap.getZoom() !== zoomLevel) { - this._leafletMap.setZoom(zoomLevel); - } - } - - getZoomLevel = () => { - return this._leafletMap.getZoom(); - }; - - getMaxZoomLevel = () => { - return this._leafletMap.getMaxZoom(); - }; - - getGeohashPrecision() { - return zoomToPrecision(this._leafletMap.getZoom(), 12, this._leafletMap.getMaxZoom()); - } - - getLeafletBounds() { - return this._leafletMap.getBounds(); - } - - getMetersPerPixel() { - const pointC = this._leafletMap.latLngToContainerPoint(this._leafletMap.getCenter()); // center (pixels) - const pointX = [pointC.x + 1, pointC.y]; // add one pixel to x - const pointY = [pointC.x, pointC.y + 1]; // add one pixel to y - - const latLngC = this._leafletMap.containerPointToLatLng(pointC); - const latLngX = this._leafletMap.containerPointToLatLng(pointX); - const latLngY = this._leafletMap.containerPointToLatLng(pointY); - - 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 Math.min(distanceX, distanceY); - } - - _getLeafletBounds(resizeOnFail) { - const boundsRaw = this._leafletMap.getBounds(); - const bounds = this._leafletMap.wrapLatLngBounds(boundsRaw); - - if (!bounds) { - return null; - } - - const southEast = bounds.getSouthEast(); - const northWest = bounds.getNorthWest(); - if (southEast.lng === northWest.lng || southEast.lat === northWest.lat) { - if (resizeOnFail) { - this._leafletMap.invalidateSize(); - return this._getLeafletBounds(false); - } else { - return null; - } - } else { - return bounds; - } - } - - getBounds() { - const bounds = this._getLeafletBounds(true); - if (!bounds) { - return null; - } - - const southEast = bounds.getSouthEast(); - const northWest = bounds.getNorthWest(); - - const southEastLng = southEast.lng; - const northWestLng = northWest.lng; - const southEastLat = southEast.lat; - const northWestLat = northWest.lat; - - // When map has not width or height, the map has no dimensions. - // These dimensions are enforced due to CSS style rules that enforce min-width/height of 0 - // that enforcement also resolves errors with the heatmap layer plugin. - - return { - bottom_right: { - lat: southEastLat, - lon: southEastLng, - }, - top_left: { - lat: northWestLat, - lon: northWestLng, - }, - }; - } - - setDesaturateBaseLayer(isDesaturated) { - if (isDesaturated === this._baseLayerIsDesaturated) { - return; - } - this._baseLayerIsDesaturated = isDesaturated; - this._updateDesaturation(); - if (this._leafletBaseLayer) { - this._leafletBaseLayer.redraw(); - } - } - - addDrawControl() { - const drawColor = '#000'; - const drawOptions = { - draw: { - polyline: false, - marker: false, - circle: false, - rectangle: { - shapeOptions: { - stroke: false, - color: drawColor, - }, - }, - polygon: { - shapeOptions: { - color: drawColor, - }, - }, - circlemarker: false, - }, - }; - // eslint-disable-next-line no-undef - this._leafletDrawControl = new L.Control.Draw(drawOptions); - this._leafletMap.addControl(this._leafletDrawControl); - } - - addFitControl() { - if (this._leafletFitControl || !this._leafletMap) { - return; - } - - // eslint-disable-next-line no-undef - const fitContainer = L.DomUtil.create('div', 'leaflet-control leaflet-bar leaflet-control-fit'); - this._leafletFitControl = makeFitControl(fitContainer, this); - this._leafletMap.addControl(this._leafletFitControl); - } - - addLegendControl() { - if (this._leafletLegendControl || !this._leafletMap) { - return; - } - this._updateLegend(); - } - - setLegendPosition(position) { - if (this._legendPosition === position) { - if (!this._leafletLegendControl) { - this._updateLegend(); - } - } else { - this._legendPosition = position; - this._updateLegend(); - } - } - - _updateLegend() { - if (this._leafletLegendControl) { - this._leafletMap.removeControl(this._leafletLegendControl); - } - const $wrapper = $('
').addClass('visMapLegend__wrapper'); - this._leafletLegendControl = makeLegendControl($wrapper, this, this._legendPosition); - this._leafletMap.addControl(this._leafletLegendControl); - } - - resize() { - this._leafletMap.invalidateSize(); - this._updateExtent(); - } - - setMinZoom(zoom) { - this._leafletMap.setMinZoom(zoom); - } - - setMaxZoom(zoom) { - this._leafletMap.setMaxZoom(zoom); - } - - getLeafletBaseLayer() { - return this._leafletBaseLayer; - } - - setBaseLayer(settings) { - if (isEqual(settings, this._baseLayerSettings)) { - return; - } - - if (settings === null) { - if (this._leafletBaseLayer && this._leafletMap) { - this._removeAttributions(this._baseLayerSettings.options.attribution); - this._leafletMap.removeLayer(this._leafletBaseLayer); - this._leafletBaseLayer = null; - this._baseLayerSettings = null; - } - return; - } - - this._baseLayerSettings = settings; - if (this._leafletBaseLayer) { - this._leafletMap.removeLayer(this._leafletBaseLayer); - this._leafletBaseLayer = null; - } - - 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); - baseLayer = this._getWMSBaseLayer(settings.options); - } else if (settings.baseLayerType === 'tms') { - baseLayer = this._getTMSBaseLayer(settings.options); - } - - if (baseLayer) { - baseLayer.on('tileload', () => this._updateDesaturation()); - baseLayer.on('load', () => { - this.emit('baseLayer:loaded'); - }); - baseLayer.on('loading', () => { - this.emit('baseLayer:loading'); - }); - - this._leafletBaseLayer = baseLayer; - this._leafletBaseLayer.addTo(this._leafletMap); - this._leafletBaseLayer.bringToBack(); - if (settings.options.minZoom > this._leafletMap.getZoom()) { - this._leafletMap.setZoom(settings.options.minZoom); - } - this._addAttributions(settings.options.attribution); - this.resize(); - } - } - - isInside(bucketRectBounds) { - const mapBounds = this._leafletMap.getBounds(); - return mapBounds.intersects(bucketRectBounds); - } - - async fitToData() { - if (!this._leafletMap) { - return; - } - - const boundsArray = await Promise.all( - this._layers.map(async (layer) => { - return await layer.getBounds(); - }) - ); - - let bounds = null; - boundsArray.forEach(async (b) => { - if (bounds) { - bounds.extend(b); - } else { - bounds = b; - } - }); - - if (bounds && bounds.isValid()) { - this._leafletMap.fitBounds(bounds); - } - } - - _getTMSBaseLayer(options) { - // eslint-disable-next-line no-undef - return L.tileLayer(options.url, { - minZoom: options.minZoom, - maxZoom: options.maxZoom, - subdomains: options.subdomains || [], - }); - } - - _getWMSBaseLayer(options) { - const wmsOptions = { - format: options.format || '', - layers: options.layers || '', - minZoom: options.minZoom, - maxZoom: options.maxZoom, - styles: options.styles || '', - transparent: options.transparent, - version: options.version || '1.3.0', - }; - - return typeof options.url === 'string' && options.url.length - ? // eslint-disable-next-line no-undef - L.tileLayer.wms(options.url, wmsOptions) - : null; - } - - _updateExtent() { - this._layers.forEach((layer) => layer.updateExtent()); - } - - _updateDesaturation() { - const tiles = $('img.leaflet-tile-loaded'); - // Don't apply client-side styling to EMS basemaps - if (get(this._baseLayerSettings, 'options.origin') === ORIGIN.EMS) { - tiles.addClass('filters-off'); - } else { - if (this._baseLayerIsDesaturated) { - tiles.removeClass('filters-off'); - } else if (!this._baseLayerIsDesaturated) { - tiles.addClass('filters-off'); - } - } - } - - persistUiStateForVisualization(uiState) { - function persistMapStateInUiState() { - const centerFromUIState = uiState.get('mapCenter'); - const zoomFromUiState = parseInt(uiState.get('mapZoom')); - - if (isNaN(zoomFromUiState) || this.getZoomLevel() !== zoomFromUiState) { - uiState.set('mapZoom', this.getZoomLevel()); - } - const centerFromMap = this.getCenter(); - if ( - !centerFromUIState || - centerFromMap.lon !== centerFromUIState[1] || - centerFromMap.lat !== centerFromUIState[0] - ) { - uiState.set('mapCenter', [centerFromMap.lat, centerFromMap.lon]); - } - } - - this.on('dragend', persistMapStateInUiState); - this.on('zoomend', persistMapStateInUiState); - } - - useUiStateFromVisualization(uiState) { - const zoomFromUiState = parseInt(uiState?.get('mapZoom')); - const centerFromUIState = uiState?.get('mapCenter'); - if (!isNaN(zoomFromUiState)) { - this.setZoomLevel(zoomFromUiState); - } - if (centerFromUIState) { - this.setCenter(centerFromUIState[0], centerFromUIState[1]); - } - } -} - -function getAttributionArray(attribution) { - const attributionString = attribution || ''; - let attributions = attributionString.split(/\s*\|\s*/); - if (attributions.length === 1) { - //temp work-around due to inconsistency in manifests of how attributions are delimited - attributions = attributions[0].split(','); - } - return attributions; -} diff --git a/src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts b/src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts deleted file mode 100644 index 9d3f982bd78b2..0000000000000 --- a/src/plugins/maps_legacy/public/map/kibana_map_layer.d.ts +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export class KibanaMapLayer { - constructor(); - - getBounds(): Promise; - - addToLeafletMap(leafletMap: unknown): void; - - removeFromLeafletMap(leafletMap: unknown): void; - - appendLegendContents(): void; - - updateExtent(): void; - - movePointer(): void; - - getAttributions(): unknown; -} diff --git a/src/plugins/maps_legacy/public/map/kibana_map_layer.js b/src/plugins/maps_legacy/public/map/kibana_map_layer.js deleted file mode 100644 index 877ddec5f332f..0000000000000 --- a/src/plugins/maps_legacy/public/map/kibana_map_layer.js +++ /dev/null @@ -1,38 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { EventEmitter } from 'events'; - -export class KibanaMapLayer extends EventEmitter { - constructor() { - super(); - this._leafletLayer = null; - } - - async getBounds() { - return this._leafletLayer.getBounds(); - } - - addToLeafletMap(leafletMap) { - this._leafletLayer.addTo(leafletMap); - } - - removeFromLeafletMap(leafletMap) { - leafletMap.removeLayer(this._leafletLayer); - } - - appendLegendContents() {} - - updateExtent() {} - - movePointer() {} - - getAttributions() { - return this._attribution; - } -} diff --git a/src/plugins/maps_legacy/public/map/precision.ts b/src/plugins/maps_legacy/public/map/precision.ts deleted file mode 100644 index bf81f211e41af..0000000000000 --- a/src/plugins/maps_legacy/public/map/precision.ts +++ /dev/null @@ -1,63 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// @ts-ignore -import { getUiSettings } from '../kibana_services'; -import { geohashColumns } from './geohash_columns'; - -/** - * Get the number of geohash columns (world-wide) for a given precision - * @param precision the geohash precision - * @returns {number} the number of columns - */ - -const DEFAULT_PRECISION = 2; - -function getMaxPrecision() { - const config = getUiSettings(); - return parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; -} - -export function getZoomPrecision() { - /** - * Map Leaflet zoom levels to geohash precision levels. - * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide. - */ - const zoomPrecision: any = {}; - const minGeohashPixels = 16; - const maxPrecision = getMaxPrecision(); - - for (let zoom = 0; zoom <= 21; zoom += 1) { - const worldPixels = 256 * Math.pow(2, zoom); - zoomPrecision[zoom] = 1; - for (let precision = 2; precision <= maxPrecision; precision += 1) { - const columns = geohashColumns(precision); - if (worldPixels / columns >= minGeohashPixels) { - zoomPrecision[zoom] = precision; - } else { - break; - } - } - } - return zoomPrecision; -} - -export function getPrecision(val: string) { - let precision = parseInt(val, 10); - const maxPrecision = getMaxPrecision(); - - if (Number.isNaN(precision)) { - precision = DEFAULT_PRECISION; - } - - if (precision > maxPrecision) { - return maxPrecision; - } - - return precision; -} diff --git a/src/plugins/maps_legacy/public/map/zoom_to_precision.ts b/src/plugins/maps_legacy/public/map/zoom_to_precision.ts deleted file mode 100644 index 6ff43c291e400..0000000000000 --- a/src/plugins/maps_legacy/public/map/zoom_to_precision.ts +++ /dev/null @@ -1,49 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { geohashColumns } from './geohash_columns'; - -const defaultMaxPrecision = 12; -const minGeoHashPixels = 16; - -const calculateZoomToPrecisionMap = (maxZoom: number): Map => { - /** - * Map Leaflet zoom levels to geohash precision levels. - * The size of a geohash column-width on the map should be at least `minGeohashPixels` pixels wide. - */ - const zoomPrecisionMap = new Map(); - - for (let zoom = 0; zoom <= maxZoom; zoom += 1) { - if (typeof zoomPrecisionMap.get(zoom) === 'number') { - continue; - } - - const worldPixels = 256 * Math.pow(2, zoom); - - zoomPrecisionMap.set(zoom, 1); - - for (let precision = 2; precision <= defaultMaxPrecision; precision += 1) { - const columns = geohashColumns(precision); - - if (worldPixels / columns >= minGeoHashPixels) { - zoomPrecisionMap.set(zoom, precision); - } else { - break; - } - } - } - - return zoomPrecisionMap; -}; - -export function zoomToPrecision(mapZoom: number, maxPrecision: number, maxZoom: number) { - const zoomPrecisionMap = calculateZoomToPrecisionMap(typeof maxZoom === 'number' ? maxZoom : 21); - const precision = zoomPrecisionMap.get(mapZoom); - - return precision ? Math.min(precision, maxPrecision) : maxPrecision; -} diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts deleted file mode 100644 index 63b3c3845f549..0000000000000 --- a/src/plugins/maps_legacy/public/plugin.ts +++ /dev/null @@ -1,61 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// @ts-ignore -import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public'; -// @ts-ignore -import { - setToasts, - setUiSettings, - setMapsEmsConfig, - setGetServiceSettings, -} from './kibana_services'; -// @ts-ignore -import { getPrecision, getZoomPrecision } from './map/precision'; -import { MapsLegacyPluginSetup, MapsLegacyPluginStart } from './index'; -import { MapsLegacyConfig } from '../config'; -// @ts-ignore -import { BaseMapsVisualizationProvider } from './map/base_maps_visualization'; -import type { MapsEmsPluginSetup } from '../../maps_ems/public'; - -/** - * These are the interfaces with your public contracts. You should export these - * for other plugins to use in _their_ `SetupDeps`/`StartDeps` interfaces. - * @public - */ - -export interface MapsLegacySetupDependencies { - mapsEms: MapsEmsPluginSetup; -} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface MapsLegacyStartDependencies {} - -export class MapsLegacyPlugin implements Plugin { - readonly _initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this._initializerContext = initializerContext; - } - - public setup(core: CoreSetup, plugins: MapsLegacySetupDependencies) { - setToasts(core.notifications.toasts); - setUiSettings(core.uiSettings); - setMapsEmsConfig(plugins.mapsEms.config); - setGetServiceSettings(plugins.mapsEms.getServiceSettings); - - const getBaseMapsVis = () => new BaseMapsVisualizationProvider(); - - return { - getZoomPrecision, - getPrecision, - getBaseMapsVis, - }; - } - - public start(core: CoreStart, plugins: MapsLegacyStartDependencies) {} -} diff --git a/src/plugins/maps_legacy/public/tooltip_provider.d.ts b/src/plugins/maps_legacy/public/tooltip_provider.d.ts deleted file mode 100644 index 33a17cc472d6c..0000000000000 --- a/src/plugins/maps_legacy/public/tooltip_provider.d.ts +++ /dev/null @@ -1,9 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export function mapTooltipProvider(element: unknown, formatter: unknown): () => unknown; diff --git a/src/plugins/maps_legacy/public/tooltip_provider.js b/src/plugins/maps_legacy/public/tooltip_provider.js deleted file mode 100644 index d774f19be39a8..0000000000000 --- a/src/plugins/maps_legacy/public/tooltip_provider.js +++ /dev/null @@ -1,32 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React from 'react'; -import ReactDOMServer from 'react-dom/server'; - -function getToolTipContent(details) { - return ReactDOMServer.renderToStaticMarkup( - - - {details.map((detail, i) => ( - - - - - ))} - -
{detail.label}{detail.value}
- ); -} - -export function mapTooltipProvider(element, formatter) { - return (...args) => { - const details = formatter(...args); - return details && getToolTipContent(details); - }; -} diff --git a/src/plugins/maps_legacy/server/index.ts b/src/plugins/maps_legacy/server/index.ts deleted file mode 100644 index 57a7bfdd1828f..0000000000000 --- a/src/plugins/maps_legacy/server/index.ts +++ /dev/null @@ -1,43 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Plugin, PluginConfigDescriptor } from 'kibana/server'; -import { CoreSetup, PluginInitializerContext } from 'src/core/server'; -import { configSchema, MapsLegacyConfig } from '../config'; -import { getUiSettings } from './ui_settings'; - -export const config: PluginConfigDescriptor = { - exposeToBrowser: {}, - schema: configSchema, -}; - -export interface MapsLegacyPluginSetup { - config: MapsLegacyConfig; -} - -export class MapsLegacyPlugin implements Plugin { - readonly _initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this._initializerContext = initializerContext; - } - - public setup(core: CoreSetup) { - core.uiSettings.register(getUiSettings()); - - const pluginConfig = this._initializerContext.config.get(); - return { - config: pluginConfig, - }; - } - - public start() {} -} - -export const plugin = (initializerContext: PluginInitializerContext) => - new MapsLegacyPlugin(initializerContext); diff --git a/src/plugins/maps_legacy/server/ui_settings.ts b/src/plugins/maps_legacy/server/ui_settings.ts deleted file mode 100644 index fe516de822149..0000000000000 --- a/src/plugins/maps_legacy/server/ui_settings.ts +++ /dev/null @@ -1,102 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { UiSettingsParams } from 'kibana/server'; -import { schema } from '@kbn/config-schema'; - -export function getUiSettings(): Record> { - return { - 'visualization:tileMap:maxPrecision': { - name: i18n.translate('maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionTitle', { - defaultMessage: 'Maximum tile map precision', - }), - value: 7, - description: i18n.translate( - 'maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionText', - { - defaultMessage: - 'The maximum geoHash precision displayed on tile maps: 7 is high, 10 is very high, 12 is the max. {cellDimensionsLink}', - description: - 'Part of composite text: maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionText + ' + - 'maps_legacy.advancedSettings.visualization.tileMap.maxPrecision.cellDimensionsLinkText', - values: { - cellDimensionsLink: - `` + - i18n.translate( - 'maps_legacy.advancedSettings.visualization.tileMap.maxPrecision.cellDimensionsLinkText', - { - defaultMessage: 'Explanation of cell dimensions', - } - ) + - '', - }, - } - ), - schema: schema.number(), - category: ['visualization'], - }, - 'visualization:tileMap:WMSdefaults': { - name: i18n.translate('maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsTitle', { - defaultMessage: 'Default WMS properties', - }), - value: JSON.stringify( - { - enabled: false, - url: '', - options: { - version: '', - layers: '', - format: 'image/png', - transparent: true, - attribution: '', - styles: '', - }, - }, - null, - 2 - ), - type: 'json', - description: i18n.translate( - 'maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsText', - { - defaultMessage: - 'Default {propertiesLink} for the WMS map server support in the coordinate map', - description: - 'Part of composite text: maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsText + ' + - 'maps_legacy.advancedSettings.visualization.tileMap.wmsDefaults.propertiesLinkText', - values: { - propertiesLink: - '' + - i18n.translate( - 'maps_legacy.advancedSettings.visualization.tileMap.wmsDefaults.propertiesLinkText', - { - defaultMessage: 'properties', - } - ) + - '', - }, - } - ), - schema: schema.object({ - enabled: schema.boolean(), - url: schema.string(), - options: schema.object({ - version: schema.string(), - layers: schema.string(), - format: schema.string(), - transparent: schema.boolean(), - attribution: schema.string(), - styles: schema.string(), - }), - }), - category: ['visualization'], - }, - }; -} diff --git a/src/plugins/maps_legacy/tsconfig.json b/src/plugins/maps_legacy/tsconfig.json deleted file mode 100644 index b6fcb9345b1ce..0000000000000 --- a/src/plugins/maps_legacy/tsconfig.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "./target/types", - "emitDeclarationOnly": true, - "declaration": true, - "declarationMap": true - }, - "include": ["public/**/*", "server/**/*", "config.ts"], - "references": [ - { "path": "../vis_default_editor/tsconfig.json" }, - { "path": "../maps_ems/tsconfig.json" } - ] -} diff --git a/src/plugins/region_map/README.md b/src/plugins/region_map/README.md deleted file mode 100644 index 540ab47c102d3..0000000000000 --- a/src/plugins/region_map/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Region map visualization - -Create choropleth maps. Display the results of a term-aggregation as e.g. countries, zip-codes, states. - -This plugin is targeted for removal in 8.0. \ No newline at end of file diff --git a/src/plugins/region_map/jest.config.js b/src/plugins/region_map/jest.config.js deleted file mode 100644 index 1107c994c0443..0000000000000 --- a/src/plugins/region_map/jest.config.js +++ /dev/null @@ -1,13 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/src/plugins/region_map'], -}; diff --git a/src/plugins/region_map/kibana.json b/src/plugins/region_map/kibana.json deleted file mode 100644 index 1a24b6f8f05e8..0000000000000 --- a/src/plugins/region_map/kibana.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "id": "regionMap", - "owner": { - "name": "GIS", - "githubTeam": "kibana-gis" - }, - "version": "8.0.0", - "kibanaVersion": "kibana", - "ui": true, - "server": true, - "requiredPlugins": [ - "visualizations", - "expressions", - "mapsLegacy", - "mapsEms", - "kibanaLegacy", - "data", - "share" - ], - "requiredBundles": ["kibanaUtils", "charts", "visDefaultEditor"] -} diff --git a/src/plugins/region_map/package.json b/src/plugins/region_map/package.json deleted file mode 100644 index 609ab2706f9c0..0000000000000 --- a/src/plugins/region_map/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "region_map", - "version": "kibana" -} \ No newline at end of file diff --git a/src/plugins/region_map/public/__snapshots__/region_map_fn.test.ts.snap b/src/plugins/region_map/public/__snapshots__/region_map_fn.test.ts.snap deleted file mode 100644 index df72e75f5ad6b..0000000000000 --- a/src/plugins/region_map/public/__snapshots__/region_map_fn.test.ts.snap +++ /dev/null @@ -1,55 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`interpreter/functions#regionmap returns an object with the correct structure 1`] = ` -Object { - "as": "region_map_vis", - "type": "render", - "value": Object { - "visConfig": Object { - "addTooltip": true, - "colorSchema": "Yellow to Red", - "emsHotLink": "", - "isDisplayWarning": true, - "legendPosition": "bottomright", - "mapCenter": Array [ - 0, - 0, - ], - "mapZoom": 2, - "metric": Object { - "accessor": 0, - "aggType": "count", - "format": Object { - "id": "number", - }, - "params": Object {}, - }, - "outlineWeight": 1, - "selectedJoinField": null, - "showAllShapes": true, - "wms": Object { - "enabled": false, - "options": Object { - "format": "image/png", - "transparent": true, - }, - }, - }, - "visData": Object { - "columns": Array [ - Object { - "id": "col-0-1", - "name": "Count", - }, - ], - "rows": Array [ - Object { - "col-0-1": 0, - }, - ], - "type": "datatable", - }, - "visType": "region_map", - }, -} -`; diff --git a/src/plugins/region_map/public/choropleth_layer.js b/src/plugins/region_map/public/choropleth_layer.js deleted file mode 100644 index fe4dcb0432a13..0000000000000 --- a/src/plugins/region_map/public/choropleth_layer.js +++ /dev/null @@ -1,500 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import $ from 'jquery'; -import _ from 'lodash'; -import d3 from 'd3'; -import { i18n } from '@kbn/i18n'; -import * as topojson from 'topojson-client'; -import { getNotifications } from './kibana_services'; -import { colorUtil, KibanaMapLayer } from '../../maps_legacy/public'; -import { truncatedColorMaps } from '../../charts/public'; - -const EMPTY_STYLE = { - weight: 1, - opacity: 0.6, - color: 'rgb(200,200,200)', - fillOpacity: 0, -}; - -export class ChoroplethLayer extends KibanaMapLayer { - static _doInnerJoin(sortedMetrics, sortedGeojsonFeatures, joinField) { - let j = 0; - for (let i = 0; i < sortedGeojsonFeatures.length; i++) { - const property = sortedGeojsonFeatures[i].properties[joinField]; - sortedGeojsonFeatures[i].__kbnJoinedMetric = null; - const position = sortedMetrics.length - ? compareLexicographically(property, sortedMetrics[j].term) - : -1; - if (position === -1) { - //just need to cycle on - } else if (position === 0) { - sortedGeojsonFeatures[i].__kbnJoinedMetric = sortedMetrics[j]; - } else if (position === 1) { - //needs to catch up - while (j < sortedMetrics.length) { - const newTerm = sortedMetrics[j].term; - const newPosition = compareLexicographically(newTerm, property); - if (newPosition === -1) { - //not far enough - } else if (newPosition === 0) { - sortedGeojsonFeatures[i].__kbnJoinedMetric = sortedMetrics[j]; - break; - } else if (newPosition === 1) { - //too far! - break; - } - if (j === sortedMetrics.length - 1) { - //always keep a reference to the last metric - break; - } else { - j++; - } - } - } - } - } - - constructor( - name, - attribution, - format, - showAllShapes, - meta, - layerConfig, - serviceSettings, - leaflet - ) { - super(); - this._serviceSettings = serviceSettings; - this._metrics = null; - this._joinField = null; - this._colorRamp = truncatedColorMaps[Object.keys(truncatedColorMaps)[0]].value; - this._lineWeight = 1; - this._tooltipFormatter = () => ''; - this._attribution = attribution; - this._boundsOfData = null; - this._showAllShapes = showAllShapes; - this._layerName = name; - this._layerConfig = layerConfig; - this._leaflet = leaflet; - - // eslint-disable-next-line no-undef - this._leafletLayer = this._leaflet.geoJson(null, { - onEachFeature: (feature, layer) => { - layer.on('click', () => { - this.emit('select', feature.properties[this._joinField]); - }); - let location = null; - layer.on({ - mouseover: () => { - const tooltipContents = this._tooltipFormatter(feature); - if (!location) { - // eslint-disable-next-line no-undef - const leafletGeojson = this._leaflet.geoJson(feature); - location = leafletGeojson.getBounds().getCenter(); - } - this.emit('showTooltip', { - content: tooltipContents, - position: location, - }); - }, - mouseout: () => { - this.emit('hideTooltip'); - }, - }); - }, - style: this._makeEmptyStyleFunction(), - }); - - this._loaded = false; - this._error = false; - this._isJoinValid = false; - this._whenDataLoaded = new Promise(async (resolve) => { - try { - const data = await this._makeJsonAjaxCall(); - let featureCollection; - let formatType; - if (typeof format === 'string') { - formatType = format; - } else if (format && format.type) { - formatType = format.type; - } else { - formatType = 'geojson'; - } - - if (formatType === 'geojson') { - featureCollection = data; - } else if (formatType === 'topojson') { - const features = _.get(data, 'objects.' + meta.feature_collection_path); - featureCollection = topojson.feature(data, features); //conversion to geojson - } else { - //should never happen - throw new Error( - i18n.translate('regionMap.choroplethLayer.unrecognizedFormatErrorMessage', { - defaultMessage: 'Unrecognized format {formatType}', - values: { formatType }, - }) - ); - } - this._sortedFeatures = featureCollection.features.slice(); - this._sortFeatures(); - - if (showAllShapes) { - this._leafletLayer.addData(featureCollection); - } else { - //we need to delay adding the data until we have performed the join and know which features - //should be displayed - } - this._loaded = true; - this._setStyle(); - resolve(); - } catch (e) { - this._loaded = true; - this._error = true; - - let errorMessage; - if (e.status === 404) { - errorMessage = i18n.translate( - 'regionMap.choroplethLayer.downloadingVectorData404ErrorMessage', - { - defaultMessage: - "Server responding with '404' when attempting to fetch {name}. \ -Make sure the file exists at that location.", - values: { name: name }, - } - ); - } else { - errorMessage = i18n.translate( - 'regionMap.choroplethLayer.downloadingVectorDataErrorMessage', - { - defaultMessage: - 'Cannot download {name} file. Please ensure the \ -CORS configuration of the server permits requests from the Kibana application on this host.', - values: { name: name }, - } - ); - } - - getNotifications().toasts.addDanger({ - title: i18n.translate( - 'regionMap.choroplethLayer.downloadingVectorDataErrorMessageTitle', - { - defaultMessage: 'Error downloading vector data', - } - ), - text: errorMessage, - }); - - resolve(); - } - }); - } - - //This method is stubbed in the tests to avoid network request during unit tests. - async _makeJsonAjaxCall() { - return this._serviceSettings.getJsonForRegionLayer(this._layerConfig); - } - - _invalidateJoin() { - this._isJoinValid = false; - } - - _doInnerJoin() { - ChoroplethLayer._doInnerJoin(this._metrics, this._sortedFeatures, this._joinField); - this._isJoinValid = true; - } - - _setStyle() { - if (this._error || !this._loaded || !this._metrics || !this._joinField) { - return; - } - - if (!this._isJoinValid) { - this._doInnerJoin(); - if (!this._showAllShapes) { - const featureCollection = { - type: 'FeatureCollection', - features: this._sortedFeatures.filter((feature) => feature.__kbnJoinedMetric), - }; - this._leafletLayer.addData(featureCollection); - } - } - - const styler = this._makeChoroplethStyler(); - this._leafletLayer.setStyle(styler.leafletStyleFunction); - - if (this._metrics && this._metrics.length > 0) { - const { min, max } = getMinMax(this._metrics); - this._legendColors = colorUtil.getLegendColors(this._colorRamp); - const quantizeDomain = min !== max ? [min, max] : d3.scale.quantize().domain(); - this._legendQuantizer = d3.scale.quantize().domain(quantizeDomain).range(this._legendColors); - } - this._boundsOfData = styler.getLeafletBounds(); - this.emit('styleChanged', { - mismatches: styler.getMismatches(), - }); - } - - getUrl() { - return this._layerName; - } - - setTooltipFormatter(tooltipFormatter, fieldFormatter, fieldName, metricLabel) { - this._tooltipFormatter = (geojsonFeature) => { - if (!this._metrics) { - return ''; - } - const match = this._metrics.find((bucket) => { - return ( - compareLexicographically(bucket.term, geojsonFeature.properties[this._joinField]) === 0 - ); - }); - return tooltipFormatter(match, fieldFormatter, fieldName, metricLabel); - }; - } - - setJoinField(joinfield) { - if (joinfield === this._joinField) { - return; - } - this._joinField = joinfield; - this._sortFeatures(); - this._setStyle(); - } - - cloneChoroplethLayerForNewData( - name, - attribution, - format, - showAllData, - meta, - layerConfig, - serviceSettings, - leaflet - ) { - const clonedLayer = new ChoroplethLayer( - name, - attribution, - format, - showAllData, - meta, - layerConfig, - serviceSettings, - leaflet - ); - clonedLayer.setJoinField(this._joinField); - clonedLayer.setColorRamp(this._colorRamp); - clonedLayer.setLineWeight(this._lineWeight); - clonedLayer.setTooltipFormatter(this._tooltipFormatter); - if (this._metrics) { - clonedLayer.setMetrics(this._metrics, this._valueFormatter, this._metricTitle); - } - return clonedLayer; - } - - _sortFeatures() { - if (this._sortedFeatures && this._joinField) { - this._sortedFeatures.sort((a, b) => { - const termA = a.properties[this._joinField]; - const termB = b.properties[this._joinField]; - return compareLexicographically(termA, termB); - }); - this._invalidateJoin(); - } - } - - whenDataLoaded() { - return this._whenDataLoaded; - } - - setMetrics(metrics, fieldFormatter, metricTitle) { - this._metrics = metrics.slice(); - this._valueFormatter = fieldFormatter; - this._metricTitle = metricTitle; - - this._metrics.sort((a, b) => compareLexicographically(a.term, b.term)); - this._invalidateJoin(); - this._setStyle(); - } - - setColorRamp(colorRamp) { - if (_.isEqual(colorRamp, this._colorRamp)) { - return; - } - this._colorRamp = colorRamp; - this._setStyle(); - } - - setLineWeight(lineWeight) { - if (this._lineWeight === lineWeight) { - return; - } - this._lineWeight = lineWeight; - this._setStyle(); - } - - canReuseInstance(name, showAllShapes) { - return this._layerName === name && this._showAllShapes === showAllShapes; - } - - canReuseInstanceForNewMetrics(name, showAllShapes, newMetrics) { - if (this._layerName !== name) { - return false; - } - - if (showAllShapes) { - return this._showAllShapes === showAllShapes; - } - - if (!this._metrics) { - return; - } - - const currentKeys = Object.keys(this._metrics); - const newKeys = Object.keys(newMetrics); - return _.isEqual(currentKeys, newKeys); - } - - getBounds() { - const bounds = super.getBounds(); - return this._boundsOfData ? this._boundsOfData : bounds; - } - - appendLegendContents(jqueryDiv) { - if (!this._legendColors || !this._legendQuantizer) { - return; - } - - const titleText = this._metricTitle; - const $title = $('
').addClass('visMapLegend__title').text(titleText); - jqueryDiv.append($title); - - this._legendColors.forEach((color) => { - const labelText = this._legendQuantizer - .invertExtent(color) - .map((val) => { - return this._valueFormatter.convert(val); - }) - .join(' – '); - - const label = $('
'); - const icon = $('').css({ - background: color, - 'border-color': makeColorDarker(color), - }); - - const text = $('').text(labelText); - label.append(icon); - label.append(text); - - jqueryDiv.append(label); - }); - } - - _makeEmptyStyleFunction() { - const emptyStyle = _.assign({}, EMPTY_STYLE, { - weight: this._lineWeight, - }); - - return () => { - return emptyStyle; - }; - } - - _makeChoroplethStyler() { - const emptyStyle = this._makeEmptyStyleFunction(); - if (this._metrics.length === 0) { - return { - leafletStyleFunction: () => { - return emptyStyle(); - }, - getMismatches: () => { - return []; - }, - getLeafletBounds: () => { - return null; - }, - }; - } - - const { min, max } = getMinMax(this._metrics); - - // eslint-disable-next-line no-undef - const boundsOfAllFeatures = new this._leaflet.LatLngBounds(); - return { - leafletStyleFunction: (geojsonFeature) => { - const match = geojsonFeature.__kbnJoinedMetric; - if (!match) { - return emptyStyle(); - } - // eslint-disable-next-line no-undef - const boundsOfFeature = this._leaflet.geoJson(geojsonFeature).getBounds(); - boundsOfAllFeatures.extend(boundsOfFeature); - - return { - fillColor: getChoroplethColor(match.value, min, max, this._colorRamp), - weight: this._lineWeight, - opacity: 1, - color: 'white', - fillOpacity: 0.7, - }; - }, - /** - * should not be called until getLeafletStyleFunction has been called - * @return {Array} - */ - getMismatches: () => { - const mismatches = this._metrics.slice(); - this._sortedFeatures.forEach((feature) => { - const index = mismatches.indexOf(feature.__kbnJoinedMetric); - if (index >= 0) { - mismatches.splice(index, 1); - } - }); - return mismatches.map((b) => b.term); - }, - getLeafletBounds: function () { - return boundsOfAllFeatures.isValid() ? boundsOfAllFeatures : null; - }, - }; - } -} - -//lexicographic compare -function compareLexicographically(termA, termB) { - termA = typeof termA === 'string' ? termA : termA.toString(); - termB = typeof termB === 'string' ? termB : termB.toString(); - return termA.localeCompare(termB); -} - -function makeColorDarker(color) { - const amount = 1.3; //magic number, carry over from earlier - return d3.hcl(color).darker(amount).toString(); -} - -function getMinMax(data) { - let min = data[0].value; - let max = data[0].value; - for (let i = 1; i < data.length; i += 1) { - min = Math.min(data[i].value, min); - max = Math.max(data[i].value, max); - } - return { min, max }; -} - -function getChoroplethColor(value, min, max, colorRamp) { - if (min === max) { - return colorUtil.getColor(colorRamp, colorRamp.length - 1); - } - const fraction = (value - min) / (max - min); - const index = Math.round(colorRamp.length * fraction) - 1; - const i = Math.max(Math.min(colorRamp.length - 1, index), 0); - - return colorUtil.getColor(colorRamp, i); -} diff --git a/src/plugins/region_map/public/components/index.tsx b/src/plugins/region_map/public/components/index.tsx deleted file mode 100644 index 55e26ec311c41..0000000000000 --- a/src/plugins/region_map/public/components/index.tsx +++ /dev/null @@ -1,18 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { lazy } from 'react'; -import { IServiceSettings } from 'src/plugins/maps_ems/public'; -import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; -import { RegionMapVisParams } from '../region_map_types'; - -const RegionMapOptions = lazy(() => import('./region_map_options')); - -export const createRegionMapOptions = (getServiceSettings: () => Promise) => ( - props: VisEditorOptionsProps -) => ; diff --git a/src/plugins/region_map/public/components/region_map_options.tsx b/src/plugins/region_map/public/components/region_map_options.tsx deleted file mode 100644 index e3be8f9dcec09..0000000000000 --- a/src/plugins/region_map/public/components/region_map_options.tsx +++ /dev/null @@ -1,211 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useCallback, useMemo } from 'react'; -import { EuiIcon, EuiLink, EuiPanel, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; -import { truncatedColorSchemas } from '../../../charts/public'; -import { FileLayerField, VectorLayer, IServiceSettings } from '../../../maps_ems/public'; -import { SelectOption, SwitchOption, NumberInputOption } from '../../../vis_default_editor/public'; -import { WmsOptions } from '../../../maps_legacy/public'; -import { RegionMapVisParams } from '../region_map_types'; -import { getTmsLayers, getVectorLayers } from '../kibana_services'; - -const mapLayerForOption = ({ layerId, name }: VectorLayer) => ({ - text: name, - value: layerId, -}); - -const mapFieldForOption = ({ description, name }: FileLayerField) => ({ - text: description, - value: name, -}); - -const tmsLayers = getTmsLayers(); -const vectorLayers = getVectorLayers(); -const vectorLayerOptions = vectorLayers.map(mapLayerForOption); - -export type RegionMapOptionsProps = { - getServiceSettings: () => Promise; -} & VisEditorOptionsProps; - -function RegionMapOptions(props: RegionMapOptionsProps) { - const { getServiceSettings, stateParams, setValue } = props; - const fieldOptions = useMemo( - () => - ((stateParams.selectedLayer && stateParams.selectedLayer.fields) || []).map( - mapFieldForOption - ), - [stateParams.selectedLayer] - ); - - const setEmsHotLink = useCallback( - async (layer: VectorLayer) => { - const serviceSettings = await getServiceSettings(); - const emsHotLink = await serviceSettings.getEMSHotLink(layer); - setValue('emsHotLink', emsHotLink); - }, - [setValue, getServiceSettings] - ); - - const setLayer = useCallback( - async (paramName: 'selectedLayer', value: VectorLayer['layerId']) => { - const newLayer = vectorLayers.find(({ layerId }: VectorLayer) => layerId === value); - - if (newLayer) { - setValue(paramName, newLayer); - setValue('selectedJoinField', newLayer.fields[0]); - setEmsHotLink(newLayer); - } - }, - [setEmsHotLink, setValue] - ); - - const setField = useCallback( - (paramName: 'selectedJoinField', value: FileLayerField['name']) => { - if (stateParams.selectedLayer) { - setValue( - paramName, - stateParams.selectedLayer.fields.find((f) => f.name === value) - ); - } - }, - [setValue, stateParams.selectedLayer] - ); - - return ( - <> - - -

- -

-
- - - - - {' '} - - - - ) - } - options={vectorLayerOptions} - paramName="selectedLayer" - value={stateParams.selectedLayer && stateParams.selectedLayer.layerId} - setValue={setLayer} - /> - - - - - - -
- - - - - -

- -

-
- - - - - -
- - - - - - ); -} - -// default export required for React.Lazy -// eslint-disable-next-line import/no-default-export -export { RegionMapOptions as default }; diff --git a/src/plugins/region_map/public/get_deprecation_message.tsx b/src/plugins/region_map/public/get_deprecation_message.tsx deleted file mode 100644 index 2606c8ed108e2..0000000000000 --- a/src/plugins/region_map/public/get_deprecation_message.tsx +++ /dev/null @@ -1,73 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { getQueryService, getShareService } from './kibana_services'; -import { Vis } from '../../visualizations/public'; -import { LegacyMapDeprecationMessage } from '../../maps_legacy/public'; - -function getEmsLayerId(id: string | number, layerId: string) { - if (typeof id === 'string') { - return id; - } - - // Region maps from 6.x will have numerical EMS id refering to S3 bucket id. - // In this case, use layerId with contains the EMS layer name. - const split = layerId.split('.'); - return split.length === 2 ? split[1] : undefined; -} - -export function getDeprecationMessage(vis: Vis) { - const title = i18n.translate('regionMap.mapVis.regionMapTitle', { defaultMessage: 'Region Map' }); - - async function onClick(e: React.MouseEvent) { - e.preventDefault(); - - const locator = getShareService().url.locators.get('MAPS_APP_REGION_MAP_LOCATOR'); - if (!locator) return; - - const query = getQueryService(); - const params: { [key: string]: any } = { - label: vis.title ? vis.title : title, - emsLayerId: vis.params.selectedLayer.isEMS - ? getEmsLayerId(vis.params.selectedLayer.id, vis.params.selectedLayer.layerId) - : undefined, - leftFieldName: vis.params.selectedLayer.isEMS ? vis.params.selectedJoinField.name : undefined, - colorSchema: vis.params.colorSchema, - indexPatternId: vis.data.indexPattern?.id, - indexPatternTitle: vis.data.indexPattern?.title, - metricAgg: 'count', - filters: query.filterManager.getFilters(), - query: query.queryString.getQuery(), - timeRange: query.timefilter.timefilter.getTime(), - }; - - const bucketAggs = vis.data?.aggs?.byType('buckets'); - if (bucketAggs?.length && bucketAggs[0].type.dslName === 'terms') { - params.termsFieldName = bucketAggs[0].getField()?.name; - params.termsSize = bucketAggs[0].getParam('size'); - } - - const metricAggs = vis.data?.aggs?.byType('metrics'); - if (metricAggs?.length) { - params.metricAgg = metricAggs[0].type.dslName; - params.metricFieldName = metricAggs[0].getField()?.name; - } - - locator.navigate(params); - } - - return ( - - ); -} diff --git a/src/plugins/region_map/public/index.ts b/src/plugins/region_map/public/index.ts deleted file mode 100644 index b2b0f38e6e96d..0000000000000 --- a/src/plugins/region_map/public/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { PluginInitializerContext } from 'kibana/public'; -import { RegionMapPlugin as Plugin } from './plugin'; - -export interface RegionMapsConfigType { - includeElasticMapsService: boolean; - layers: any[]; -} - -export function plugin(initializerContext: PluginInitializerContext) { - return new Plugin(initializerContext); -} diff --git a/src/plugins/region_map/public/kibana_services.ts b/src/plugins/region_map/public/kibana_services.ts deleted file mode 100644 index 030d021006d98..0000000000000 --- a/src/plugins/region_map/public/kibana_services.ts +++ /dev/null @@ -1,39 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { CoreStart } from 'kibana/public'; -import { NotificationsStart } from 'kibana/public'; -import { createGetterSetter } from '../../kibana_utils/public'; -import { DataPublicPluginStart } from '../../data/public'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; -import { SharePluginStart } from '../../share/public'; -import { VectorLayer, TmsLayer } from '../../maps_ems/public'; - -export const [getCoreService, setCoreService] = createGetterSetter('Core'); - -export const [getFormatService, setFormatService] = createGetterSetter< - DataPublicPluginStart['fieldFormats'] ->('data.fieldFormats'); - -export const [getNotifications, setNotifications] = createGetterSetter( - 'Notifications' -); - -export const [getQueryService, setQueryService] = createGetterSetter< - DataPublicPluginStart['query'] ->('Query'); - -export const [getShareService, setShareService] = createGetterSetter('Share'); - -export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( - 'KibanaLegacy' -); - -export const [getTmsLayers, setTmsLayers] = createGetterSetter('TmsLayers'); - -export const [getVectorLayers, setVectorLayers] = createGetterSetter('VectorLayers'); diff --git a/src/plugins/region_map/public/plugin.ts b/src/plugins/region_map/public/plugin.ts deleted file mode 100644 index 724404849aea8..0000000000000 --- a/src/plugins/region_map/public/plugin.ts +++ /dev/null @@ -1,120 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - CoreSetup, - CoreStart, - Plugin, - PluginInitializerContext, - IUiSettingsClient, - NotificationsStart, -} from 'kibana/public'; -import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; -// @ts-ignore -import { createRegionMapFn } from './region_map_fn'; -// @ts-ignore -import { createRegionMapTypeDefinition } from './region_map_type'; -import { MapsLegacyPluginSetup } from '../../maps_legacy/public'; -import { IServiceSettings, MapsEmsPluginSetup } from '../../maps_ems/public'; -import { - setCoreService, - setFormatService, - setNotifications, - setKibanaLegacy, - setQueryService, - setShareService, -} from './kibana_services'; -import { DataPublicPluginStart } from '../../data/public'; -import { RegionMapsConfigType } from './index'; -import { MapsLegacyConfig } from '../../maps_legacy/config'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; -import { SharePluginStart } from '../../share/public'; -import { getRegionMapRenderer } from './region_map_renderer'; - -/** @private */ -export interface RegionMapVisualizationDependencies { - uiSettings: IUiSettingsClient; - regionmapsConfig: RegionMapsConfig; - getServiceSettings: () => Promise; - BaseMapsVisualization: any; -} - -/** @internal */ -export interface RegionMapPluginSetupDependencies { - expressions: ReturnType; - visualizations: VisualizationsSetup; - mapsLegacy: MapsLegacyPluginSetup; - mapsEms: MapsEmsPluginSetup; -} - -/** @internal */ -export interface RegionMapPluginStartDependencies { - data: DataPublicPluginStart; - notifications: NotificationsStart; - kibanaLegacy: KibanaLegacyStart; - share: SharePluginStart; -} - -/** @internal */ -export interface RegionMapsConfig { - includeElasticMapsService: boolean; - layers: any[]; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface RegionMapPluginSetup {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface RegionMapPluginStart {} - -/** @internal */ -export class RegionMapPlugin implements Plugin { - readonly _initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this._initializerContext = initializerContext; - } - - public setup( - core: CoreSetup, - { expressions, visualizations, mapsLegacy, mapsEms }: RegionMapPluginSetupDependencies - ) { - const config = { - ...this._initializerContext.config.get(), - // The maps legacy plugin updates the regionmap config directly in service_settings, - // future work on how configurations across the different plugins are organized would - // ideally constrain regionmap config updates to occur only from this plugin - ...mapsEms.config.regionmap, - }; - const visualizationDependencies: Readonly = { - uiSettings: core.uiSettings, - regionmapsConfig: config as RegionMapsConfig, - getServiceSettings: mapsEms.getServiceSettings, - BaseMapsVisualization: mapsLegacy.getBaseMapsVis(), - }; - - expressions.registerFunction(createRegionMapFn); - expressions.registerRenderer(getRegionMapRenderer(visualizationDependencies)); - - visualizations.createBaseVisualization( - createRegionMapTypeDefinition(visualizationDependencies) - ); - - return {}; - } - - public start(core: CoreStart, plugins: RegionMapPluginStartDependencies) { - setCoreService(core); - setFormatService(plugins.data.fieldFormats); - setQueryService(plugins.data.query); - setNotifications(core.notifications); - setKibanaLegacy(plugins.kibanaLegacy); - setShareService(plugins.share); - return {}; - } -} diff --git a/src/plugins/region_map/public/region_map_fn.test.ts b/src/plugins/region_map/public/region_map_fn.test.ts deleted file mode 100644 index ffb8f22f0aa1c..0000000000000 --- a/src/plugins/region_map/public/region_map_fn.test.ts +++ /dev/null @@ -1,51 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { functionWrapper } from '../../expressions/common/expression_functions/specs/tests/utils'; -import { createRegionMapFn } from './region_map_fn'; - -describe('interpreter/functions#regionmap', () => { - const fn = functionWrapper(createRegionMapFn()); - const context = { - type: 'datatable', - rows: [{ 'col-0-1': 0 }], - columns: [{ id: 'col-0-1', name: 'Count' }], - }; - const visConfig = { - legendPosition: 'bottomright', - addTooltip: true, - colorSchema: 'Yellow to Red', - emsHotLink: '', - selectedJoinField: null, - isDisplayWarning: true, - wms: { - enabled: false, - options: { - format: 'image/png', - transparent: true, - }, - }, - mapZoom: 2, - mapCenter: [0, 0], - outlineWeight: 1, - showAllShapes: true, - metric: { - accessor: 0, - format: { - id: 'number', - }, - params: {}, - aggType: 'count', - }, - }; - - it('returns an object with the correct structure', () => { - const actual = fn(context, { visConfig: JSON.stringify(visConfig) }); - expect(actual).toMatchSnapshot(); - }); -}); diff --git a/src/plugins/region_map/public/region_map_fn.ts b/src/plugins/region_map/public/region_map_fn.ts deleted file mode 100644 index df3471bc92051..0000000000000 --- a/src/plugins/region_map/public/region_map_fn.ts +++ /dev/null @@ -1,63 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -import type { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public'; -import { RegionMapVisConfig } from './region_map_types'; - -interface Arguments { - visConfig: string | null; -} - -export interface RegionMapVisRenderValue { - visData: Datatable; - visType: 'region_map'; - visConfig: RegionMapVisConfig; -} - -export type RegionMapExpressionFunctionDefinition = ExpressionFunctionDefinition< - 'regionmap', - Datatable, - Arguments, - Render ->; - -export const createRegionMapFn = (): RegionMapExpressionFunctionDefinition => ({ - name: 'regionmap', - type: 'render', - context: { - types: ['datatable'], - }, - help: i18n.translate('regionMap.function.help', { - defaultMessage: 'Regionmap visualization', - }), - args: { - visConfig: { - types: ['string', 'null'], - default: '"{}"', - help: '', - }, - }, - fn(context, args, handlers) { - const visConfig = args.visConfig && JSON.parse(args.visConfig); - - if (handlers?.inspectorAdapters?.tables) { - handlers.inspectorAdapters.tables.logDatatable('default', context); - } - return { - type: 'render', - as: 'region_map_vis', - value: { - visData: context, - visType: 'region_map', - visConfig, - }, - }; - }, -}); diff --git a/src/plugins/region_map/public/region_map_renderer.tsx b/src/plugins/region_map/public/region_map_renderer.tsx deleted file mode 100644 index e74a2013daf3b..0000000000000 --- a/src/plugins/region_map/public/region_map_renderer.tsx +++ /dev/null @@ -1,41 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { lazy } from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; - -import { ExpressionRenderDefinition } from 'src/plugins/expressions'; -import { VisualizationContainer } from '../../visualizations/public'; -import { RegionMapVisualizationDependencies } from './plugin'; -import { RegionMapVisRenderValue } from './region_map_fn'; - -const RegionMapVisualization = lazy(() => import('./region_map_visualization_component')); - -export const getRegionMapRenderer: ( - deps: RegionMapVisualizationDependencies -) => ExpressionRenderDefinition = (deps) => ({ - name: 'region_map_vis', - reuseDomNode: true, - render: async (domNode, { visConfig, visData }, handlers) => { - handlers.onDestroy(() => { - unmountComponentAtNode(domNode); - }); - - render( - - - , - domNode - ); - }, -}); diff --git a/src/plugins/region_map/public/region_map_type.ts b/src/plugins/region_map/public/region_map_type.ts deleted file mode 100644 index 5797812be34b0..0000000000000 --- a/src/plugins/region_map/public/region_map_type.ts +++ /dev/null @@ -1,143 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -import { VisTypeDefinition } from '../../visualizations/public'; -import { ORIGIN, VectorLayer } from '../../maps_ems/public'; - -import { getDeprecationMessage } from './get_deprecation_message'; -import { RegionMapVisualizationDependencies } from './plugin'; -import { createRegionMapOptions } from './components'; -import { toExpressionAst } from './to_ast'; -import { RegionMapVisParams } from './region_map_types'; -import { mapToLayerWithId } from './util'; -import { setTmsLayers, setVectorLayers } from './kibana_services'; - -export function createRegionMapTypeDefinition({ - uiSettings, - regionmapsConfig, - getServiceSettings, -}: RegionMapVisualizationDependencies): VisTypeDefinition { - return { - name: 'region_map', - getInfoMessage: getDeprecationMessage, - title: i18n.translate('regionMap.mapVis.regionMapTitle', { defaultMessage: 'Region Map' }), - description: i18n.translate('regionMap.mapVis.regionMapDescription', { - defaultMessage: - 'Show metrics on a thematic map. Use one of the \ -provided base maps, or add your own. Darker colors represent higher values.', - }), - icon: 'visMapRegion', - visConfig: { - defaults: { - legendPosition: 'bottomright', - addTooltip: true, - colorSchema: 'Yellow to Red', - emsHotLink: '', - isDisplayWarning: true, - wms: uiSettings.get('visualization:tileMap:WMSdefaults'), - mapZoom: 2, - mapCenter: [0, 0], - outlineWeight: 1, - showAllShapes: true, // still under consideration - }, - }, - editorConfig: { - optionsTemplate: createRegionMapOptions(getServiceSettings), - schemas: [ - { - group: 'metrics', - name: 'metric', - title: i18n.translate('regionMap.mapVis.regionMapEditorConfig.schemas.metricTitle', { - defaultMessage: 'Value', - }), - min: 1, - max: 1, - aggFilter: [ - 'count', - 'avg', - 'sum', - 'min', - 'max', - 'cardinality', - 'top_hits', - 'sum_bucket', - 'min_bucket', - 'max_bucket', - 'avg_bucket', - ], - defaults: [{ schema: 'metric', type: 'count' }], - }, - { - group: 'buckets', - name: 'segment', - title: i18n.translate('regionMap.mapVis.regionMapEditorConfig.schemas.segmentTitle', { - defaultMessage: 'Shape field', - }), - min: 1, - max: 1, - aggFilter: ['terms'], - }, - ], - }, - toExpressionAst, - setup: async (vis) => { - const serviceSettings = await getServiceSettings(); - const tmsLayers = await serviceSettings.getTMSServices(); - setTmsLayers(tmsLayers); - setVectorLayers([]); - - if (!vis.params.wms.selectedTmsLayer && tmsLayers.length) { - vis.params.wms.selectedTmsLayer = tmsLayers[0]; - } - - const vectorLayers = regionmapsConfig.layers.map( - mapToLayerWithId.bind(null, ORIGIN.KIBANA_YML) - ); - let selectedLayer = vectorLayers[0]; - let selectedJoinField = selectedLayer ? selectedLayer.fields[0] : undefined; - if (regionmapsConfig.includeElasticMapsService) { - const layers = await serviceSettings.getFileLayers(); - const newLayers = layers - .map(mapToLayerWithId.bind(null, ORIGIN.EMS)) - .filter( - (layer: VectorLayer) => - !vectorLayers.some((vectorLayer) => vectorLayer.layerId === layer.layerId) - ); - - // backfill v1 manifest for now - newLayers.forEach((layer: VectorLayer) => { - if (layer.format === 'geojson') { - layer.format = { - type: 'geojson', - }; - } - }); - - const allVectorLayers = [...vectorLayers, ...newLayers]; - setVectorLayers(allVectorLayers); - - [selectedLayer] = allVectorLayers; - selectedJoinField = selectedLayer ? selectedLayer.fields[0] : undefined; - - if (selectedLayer && !vis.params.selectedLayer && selectedLayer.isEMS) { - vis.params.emsHotLink = await serviceSettings.getEMSHotLink(selectedLayer); - } - } - - if (!vis.params.selectedLayer) { - vis.params.selectedLayer = selectedLayer; - vis.params.selectedJoinField = selectedJoinField; - } - - return vis; - }, - requiresSearch: true, - }; -} diff --git a/src/plugins/region_map/public/region_map_types.ts b/src/plugins/region_map/public/region_map_types.ts deleted file mode 100644 index 0a9235f1c82df..0000000000000 --- a/src/plugins/region_map/public/region_map_types.ts +++ /dev/null @@ -1,31 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { SchemaConfig } from 'src/plugins/visualizations/public'; -import { VectorLayer, FileLayerField } from '../../maps_ems/public'; -import { WMSOptions } from '../../maps_legacy/public'; - -export interface RegionMapVisParams { - readonly addTooltip: true; - readonly legendPosition: 'bottomright'; - colorSchema: string; - emsHotLink?: string | null; - mapCenter: [number, number]; - mapZoom: number; - outlineWeight: number | ''; - isDisplayWarning: boolean; - showAllShapes: boolean; - selectedLayer?: VectorLayer; - selectedJoinField?: FileLayerField; - wms: WMSOptions; -} - -export interface RegionMapVisConfig extends RegionMapVisParams { - metric: SchemaConfig; - bucket?: SchemaConfig; -} diff --git a/src/plugins/region_map/public/region_map_visualization.js b/src/plugins/region_map/public/region_map_visualization.js deleted file mode 100644 index 80bee417009a4..0000000000000 --- a/src/plugins/region_map/public/region_map_visualization.js +++ /dev/null @@ -1,239 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { getFormatService, getNotifications, getKibanaLegacy } from './kibana_services'; -import { truncatedColorMaps } from '../../charts/public'; -import { tooltipFormatter } from './tooltip_formatter'; -import { mapTooltipProvider, lazyLoadMapsLegacyModules } from '../../maps_legacy/public'; -import { ORIGIN } from '../../maps_ems/public'; - -export function createRegionMapVisualization({ - regionmapsConfig, - uiSettings, - BaseMapsVisualization, - getServiceSettings, -}) { - return class RegionMapsVisualization extends BaseMapsVisualization { - constructor(container, handlers, initialVisParams) { - super(container, handlers, initialVisParams); - this._choroplethLayer = null; - this._tooltipFormatter = mapTooltipProvider(container, tooltipFormatter); - } - - async render(esResponse, visParams) { - getKibanaLegacy().loadFontAwesome(); - await super.render(esResponse, visParams); - if (this._choroplethLayer) { - await this._choroplethLayer.whenDataLoaded(); - } - } - - async _updateData(table) { - this._chartData = table; - const termColumn = this._params.bucket ? table.columns[this._params.bucket.accessor] : null; - const valueColumn = table.columns[this._params.metric.accessor]; - let results; - if (!this._hasColumns() || !table.rows.length) { - results = []; - } else { - results = table.rows.map((row) => { - const term = row[termColumn.id]; - const value = row[valueColumn.id]; - return { term: term, value: value }; - }); - } - - const selectedLayer = await this._loadConfig(this._params.selectedLayer); - if (!this._params.selectedJoinField && selectedLayer) { - this._params.selectedJoinField = selectedLayer.fields[0]; - } - - if (!selectedLayer) { - return; - } - - await this._updateChoroplethLayerForNewMetrics( - selectedLayer.name, - selectedLayer.attribution, - this._params.showAllShapes, - results - ); - - const metricFieldFormatter = getFormatService().deserialize(this._params.metric.format); - - this._choroplethLayer.setMetrics(results, metricFieldFormatter, valueColumn.name); - if (termColumn && valueColumn) { - this._choroplethLayer.setTooltipFormatter( - this._tooltipFormatter, - metricFieldFormatter, - termColumn.name, - valueColumn.name - ); - } - - this._kibanaMap.useUiStateFromVisualization(this.handlers.uiState); - } - - async _loadConfig(fileLayerConfig) { - // Load the selected layer from the metadata-service. - // 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); - } - - //Configured in the kibana.yml. Needs to be resolved through the settings. - const configuredLayer = regionmapsConfig.layers.find( - (layer) => layer.name === fileLayerConfig.name - ); - - if (configuredLayer) { - return { - ...configuredLayer, - attribution: escape(configuredLayer.attribution ? configuredLayer.attribution : ''), - }; - } - - return null; - } - - async _updateParams() { - await super._updateParams(); - - const selectedLayer = await this._loadConfig(this._params.selectedLayer); - - if (!this._params.selectedJoinField && selectedLayer) { - this._params.selectedJoinField = selectedLayer.fields[0]; - } - - if (!this._params.selectedJoinField || !selectedLayer) { - return; - } - - await this._updateChoroplethLayerForNewProperties( - selectedLayer.name, - selectedLayer.attribution, - this._params.showAllShapes - ); - - const metricFieldFormatter = getFormatService().deserialize(this._params.metric.format); - - this._choroplethLayer.setJoinField(this._params.selectedJoinField.name); - this._choroplethLayer.setColorRamp(truncatedColorMaps[this._params.colorSchema].value); - this._choroplethLayer.setLineWeight(this._params.outlineWeight); - this._choroplethLayer.setTooltipFormatter( - this._tooltipFormatter, - metricFieldFormatter, - this._metricLabel - ); - } - - async _updateChoroplethLayerForNewMetrics(name, attribution, showAllData, newMetrics) { - if ( - this._choroplethLayer && - this._choroplethLayer.canReuseInstanceForNewMetrics(name, showAllData, newMetrics) - ) { - return; - } - await this._recreateChoroplethLayer(name, attribution, showAllData); - } - - async _updateChoroplethLayerForNewProperties(name, attribution, showAllData) { - if (this._choroplethLayer && this._choroplethLayer.canReuseInstance(name, showAllData)) { - return; - } - await this._recreateChoroplethLayer(name, attribution, showAllData); - } - - async _recreateChoroplethLayer(name, attribution, showAllData) { - const selectedLayer = await this._loadConfig(this._params.selectedLayer); - this._kibanaMap.removeLayer(this._choroplethLayer); - - if (this._choroplethLayer) { - this._choroplethLayer = this._choroplethLayer.cloneChoroplethLayerForNewData( - name, - attribution, - selectedLayer.format, - showAllData, - selectedLayer.meta, - selectedLayer, - await getServiceSettings(), - (await lazyLoadMapsLegacyModules()).L - ); - } else { - const { ChoroplethLayer } = await import('./choropleth_layer'); - this._choroplethLayer = new ChoroplethLayer( - name, - attribution, - selectedLayer.format, - showAllData, - selectedLayer.meta, - selectedLayer, - await getServiceSettings(), - (await lazyLoadMapsLegacyModules()).L - ); - } - - this._choroplethLayer.on('select', (event) => { - const { rows, columns } = this._chartData; - const rowIndex = rows.findIndex((row) => row[columns[0].id] === event); - this.handlers.event({ - name: 'filterBucket', - data: { - data: [ - { - table: this._chartData, - column: 0, - row: rowIndex, - value: event, - }, - ], - }, - }); - }); - - this._choroplethLayer.on('styleChanged', (event) => { - const shouldShowWarning = - this._params.isDisplayWarning && uiSettings.get('visualization:regionmap:showWarnings'); - if (event.mismatches.length > 0 && shouldShowWarning) { - getNotifications().toasts.addWarning({ - title: i18n.translate('regionMap.visualization.unableToShowMismatchesWarningTitle', { - defaultMessage: - 'Unable to show {mismatchesLength} {oneMismatch, plural, one {result} other {results}} on map', - values: { - mismatchesLength: event.mismatches.length, - oneMismatch: event.mismatches.length > 1 ? 0 : 1, - }, - }), - text: i18n.translate('regionMap.visualization.unableToShowMismatchesWarningText', { - defaultMessage: - "Ensure that each of these term matches a shape on that shape's join field: {mismatches}", - values: { - mismatches: event.mismatches ? event.mismatches.join(', ') : '', - }, - }), - }); - } - }); - - this._kibanaMap.addLayer(this._choroplethLayer); - } - - _hasColumns() { - return this._chartData && this._chartData.columns.length === 2; - } - }; -} diff --git a/src/plugins/region_map/public/region_map_visualization.scss b/src/plugins/region_map/public/region_map_visualization.scss deleted file mode 100644 index ee593e2fc9c8c..0000000000000 --- a/src/plugins/region_map/public/region_map_visualization.scss +++ /dev/null @@ -1,4 +0,0 @@ -.rgmChart__wrapper, .rgmChart { - flex: 1 1 0; - display: flex; -} diff --git a/src/plugins/region_map/public/region_map_visualization_component.tsx b/src/plugins/region_map/public/region_map_visualization_component.tsx deleted file mode 100644 index cab2294475982..0000000000000 --- a/src/plugins/region_map/public/region_map_visualization_component.tsx +++ /dev/null @@ -1,92 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useEffect, useMemo, useRef } from 'react'; -import { EuiResizeObserver } from '@elastic/eui'; -import { throttle } from 'lodash'; - -import { IInterpreterRenderHandlers, Datatable } from 'src/plugins/expressions'; -import { PersistedState } from 'src/plugins/visualizations/public'; -import { RegionMapVisualizationDependencies } from './plugin'; -import { RegionMapVisConfig } from './region_map_types'; -// @ts-expect-error -import { createRegionMapVisualization } from './region_map_visualization'; - -import './region_map_visualization.scss'; - -interface RegionMapVisController { - render(visData?: Datatable, visConfig?: RegionMapVisConfig): Promise; - resize(): void; - destroy(): void; -} - -interface TileMapVisualizationProps { - deps: RegionMapVisualizationDependencies; - handlers: IInterpreterRenderHandlers; - visData: Datatable; - visConfig: RegionMapVisConfig; -} - -const RegionMapVisualization = ({ - deps, - handlers, - visData, - visConfig, -}: TileMapVisualizationProps) => { - const chartDiv = useRef(null); - const visController = useRef(null); - const isFirstRender = useRef(true); - const uiState = handlers.uiState as PersistedState | undefined; - - useEffect(() => { - if (chartDiv.current && isFirstRender.current) { - isFirstRender.current = false; - const Controller = createRegionMapVisualization(deps); - visController.current = new Controller(chartDiv.current, handlers, visConfig); - } - }, [deps, handlers, visConfig, visData]); - - useEffect(() => { - visController.current?.render(visData, visConfig).then(handlers.done); - }, [visData, visConfig, handlers.done]); - - useEffect(() => { - const onUiStateChange = () => { - visController.current?.render().then(handlers.done); - }; - - uiState?.on('change', onUiStateChange); - - return () => { - uiState?.off('change', onUiStateChange); - }; - }, [uiState, handlers.done]); - - useEffect(() => { - return () => { - visController.current?.destroy(); - visController.current = null; - }; - }, []); - - const updateChartSize = useMemo(() => throttle(() => visController.current?.resize(), 300), []); - - return ( - - {(resizeRef) => ( -
-
-
- )} - - ); -}; - -// default export required for React.Lazy -// eslint-disable-next-line import/no-default-export -export { RegionMapVisualization as default }; diff --git a/src/plugins/region_map/public/to_ast.ts b/src/plugins/region_map/public/to_ast.ts deleted file mode 100644 index b68731cab30bb..0000000000000 --- a/src/plugins/region_map/public/to_ast.ts +++ /dev/null @@ -1,48 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '../../data/public'; -import { buildExpression, buildExpressionFunction } from '../../expressions/public'; -import { getVisSchemas, VisToExpressionAst } from '../../visualizations/public'; -import { RegionMapExpressionFunctionDefinition } from './region_map_fn'; -import { RegionMapVisConfig, RegionMapVisParams } from './region_map_types'; - -export const toExpressionAst: VisToExpressionAst = (vis, params) => { - const esaggs = buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: false, - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); - - const schemas = getVisSchemas(vis, params); - - const visConfig: RegionMapVisConfig = { - ...vis.params, - metric: schemas.metric[0], - }; - - if (schemas.segment) { - visConfig.bucket = schemas.segment[0]; - } - - const regionmap = buildExpressionFunction('regionmap', { - visConfig: JSON.stringify(visConfig), - }); - - const ast = buildExpression([esaggs, regionmap]); - - return ast.toAst(); -}; diff --git a/src/plugins/region_map/public/tooltip_formatter.js b/src/plugins/region_map/public/tooltip_formatter.js deleted file mode 100644 index 101d49b9d88b8..0000000000000 --- a/src/plugins/region_map/public/tooltip_formatter.js +++ /dev/null @@ -1,29 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export function tooltipFormatter(metric, fieldFormatter, fieldName, metricName) { - if (!metric) { - return ''; - } - - const details = []; - if (fieldName && metric) { - details.push({ - label: fieldName, - value: metric.term, - }); - } - - if (metric) { - details.push({ - label: metricName, - value: fieldFormatter ? fieldFormatter.convert(metric.value, 'text') : metric.value, - }); - } - return details; -} diff --git a/src/plugins/region_map/public/util.ts b/src/plugins/region_map/public/util.ts deleted file mode 100644 index 8e15a72b0365d..0000000000000 --- a/src/plugins/region_map/public/util.ts +++ /dev/null @@ -1,15 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FileLayer, VectorLayer, ORIGIN } from '../../maps_ems/public'; - -export const mapToLayerWithId = (prefix: string, layer: FileLayer): VectorLayer => ({ - ...layer, - layerId: `${prefix}.${layer.name}`, - isEMS: ORIGIN.EMS === prefix, -}); diff --git a/src/plugins/region_map/server/index.ts b/src/plugins/region_map/server/index.ts deleted file mode 100644 index eb185c773458b..0000000000000 --- a/src/plugins/region_map/server/index.ts +++ /dev/null @@ -1,18 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { CoreSetup } from 'src/core/server'; -import { getUiSettings } from './ui_settings'; - -export const plugin = () => ({ - setup(core: CoreSetup) { - core.uiSettings.register(getUiSettings()); - }, - - start() {}, -}); diff --git a/src/plugins/region_map/server/ui_settings.ts b/src/plugins/region_map/server/ui_settings.ts deleted file mode 100644 index 30b48064703c2..0000000000000 --- a/src/plugins/region_map/server/ui_settings.ts +++ /dev/null @@ -1,31 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { UiSettingsParams } from 'kibana/server'; -import { schema } from '@kbn/config-schema'; - -export function getUiSettings(): Record> { - return { - 'visualization:regionmap:showWarnings': { - name: i18n.translate('regionMap.advancedSettings.visualization.showRegionMapWarningsTitle', { - defaultMessage: 'Show region map warning', - }), - value: true, - description: i18n.translate( - 'regionMap.advancedSettings.visualization.showRegionMapWarningsText', - { - defaultMessage: - 'Whether the region map shows a warning when terms cannot be joined to a shape on the map.', - } - ), - schema: schema.boolean(), - category: ['visualization'], - }, - }; -} diff --git a/src/plugins/region_map/tsconfig.json b/src/plugins/region_map/tsconfig.json deleted file mode 100644 index fec191402f2ab..0000000000000 --- a/src/plugins/region_map/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "./target/types", - "emitDeclarationOnly": true, - "declaration": true, - "declarationMap": true - }, - "include": ["public/**/*", "server/**/*"], - "references": [ - { "path": "../maps_legacy/tsconfig.json" }, - { "path": "../maps_ems/tsconfig.json" }, - { "path": "../vis_default_editor/tsconfig.json" }, - ] -} diff --git a/src/plugins/tile_map/README.md b/src/plugins/tile_map/README.md deleted file mode 100644 index 633ee7dba46d6..0000000000000 --- a/src/plugins/tile_map/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Coordinate map visualization - -Create a coordinate map. Display the results of a geohash_tile aggregation as bubbles, rectangles, or heatmap color blobs. - -This plugin is targeted for removal in 8.0. \ No newline at end of file diff --git a/src/plugins/tile_map/jest.config.js b/src/plugins/tile_map/jest.config.js deleted file mode 100644 index 7c51c61eca2a4..0000000000000 --- a/src/plugins/tile_map/jest.config.js +++ /dev/null @@ -1,13 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -module.exports = { - preset: '@kbn/test', - rootDir: '../../..', - roots: ['/src/plugins/tile_map'], -}; diff --git a/src/plugins/tile_map/kibana.json b/src/plugins/tile_map/kibana.json deleted file mode 100644 index 48ed613b72cd3..0000000000000 --- a/src/plugins/tile_map/kibana.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "id": "tileMap", - "owner": { - "name": "GIS", - "githubTeam": "kibana-gis" - }, - "version": "8.0.0", - "kibanaVersion": "kibana", - "ui": true, - "server": true, - "requiredPlugins": [ - "visualizations", - "expressions", - "mapsLegacy", - "mapsEms", - "kibanaLegacy", - "data", - "share" - ], - "requiredBundles": ["kibanaUtils", "charts", "visDefaultEditor"] -} diff --git a/src/plugins/tile_map/package.json b/src/plugins/tile_map/package.json deleted file mode 100644 index d9d0359f66048..0000000000000 --- a/src/plugins/tile_map/package.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "tile_map", - "version": "kibana" -} \ No newline at end of file diff --git a/src/plugins/tile_map/public/__snapshots__/tile_map_fn.test.ts.snap b/src/plugins/tile_map/public/__snapshots__/tile_map_fn.test.ts.snap deleted file mode 100644 index 7aab8b02890c0..0000000000000 --- a/src/plugins/tile_map/public/__snapshots__/tile_map_fn.test.ts.snap +++ /dev/null @@ -1,55 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`interpreter/functions#tilemap returns an object with the correct structure 1`] = ` -Object { - "as": "tile_map_vis", - "type": "render", - "value": Object { - "visConfig": Object { - "addTooltip": true, - "colorSchema": "Yellow to Red", - "dimensions": Object { - "geocentroid": null, - "geohash": null, - "metric": Object { - "accessor": 0, - "aggType": "count", - "format": Object { - "id": "number", - }, - "params": Object {}, - }, - }, - "heatClusterSize": 1.5, - "isDesaturated": true, - "legendPosition": "bottomright", - "mapCenter": Array [ - 0, - 0, - ], - "mapType": "Scaled Circle Markers", - "mapZoom": 2, - "wms": Object { - "enabled": false, - "options": Object { - "format": "image/png", - "transparent": true, - }, - }, - }, - "visData": Object { - "featureCollection": Object { - "features": Array [], - "type": "FeatureCollection", - }, - "meta": Object { - "geohashGridDimensionsAtEquator": null, - "geohashPrecision": null, - "max": null, - "min": null, - }, - }, - "visType": "tile_map", - }, -} -`; diff --git a/src/plugins/tile_map/public/components/collections.ts b/src/plugins/tile_map/public/components/collections.ts deleted file mode 100644 index f75d83c4a055f..0000000000000 --- a/src/plugins/tile_map/public/components/collections.ts +++ /dev/null @@ -1,65 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { MapTypes } from '../utils/map_types'; - -export const collections = { - mapTypes: [ - { - value: MapTypes.ScaledCircleMarkers, - text: i18n.translate('tileMap.mapTypes.scaledCircleMarkersText', { - defaultMessage: 'Scaled circle markers', - }), - }, - { - value: MapTypes.ShadedCircleMarkers, - text: i18n.translate('tileMap.mapTypes.shadedCircleMarkersText', { - defaultMessage: 'Shaded circle markers', - }), - }, - { - value: MapTypes.ShadedGeohashGrid, - text: i18n.translate('tileMap.mapTypes.shadedGeohashGridText', { - defaultMessage: 'Shaded geohash grid', - }), - }, - { - value: MapTypes.Heatmap, - text: i18n.translate('tileMap.mapTypes.heatmapText', { - defaultMessage: 'Heatmap', - }), - }, - ], - legendPositions: [ - { - value: 'bottomleft', - text: i18n.translate('tileMap.legendPositions.bottomLeftText', { - defaultMessage: 'Bottom left', - }), - }, - { - value: 'bottomright', - text: i18n.translate('tileMap.legendPositions.bottomRightText', { - defaultMessage: 'Bottom right', - }), - }, - { - value: 'topleft', - text: i18n.translate('tileMap.legendPositions.topLeftText', { - defaultMessage: 'Top left', - }), - }, - { - value: 'topright', - text: i18n.translate('tileMap.legendPositions.topRightText', { - defaultMessage: 'Top right', - }), - }, - ], -}; diff --git a/src/plugins/tile_map/public/components/index.tsx b/src/plugins/tile_map/public/components/index.tsx deleted file mode 100644 index 31c8faec2409d..0000000000000 --- a/src/plugins/tile_map/public/components/index.tsx +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { lazy } from 'react'; -import type { TileMapOptionsProps } from './tile_map_options'; - -const TileMapOptions = lazy(() => import('./tile_map_options')); - -export const TileMapOptionsLazy = (props: TileMapOptionsProps) => ; diff --git a/src/plugins/tile_map/public/components/tile_map_options.tsx b/src/plugins/tile_map/public/components/tile_map_options.tsx deleted file mode 100644 index dbe28f0e2c2dd..0000000000000 --- a/src/plugins/tile_map/public/components/tile_map_options.tsx +++ /dev/null @@ -1,103 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useEffect } from 'react'; -import { EuiPanel, EuiSpacer } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; -import { - BasicOptions, - SelectOption, - SwitchOption, - RangeOption, -} from '../../../vis_default_editor/public'; -import { truncatedColorSchemas } from '../../../charts/public'; -import { WmsOptions } from '../../../maps_legacy/public'; -import { TileMapVisParams } from '../types'; -import { MapTypes } from '../utils/map_types'; -import { getTmsLayers } from '../services'; -import { collections } from './collections'; - -export type TileMapOptionsProps = VisEditorOptionsProps; - -const tmsLayers = getTmsLayers(); - -function TileMapOptions(props: TileMapOptionsProps) { - const { stateParams, setValue, vis } = props; - - useEffect(() => { - if (!stateParams.mapType) { - setValue('mapType', collections.mapTypes[0].value); - } - }, [setValue, stateParams.mapType]); - - return ( - <> - - - - {stateParams.mapType === MapTypes.Heatmap ? ( - - ) : ( - - )} - - - - - - - - - - - ); -} - -// default export required for React.Lazy -// eslint-disable-next-line import/no-default-export -export { TileMapOptions as default }; diff --git a/src/plugins/tile_map/public/css_filters.js b/src/plugins/tile_map/public/css_filters.js deleted file mode 100644 index c1d5e68d5273f..0000000000000 --- a/src/plugins/tile_map/public/css_filters.js +++ /dev/null @@ -1,29 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; - -/** - * just a place to put feature detection checks - */ -export const supportsCssFilters = (function () { - const e = document.createElement('img'); - const rules = ['webkitFilter', 'mozFilter', 'msFilter', 'filter']; - const test = 'grayscale(1)'; - - rules.forEach(function (rule) { - e.style[rule] = test; - }); - - document.body.appendChild(e); - const styles = window.getComputedStyle(e); - const can = _(styles).pick(rules).includes(test); - document.body.removeChild(e); - - return can; -})(); diff --git a/src/plugins/tile_map/public/geohash_layer.js b/src/plugins/tile_map/public/geohash_layer.js deleted file mode 100644 index e84a23c04056a..0000000000000 --- a/src/plugins/tile_map/public/geohash_layer.js +++ /dev/null @@ -1,172 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { min, isEqual } from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { KibanaMapLayer } 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'; -import { MapTypes } from './utils/map_types'; - -export class GeohashLayer extends KibanaMapLayer { - constructor(featureCollection, featureCollectionMetaData, options, zoom, kibanaMap, leaflet) { - super(); - - this._featureCollection = featureCollection; - this._featureCollectionMetaData = featureCollectionMetaData; - - this._geohashOptions = options; - this._zoom = zoom; - this._kibanaMap = kibanaMap; - this._leaflet = leaflet; - const geojson = this._leaflet.geoJson(this._featureCollection); - this._bounds = geojson.getBounds(); - this._createGeohashMarkers(); - this._lastBounds = null; - } - - _createGeohashMarkers() { - const markerOptions = { - isFilteredByCollar: this._geohashOptions.isFilteredByCollar, - valueFormatter: this._geohashOptions.valueFormatter, - tooltipFormatter: this._geohashOptions.tooltipFormatter, - label: this._geohashOptions.label, - colorRamp: this._geohashOptions.colorRamp, - }; - switch (this._geohashOptions.mapType) { - case MapTypes.ScaledCircleMarkers: - this._geohashMarkers = new ScaledCirclesMarkers( - this._featureCollection, - this._featureCollectionMetaData, - markerOptions, - this._zoom, - this._kibanaMap, - this._leaflet - ); - break; - case MapTypes.ShadedCircleMarkers: - this._geohashMarkers = new ShadedCirclesMarkers( - this._featureCollection, - this._featureCollectionMetaData, - markerOptions, - this._zoom, - this._kibanaMap, - this._leaflet - ); - break; - case MapTypes.ShadedGeohashGrid: - this._geohashMarkers = new GeohashGridMarkers( - this._featureCollection, - this._featureCollectionMetaData, - markerOptions, - this._zoom, - this._kibanaMap, - this._leaflet - ); - break; - case MapTypes.Heatmap: - let radius = 15; - if (this._featureCollectionMetaData.geohashGridDimensionsAtEquator) { - const minGridLength = min(this._featureCollectionMetaData.geohashGridDimensionsAtEquator); - const metersPerPixel = this._kibanaMap.getMetersPerPixel(); - radius = minGridLength / metersPerPixel / 2; - } - radius = radius * parseFloat(this._geohashOptions.heatmap.heatClusterSize); - this._geohashMarkers = new HeatmapMarkers( - this._featureCollection, - { - radius: radius, - blur: radius, - maxZoom: this._kibanaMap.getZoomLevel(), - minOpacity: 0.1, - tooltipFormatter: this._geohashOptions.tooltipFormatter, - }, - this._zoom, - this._featureCollectionMetaData.max, - this._leaflet - ); - break; - default: - throw new Error( - i18n.translate('tileMap.geohashLayer.mapTitle', { - defaultMessage: '{mapType} mapType not recognized', - values: { - mapType: this._geohashOptions.mapType, - }, - }) - ); - } - - this._geohashMarkers.on('showTooltip', (event) => this.emit('showTooltip', event)); - this._geohashMarkers.on('hideTooltip', (event) => this.emit('hideTooltip', event)); - this._leafletLayer = this._geohashMarkers.getLeafletLayer(); - } - - appendLegendContents(jqueryDiv) { - return this._geohashMarkers.appendLegendContents(jqueryDiv); - } - - movePointer(...args) { - this._geohashMarkers.movePointer(...args); - } - - async getBounds() { - if (this._geohashOptions.fetchBounds) { - const geoHashBounds = await this._geohashOptions.fetchBounds(); - if (geoHashBounds) { - 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); - } - } - - return this._bounds; - } - - updateExtent() { - // Client-side filtering is only enabled when server-side filter is not used - if (!this._geohashOptions.isFilteredByCollar) { - const bounds = this._kibanaMap.getLeafletBounds(); - if (!this._lastBounds || !this._lastBounds.equals(bounds)) { - //this removal is required to trigger the bounds filter again - this._kibanaMap.removeLayer(this); - this._createGeohashMarkers(); - this._kibanaMap.addLayer(this); - } - this._lastBounds = bounds; - } - } - - isReusable(options) { - if (isEqual(this._geohashOptions, options)) { - return true; - } - - //check if any impacts leaflet styler function - if (this._geohashOptions.colorRamp !== options.colorRamp) { - return false; - } else if (this._geohashOptions.mapType !== options.mapType) { - return false; - } else if ( - this._geohashOptions.mapType === 'Heatmap' && - !isEqual(this._geohashOptions.heatmap, options) - ) { - return false; - } else { - return true; - } - } -} diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx deleted file mode 100644 index 6f71aa15b8a6b..0000000000000 --- a/src/plugins/tile_map/public/get_deprecation_message.tsx +++ /dev/null @@ -1,70 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { getQueryService, getShareService } from './services'; -import { indexPatterns } from '../../data/public'; -import { Vis } from '../../visualizations/public'; -import { LegacyMapDeprecationMessage } from '../../maps_legacy/public'; - -export function getDeprecationMessage(vis: Vis) { - const title = i18n.translate('tileMap.vis.mapTitle', { - defaultMessage: 'Coordinate Map', - }); - - async function onClick(e: React.MouseEvent) { - e.preventDefault(); - - const locator = getShareService().url.locators.get('MAPS_APP_TILE_MAP_LOCATOR'); - if (!locator) return; - - const query = getQueryService(); - const params: { [key: string]: any } = { - label: vis.title ? vis.title : title, - mapType: vis.params.mapType, - colorSchema: vis.params.colorSchema, - indexPatternId: vis.data.indexPattern?.id, - metricAgg: 'count', - filters: query.filterManager.getFilters(), - query: query.queryString.getQuery(), - timeRange: query.timefilter.timefilter.getTime(), - }; - - const bucketAggs = vis.data?.aggs?.byType('buckets'); - if (bucketAggs?.length && bucketAggs[0].type.dslName === 'geohash_grid') { - params.geoFieldName = bucketAggs[0].getField()?.name; - } else if (vis.data.indexPattern) { - // attempt to default to first geo point field when geohash is not configured yet - const geoField = vis.data.indexPattern.fields.find((field) => { - return ( - !indexPatterns.isNestedField(field) && field.aggregatable && field.type === 'geo_point' - ); - }); - if (geoField) { - params.geoFieldName = geoField.name; - } - } - - const metricAggs = vis.data?.aggs?.byType('metrics'); - if (metricAggs?.length) { - params.metricAgg = metricAggs[0].type.dslName; - params.metricFieldName = metricAggs[0].getField()?.name; - } - - locator.navigate(params); - } - - return ( - - ); -} diff --git a/src/plugins/tile_map/public/index.ts b/src/plugins/tile_map/public/index.ts deleted file mode 100644 index 3104dde0d5ac6..0000000000000 --- a/src/plugins/tile_map/public/index.ts +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { PluginInitializerContext } from 'kibana/public'; -import { TileMapPlugin as Plugin } from './plugin'; - -export function plugin(initializerContext: PluginInitializerContext) { - return new Plugin(initializerContext); -} diff --git a/src/plugins/tile_map/public/markers/geohash_grid.js b/src/plugins/tile_map/public/markers/geohash_grid.js deleted file mode 100644 index c8c327d7a8a61..0000000000000 --- a/src/plugins/tile_map/public/markers/geohash_grid.js +++ /dev/null @@ -1,24 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { ScaledCirclesMarkers } from './scaled_circles'; - -export class GeohashGridMarkers extends ScaledCirclesMarkers { - getMarkerFunction() { - return (feature) => { - const geohashRect = feature.properties.geohash_meta.rectangle; - // get bounds from northEast[3] and southWest[1] - // corners in geohash rectangle - const corners = [ - [geohashRect[3][0], geohashRect[3][1]], - [geohashRect[1][0], geohashRect[1][1]], - ]; - 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 deleted file mode 100644 index 5b5649b1e992c..0000000000000 --- a/src/plugins/tile_map/public/markers/heatmap.js +++ /dev/null @@ -1,183 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import d3 from 'd3'; -import { EventEmitter } from 'events'; - -/** - * Map overlay: canvas layer with leaflet.heat plugin - * - * @param map {Leaflet Object} - * @param geoJson {geoJson Object} - * @param params {Object} - */ -export class HeatmapMarkers extends EventEmitter { - constructor(featureCollection, options, zoom, max, leaflet) { - super(); - this._geojsonFeatureCollection = featureCollection; - const points = dataToHeatArray(featureCollection, max); - this._leafletLayer = new leaflet.HeatLayer(points, options); - this._tooltipFormatter = options.tooltipFormatter; - this._zoom = zoom; - this._disableTooltips = false; - this._getLatLng = _.memoize( - function (feature) { - return leaflet.latLng(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); - }, - function (feature) { - // turn coords into a string for the memoize cache - return [feature.geometry.coordinates[1], feature.geometry.coordinates[0]].join(','); - } - ); - this._addTooltips(); - } - - getBounds() { - return this._leafletLayer.getBounds(); - } - - getLeafletLayer() { - return this._leafletLayer; - } - - appendLegendContents() {} - - movePointer(type, event) { - if (type === 'mousemove') { - this._debounceMoveMoveLocation(event); - } else if (type === 'mouseout') { - this.emit('hideTooltip'); - } else if (type === 'mousedown') { - this._disableTooltips = true; - this.emit('hideTooltip'); - } else if (type === 'mouseup') { - this._disableTooltips = false; - } - } - - _addTooltips() { - const mouseMoveLocation = (e) => { - if (!this._geojsonFeatureCollection.features.length || this._disableTooltips) { - this.emit('hideTooltip'); - return; - } - - const feature = this._nearestFeature(e.latlng); - if (this._tooltipProximity(e.latlng, feature)) { - const content = this._tooltipFormatter(feature); - if (!content) { - return; - } - this.emit('showTooltip', { - content: content, - position: e.latlng, - }); - } else { - this.emit('hideTooltip'); - } - }; - - this._debounceMoveMoveLocation = _.debounce(mouseMoveLocation.bind(this), 15, { - leading: true, - trailing: false, - }); - } - - /** - * Finds nearest feature in mapData to event latlng - * - * @method _nearestFeature - * @param latLng {Leaflet latLng} - * @return nearestPoint {Leaflet latLng} - */ - _nearestFeature(latLng) { - const self = this; - let nearest; - - if (latLng.lng < -180 || latLng.lng > 180) { - return; - } - - _.reduce( - this._geojsonFeatureCollection.features, - function (distance, feature) { - const featureLatLng = self._getLatLng(feature); - const dist = latLng.distanceTo(featureLatLng); - - if (dist < distance) { - nearest = feature; - return dist; - } - - return distance; - }, - Infinity - ); - - return nearest; - } - - /** - * display tooltip if feature is close enough to event latlng - * - * @method _tooltipProximity - * @param latlng {Leaflet latLng Object} - * @param feature {geoJson Object} - * @return {Boolean} - */ - _tooltipProximity(latlng, feature) { - if (!feature) return; - - let showTip = false; - const featureLatLng = this._getLatLng(feature); - - // zoomScale takes map zoom and returns proximity value for tooltip display - // domain (input values) is map zoom (min 1 and max 18) - // range (output values) is distance in meters - // used to compare proximity of event latlng to feature latlng - const zoomScale = d3.scale - .linear() - .domain([1, 4, 7, 10, 13, 16, 18]) - .range([1000000, 300000, 100000, 15000, 2000, 150, 50]); - - const proximity = zoomScale(this._zoom); - const distance = latlng.distanceTo(featureLatLng); - - // maxLngDif is max difference in longitudes - // to prevent feature tooltip from appearing 360° - // away from event latlng - const maxLngDif = 40; - const lngDif = Math.abs(latlng.lng - featureLatLng.lng); - - if (distance < proximity && lngDif < maxLngDif) { - showTip = true; - } - - d3.scale.pow().exponent(0.2).domain([1, 18]).range([1500000, 50]); - return showTip; - } -} - -/** - * returns normalized data for heat map intensity - * - * @method dataToHeatArray - * @param featureCollection {Array} - * @return {Array} - */ -function dataToHeatArray(featureCollection, max) { - return featureCollection.features.map((feature) => { - const lat = feature.geometry.coordinates[1]; - const lng = feature.geometry.coordinates[0]; - // show bucket value normalized to max value - const heatIntensity = feature.properties.value / max; - - return [lat, lng, heatIntensity]; - }); -} diff --git a/src/plugins/tile_map/public/markers/scaled_circles.js b/src/plugins/tile_map/public/markers/scaled_circles.js deleted file mode 100644 index 54fba95953255..0000000000000 --- a/src/plugins/tile_map/public/markers/scaled_circles.js +++ /dev/null @@ -1,236 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import d3 from 'd3'; -import $ from 'jquery'; -import { EventEmitter } from 'events'; -import { colorUtil } from '../../../maps_legacy/public'; -import { truncatedColorMaps } from '../../../charts/public'; - -export class ScaledCirclesMarkers extends EventEmitter { - constructor( - featureCollection, - featureCollectionMetaData, - options, - targetZoom, - kibanaMap, - leaflet - ) { - super(); - this._featureCollection = featureCollection; - this._featureCollectionMetaData = featureCollectionMetaData; - - this._zoom = targetZoom; - - this._valueFormatter = - options.valueFormatter || - ((x) => { - x; - }); - this._tooltipFormatter = - options.tooltipFormatter || - ((x) => { - x; - }); - this._label = options.label; - this._colorRamp = options.colorRamp; - - this._legendColors = null; - this._legendQuantizer = null; - this._leaflet = leaflet; - - this._popups = []; - - const layerOptions = { - pointToLayer: this.getMarkerFunction(), - style: this.getStyleFunction(), - onEachFeature: (feature, layer) => { - this._bindPopup(feature, layer); - }, - }; - // Filter leafletlayer on client when results are not filtered on the server - if (!options.isFilteredByCollar) { - layerOptions.filter = (feature) => { - const bucketRectBounds = feature.properties.geohash_meta.rectangle; - return kibanaMap.isInside(bucketRectBounds); - }; - } - this._leafletLayer = this._leaflet.geoJson(null, layerOptions); - this._leafletLayer.addData(this._featureCollection); - } - - getLeafletLayer() { - return this._leafletLayer; - } - - getStyleFunction() { - const min = _.get(this._featureCollectionMetaData, 'min', 0); - const max = _.get(this._featureCollectionMetaData, 'max', 1); - - const quantizeDomain = min !== max ? [min, max] : d3.scale.quantize().domain(); - - this._legendColors = this.getLegendColors(); - this._legendQuantizer = d3.scale.quantize().domain(quantizeDomain).range(this._legendColors); - - return makeStyleFunction(this._legendColors, quantizeDomain); - } - - movePointer() {} - - getLabel() { - if (this._popups.length) { - return this._label; - } - return ''; - } - - appendLegendContents(jqueryDiv) { - if (!this._legendColors || !this._legendQuantizer) { - return; - } - - const titleText = this.getLabel(); - const $title = $('
').addClass('visMapLegend__title').text(titleText); - jqueryDiv.append($title); - - this._legendColors.forEach((color) => { - const labelText = this._legendQuantizer - .invertExtent(color) - .map(this._valueFormatter) - .join(' – '); - - const label = $('
'); - const icon = $('').css({ - background: color, - 'border-color': makeColorDarker(color), - }); - - const text = $('').text(labelText); - label.append(icon); - label.append(text); - - jqueryDiv.append(label); - }); - } - - /** - * Binds popup and events to each feature on map - * - * @method bindPopup - * @param feature {Object} - * @param layer {Object} - * return {undefined} - */ - _bindPopup(feature, layer) { - const popup = layer.on({ - mouseover: (e) => { - const layer = e.target; - // bring layer to front if not older browser - if (!this._leaflet.Browser.ie && !this._leaflet.Browser.opera) { - layer.bringToFront(); - } - this._showTooltip(feature); - }, - mouseout: () => { - this.emit('hideTooltip'); - }, - }); - - this._popups.push(popup); - } - - /** - * Checks if event latlng is within bounds of mapData - * features and shows tooltip for that feature - * - * @method _showTooltip - * @param feature {LeafletFeature} - * @return undefined - */ - _showTooltip(feature) { - const content = this._tooltipFormatter(feature); - if (!content) { - return; - } - - const latLng = this._leaflet.latLng( - feature.geometry.coordinates[1], - feature.geometry.coordinates[0] - ); - this.emit('showTooltip', { - content: content, - position: latLng, - }); - } - - getMarkerFunction() { - const scaleFactor = 0.6; - return (feature, latlng) => { - const value = feature.properties.value; - const scaledRadius = this._radiusScale(value) * scaleFactor; - return this._leaflet.circleMarker(latlng).setRadius(scaledRadius); - }; - } - - /** - * radiusScale returns a number for scaled circle markers - * for relative sizing of markers - * - * @method _radiusScale - * @param value {Number} - * @return {Number} - */ - _radiusScale(value) { - //magic numbers - const precisionBiasBase = 5; - const precisionBiasNumerator = 200; - - const precision = _.max( - this._featureCollection.features.map((feature) => { - return String(feature.properties.geohash).length; - }) - ); - - const pct = Math.abs(value) / Math.abs(this._featureCollectionMetaData.max); - const zoomRadius = 0.5 * Math.pow(2, this._zoom); - const precisionScale = precisionBiasNumerator / Math.pow(precisionBiasBase, precision); - - // square root value percentage - return Math.pow(pct, 0.5) * zoomRadius * precisionScale; - } - - getBounds() { - return this._leafletLayer.getBounds(); - } - - getLegendColors() { - const colorRamp = _.get(truncatedColorMaps[this._colorRamp], 'value'); - return colorUtil.getLegendColors(colorRamp); - } -} - -function makeColorDarker(color) { - const amount = 1.3; //magic number, carry over from earlier - return d3.hcl(color).darker(amount).toString(); -} - -function makeStyleFunction(legendColors, quantizeDomain) { - const legendQuantizer = d3.scale.quantize().domain(quantizeDomain).range(legendColors); - return (feature) => { - const value = _.get(feature, 'properties.value'); - const color = legendQuantizer(value); - return { - fillColor: color, - color: makeColorDarker(color), - weight: 1.5, - opacity: 1, - fillOpacity: 0.75, - }; - }; -} diff --git a/src/plugins/tile_map/public/markers/shaded_circles.js b/src/plugins/tile_map/public/markers/shaded_circles.js deleted file mode 100644 index a47fcd71427f3..0000000000000 --- a/src/plugins/tile_map/public/markers/shaded_circles.js +++ /dev/null @@ -1,52 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import _ from 'lodash'; -import { ScaledCirclesMarkers } from './scaled_circles'; - -export class ShadedCirclesMarkers extends ScaledCirclesMarkers { - getMarkerFunction() { - // multiplier to reduce size of all circles - const scaleFactor = 0.8; - return (feature, latlng) => { - const radius = this._geohashMinDistance(feature) * scaleFactor; - return this._leaflet.circle(latlng, radius); - }; - } - - /** - * _geohashMinDistance returns a min distance in meters for sizing - * circle markers to fit within geohash grid rectangle - * - * @method _geohashMinDistance - * @param feature {Object} - * @return {Number} - */ - _geohashMinDistance(feature) { - const centerPoint = feature.properties.geohash_meta.center; - const geohashRect = feature.properties.geohash_meta.rectangle; - - // centerPoint is an array of [lat, lng] - // geohashRect is the 4 corners of the geoHash rectangle - // an array that starts at the southwest corner and proceeds - // clockwise, each value being an array of [lat, lng] - - // center lat and southeast lng - const east = this._leaflet.latLng([centerPoint[0], geohashRect[2][1]]); - // southwest lat and center lng - const north = this._leaflet.latLng([geohashRect[3][0], centerPoint[1]]); - - // get latLng of geohash center point - 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)); - const northRadius = Math.floor(center.distanceTo(north)); - return _.min([eastRadius, northRadius]); - } -} diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts deleted file mode 100644 index 78cd12ffbccad..0000000000000 --- a/src/plugins/tile_map/public/plugin.ts +++ /dev/null @@ -1,102 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - CoreSetup, - CoreStart, - Plugin, - PluginInitializerContext, - IUiSettingsClient, -} from 'kibana/public'; -import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public'; -import { VisualizationsSetup } from '../../visualizations/public'; -import { MapsLegacyPluginSetup } from '../../maps_legacy/public'; -import { MapsEmsPluginSetup } from '../../maps_ems/public'; -import { IServiceSettings } from '../../maps_ems/public'; -import { DataPublicPluginStart } from '../../data/public'; -import { - setCoreService, - setFormatService, - setQueryService, - setKibanaLegacy, - setShareService, -} from './services'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; -import { SharePluginStart } from '../../share/public'; - -import { createTileMapFn } from './tile_map_fn'; -import { createTileMapTypeDefinition } from './tile_map_type'; -import { getTileMapRenderer } from './tile_map_renderer'; - -/** @private */ -export interface TileMapVisualizationDependencies { - uiSettings: IUiSettingsClient; - getZoomPrecision: any; - getPrecision: any; - BaseMapsVisualization: any; - getServiceSettings: () => Promise; -} - -/** @internal */ -export interface TileMapPluginSetupDependencies { - expressions: ReturnType; - visualizations: VisualizationsSetup; - mapsLegacy: MapsLegacyPluginSetup; - mapsEms: MapsEmsPluginSetup; -} - -/** @internal */ -export interface TileMapPluginStartDependencies { - data: DataPublicPluginStart; - kibanaLegacy: KibanaLegacyStart; - share: SharePluginStart; -} - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface TileMapPluginSetup {} -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface TileMapPluginStart {} - -/** @internal */ -export class TileMapPlugin implements Plugin { - initializerContext: PluginInitializerContext; - - constructor(initializerContext: PluginInitializerContext) { - this.initializerContext = initializerContext; - } - - public setup( - core: CoreSetup, - { expressions, visualizations, mapsLegacy, mapsEms }: TileMapPluginSetupDependencies - ) { - const { getZoomPrecision, getPrecision } = mapsLegacy; - const visualizationDependencies: Readonly = { - getZoomPrecision, - getPrecision, - BaseMapsVisualization: mapsLegacy.getBaseMapsVis(), - uiSettings: core.uiSettings, - getServiceSettings: mapsEms.getServiceSettings, - }; - - expressions.registerFunction(createTileMapFn); - expressions.registerRenderer(getTileMapRenderer(visualizationDependencies)); - - visualizations.createBaseVisualization(createTileMapTypeDefinition(visualizationDependencies)); - - return {}; - } - - public start(core: CoreStart, plugins: TileMapPluginStartDependencies) { - setFormatService(plugins.data.fieldFormats); - setQueryService(plugins.data.query); - setKibanaLegacy(plugins.kibanaLegacy); - setShareService(plugins.share); - setCoreService(core); - return {}; - } -} diff --git a/src/plugins/tile_map/public/services.ts b/src/plugins/tile_map/public/services.ts deleted file mode 100644 index cef4fbae03f38..0000000000000 --- a/src/plugins/tile_map/public/services.ts +++ /dev/null @@ -1,32 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { CoreStart } from 'kibana/public'; -import { createGetterSetter } from '../../kibana_utils/public'; -import { DataPublicPluginStart } from '../../data/public'; -import { KibanaLegacyStart } from '../../kibana_legacy/public'; -import { SharePluginStart } from '../../share/public'; -import { TmsLayer } from '../../maps_ems/public'; - -export const [getCoreService, setCoreService] = createGetterSetter('Core'); - -export const [getFormatService, setFormatService] = createGetterSetter< - DataPublicPluginStart['fieldFormats'] ->('vislib data.fieldFormats'); - -export const [getQueryService, setQueryService] = createGetterSetter< - DataPublicPluginStart['query'] ->('Query'); - -export const [getShareService, setShareService] = createGetterSetter('Share'); - -export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( - 'KibanaLegacy' -); - -export const [getTmsLayers, setTmsLayers] = createGetterSetter('TmsLayers'); diff --git a/src/plugins/tile_map/public/tile_map_fn.test.ts b/src/plugins/tile_map/public/tile_map_fn.test.ts deleted file mode 100644 index 7e8e065e959dd..0000000000000 --- a/src/plugins/tile_map/public/tile_map_fn.test.ts +++ /dev/null @@ -1,85 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { functionWrapper } from '../../expressions/common/expression_functions/specs/tests/utils'; -import { createTileMapFn } from './tile_map_fn'; - -jest.mock('./utils', () => ({ - convertToGeoJson: jest.fn().mockReturnValue({ - featureCollection: { - type: 'FeatureCollection', - features: [], - }, - meta: { - min: null, - max: null, - geohashPrecision: null, - geohashGridDimensionsAtEquator: null, - }, - }), -})); - -import { convertToGeoJson } from './utils'; - -describe('interpreter/functions#tilemap', () => { - const fn = functionWrapper(createTileMapFn()); - const context = { - type: 'datatable', - rows: [{ 'col-0-1': 0 }], - columns: [{ id: 'col-0-1', name: 'Count' }], - }; - const visConfig = { - colorSchema: 'Yellow to Red', - mapType: 'Scaled Circle Markers', - isDesaturated: true, - addTooltip: true, - heatClusterSize: 1.5, - legendPosition: 'bottomright', - mapZoom: 2, - mapCenter: [0, 0], - wms: { - enabled: false, - options: { - format: 'image/png', - transparent: true, - }, - }, - dimensions: { - metric: { - accessor: 0, - format: { - id: 'number', - }, - params: {}, - aggType: 'count', - }, - geohash: null, - geocentroid: null, - }, - }; - - beforeEach(() => { - jest.clearAllMocks(); - }); - - it('returns an object with the correct structure', async () => { - const actual = await fn(context, { visConfig: JSON.stringify(visConfig) }); - expect(actual).toMatchSnapshot(); - }); - - it('calls response handler with correct values', async () => { - const { geohash, metric, geocentroid } = visConfig.dimensions; - await fn(context, { visConfig: JSON.stringify(visConfig) }); - expect(convertToGeoJson).toHaveBeenCalledTimes(1); - expect(convertToGeoJson).toHaveBeenCalledWith(context, { - geohash, - metric, - geocentroid, - }); - }); -}); diff --git a/src/plugins/tile_map/public/tile_map_fn.ts b/src/plugins/tile_map/public/tile_map_fn.ts deleted file mode 100644 index 53372b46c0bf8..0000000000000 --- a/src/plugins/tile_map/public/tile_map_fn.ts +++ /dev/null @@ -1,71 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -import type { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public'; -import { TileMapVisConfig, TileMapVisData } from './types'; - -interface Arguments { - visConfig: string | null; -} - -export interface TileMapVisRenderValue { - visData: TileMapVisData; - visType: 'tile_map'; - visConfig: TileMapVisConfig; -} - -export type TileMapExpressionFunctionDefinition = ExpressionFunctionDefinition< - 'tilemap', - Datatable, - Arguments, - Promise> ->; - -export const createTileMapFn = (): TileMapExpressionFunctionDefinition => ({ - name: 'tilemap', - type: 'render', - context: { - types: ['datatable'], - }, - help: i18n.translate('tileMap.function.help', { - defaultMessage: 'Tilemap visualization', - }), - args: { - visConfig: { - types: ['string', 'null'], - default: '"{}"', - help: '', - }, - }, - async fn(context, args, handlers) { - const visConfig = args.visConfig && JSON.parse(args.visConfig); - const { geohash, metric, geocentroid } = visConfig.dimensions; - - const { convertToGeoJson } = await import('./utils'); - const convertedData = convertToGeoJson(context, { - geohash, - metric, - geocentroid, - }); - - if (handlers?.inspectorAdapters?.tables) { - handlers.inspectorAdapters.tables.logDatatable('default', context); - } - return { - type: 'render', - as: 'tile_map_vis', - value: { - visData: convertedData, - visType: 'tile_map', - visConfig, - }, - }; - }, -}); diff --git a/src/plugins/tile_map/public/tile_map_renderer.tsx b/src/plugins/tile_map/public/tile_map_renderer.tsx deleted file mode 100644 index 7339e4bf64b1c..0000000000000 --- a/src/plugins/tile_map/public/tile_map_renderer.tsx +++ /dev/null @@ -1,41 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { lazy } from 'react'; -import { render, unmountComponentAtNode } from 'react-dom'; - -import { ExpressionRenderDefinition } from 'src/plugins/expressions'; -import { VisualizationContainer } from '../../visualizations/public'; -import { TileMapVisualizationDependencies } from './plugin'; -import { TileMapVisRenderValue } from './tile_map_fn'; - -const TileMapVisualization = lazy(() => import('./tile_map_visualization_component')); - -export const getTileMapRenderer: ( - deps: TileMapVisualizationDependencies -) => ExpressionRenderDefinition = (deps) => ({ - name: 'tile_map_vis', - reuseDomNode: true, - render: async (domNode, { visConfig, visData }, handlers) => { - handlers.onDestroy(() => { - unmountComponentAtNode(domNode); - }); - - render( - - - , - domNode - ); - }, -}); diff --git a/src/plugins/tile_map/public/tile_map_type.ts b/src/plugins/tile_map/public/tile_map_type.ts deleted file mode 100644 index 5e71351f1bd56..0000000000000 --- a/src/plugins/tile_map/public/tile_map_type.ts +++ /dev/null @@ -1,95 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; -import { VisTypeDefinition } from 'src/plugins/visualizations/public'; - -// @ts-expect-error -import { supportsCssFilters } from './css_filters'; -import { TileMapOptionsLazy } from './components'; -import { getDeprecationMessage } from './get_deprecation_message'; -import { TileMapVisualizationDependencies } from './plugin'; -import { toExpressionAst } from './to_ast'; -import { TileMapVisParams } from './types'; -import { setTmsLayers } from './services'; - -export function createTileMapTypeDefinition( - dependencies: TileMapVisualizationDependencies -): VisTypeDefinition { - const { uiSettings, getServiceSettings } = dependencies; - - return { - name: 'tile_map', - getInfoMessage: getDeprecationMessage, - title: i18n.translate('tileMap.vis.mapTitle', { - defaultMessage: 'Coordinate Map', - }), - icon: 'visMapCoordinate', - description: i18n.translate('tileMap.vis.mapDescription', { - defaultMessage: 'Plot latitude and longitude coordinates on a map', - }), - visConfig: { - canDesaturate: Boolean(supportsCssFilters), - defaults: { - colorSchema: 'Yellow to Red', - mapType: 'Scaled Circle Markers', - isDesaturated: true, - addTooltip: true, - heatClusterSize: 1.5, - legendPosition: 'bottomright', - mapZoom: 2, - mapCenter: [0, 0], - wms: uiSettings.get('visualization:tileMap:WMSdefaults'), - }, - }, - toExpressionAst, - editorConfig: { - optionsTemplate: TileMapOptionsLazy, - schemas: [ - { - group: 'metrics', - name: 'metric', - title: i18n.translate('tileMap.vis.map.editorConfig.schemas.metricTitle', { - defaultMessage: 'Value', - }), - min: 1, - max: 1, - aggFilter: ['count', 'avg', 'sum', 'min', 'max', 'cardinality', 'top_hits'], - defaults: [{ schema: 'metric', type: 'count' }], - }, - { - group: 'buckets', - name: 'segment', - title: i18n.translate('tileMap.vis.map.editorConfig.schemas.geoCoordinatesTitle', { - defaultMessage: 'Geo coordinates', - }), - aggFilter: ['geohash_grid'], - min: 1, - max: 1, - }, - ], - }, - setup: async (vis) => { - let tmsLayers; - - try { - const serviceSettings = await getServiceSettings(); - tmsLayers = await serviceSettings.getTMSServices(); - } catch (e) { - return vis; - } - - setTmsLayers(tmsLayers); - if (!vis.params.wms.selectedTmsLayer && tmsLayers.length) { - vis.params.wms.selectedTmsLayer = tmsLayers[0]; - } - return vis; - }, - requiresSearch: true, - }; -} diff --git a/src/plugins/tile_map/public/tile_map_visualization.js b/src/plugins/tile_map/public/tile_map_visualization.js deleted file mode 100644 index ebce2de51bbbc..0000000000000 --- a/src/plugins/tile_map/public/tile_map_visualization.js +++ /dev/null @@ -1,256 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { get, round } from 'lodash'; -import { getFormatService, getQueryService, getKibanaLegacy } from './services'; -import { mapTooltipProvider, lazyLoadMapsLegacyModules } from '../../maps_legacy/public'; -import { tooltipFormatter } from './tooltip_formatter'; -import { geoContains } from './utils'; - -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; - - return class CoordinateMapsVisualization extends BaseMapsVisualization { - constructor(element, handlers, initialVisParams) { - super(element, handlers, initialVisParams); - - this._geohashLayer = null; - this._tooltipFormatter = mapTooltipProvider(element, tooltipFormatter); - } - - updateGeohashAgg = () => { - const geohashAgg = this._getGeoHashAgg(); - if (!geohashAgg) return; - const updateVarsObject = { - name: 'bounds', - data: {}, - }; - const bounds = this._kibanaMap.getBounds(); - const mapCollar = scaleBounds(bounds); - if (!geoContains(geohashAgg.sourceParams.params.boundingBox, mapCollar)) { - updateVarsObject.data.boundingBox = { - top_left: mapCollar.top_left, - bottom_right: mapCollar.bottom_right, - }; - } else { - updateVarsObject.data.boundingBox = geohashAgg.sourceParams.params.boundingBox; - } - // todo: autoPrecision should be vis parameter, not aggConfig one - const zoomPrecision = getZoomPrecision(); - updateVarsObject.data.precision = geohashAgg.sourceParams.params.autoPrecision - ? zoomPrecision[this.handlers.uiState.get('mapZoom')] - : getPrecision(geohashAgg.sourceParams.params.precision); - - this.handlers.event(updateVarsObject); - }; - - async render(esResponse, visParams) { - getKibanaLegacy().loadFontAwesome(); - await super.render(esResponse, visParams); - } - - async _makeKibanaMap() { - await super._makeKibanaMap(this._params); - - let previousPrecision = this._kibanaMap.getGeohashPrecision(); - let precisionChange = false; - - this.handlers.uiState.on('change', (prop) => { - if (prop === 'mapZoom' || prop === 'mapCenter') { - this.updateGeohashAgg(); - } - }); - - this._kibanaMap.on('zoomchange', () => { - precisionChange = previousPrecision !== this._kibanaMap.getGeohashPrecision(); - previousPrecision = this._kibanaMap.getGeohashPrecision(); - }); - this._kibanaMap.on('zoomend', () => { - const geohashAgg = this._getGeoHashAgg(); - if (!geohashAgg) { - return; - } - const isAutoPrecision = - typeof geohashAgg.sourceParams.params.autoPrecision === 'boolean' - ? geohashAgg.sourceParams.params.autoPrecision - : true; - if (!isAutoPrecision) { - return; - } - if (precisionChange) { - this.updateGeohashAgg(); - } else { - //when we filter queries by collar - this._updateData(this._geoJsonFeatureCollectionAndMeta); - } - }); - - this._kibanaMap.addDrawControl(); - this._kibanaMap.on('drawCreated:rectangle', (event) => { - const geohashAgg = this._getGeoHashAgg(); - this.addSpatialFilter(geohashAgg, 'geo_bounding_box', event.bounds); - }); - this._kibanaMap.on('drawCreated:polygon', (event) => { - const geohashAgg = this._getGeoHashAgg(); - this.addSpatialFilter(geohashAgg, 'geo_polygon', { points: event.points }); - }); - } - - async _updateData(geojsonFeatureCollectionAndMeta) { - // Only recreate geohash layer when there is new aggregation data - // Exception is Heatmap: which needs to be redrawn every zoom level because the clustering is based on meters per pixel - if ( - this._getMapsParams().mapType !== 'Heatmap' && - geojsonFeatureCollectionAndMeta === this._geoJsonFeatureCollectionAndMeta - ) { - return; - } - - if (this._geohashLayer) { - this._kibanaMap.removeLayer(this._geohashLayer); - this._geohashLayer = null; - } - - if (!geojsonFeatureCollectionAndMeta) { - this._geoJsonFeatureCollectionAndMeta = null; - this._kibanaMap.removeLayer(this._geohashLayer); - this._geohashLayer = null; - return; - } - - if ( - !this._geoJsonFeatureCollectionAndMeta || - !geojsonFeatureCollectionAndMeta.featureCollection.features.length - ) { - this._geoJsonFeatureCollectionAndMeta = geojsonFeatureCollectionAndMeta; - this.updateGeohashAgg(); - } - - this._geoJsonFeatureCollectionAndMeta = geojsonFeatureCollectionAndMeta; - this._recreateGeohashLayer(); - } - - async _recreateGeohashLayer() { - const { GeohashLayer } = await import('./geohash_layer'); - - if (this._geohashLayer) { - this._kibanaMap.removeLayer(this._geohashLayer); - this._geohashLayer = null; - } - const geohashOptions = this._getGeohashOptions(); - this._geohashLayer = new GeohashLayer( - this._geoJsonFeatureCollectionAndMeta.featureCollection, - this._geoJsonFeatureCollectionAndMeta.meta, - geohashOptions, - this._kibanaMap.getZoomLevel(), - this._kibanaMap, - (await lazyLoadMapsLegacyModules()).L - ); - this._kibanaMap.addLayer(this._geohashLayer); - } - - async _updateParams() { - await super._updateParams(); - - this._kibanaMap.setDesaturateBaseLayer(this._params.isDesaturated); - - //avoid recreating the leaflet layer when there are option-changes that do not effect the representation - //e.g. tooltip-visibility, legend position, basemap-desaturation, ... - const geohashOptions = this._getGeohashOptions(); - if (!this._geohashLayer || !this._geohashLayer.isReusable(geohashOptions)) { - if (this._geoJsonFeatureCollectionAndMeta) { - this._recreateGeohashLayer(); - } - this._updateData(this._geoJsonFeatureCollectionAndMeta); - } - } - - _getGeohashOptions() { - const newParams = this._getMapsParams(); - const metricDimension = this._params.dimensions.metric; - const metricLabel = metricDimension ? metricDimension.label : ''; - const metricFormat = getFormatService().deserialize( - metricDimension && metricDimension.format - ); - - return { - label: metricLabel, - valueFormatter: this._geoJsonFeatureCollectionAndMeta - ? metricFormat.getConverterFor('text') - : null, - tooltipFormatter: this._geoJsonFeatureCollectionAndMeta - ? this._tooltipFormatter.bind(null, metricLabel, metricFormat.getConverterFor('text')) - : null, - mapType: newParams.mapType, - isFilteredByCollar: this._isFilteredByCollar(), - colorRamp: newParams.colorSchema, - heatmap: { - heatClusterSize: newParams.heatClusterSize, - }, - }; - } - - addSpatialFilter(agg, filterName, filterData) { - if (!agg) { - return; - } - - const indexPatternName = agg.indexPatternId; - const field = agg.field; - const filter = { meta: { negate: false, index: indexPatternName } }; - filter[filterName] = { ignore_unmapped: true }; - filter[filterName][field] = filterData; - - const { filterManager } = getQueryService(); - filterManager.addFilters([filter]); - } - - _getGeoHashAgg() { - return ( - this._geoJsonFeatureCollectionAndMeta && this._geoJsonFeatureCollectionAndMeta.meta.geohash - ); - } - - _isFilteredByCollar() { - const DEFAULT = false; - const agg = this._getGeoHashAgg(); - if (agg) { - return get(agg, 'sourceParams.params.isFilteredByCollar', DEFAULT); - } else { - return DEFAULT; - } - } - }; -}; diff --git a/src/plugins/tile_map/public/tile_map_visualization.scss b/src/plugins/tile_map/public/tile_map_visualization.scss deleted file mode 100644 index 4298b06c763da..0000000000000 --- a/src/plugins/tile_map/public/tile_map_visualization.scss +++ /dev/null @@ -1,4 +0,0 @@ -.tlmChart__wrapper, .tlmChart { - flex: 1 1 0; - display: flex; -} diff --git a/src/plugins/tile_map/public/tile_map_visualization_component.tsx b/src/plugins/tile_map/public/tile_map_visualization_component.tsx deleted file mode 100644 index 094efc63312e5..0000000000000 --- a/src/plugins/tile_map/public/tile_map_visualization_component.tsx +++ /dev/null @@ -1,92 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import React, { useEffect, useMemo, useRef } from 'react'; -import { EuiResizeObserver } from '@elastic/eui'; -import { throttle } from 'lodash'; - -import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; -import { PersistedState } from 'src/plugins/visualizations/public'; -import { TileMapVisualizationDependencies } from './plugin'; -import { TileMapVisConfig, TileMapVisData } from './types'; -// @ts-expect-error -import { createTileMapVisualization } from './tile_map_visualization'; - -import './tile_map_visualization.scss'; - -interface TileMapVisController { - render(visData?: TileMapVisData, visConfig?: TileMapVisConfig): Promise; - resize(): void; - destroy(): void; -} - -interface TileMapVisualizationProps { - deps: TileMapVisualizationDependencies; - handlers: IInterpreterRenderHandlers; - visData: TileMapVisData; - visConfig: TileMapVisConfig; -} - -const TileMapVisualization = ({ - deps, - handlers, - visData, - visConfig, -}: TileMapVisualizationProps) => { - const chartDiv = useRef(null); - const visController = useRef(null); - const isFirstRender = useRef(true); - const uiState = handlers.uiState as PersistedState; - - useEffect(() => { - if (chartDiv.current && isFirstRender.current) { - isFirstRender.current = false; - const Controller = createTileMapVisualization(deps); - visController.current = new Controller(chartDiv.current, handlers, visConfig); - } - }, [deps, handlers, visConfig, visData]); - - useEffect(() => { - visController.current?.render(visData, visConfig).then(handlers.done); - }, [visData, visConfig, handlers.done]); - - useEffect(() => { - const onUiStateChange = () => { - visController.current?.render().then(handlers.done); - }; - - uiState.on('change', onUiStateChange); - - return () => { - uiState.off('change', onUiStateChange); - }; - }, [uiState, handlers.done]); - - useEffect(() => { - return () => { - visController.current?.destroy(); - visController.current = null; - }; - }, []); - - const updateChartSize = useMemo(() => throttle(() => visController.current?.resize(), 300), []); - - return ( - - {(resizeRef) => ( -
-
-
- )} - - ); -}; - -// default export required for React.Lazy -// eslint-disable-next-line import/no-default-export -export { TileMapVisualization as default }; diff --git a/src/plugins/tile_map/public/to_ast.ts b/src/plugins/tile_map/public/to_ast.ts deleted file mode 100644 index b23a10909661b..0000000000000 --- a/src/plugins/tile_map/public/to_ast.ts +++ /dev/null @@ -1,48 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { - EsaggsExpressionFunctionDefinition, - IndexPatternLoadExpressionFunctionDefinition, -} from '../../data/public'; -import { buildExpression, buildExpressionFunction } from '../../expressions/public'; -import { getVisSchemas, VisToExpressionAst } from '../../visualizations/public'; -import { TileMapExpressionFunctionDefinition } from './tile_map_fn'; -import { TileMapVisConfig, TileMapVisParams } from './types'; - -export const toExpressionAst: VisToExpressionAst = (vis, params) => { - const esaggs = buildExpressionFunction('esaggs', { - index: buildExpression([ - buildExpressionFunction('indexPatternLoad', { - id: vis.data.indexPattern!.id!, - }), - ]), - metricsAtAllLevels: false, - partialRows: false, - aggs: vis.data.aggs!.aggs.map((agg) => buildExpression(agg.toExpressionAst())), - }); - - const schemas = getVisSchemas(vis, params); - - const visConfig: TileMapVisConfig = { - ...vis.params, - dimensions: { - metric: schemas.metric[0], - geohash: schemas.segment ? schemas.segment[0] : null, - geocentroid: schemas.geo_centroid ? schemas.geo_centroid[0] : null, - }, - }; - - const tilemap = buildExpressionFunction('tilemap', { - visConfig: JSON.stringify(visConfig), - }); - - const ast = buildExpression([esaggs, tilemap]); - - return ast.toAst(); -}; diff --git a/src/plugins/tile_map/public/tooltip_formatter.js b/src/plugins/tile_map/public/tooltip_formatter.js deleted file mode 100644 index 28a08d60b0be9..0000000000000 --- a/src/plugins/tile_map/public/tooltip_formatter.js +++ /dev/null @@ -1,34 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { i18n } from '@kbn/i18n'; - -export function tooltipFormatter(metricTitle, metricFormat, feature) { - if (!feature) { - return ''; - } - - return [ - { - label: metricTitle, - value: metricFormat(feature.properties.value), - }, - { - label: i18n.translate('tileMap.tooltipFormatter.latitudeLabel', { - defaultMessage: 'Latitude', - }), - value: feature.geometry.coordinates[1], - }, - { - label: i18n.translate('tileMap.tooltipFormatter.longitudeLabel', { - defaultMessage: 'Longitude', - }), - value: feature.geometry.coordinates[0], - }, - ]; -} diff --git a/src/plugins/tile_map/public/types.ts b/src/plugins/tile_map/public/types.ts deleted file mode 100644 index 89aa27c36b659..0000000000000 --- a/src/plugins/tile_map/public/types.ts +++ /dev/null @@ -1,46 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FeatureCollection } from 'geojson'; -import type { SchemaConfig } from 'src/plugins/visualizations/public'; -import type { DatatableColumnMeta } from 'src/plugins/expressions'; -import type { WMSOptions } from 'src/plugins/maps_legacy/public'; -import type { MapTypes } from './utils/map_types'; - -export interface TileMapVisData { - featureCollection: FeatureCollection; - meta: { - min: number; - max: number; - geohash?: DatatableColumnMeta; - geohashPrecision: number | undefined; - geohashGridDimensionsAtEquator: [number, number] | undefined; - }; -} - -export interface TileMapVisDimensions { - metric: SchemaConfig; - geohash: SchemaConfig | null; - geocentroid: SchemaConfig | null; -} - -export interface TileMapVisParams { - colorSchema: string; - mapType: MapTypes; - isDesaturated: boolean; - addTooltip: boolean; - heatClusterSize: number; - legendPosition: 'bottomright' | 'bottomleft' | 'topright' | 'topleft'; - mapZoom: number; - mapCenter: [number, number]; - wms: WMSOptions; -} - -export interface TileMapVisConfig extends TileMapVisParams { - dimensions: TileMapVisDimensions; -} diff --git a/src/plugins/tile_map/public/utils/convert_to_geojson.ts b/src/plugins/tile_map/public/utils/convert_to_geojson.ts deleted file mode 100644 index 57ece8d5ccd47..0000000000000 --- a/src/plugins/tile_map/public/utils/convert_to_geojson.ts +++ /dev/null @@ -1,122 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { Feature } from 'geojson'; -import type { Datatable } from '../../../expressions/public'; -import type { TileMapVisDimensions, TileMapVisData } from '../types'; -import { decodeGeoHash } from './decode_geo_hash'; -import { gridDimensions } from './grid_dimensions'; - -export function convertToGeoJson( - tabifiedResponse: Datatable, - { geohash, geocentroid, metric }: TileMapVisDimensions -): TileMapVisData { - let features: Feature[]; - let min = Infinity; - let max = -Infinity; - - if (tabifiedResponse && tabifiedResponse.rows) { - const table = tabifiedResponse; - const geohashColumn = geohash ? table.columns[geohash.accessor] : null; - - if (!geohashColumn) { - features = []; - } else { - const metricColumn = table.columns[metric.accessor]; - const geocentroidColumn = geocentroid ? table.columns[geocentroid.accessor] : null; - - features = table.rows - .map((row) => { - const geohashValue = row[geohashColumn.id]; - if (!geohashValue) return false; - const geohashLocation = decodeGeoHash(geohashValue); - - let pointCoordinates: number[]; - if (geocentroidColumn) { - const location = row[geocentroidColumn.id]; - pointCoordinates = [location.lon, location.lat]; - } else { - pointCoordinates = [geohashLocation.longitude[2], geohashLocation.latitude[2]]; - } - - const rectangle = [ - [geohashLocation.latitude[0], geohashLocation.longitude[0]], - [geohashLocation.latitude[0], geohashLocation.longitude[1]], - [geohashLocation.latitude[1], geohashLocation.longitude[1]], - [geohashLocation.latitude[1], geohashLocation.longitude[0]], - ]; - - const centerLatLng = [geohashLocation.latitude[2], geohashLocation.longitude[2]]; - - if (geohash?.params.useGeocentroid) { - // see https://github.com/elastic/elasticsearch/issues/24694 for why clampGrid is used - pointCoordinates[0] = clampGrid( - pointCoordinates[0], - geohashLocation.longitude[0], - geohashLocation.longitude[1] - ); - pointCoordinates[1] = clampGrid( - pointCoordinates[1], - geohashLocation.latitude[0], - geohashLocation.latitude[1] - ); - } - - const value = row[metricColumn.id]; - min = Math.min(min, value); - max = Math.max(max, value); - - return { - type: 'Feature', - geometry: { - type: 'Point', - coordinates: pointCoordinates, - }, - properties: { - geohash: geohashValue, - geohash_meta: { - center: centerLatLng, - rectangle, - }, - value, - }, - } as Feature; - }) - .filter((row): row is Feature => !!row); - } - } else { - features = []; - } - - const convertedData: TileMapVisData = { - featureCollection: { - type: 'FeatureCollection', - features, - }, - meta: { - min, - max, - geohashPrecision: geohash?.params.precision, - geohashGridDimensionsAtEquator: geohash?.params.precision - ? gridDimensions(geohash.params.precision) - : undefined, - }, - }; - - if (geohash && geohash.accessor) { - convertedData.meta.geohash = tabifiedResponse.columns[geohash.accessor].meta; - } - - return convertedData; -} - -function clampGrid(val: number, min: number, max: number) { - if (val > max) val = max; - else if (val < min) val = min; - return val; -} diff --git a/src/plugins/tile_map/public/utils/decode_geo_hash.test.ts b/src/plugins/tile_map/public/utils/decode_geo_hash.test.ts deleted file mode 100644 index 8a62a6f7d6a39..0000000000000 --- a/src/plugins/tile_map/public/utils/decode_geo_hash.test.ts +++ /dev/null @@ -1,16 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { decodeGeoHash } from './decode_geo_hash'; - -test('decodeGeoHash', () => { - expect(decodeGeoHash('drm3btev3e86')).toEqual({ - latitude: [41.119999922811985, 41.12000009045005, 41.12000000663102], - longitude: [-71.34000029414892, -71.3399999588728, -71.34000012651086], - }); -}); diff --git a/src/plugins/tile_map/public/utils/decode_geo_hash.ts b/src/plugins/tile_map/public/utils/decode_geo_hash.ts deleted file mode 100644 index bbabfd007d5c8..0000000000000 --- a/src/plugins/tile_map/public/utils/decode_geo_hash.ts +++ /dev/null @@ -1,89 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -interface DecodedGeoHash { - latitude: number[]; - longitude: number[]; -} - -/** - * Decodes geohash to object containing - * top-left and bottom-right corners of - * rectangle and center point. - */ -export function decodeGeoHash(geohash: string): DecodedGeoHash { - const BITS: number[] = [16, 8, 4, 2, 1]; - const BASE32: string = '0123456789bcdefghjkmnpqrstuvwxyz'; - let isEven: boolean = true; - const lat: number[] = []; - const lon: number[] = []; - lat[0] = -90.0; - lat[1] = 90.0; - lon[0] = -180.0; - lon[1] = 180.0; - let latErr: number = 90.0; - let lonErr: number = 180.0; - [...geohash].forEach((nextChar: string) => { - const cd: number = BASE32.indexOf(nextChar); - for (let j = 0; j < 5; j++) { - const mask: number = BITS[j]; - if (isEven) { - lonErr = lonErr /= 2; - refineInterval(lon, cd, mask); - } else { - latErr = latErr /= 2; - refineInterval(lat, cd, mask); - } - isEven = !isEven; - } - }); - lat[2] = (lat[0] + lat[1]) / 2; - lon[2] = (lon[0] + lon[1]) / 2; - - return { - latitude: lat, - longitude: lon, - }; -} - -function refineInterval(interval: number[], cd: number, mask: number) { - if (cd & mask) { /* eslint-disable-line */ - interval[0] = (interval[0] + interval[1]) / 2; - } else { - interval[1] = (interval[0] + interval[1]) / 2; - } -} - -interface GeoBoundingBoxCoordinate { - lat: number; - lon: number; -} - -interface GeoBoundingBox { - top_left: GeoBoundingBoxCoordinate; - bottom_right: GeoBoundingBoxCoordinate; -} - -export function geoContains(collar?: GeoBoundingBox, bounds?: GeoBoundingBox) { - if (!bounds || !collar) return false; - // test if bounds top_left is outside collar - if (bounds.top_left.lat > collar.top_left.lat || bounds.top_left.lon < collar.top_left.lon) { - return false; - } - - // test if bounds bottom_right is outside collar - if ( - bounds.bottom_right.lat < collar.bottom_right.lat || - bounds.bottom_right.lon > collar.bottom_right.lon - ) { - return false; - } - - // both corners are inside collar so collar contains bounds - return true; -} diff --git a/src/plugins/tile_map/public/utils/grid_dimensions.ts b/src/plugins/tile_map/public/utils/grid_dimensions.ts deleted file mode 100644 index 346d42227cd24..0000000000000 --- a/src/plugins/tile_map/public/utils/grid_dimensions.ts +++ /dev/null @@ -1,28 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -// 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: { [key: number]: [number, number] } = { - 1: [5009400, 4992600], - 2: [1252300, 624100], - 3: [156500, 156000], - 4: [39100, 19500], - 5: [4900, 4900], - 6: [1200, 609.4], - 7: [152.9, 152.4], - 8: [38.2, 19], - 9: [4.8, 4.8], - 10: [1.2, 0.595], - 11: [0.149, 0.149], - 12: [0.037, 0.019], -}; - -export function gridDimensions(precision: number) { - return gridAtEquator[precision]; -} diff --git a/src/plugins/tile_map/public/utils/index.ts b/src/plugins/tile_map/public/utils/index.ts deleted file mode 100644 index a89f1e9d53764..0000000000000 --- a/src/plugins/tile_map/public/utils/index.ts +++ /dev/null @@ -1,10 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export { convertToGeoJson } from './convert_to_geojson'; -export { geoContains } from './decode_geo_hash'; diff --git a/src/plugins/tile_map/public/utils/map_types.ts b/src/plugins/tile_map/public/utils/map_types.ts deleted file mode 100644 index afcc8e02ac963..0000000000000 --- a/src/plugins/tile_map/public/utils/map_types.ts +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export enum MapTypes { - ScaledCircleMarkers = 'Scaled Circle Markers', - ShadedCircleMarkers = 'Shaded Circle Markers', - ShadedGeohashGrid = 'Shaded Geohash Grid', - Heatmap = 'Heatmap', -} diff --git a/src/plugins/tile_map/server/index.ts b/src/plugins/tile_map/server/index.ts deleted file mode 100644 index a7fa77a67d909..0000000000000 --- a/src/plugins/tile_map/server/index.ts +++ /dev/null @@ -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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -export const plugin = () => ({ - setup() {}, - start() {}, -}); diff --git a/src/plugins/tile_map/tsconfig.json b/src/plugins/tile_map/tsconfig.json deleted file mode 100644 index fec191402f2ab..0000000000000 --- a/src/plugins/tile_map/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "extends": "../../../tsconfig.base.json", - "compilerOptions": { - "outDir": "./target/types", - "emitDeclarationOnly": true, - "declaration": true, - "declarationMap": true - }, - "include": ["public/**/*", "server/**/*"], - "references": [ - { "path": "../maps_legacy/tsconfig.json" }, - { "path": "../maps_ems/tsconfig.json" }, - { "path": "../vis_default_editor/tsconfig.json" }, - ] -} 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 95b3b573a6bfa..bc7d72c042841 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 @@ -273,10 +273,8 @@ The URL is an identifier only. Kibana and your browser will never access this UR vegaLogger.warn = this._onWarning.bind(this); this.spec = compile(this.vlspec as TopLevelSpec, { logger: vegaLogger }).spec; - // When using VL with the type=map and user did not provid their own projection settings, + // When using Vega-Lite (VL) with the type=map and user did not provid their own projection settings, // remove the default projection that was generated by VegaLite compiler. - // This way we let leaflet-vega library inject a different default projection for tile maps. - // Also, VL injects default padding and autosize values, but neither should be set for vega-leaflet. if (this.useMap) { if (!this.spec || !this.vlspec) return; const hasConfig = _.isPlainObject(this.vlspec.config); diff --git a/test/functional/apps/dashboard/dashboard_state.ts b/test/functional/apps/dashboard/dashboard_state.ts index ea2031f370eba..1a9cf3b7593a0 100644 --- a/test/functional/apps/dashboard/dashboard_state.ts +++ b/test/functional/apps/dashboard/dashboard_state.ts @@ -18,7 +18,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { 'visualize', 'header', 'discover', - 'tileMap', 'visChart', 'share', 'timePicker', @@ -27,11 +26,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const browser = getService('browser'); const queryBar = getService('queryBar'); const pieChart = getService('pieChart'); - const inspector = getService('inspector'); const retry = getService('retry'); const elasticChart = getService('elasticChart'); const kibanaServer = getService('kibanaServer'); - const dashboardPanelActions = getService('dashboardPanelActions'); const dashboardAddPanel = getService('dashboardAddPanel'); const enableNewChartLibraryDebug = async () => { @@ -166,38 +163,6 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { expect(headers.length).to.be(0); }); - it('Tile map with no changes will update with visualization changes', async () => { - await PageObjects.dashboard.gotoDashboardLandingPage(); - - await PageObjects.dashboard.clickNewDashboard(); - await PageObjects.timePicker.setHistoricalDataRange(); - - await dashboardAddPanel.addVisualization('Visualization TileMap'); - await PageObjects.dashboard.saveDashboard('No local edits'); - - await dashboardPanelActions.openInspector(); - const tileMapData = await inspector.getTableData(); - await inspector.close(); - - await PageObjects.dashboard.switchToEditMode(); - await dashboardPanelActions.openContextMenu(); - await dashboardPanelActions.clickEdit(); - - await PageObjects.tileMap.clickMapZoomIn(); - await PageObjects.tileMap.clickMapZoomIn(); - await PageObjects.tileMap.clickMapZoomIn(); - await PageObjects.tileMap.clickMapZoomIn(); - - await PageObjects.visualize.saveVisualizationExpectSuccess('Visualization TileMap'); - - await PageObjects.header.clickDashboard(); - - await dashboardPanelActions.openInspector(); - const changedTileMapData = await inspector.getTableData(); - await inspector.close(); - expect(changedTileMapData.length).to.not.equal(tileMapData.length); - }); - const getUrlFromShare = async () => { await PageObjects.share.clickShareTopNavButton(); const sharedUrl = await PageObjects.share.getSharedUrl(); diff --git a/test/functional/apps/dashboard/embeddable_library.ts b/test/functional/apps/dashboard/embeddable_library.ts index d66f6e834c367..fd1aa0d91def7 100644 --- a/test/functional/apps/dashboard/embeddable_library.ts +++ b/test/functional/apps/dashboard/embeddable_library.ts @@ -68,44 +68,5 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { ); expect(libraryActionExists).to.be(true); }); - - it('unlink map panel from embeddable library', async () => { - // add map panel from library - await dashboardAddPanel.clickOpenAddPanel(); - await dashboardAddPanel.filterEmbeddableNames('Rendering Test: geo map'); - await find.clickByButtonText('Rendering Test: geo map'); - await dashboardAddPanel.closeAddPanel(); - - const originalPanel = await testSubjects.find('embeddablePanelHeading-RenderingTest:geomap'); - await panelActions.unlinkFromLibary(originalPanel); - await testSubjects.existOrFail('unlinkPanelSuccess'); - - const updatedPanel = await testSubjects.find('embeddablePanelHeading-RenderingTest:geomap'); - const libraryActionExists = await testSubjects.descendantExists( - 'embeddablePanelNotification-ACTION_LIBRARY_NOTIFICATION', - updatedPanel - ); - expect(libraryActionExists).to.be(false); - - await dashboardAddPanel.clickOpenAddPanel(); - await dashboardAddPanel.filterEmbeddableNames('Rendering Test: geo map'); - await find.existsByLinkText('Rendering Test: geo map'); - await dashboardAddPanel.closeAddPanel(); - }); - - it('save map panel to embeddable library', async () => { - const originalPanel = await testSubjects.find('embeddablePanelHeading-RenderingTest:geomap'); - await panelActions.saveToLibrary('Rendering Test: geo map - copy', originalPanel); - await testSubjects.existOrFail('addPanelToLibrarySuccess'); - - const updatedPanel = await testSubjects.find( - 'embeddablePanelHeading-RenderingTest:geomap-copy' - ); - const libraryActionExists = await testSubjects.descendantExists( - 'embeddablePanelNotification-ACTION_LIBRARY_NOTIFICATION', - updatedPanel - ); - expect(libraryActionExists).to.be(true); - }); }); } diff --git a/test/functional/apps/visualize/_region_map.ts b/test/functional/apps/visualize/_region_map.ts deleted file mode 100644 index 916e8dbaee3a0..0000000000000 --- a/test/functional/apps/visualize/_region_map.ts +++ /dev/null @@ -1,105 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - describe('vector map', function () { - const inspector = getService('inspector'); - const log = getService('log'); - const find = getService('find'); - const PageObjects = getPageObjects(['visualize', 'visEditor', 'timePicker']); - - before(async function () { - await PageObjects.visualize.initTests(); - log.debug('navigateToApp visualize'); - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - log.debug('clickRegionMap'); - await PageObjects.visualize.clickRegionMap(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - log.debug('Bucket = Shape field'); - await PageObjects.visEditor.clickBucket('Shape field'); - log.debug('Aggregation = Terms'); - await PageObjects.visEditor.selectAggregation('Terms'); - log.debug('Field = geo.src'); - await PageObjects.visEditor.selectField('geo.src'); - await PageObjects.visEditor.clickGo(); - }); - - describe('vector map', function indexPatternCreation() { - it('should have inspector enabled', async function () { - await inspector.expectIsEnabled(); - }); - - it('should show results after clicking play (join on states)', async function () { - const expectedData = [ - ['CN', '2,592'], - ['IN', '2,373'], - ['US', '1,194'], - ['ID', '489'], - ['BR', '415'], - ]; - await inspector.open(); - await inspector.expectTableData(expectedData); - await inspector.close(); - }); - - it('should change results after changing layer to world', async function () { - await PageObjects.visEditor.clickOptionsTab(); - await PageObjects.visEditor.setSelectByOptionText( - 'regionMapOptionsSelectLayer', - 'World Countries' - ); - - // ensure all fields are there - await PageObjects.visEditor.setSelectByOptionText( - 'regionMapOptionsSelectJoinField', - 'ISO 3166-1 alpha-2 code' - ); - await PageObjects.visEditor.setSelectByOptionText( - 'regionMapOptionsSelectJoinField', - 'ISO 3166-1 alpha-3 code' - ); - await PageObjects.visEditor.setSelectByOptionText( - 'regionMapOptionsSelectJoinField', - 'name' - ); - await PageObjects.visEditor.setSelectByOptionText( - 'regionMapOptionsSelectJoinField', - 'ISO 3166-1 alpha-2 code' - ); - - await inspector.open(); - const actualData = await inspector.getTableData(); - const expectedData = [ - ['CN', '2,592'], - ['IN', '2,373'], - ['US', '1,194'], - ['ID', '489'], - ['BR', '415'], - ]; - expect(actualData).to.eql(expectedData); - - await inspector.close(); - }); - - it('should contain a dropdown with the default road_map base layer as an option', async () => { - const selectField = await find.byCssSelector('#wmsOptionsSelectTmsLayer'); - const $ = await selectField.parseDomContent(); - const optionsText = $('option') - .toArray() - .map((option) => $(option).text()); - - expect(optionsText.includes('road_map')).to.be(true); - }); - }); - }); -} diff --git a/test/functional/apps/visualize/_tile_map.ts b/test/functional/apps/visualize/_tile_map.ts deleted file mode 100644 index 812b6a7d86802..0000000000000 --- a/test/functional/apps/visualize/_tile_map.ts +++ /dev/null @@ -1,225 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import expect from '@kbn/expect'; - -import { FtrProviderContext } from '../../ftr_provider_context'; - -export default function ({ getService, getPageObjects }: FtrProviderContext) { - const log = getService('log'); - const retry = getService('retry'); - const inspector = getService('inspector'); - const filterBar = getService('filterBar'); - const browser = getService('browser'); - const PageObjects = getPageObjects([ - 'common', - 'visualize', - 'visEditor', - 'visChart', - 'timePicker', - 'tileMap', - ]); - - describe('tile map visualize app', function () { - describe('incomplete config', function describeIndexTests() { - before(async function () { - await PageObjects.visualize.initTests(); - await browser.setWindowSize(1280, 1000); - - log.debug('navigateToApp visualize'); - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - log.debug('clickTileMap'); - await PageObjects.visualize.clickTileMap(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - // do not configure aggs - }); - - it('should be able to zoom in twice', async () => { - // should not throw - await PageObjects.tileMap.clickMapZoomIn(); - await PageObjects.tileMap.clickMapZoomIn(); - }); - }); - - describe('complete config', function describeIndexTests() { - before(async function () { - await browser.setWindowSize(1280, 1000); - - log.debug('navigateToApp visualize'); - await PageObjects.visualize.navigateToNewAggBasedVisualization(); - log.debug('clickTileMap'); - await PageObjects.visualize.clickTileMap(); - await PageObjects.visualize.clickNewSearch(); - await PageObjects.timePicker.setDefaultAbsoluteRange(); - log.debug('select bucket Geo Coordinates'); - await PageObjects.visEditor.clickBucket('Geo coordinates'); - log.debug('Click aggregation Geohash'); - await PageObjects.visEditor.selectAggregation('Geohash'); - log.debug('Click field geo.coordinates'); - await retry.try(async function tryingForTime() { - await PageObjects.visEditor.selectField('geo.coordinates'); - }); - await PageObjects.visEditor.clickGo(); - }); - - type SampleTableData = Array; - - /** - * manually compare data due to possible small difference in numbers. This is browser dependent. - */ - function compareTableData(actual: string[][], expected: SampleTableData[]) { - log.debug('comparing expected: ', expected); - log.debug('with actual: ', actual); - - const roundedValues = actual.map((row) => { - // Parse last element in each row as JSON and floor the lat/long value - const coords = JSON.parse(row[row.length - 1]); - return [ - ...row.slice(0, -1), - { - lat: Math.floor(parseFloat(coords.lat)), - lon: Math.floor(parseFloat(coords.lon)), - }, - ]; - }); - - expect(roundedValues).to.eql(expected); - } - - describe('tile map chart', function indexPatternCreation() { - it('should have inspector enabled', async function () { - await inspector.expectIsEnabled(); - }); - - it('should show correct tile map data on default zoom level', async function () { - const expectedTableData = [ - ['-', '9', '5,787', { lat: 37, lon: -104 }], - ['-', 'd', '5,600', { lat: 37, lon: -82 }], - ['-', 'c', '1,319', { lat: 47, lon: -110 }], - ['-', 'b', '999', { lat: 62, lon: -156 }], - ['-', 'f', '187', { lat: 45, lon: -83 }], - ['-', '8', '108', { lat: 18, lon: -157 }], - ]; - // level 1 - await PageObjects.tileMap.clickMapZoomOut(); - // level 0 - await PageObjects.tileMap.clickMapZoomOut(); - - await inspector.open(); - await inspector.setTablePageSize(50); - const actualTableData = await inspector.getTableData(); - await inspector.close(); - compareTableData(actualTableData, expectedTableData); - }); - - it('should not be able to zoom out beyond 0', async function () { - await PageObjects.tileMap.zoomAllTheWayOut(); - const enabled = await PageObjects.tileMap.getMapZoomOutEnabled(); - expect(enabled).to.be(false); - }); - - it('Fit data bounds should zoom to level 3', async function () { - const expectedPrecision2DataTable = [ - ['-', 'dn', '1,429', { lat: 36, lon: -85 }], - ['-', 'dp', '1,418', { lat: 41, lon: -85 }], - ['-', '9y', '1,215', { lat: 36, lon: -96 }], - ['-', '9z', '1,099', { lat: 42, lon: -96 }], - ['-', 'dr', '1,076', { lat: 42, lon: -74 }], - ['-', 'dj', '982', { lat: 31, lon: -85 }], - ['-', '9v', '938', { lat: 31, lon: -96 }], - ['-', '9q', '722', { lat: 36, lon: -120 }], - ['-', '9w', '475', { lat: 36, lon: -107 }], - ['-', 'cb', '457', { lat: 46, lon: -96 }], - ['-', 'c2', '453', { lat: 47, lon: -120 }], - ['-', '9x', '420', { lat: 41, lon: -107 }], - ['-', 'dq', '399', { lat: 37, lon: -78 }], - ['-', '9r', '396', { lat: 41, lon: -120 }], - ['-', '9t', '274', { lat: 32, lon: -107 }], - ['-', 'c8', '271', { lat: 47, lon: -107 }], - ['-', 'dh', '214', { lat: 26, lon: -82 }], - ['-', 'b6', '207', { lat: 60, lon: -162 }], - ['-', 'bd', '206', { lat: 59, lon: -153 }], - ['-', 'b7', '167', { lat: 64, lon: -163 }], - ]; - - await PageObjects.tileMap.clickMapFitDataBounds(); - await inspector.open(); - const data = await inspector.getTableData(); - await inspector.close(); - compareTableData(data, expectedPrecision2DataTable); - }); - - it('Fit data bounds works with pinned filter data', async () => { - const expectedPrecision2DataTable = [ - ['-', 'f05', '1', { lat: 45, lon: -85 }], - ['-', 'dpr', '1', { lat: 40, lon: -79 }], - ['-', '9qh', '1', { lat: 33, lon: -118 }], - ]; - - await filterBar.addFilter('bytes', 'is between', '19980', '19990'); - await filterBar.toggleFilterPinned('bytes'); - await PageObjects.tileMap.zoomAllTheWayOut(); - await PageObjects.tileMap.clickMapFitDataBounds(); - - await inspector.open(); - const data = await inspector.getTableData(); - await inspector.close(); - - await filterBar.removeAllFilters(); - compareTableData(data, expectedPrecision2DataTable); - }); - - it('Newly saved visualization retains map bounds', async () => { - const vizName1 = 'Visualization TileMap'; - - await PageObjects.tileMap.clickMapZoomIn(); - await PageObjects.tileMap.clickMapZoomIn(); - - const mapBounds = await PageObjects.tileMap.getMapBounds(); - await inspector.close(); - - await PageObjects.visualize.saveVisualizationExpectSuccess(vizName1); - - const afterSaveMapBounds = await PageObjects.tileMap.getMapBounds(); - - await inspector.close(); - // For some reason the values are slightly different, so we can't check that they are equal. But we did - // have a bug where after the save, there were _no_ map bounds. So this checks for the later case, but - // until we figure out how to make sure the map center is always the exact same, we can't comparison check. - expect(mapBounds).to.not.be(undefined); - expect(afterSaveMapBounds).to.not.be(undefined); - }); - }); - - describe('Only request data around extent of map option', () => { - it('when checked adds filters to aggregation', async () => { - const vizName1 = 'Visualization TileMap'; - await PageObjects.visualize.loadSavedVisualization(vizName1); - await inspector.open(); - await inspector.expectTableHeaders(['Filter', 'Geohash', 'Count', 'Geo Centroid']); - await inspector.close(); - }); - - it('when not checked does not add filters to aggregation', async () => { - await PageObjects.visEditor.toggleOpenEditor(2); - await PageObjects.visEditor.setIsFilteredByCollarCheckbox(false); - await PageObjects.visEditor.clickGo(); - await inspector.open(); - await inspector.expectTableHeaders(['Geohash', 'Count', 'Geo Centroid']); - await inspector.close(); - }); - - after(async () => { - await PageObjects.visEditor.setIsFilteredByCollarCheckbox(true); - await PageObjects.visEditor.clickGo(); - }); - }); - }); - }); -} diff --git a/test/functional/apps/visualize/index.ts b/test/functional/apps/visualize/index.ts index 4af871bd9347d..9004ecaf22d80 100644 --- a/test/functional/apps/visualize/index.ts +++ b/test/functional/apps/visualize/index.ts @@ -91,8 +91,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./_linked_saved_searches')); loadTestFile(require.resolve('./_visualize_listing')); loadTestFile(require.resolve('./_add_to_dashboard.ts')); - loadTestFile(require.resolve('./_tile_map')); - loadTestFile(require.resolve('./_region_map')); }); describe('visualize ciGroup12', function () { diff --git a/test/functional/page_objects/dashboard_page.ts b/test/functional/page_objects/dashboard_page.ts index ea727069c927d..210c8f61b2391 100644 --- a/test/functional/page_objects/dashboard_page.ts +++ b/test/functional/page_objects/dashboard_page.ts @@ -536,7 +536,6 @@ export class DashboardPageObject extends FtrService { { name: AREA_CHART_VIS_NAME, description: 'AreaChart' }, { name: 'Visualization☺漢字 DataTable', description: 'DataTable' }, { name: LINE_CHART_VIS_NAME, description: 'LineChart' }, - { name: 'Visualization TileMap', description: 'TileMap' }, { name: 'Visualization MetricChart', description: 'MetricChart' }, ]; } diff --git a/test/functional/page_objects/index.ts b/test/functional/page_objects/index.ts index 4c9cb150eca03..cda2c7de44d3b 100644 --- a/test/functional/page_objects/index.ts +++ b/test/functional/page_objects/index.ts @@ -24,7 +24,6 @@ import { VisualBuilderPageObject } from './visual_builder_page'; import { VisualizePageObject } from './visualize_page'; import { VisualizeEditorPageObject } from './visualize_editor_page'; import { VisualizeChartPageObject } from './visualize_chart_page'; -import { TileMapPageObject } from './tile_map_page'; import { TimeToVisualizePageObject } from './time_to_visualize_page'; import { TagCloudPageObject } from './tag_cloud_page'; import { VegaChartPageObject } from './vega_chart_page'; @@ -52,7 +51,6 @@ export const pageObjects = { visualize: VisualizePageObject, visEditor: VisualizeEditorPageObject, visChart: VisualizeChartPageObject, - tileMap: TileMapPageObject, timeToVisualize: TimeToVisualizePageObject, tagCloud: TagCloudPageObject, vegaChart: VegaChartPageObject, diff --git a/test/functional/page_objects/tile_map_page.ts b/test/functional/page_objects/tile_map_page.ts deleted file mode 100644 index 079ca919543e2..0000000000000 --- a/test/functional/page_objects/tile_map_page.ts +++ /dev/null @@ -1,93 +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 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { FtrService } from '../ftr_provider_context'; - -export class TileMapPageObject extends FtrService { - private readonly find = this.ctx.getService('find'); - private readonly testSubjects = this.ctx.getService('testSubjects'); - private readonly retry = this.ctx.getService('retry'); - private readonly log = this.ctx.getService('log'); - private readonly inspector = this.ctx.getService('inspector'); - private readonly monacoEditor = this.ctx.getService('monacoEditor'); - private readonly header = this.ctx.getPageObject('header'); - - public async getZoomSelectors(zoomSelector: string) { - return await this.find.allByCssSelector(zoomSelector); - } - - public async clickMapButton(zoomSelector: string, waitForLoading?: boolean) { - await this.retry.try(async () => { - const zooms = await this.getZoomSelectors(zoomSelector); - for (let i = 0; i < zooms.length; i++) { - await zooms[i].click(); - } - if (waitForLoading) { - await this.header.waitUntilLoadingHasFinished(); - } - }); - } - - public async getVisualizationRequest() { - this.log.debug('getVisualizationRequest'); - await this.inspector.open(); - await this.testSubjects.click('inspectorViewChooser'); - await this.testSubjects.click('inspectorViewChooserRequests'); - await this.testSubjects.click('inspectorRequestDetailRequest'); - await this.find.byCssSelector('.react-monaco-editor-container'); - - return await this.monacoEditor.getCodeEditorValue(1); - } - - public async getMapBounds(): Promise { - const request = await this.getVisualizationRequest(); - const requestObject = JSON.parse(request); - - return requestObject.aggs.filter_agg.filter.geo_bounding_box['geo.coordinates']; - } - - public async clickMapZoomIn(waitForLoading = true) { - await this.clickMapButton('a.leaflet-control-zoom-in', waitForLoading); - } - - public async clickMapZoomOut(waitForLoading = true) { - await this.clickMapButton('a.leaflet-control-zoom-out', waitForLoading); - } - - public async getMapZoomEnabled(zoomSelector: string): Promise { - const zooms = await this.getZoomSelectors(zoomSelector); - const classAttributes = await Promise.all( - zooms.map(async (zoom) => await zoom.getAttribute('class')) - ); - return !classAttributes.join('').includes('leaflet-disabled'); - } - - public async zoomAllTheWayOut(): Promise { - // we can tell we're at level 1 because zoom out is disabled - return await this.retry.try(async () => { - await this.clickMapZoomOut(); - const enabled = await this.getMapZoomOutEnabled(); - // should be able to zoom more as current config has 0 as min level. - if (enabled) { - throw new Error('Not fully zoomed out yet'); - } - }); - } - - public async getMapZoomInEnabled() { - return await this.getMapZoomEnabled('a.leaflet-control-zoom-in'); - } - - public async getMapZoomOutEnabled() { - return await this.getMapZoomEnabled('a.leaflet-control-zoom-out'); - } - - public async clickMapFitDataBounds() { - return await this.clickMapButton('a.fa-crop'); - } -} diff --git a/test/functional/page_objects/visualize_page.ts b/test/functional/page_objects/visualize_page.ts index 966a9d29b3264..1271fe5108f56 100644 --- a/test/functional/page_objects/visualize_page.ts +++ b/test/functional/page_objects/visualize_page.ts @@ -165,14 +165,6 @@ export class VisualizePageObject extends FtrService { await this.clickVisType('line'); } - public async clickRegionMap() { - await this.clickVisType('region_map'); - } - - public async hasRegionMap() { - return await this.hasVisType('region_map'); - } - public async clickMarkdownWidget() { await this.clickVisType('markdown'); } @@ -189,14 +181,6 @@ export class VisualizePageObject extends FtrService { await this.clickVisType('pie'); } - public async clickTileMap() { - await this.clickVisType('tile_map'); - } - - public async hasTileMap() { - return await this.hasVisType('tile_map'); - } - public async clickTimelion() { await this.clickVisType('timelion'); } diff --git a/test/interpreter_functional/screenshots/baseline/partial_test_3.png b/test/interpreter_functional/screenshots/baseline/partial_test_3.png deleted file mode 100644 index b0edb637e0047..0000000000000 Binary files a/test/interpreter_functional/screenshots/baseline/partial_test_3.png and /dev/null differ diff --git a/test/interpreter_functional/snapshots/baseline/partial_test_3.json b/test/interpreter_functional/snapshots/baseline/partial_test_3.json deleted file mode 100644 index e011b69de2022..0000000000000 --- a/test/interpreter_functional/snapshots/baseline/partial_test_3.json +++ /dev/null @@ -1 +0,0 @@ -{"as":"region_map_vis","type":"render","value":{"visConfig":{"addTooltip":true,"bucket":{"accessor":0},"colorSchema":"Yellow to Red","isDisplayWarning":true,"legendPosition":"bottomright","mapCenter":[0,0],"mapZoom":2,"metric":{"accessor":1,"format":{"id":"number"}},"outlineWeight":1,"selectedJoinField":{},"selectedLayer":{},"showAllShapes":true,"wms":{}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"region_map"}} \ No newline at end of file diff --git a/test/interpreter_functional/snapshots/session/partial_test_3.json b/test/interpreter_functional/snapshots/session/partial_test_3.json deleted file mode 100644 index e011b69de2022..0000000000000 --- a/test/interpreter_functional/snapshots/session/partial_test_3.json +++ /dev/null @@ -1 +0,0 @@ -{"as":"region_map_vis","type":"render","value":{"visConfig":{"addTooltip":true,"bucket":{"accessor":0},"colorSchema":"Yellow to Red","isDisplayWarning":true,"legendPosition":"bottomright","mapCenter":[0,0],"mapZoom":2,"metric":{"accessor":1,"format":{"id":"number"}},"outlineWeight":1,"selectedJoinField":{},"selectedLayer":{},"showAllShapes":true,"wms":{}},"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"2","indexPatternId":"logstash-*","params":{"field":"response.raw","missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"id":"1","indexPatternId":"logstash-*","params":{},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visType":"region_map"}} \ No newline at end of file diff --git a/test/interpreter_functional/test_suites/run_pipeline/basic.ts b/test/interpreter_functional/test_suites/run_pipeline/basic.ts index c277f12d0ff37..526373aeeaf53 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/basic.ts +++ b/test/interpreter_functional/test_suites/run_pipeline/basic.ts @@ -88,7 +88,7 @@ export default function ({ // we execute the part of expression that fetches the data and store its response const context = await expectExpression('partial_test', expression).getResponse(); - // we reuse that response to render 3 different charts and compare screenshots with baselines + // we reuse that response to render 2 different charts and compare screenshots with baselines const tagCloudExpr = `tagcloud metric={visdimension 1 format="number"} bucket={visdimension 0}`; await ( await expectExpression('partial_test_1', tagCloudExpr, context).toMatchSnapshot() @@ -98,11 +98,6 @@ export default function ({ await ( await expectExpression('partial_test_2', metricExpr, context).toMatchSnapshot() ).toMatchScreenshot(); - - const regionMapExpr = `regionmap visConfig='{"metric":{"accessor":1,"format":{"id":"number"}},"bucket":{"accessor":0},"legendPosition":"bottomright","addTooltip":true,"colorSchema":"Yellow to Red","isDisplayWarning":true,"wms":{},"mapZoom":2,"mapCenter":[0,0],"outlineWeight":1,"showAllShapes":true,"selectedLayer":{},"selectedJoinField":{}}'`; - await ( - await expectExpression('partial_test_3', regionMapExpr, context).toMatchSnapshot() - ).toMatchScreenshot(); }); }); }); diff --git a/tsconfig.json b/tsconfig.json index 769dd5ecb6a55..0307525de0156 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,4 +19,4 @@ { "path": "./src/plugins/usage_collection/tsconfig.json" }, { "path": "./x-pack/plugins/reporting/tsconfig.json" }, ] -} +} \ No newline at end of file diff --git a/x-pack/plugins/maps/kibana.json b/x-pack/plugins/maps/kibana.json index 41639d667c386..e2cc415820db5 100644 --- a/x-pack/plugins/maps/kibana.json +++ b/x-pack/plugins/maps/kibana.json @@ -15,6 +15,7 @@ "fileUpload", "uiActions", "navigation", + "expressions", "visualizations", "dashboard", "embeddable", diff --git a/x-pack/plugins/maps/public/_index.scss b/x-pack/plugins/maps/public/_index.scss index 01363209cfffd..e43ccb0e8679c 100644 --- a/x-pack/plugins/maps/public/_index.scss +++ b/x-pack/plugins/maps/public/_index.scss @@ -13,4 +13,5 @@ @import 'connected_components/index'; @import 'components/index'; @import 'classes/index'; -@import 'animations'; \ No newline at end of file +@import 'animations'; +@import 'embeddable/index'; \ No newline at end of file diff --git a/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts index 658a093321500..229532c09f955 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_region_map_layer_descriptor.ts @@ -29,6 +29,19 @@ import { getJoinAggKey } from '../../../common/get_agg_key'; const defaultDynamicProperties = getDefaultDynamicProperties(); +export interface CreateRegionMapLayerDescriptorParams { + label: string; + emsLayerId?: string; + leftFieldName?: string; + termsFieldName?: string; + termsSize?: number; + colorSchema: string; + indexPatternId?: string; + indexPatternTitle?: string; + metricAgg: string; + metricFieldName?: string; +} + export function createAggDescriptor(metricAgg: string, metricFieldName?: string): AggDescriptor { const aggTypeKey = Object.keys(AGG_TYPE).find((key) => { return AGG_TYPE[key as keyof typeof AGG_TYPE] === metricAgg; @@ -55,18 +68,7 @@ export function createRegionMapLayerDescriptor({ indexPatternTitle, metricAgg, metricFieldName, -}: { - label: string; - emsLayerId?: string; - leftFieldName?: string; - termsFieldName?: string; - termsSize?: number; - colorSchema: string; - indexPatternId?: string; - indexPatternTitle?: string; - metricAgg: string; - metricFieldName?: string; -}): LayerDescriptor | null { +}: CreateRegionMapLayerDescriptorParams): LayerDescriptor | null { if (!indexPatternId || !emsLayerId || !leftFieldName || !termsFieldName) { return null; } diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts index e3e5f3878ee56..98217a5f28ad8 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts @@ -33,6 +33,16 @@ import { isMetricCountable } from '../util/is_metric_countable'; const defaultDynamicProperties = getDefaultDynamicProperties(); +export interface CreateTileMapLayerDescriptorParams { + label: string; + mapType: string; + colorSchema: string; + indexPatternId?: string; + geoFieldName?: string; + metricAgg: string; + metricFieldName?: string; +} + function isHeatmap(mapType: string): boolean { return mapType.toLowerCase() === 'heatmap'; } @@ -81,15 +91,7 @@ export function createTileMapLayerDescriptor({ geoFieldName, metricAgg, metricFieldName, -}: { - label: string; - mapType: string; - colorSchema: string; - indexPatternId?: string; - geoFieldName?: string; - metricAgg: string; - metricFieldName?: string; -}): LayerDescriptor | null { +}: CreateTileMapLayerDescriptorParams): LayerDescriptor | null { if (!indexPatternId || !geoFieldName) { return null; } diff --git a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx index 0bdf462cca4b3..806ec29928481 100644 --- a/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx +++ b/x-pack/plugins/maps/public/connected_components/map_container/map_container.tsx @@ -49,6 +49,12 @@ export interface Props { settings: MapSettings; layerList: ILayer[]; waitUntilTimeLayersLoad$: Observable; + /* + * Set to false to exclude sharing attributes 'data-*'. + * An example usage is tile_map and region_map visualizations. The visualizations use MapEmbeddable for rendering. + * Visualize Embeddable handles sharing attributes so sharing attributes are not needed in the children. + */ + isSharable: boolean; } interface State { @@ -79,7 +85,11 @@ export class MapContainer extends Component { componentDidUpdate() { this._loadShowFitToBoundsButton(); this._loadShowTimesliderButton(); - if (this.props.areLayersLoaded && !this._isInitalLoadRenderTimerStarted) { + if ( + this.props.isSharable && + this.props.areLayersLoaded && + !this._isInitalLoadRenderTimerStarted + ) { this._isInitalLoadRenderTimerStarted = true; this._startInitialLoadRenderTimer(); } @@ -192,16 +202,18 @@ export class MapContainer extends Component { if (isFullScreen) { exitFullScreenButton = ; } + const shareAttributes = this.props.isSharable + ? { + ['data-dom-id']: this.state.domId, + ['data-render-complete']: this.state.isInitialLoadRenderTimeoutComplete, + ['data-shared-item']: true, + ['data-title']: this.props.title, + ['data-description']: this.props.description, + } + : {}; + return ( - + + ) => LayerDescriptor[]; + mapCenter?: MapCenterAndZoom; + onInitialRenderComplete?: () => void; + /* + * Set to false to exclude sharing attributes 'data-*'. + */ + isSharable?: boolean; +} + +interface State { + isLoaded: boolean; +} + +export class MapComponent extends Component { + private _isMounted = false; + private _mapEmbeddable?: MapEmbeddableType | undefined; + private readonly _embeddableRef: RefObject = React.createRef(); + + state: State = { isLoaded: false }; + + componentDidMount() { + this._isMounted = true; + this._load(); + } + + componentWillUnmount() { + this._isMounted = false; + if (this._mapEmbeddable) { + this._mapEmbeddable.destroy(); + } + } + + componentDidUpdate() { + if (this._mapEmbeddable) { + this._mapEmbeddable.updateInput({ + filters: this.props.filters, + query: this.props.query, + timeRange: this.props.timeRange, + }); + } + } + + async _load() { + const mapModules = await lazyLoadMapModules(); + if (!this._isMounted) { + return; + } + + this.setState({ isLoaded: true }); + + this._mapEmbeddable = new mapModules.MapEmbeddable( + { + editable: false, + }, + { + id: uuid(), + attributes: { + title: '', + layerListJSON: JSON.stringify([ + mapModules.createBasemapLayerDescriptor(), + ...this.props.getLayerDescriptors({ + createRegionMapLayerDescriptor: mapModules.createRegionMapLayerDescriptor, + createTileMapLayerDescriptor: mapModules.createTileMapLayerDescriptor, + }), + ]), + }, + mapCenter: this.props.mapCenter, + } + ); + this._mapEmbeddable.setOnInitialRenderComplete(this.props.onInitialRenderComplete); + if (this.props.isSharable !== undefined) { + this._mapEmbeddable.setIsSharable(this.props.isSharable); + } + if (this._embeddableRef.current) { + this._mapEmbeddable.render(this._embeddableRef.current); + } + } + + render() { + if (!this.state.isLoaded) { + return ; + } + + return
; + } +} diff --git a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx index 642280aa9dc13..3255fb6b5e8ee 100644 --- a/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx +++ b/x-pack/plugins/maps/public/embeddable/map_embeddable.tsx @@ -43,6 +43,7 @@ import { EventHandlers, } from '../reducers/non_serializable_instances'; import { + areLayersLoaded, getGeoFieldNames, getMapCenter, getMapBuffer, @@ -113,6 +114,9 @@ export class MapEmbeddable private _unsubscribeFromStore?: Unsubscribe; private _isInitialized = false; private _controlledBy: string; + private _onInitialRenderComplete?: () => void = undefined; + private _hasInitialRenderCompleteFired = false; + private _isSharable = true; constructor(config: MapEmbeddableConfig, initialInput: MapEmbeddableInput, parent?: IContainer) { super( @@ -231,6 +235,17 @@ export class MapEmbeddable this._savedMap.getStore().dispatch(setEventHandlers(eventHandlers)); }; + public setOnInitialRenderComplete(onInitialRenderComplete?: () => void): void { + this._onInitialRenderComplete = onInitialRenderComplete; + } + + /* + * Set to false to exclude sharing attributes 'data-*'. + */ + public setIsSharable(isSharable: boolean): void { + this._isSharable = isSharable; + } + getInspectorAdapters() { return getInspectorAdapters(this._savedMap.getStore().getState()); } @@ -351,6 +366,7 @@ export class MapEmbeddable title={this.getTitle()} description={this.getDescription()} waitUntilTimeLayersLoad$={waitUntilTimeLayersLoad$(this._savedMap.getStore())} + isSharable={this._isSharable} /> , @@ -510,6 +526,15 @@ export class MapEmbeddable return; } + if ( + this._onInitialRenderComplete && + !this._hasInitialRenderCompleteFired && + areLayersLoaded(this._savedMap.getStore().getState()) + ) { + this._hasInitialRenderCompleteFired = true; + this._onInitialRenderComplete(); + } + const mapExtent = getMapExtent(this._savedMap.getStore().getState()); if (this.input.filterByMapExtent && !_.isEqual(this._prevMapExtent, mapExtent)) { this.setMapExtentFilter(); diff --git a/x-pack/plugins/maps/public/embeddable/types.ts b/x-pack/plugins/maps/public/embeddable/types.ts index fd8160c567530..090a6c8d02043 100644 --- a/x-pack/plugins/maps/public/embeddable/types.ts +++ b/x-pack/plugins/maps/public/embeddable/types.ts @@ -7,6 +7,7 @@ import type { IndexPattern } from '../../../../../src/plugins/data/common/index_patterns'; import { + Embeddable, EmbeddableInput, EmbeddableOutput, SavedObjectEmbeddableInput, @@ -43,3 +44,8 @@ export type MapEmbeddableInput = MapByValueInput | MapByReferenceInput; export type MapEmbeddableOutput = EmbeddableOutput & { indexPatterns: IndexPattern[]; }; + +export type MapEmbeddableType = Embeddable & { + setOnInitialRenderComplete(onInitialRenderComplete?: () => void): void; + setIsSharable(isSharable: boolean): void; +}; diff --git a/x-pack/plugins/maps/public/lazy_load_bundle/index.ts b/x-pack/plugins/maps/public/lazy_load_bundle/index.ts index abc333ab5e069..788e5938ee168 100644 --- a/x-pack/plugins/maps/public/lazy_load_bundle/index.ts +++ b/x-pack/plugins/maps/public/lazy_load_bundle/index.ts @@ -8,22 +8,28 @@ // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { IndexPatternsContract } from 'src/plugins/data/public/index_patterns'; import { AppMountParameters } from 'kibana/public'; -import { Embeddable, IContainer } from '../../../../../src/plugins/embeddable/public'; +import { IContainer } from '../../../../../src/plugins/embeddable/public'; import { LayerDescriptor } from '../../common/descriptor_types'; -import { MapEmbeddableConfig, MapEmbeddableInput, MapEmbeddableOutput } from '../embeddable/types'; +import type { + MapEmbeddableConfig, + MapEmbeddableInput, + MapEmbeddableType, +} from '../embeddable/types'; import { SourceRegistryEntry } from '../classes/sources/source_registry'; import { LayerWizard } from '../classes/layers/layer_wizard_registry'; import type { CreateLayerDescriptorParams } from '../classes/sources/es_search_source'; import type { EMSTermJoinConfig, SampleValuesConfig } from '../ems_autosuggest'; +import type { CreateTileMapLayerDescriptorParams } from '../classes/layers/create_tile_map_layer_descriptor'; +import type { CreateRegionMapLayerDescriptorParams } from '../classes/layers/create_region_map_layer_descriptor'; let loadModulesPromise: Promise; -interface LazyLoadedMapModules { +export interface LazyLoadedMapModules { MapEmbeddable: new ( config: MapEmbeddableConfig, initialInput: MapEmbeddableInput, parent?: IContainer - ) => Embeddable; + ) => MapEmbeddableType; getIndexPatternService: () => IndexPatternsContract; getMapsCapabilities: () => any; renderApp: (params: AppMountParameters, AppUsageTracker: React.FC) => Promise<() => void>; @@ -41,15 +47,7 @@ interface LazyLoadedMapModules { geoFieldName, metricAgg, metricFieldName, - }: { - label: string; - mapType: string; - colorSchema: string; - indexPatternId?: string; - geoFieldName?: string; - metricAgg: string; - metricFieldName?: string; - }) => LayerDescriptor | null; + }: CreateTileMapLayerDescriptorParams) => LayerDescriptor | null; createRegionMapLayerDescriptor: ({ label, emsLayerId, @@ -61,18 +59,7 @@ interface LazyLoadedMapModules { indexPatternTitle, metricAgg, metricFieldName, - }: { - label: string; - emsLayerId?: string; - leftFieldName?: string; - termsFieldName?: string; - termsSize?: number; - colorSchema: string; - indexPatternId?: string; - indexPatternTitle?: string; - metricAgg: string; - metricFieldName?: string; - }) => LayerDescriptor | null; + }: CreateRegionMapLayerDescriptorParams) => LayerDescriptor | null; createBasemapLayerDescriptor: () => LayerDescriptor | null; createESSearchSourceLayerDescriptor: (params: CreateLayerDescriptorParams) => LayerDescriptor; suggestEMSTermJoinConfig: (config: SampleValuesConfig) => Promise; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/index.ts b/x-pack/plugins/maps/public/legacy_visualizations/index.ts new file mode 100644 index 0000000000000..a01e0ebefb5ad --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { createRegionMapFn, regionMapRenderer, regionMapVisType } from './region_map'; +export { createTileMapFn, tileMapRenderer, tileMapVisType } from './tile_map'; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/index.ts b/x-pack/plugins/maps/public/legacy_visualizations/region_map/index.ts new file mode 100644 index 0000000000000..cda57b1088793 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/index.ts @@ -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 { regionMapVisType } from './region_map_vis_type'; +export { createRegionMapFn } from './region_map_fn'; +export { regionMapRenderer } from './region_map_renderer'; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_editor.tsx b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_editor.tsx new file mode 100644 index 0000000000000..8830c557f7b4a --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_editor.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { Vis } from '../../../../../../src/plugins/visualizations/public'; +import { getData, getShareService } from '../../kibana_services'; +import { ViewInMaps } from '../view_in_maps'; +import { extractLayerDescriptorParams } from './utils'; +import { RegionMapVisParams } from './types'; +import { title } from './region_map_vis_type'; + +export function RegionMapEditor(props: VisEditorOptionsProps) { + const onClick = (e: React.MouseEvent) => { + e.preventDefault(); + + const locator = getShareService().url.locators.get('MAPS_APP_REGION_MAP_LOCATOR'); + if (!locator) return; + + const query = getData().query; + locator.navigate({ + ...extractLayerDescriptorParams((props.vis as unknown) as Vis), + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }); + }; + + return ; +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_fn.ts b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_fn.ts new file mode 100644 index 0000000000000..f5329aa4212bf --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_fn.ts @@ -0,0 +1,62 @@ +/* + * 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 { Filter, Query, TimeRange } from '../../../../../../src/plugins/data/common'; +import type { ExpressionValueSearchContext } from '../../../../../../src/plugins/data/common/search/expressions/kibana_context_type'; +import type { + ExpressionFunctionDefinition, + Render, +} from '../../../../../../src/plugins/expressions/public'; +import { REGION_MAP_RENDER, REGION_MAP_VIS_TYPE, RegionMapVisConfig } from './types'; + +interface Arguments { + visConfig: string; +} + +export interface RegionMapVisRenderValue { + visType: typeof REGION_MAP_VIS_TYPE; + visConfig: RegionMapVisConfig; + filters?: Filter[]; + query?: Query; + timeRange?: TimeRange; +} + +export type RegionMapExpressionFunctionDefinition = ExpressionFunctionDefinition< + 'regionmap', + ExpressionValueSearchContext, + Arguments, + Promise> +>; + +export const createRegionMapFn = (): RegionMapExpressionFunctionDefinition => ({ + name: 'regionmap', + type: 'render', + help: i18n.translate('xpack.maps.regionMap.function.help', { + defaultMessage: 'Regionmap visualization', + }), + args: { + visConfig: { + types: ['string'], + default: '"{}"', + help: '', + }, + }, + async fn(input, args) { + return { + type: 'render', + as: REGION_MAP_RENDER, + value: { + visType: REGION_MAP_VIS_TYPE, + visConfig: JSON.parse(args.visConfig), + filters: input.filters, + query: Array.isArray(input.query) ? input.query[0] : input.query, + timeRange: input.timeRange, + }, + }; + }, +}); diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_renderer.tsx b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_renderer.tsx new file mode 100644 index 0000000000000..1d3531bfed82a --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_renderer.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import type { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { RegionMapVisRenderValue } from './region_map_fn'; +import { RegionMapVisualization } from './region_map_visualization'; +import { REGION_MAP_RENDER } from './types'; + +export const regionMapRenderer = { + name: REGION_MAP_RENDER, + reuseDomNode: true, + render: async (domNode, { filters, query, timeRange, visConfig }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + { + handlers.done(); + }} + filters={filters} + query={query} + timeRange={timeRange} + visConfig={visConfig} + />, + domNode + ); + }, +} as ExpressionRenderDefinition; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_vis_type.ts b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_vis_type.ts new file mode 100644 index 0000000000000..4c6e4b2150fb1 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_vis_type.ts @@ -0,0 +1,43 @@ +/* + * 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 { VisTypeDefinition } from '../../../../../../src/plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; +import { REGION_MAP_VIS_TYPE, RegionMapVisParams } from './types'; +import { RegionMapEditor } from './region_map_editor'; + +export const title = i18n.translate('xpack.maps.regionMapMap.vis.title', { + defaultMessage: 'Region Map', +}); + +export const regionMapVisType = { + name: REGION_MAP_VIS_TYPE, + title, + icon: 'visMapRegion', + description: i18n.translate('xpack.maps.regionMap.vis.description', { + defaultMessage: 'Show metrics on a thematic map.', + }), + editorConfig: { + optionTabs: [ + { + name: '', + title: '', + editor: RegionMapEditor, + }, + ], + }, + visConfig: { + defaults: { + colorSchema: 'Yellow to Red', + mapZoom: 2, + mapCenter: [0, 0], + }, + }, + toExpressionAst, + requiresSearch: true, +} as VisTypeDefinition; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_visualization.tsx b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_visualization.tsx new file mode 100644 index 0000000000000..5bb75d781e79b --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/region_map_visualization.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { Filter, Query, TimeRange } from '../../../../../../src/plugins/data/common'; +import { RegionMapVisConfig } from './types'; +import type { LazyLoadedMapModules } from '../../lazy_load_bundle'; +import { MapComponent } from '../../embeddable/map_component'; + +interface Props { + filters?: Filter[]; + query?: Query; + timeRange?: TimeRange; + visConfig: RegionMapVisConfig; + onInitialRenderComplete: () => void; +} + +export function RegionMapVisualization(props: Props) { + const mapCenter = { + lat: props.visConfig.mapCenter[0], + lon: props.visConfig.mapCenter[1], + zoom: props.visConfig.mapZoom, + }; + function getLayerDescriptors({ + createRegionMapLayerDescriptor, + }: { + createRegionMapLayerDescriptor: LazyLoadedMapModules['createRegionMapLayerDescriptor']; + }) { + const layerDescriptor = createRegionMapLayerDescriptor(props.visConfig.layerDescriptorParams); + return layerDescriptor ? [layerDescriptor] : []; + } + return ( + + ); +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/to_ast.ts b/x-pack/plugins/maps/public/legacy_visualizations/region_map/to_ast.ts new file mode 100644 index 0000000000000..49f431980b950 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/to_ast.ts @@ -0,0 +1,30 @@ +/* + * 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 { + buildExpression, + buildExpressionFunction, +} from '../../../../../../src/plugins/expressions/public'; +import { VisToExpressionAst } from '../../../../../../src/plugins/visualizations/public'; +import { RegionMapExpressionFunctionDefinition } from './region_map_fn'; +import { RegionMapVisParams } from './types'; +import { extractLayerDescriptorParams } from './utils'; + +export const toExpressionAst: VisToExpressionAst = (vis) => { + const regionMap = buildExpressionFunction('regionmap', { + visConfig: JSON.stringify({ + ...vis.params, + mapCenter: vis.uiState.get('mapCenter', [0, 0]), + mapZoom: parseInt(vis.uiState.get('mapZoom', 2), 10), + layerDescriptorParams: extractLayerDescriptorParams(vis), + }), + }); + + const ast = buildExpression([regionMap]); + + return ast.toAst(); +}; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/types.ts b/x-pack/plugins/maps/public/legacy_visualizations/region_map/types.ts new file mode 100644 index 0000000000000..1ed725798ee58 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/types.ts @@ -0,0 +1,29 @@ +/* + * 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 { CreateRegionMapLayerDescriptorParams } from '../../classes/layers/create_region_map_layer_descriptor'; + +export const REGION_MAP_RENDER = 'region_map_vis'; +export const REGION_MAP_VIS_TYPE = 'region_map'; + +export interface RegionMapVisParams { + colorSchema: string; + mapZoom: number; + mapCenter: [number, number]; + selectedLayer: { + isEMS: boolean; + id: string | number; + layerId: string; + }; + selectedJoinField: { + name: string; + }; +} + +export interface RegionMapVisConfig extends RegionMapVisParams { + layerDescriptorParams: CreateRegionMapLayerDescriptorParams; +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/region_map/utils.ts b/x-pack/plugins/maps/public/legacy_visualizations/region_map/utils.ts new file mode 100644 index 0000000000000..a641bbb5a7c39 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/region_map/utils.ts @@ -0,0 +1,49 @@ +/* + * 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 { Vis } from '../../../../../../src/plugins/visualizations/public'; +import { RegionMapVisParams } from './types'; +import { title } from './region_map_vis_type'; + +function getEmsLayerId(id: string | number, layerId: string) { + if (typeof id === 'string') { + return id; + } + + // Region maps from 6.x will have numerical EMS id refering to S3 bucket id. + // In this case, use layerId with contains the EMS layer name. + const split = layerId.split('.'); + return split.length === 2 ? split[1] : undefined; +} + +export function extractLayerDescriptorParams(vis: Vis) { + const params: { [key: string]: any } = { + label: vis.title ? vis.title : title, + emsLayerId: vis.params.selectedLayer.isEMS + ? getEmsLayerId(vis.params.selectedLayer.id, vis.params.selectedLayer.layerId) + : undefined, + leftFieldName: vis.params.selectedLayer.isEMS ? vis.params.selectedJoinField.name : undefined, + colorSchema: vis.params.colorSchema, + indexPatternId: vis.data.indexPattern?.id, + indexPatternTitle: vis.data.indexPattern?.title, + metricAgg: 'count', + }; + + const bucketAggs = vis.data?.aggs?.byType('buckets'); + if (bucketAggs?.length && bucketAggs[0].type.dslName === 'terms') { + params.termsFieldName = bucketAggs[0].getField()?.name; + params.termsSize = bucketAggs[0].getParam('size'); + } + + const metricAggs = vis.data?.aggs?.byType('metrics'); + if (metricAggs?.length) { + params.metricAgg = metricAggs[0].type.dslName; + params.metricFieldName = metricAggs[0].getField()?.name; + } + + return params; +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/index.ts b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/index.ts new file mode 100644 index 0000000000000..04d4c160fb510 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/index.ts @@ -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 { tileMapVisType } from './tile_map_vis_type'; +export { createTileMapFn } from './tile_map_fn'; +export { tileMapRenderer } from './tile_map_renderer'; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_editor.tsx b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_editor.tsx new file mode 100644 index 0000000000000..b177b34a537f9 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_editor.tsx @@ -0,0 +1,34 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { VisEditorOptionsProps } from 'src/plugins/visualizations/public'; +import { Vis } from '../../../../../../src/plugins/visualizations/public'; +import { getData, getShareService } from '../../kibana_services'; +import { ViewInMaps } from '../view_in_maps'; +import { extractLayerDescriptorParams } from './utils'; +import { TileMapVisParams } from './types'; +import { title } from './tile_map_vis_type'; + +export function TileMapEditor(props: VisEditorOptionsProps) { + const onClick = (e: React.MouseEvent) => { + e.preventDefault(); + + const locator = getShareService().url.locators.get('MAPS_APP_TILE_MAP_LOCATOR'); + if (!locator) return; + + const query = getData().query; + locator.navigate({ + ...extractLayerDescriptorParams((props.vis as unknown) as Vis), + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }); + }; + + return ; +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_fn.ts b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_fn.ts new file mode 100644 index 0000000000000..96c962be0c31b --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_fn.ts @@ -0,0 +1,62 @@ +/* + * 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 { Filter, Query, TimeRange } from '../../../../../../src/plugins/data/common'; +import type { ExpressionValueSearchContext } from '../../../../../../src/plugins/data/common/search/expressions/kibana_context_type'; +import type { + ExpressionFunctionDefinition, + Render, +} from '../../../../../../src/plugins/expressions/public'; +import { TILE_MAP_RENDER, TILE_MAP_VIS_TYPE, TileMapVisConfig } from './types'; + +interface Arguments { + visConfig: string; +} + +export interface TileMapVisRenderValue { + visType: typeof TILE_MAP_VIS_TYPE; + visConfig: TileMapVisConfig; + filters?: Filter[]; + query?: Query; + timeRange?: TimeRange; +} + +export type TileMapExpressionFunctionDefinition = ExpressionFunctionDefinition< + 'tilemap', + ExpressionValueSearchContext, + Arguments, + Promise> +>; + +export const createTileMapFn = (): TileMapExpressionFunctionDefinition => ({ + name: 'tilemap', + type: 'render', + help: i18n.translate('xpack.maps.tileMap.function.help', { + defaultMessage: 'Tilemap visualization', + }), + args: { + visConfig: { + types: ['string'], + default: '"{}"', + help: '', + }, + }, + async fn(input, args) { + return { + type: 'render', + as: TILE_MAP_RENDER, + value: { + visType: TILE_MAP_VIS_TYPE, + visConfig: JSON.parse(args.visConfig), + filters: input.filters, + query: Array.isArray(input.query) ? input.query[0] : input.query, + timeRange: input.timeRange, + }, + }; + }, +}); diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_renderer.tsx b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_renderer.tsx new file mode 100644 index 0000000000000..5e61a0e0cd368 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_renderer.tsx @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render, unmountComponentAtNode } from 'react-dom'; +import type { ExpressionRenderDefinition } from 'src/plugins/expressions'; +import { TileMapVisRenderValue } from './tile_map_fn'; +import { TileMapVisualization } from './tile_map_visualization'; +import { TILE_MAP_RENDER } from './types'; + +export const tileMapRenderer = { + name: TILE_MAP_RENDER, + reuseDomNode: true, + render: async (domNode, { filters, query, timeRange, visConfig }, handlers) => { + handlers.onDestroy(() => { + unmountComponentAtNode(domNode); + }); + + render( + { + handlers.done(); + }} + filters={filters} + query={query} + timeRange={timeRange} + visConfig={visConfig} + />, + domNode + ); + }, +} as ExpressionRenderDefinition; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_vis_type.ts b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_vis_type.ts new file mode 100644 index 0000000000000..458adcab8c8d1 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_vis_type.ts @@ -0,0 +1,44 @@ +/* + * 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 { VisTypeDefinition } from '../../../../../../src/plugins/visualizations/public'; +import { toExpressionAst } from './to_ast'; +import { MapTypes, TileMapVisParams, TILE_MAP_VIS_TYPE } from './types'; +import { TileMapEditor } from './tile_map_editor'; + +export const title = i18n.translate('xpack.maps.tileMap.vis.title', { + defaultMessage: 'Coordinate Map', +}); + +export const tileMapVisType = { + name: TILE_MAP_VIS_TYPE, + title, + icon: 'visMapCoordinate', + description: i18n.translate('xpack.maps.tileMap.vis.description', { + defaultMessage: 'Plot latitude and longitude coordinates on a map', + }), + editorConfig: { + optionTabs: [ + { + name: '', + title: '', + editor: TileMapEditor, + }, + ], + }, + visConfig: { + defaults: { + colorSchema: 'Yellow to Red', + mapType: MapTypes.ScaledCircleMarkers, + mapZoom: 2, + mapCenter: [0, 0], + }, + }, + toExpressionAst, + requiresSearch: true, +} as VisTypeDefinition; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_visualization.tsx b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_visualization.tsx new file mode 100644 index 0000000000000..225b29de5652b --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/tile_map_visualization.tsx @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import type { Filter, Query, TimeRange } from '../../../../../../src/plugins/data/common'; +import { TileMapVisConfig } from './types'; +import type { LazyLoadedMapModules } from '../../lazy_load_bundle'; +import { MapComponent } from '../../embeddable/map_component'; + +interface Props { + filters?: Filter[]; + query?: Query; + timeRange?: TimeRange; + visConfig: TileMapVisConfig; + onInitialRenderComplete: () => void; +} + +export function TileMapVisualization(props: Props) { + const mapCenter = { + lat: props.visConfig.mapCenter[0], + lon: props.visConfig.mapCenter[1], + zoom: props.visConfig.mapZoom, + }; + function getLayerDescriptors({ + createTileMapLayerDescriptor, + }: { + createTileMapLayerDescriptor: LazyLoadedMapModules['createTileMapLayerDescriptor']; + }) { + const layerDescriptor = createTileMapLayerDescriptor(props.visConfig.layerDescriptorParams); + return layerDescriptor ? [layerDescriptor] : []; + } + return ( + + ); +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/to_ast.ts b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/to_ast.ts new file mode 100644 index 0000000000000..5417dabfee8d4 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/to_ast.ts @@ -0,0 +1,30 @@ +/* + * 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 { + buildExpression, + buildExpressionFunction, +} from '../../../../../../src/plugins/expressions/public'; +import { VisToExpressionAst } from '../../../../../../src/plugins/visualizations/public'; +import { TileMapExpressionFunctionDefinition } from './tile_map_fn'; +import { TileMapVisParams } from './types'; +import { extractLayerDescriptorParams } from './utils'; + +export const toExpressionAst: VisToExpressionAst = (vis) => { + const tileMap = buildExpressionFunction('tilemap', { + visConfig: JSON.stringify({ + ...vis.params, + mapCenter: vis.uiState.get('mapCenter', [0, 0]), + mapZoom: parseInt(vis.uiState.get('mapZoom', 2), 10), + layerDescriptorParams: extractLayerDescriptorParams(vis), + }), + }); + + const ast = buildExpression([tileMap]); + + return ast.toAst(); +}; diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/types.ts b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/types.ts new file mode 100644 index 0000000000000..4e65fb82b797d --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/types.ts @@ -0,0 +1,29 @@ +/* + * 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 { CreateTileMapLayerDescriptorParams } from '../../classes/layers/create_tile_map_layer_descriptor'; + +export const TILE_MAP_RENDER = 'tile_map_vis'; +export const TILE_MAP_VIS_TYPE = 'tile_map'; + +export enum MapTypes { + ScaledCircleMarkers = 'Scaled Circle Markers', + ShadedCircleMarkers = 'Shaded Circle Markers', + ShadedGeohashGrid = 'Shaded Geohash Grid', + Heatmap = 'Heatmap', +} + +export interface TileMapVisParams { + colorSchema: string; + mapType: MapTypes; + mapZoom: number; + mapCenter: [number, number]; +} + +export interface TileMapVisConfig extends TileMapVisParams { + layerDescriptorParams: CreateTileMapLayerDescriptorParams; +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/tile_map/utils.ts b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/utils.ts new file mode 100644 index 0000000000000..3fcb3d8915701 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/tile_map/utils.ts @@ -0,0 +1,44 @@ +/* + * 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 { Vis } from '../../../../../../src/plugins/visualizations/public'; +import { indexPatterns } from '../../../../../../src/plugins/data/public'; +import { TileMapVisParams } from './types'; +import { title } from './tile_map_vis_type'; + +export function extractLayerDescriptorParams(vis: Vis) { + const params: { [key: string]: any } = { + label: vis.title ? vis.title : title, + mapType: vis.params.mapType, + colorSchema: vis.params.colorSchema, + indexPatternId: vis.data.indexPattern?.id, + metricAgg: 'count', + }; + + const bucketAggs = vis.data?.aggs?.byType('buckets'); + if (bucketAggs?.length && bucketAggs[0].type.dslName === 'geohash_grid') { + params.geoFieldName = bucketAggs[0].getField()?.name; + } else if (vis.data.indexPattern) { + // attempt to default to first geo point field when geohash is not configured yet + const geoField = vis.data.indexPattern.fields.find((field) => { + return ( + !indexPatterns.isNestedField(field) && field.aggregatable && field.type === 'geo_point' + ); + }); + if (geoField) { + params.geoFieldName = geoField.name; + } + } + + const metricAggs = vis.data?.aggs?.byType('metrics'); + if (metricAggs?.length) { + params.metricAgg = metricAggs[0].type.dslName; + params.metricFieldName = metricAggs[0].getField()?.name; + } + + return params; +} diff --git a/x-pack/plugins/maps/public/legacy_visualizations/view_in_maps.tsx b/x-pack/plugins/maps/public/legacy_visualizations/view_in_maps.tsx new file mode 100644 index 0000000000000..39d959865a9a0 --- /dev/null +++ b/x-pack/plugins/maps/public/legacy_visualizations/view_in_maps.tsx @@ -0,0 +1,51 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiButton, EuiCallOut } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { i18n } from '@kbn/i18n'; + +interface Props { + onClick: (e: React.MouseEvent) => void; + visualizationLabel: string; +} + +export function ViewInMaps(props: Props) { + return ( + +

+ +

+

+ +

+
+ + + +
+
+ ); +} diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 3253078c8c11b..4ee2a83589c95 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -36,6 +36,7 @@ import type { VisualizationsSetup, VisualizationsStart, } from '../../../../src/plugins/visualizations/public'; +import type { Plugin as ExpressionsPublicPlugin } from '../../../../src/plugins/expressions/public'; import { APP_ICON_SOLUTION, APP_ID, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../src/plugins/ui_actions/public'; import { visualizeGeoFieldAction } from './trigger_actions/visualize_geo_field_action'; @@ -73,9 +74,18 @@ import { MapsAppRegionMapLocatorDefinition, MapsAppTileMapLocatorDefinition, } from './locators'; +import { + createRegionMapFn, + regionMapRenderer, + regionMapVisType, + createTileMapFn, + tileMapRenderer, + tileMapVisType, +} from './legacy_visualizations'; import { SecurityPluginStart } from '../../security/public'; export interface MapsPluginSetupDependencies { + expressions: ReturnType; inspector: InspectorSetupContract; home?: HomePublicPluginSetup; visualizations: VisualizationsSetup; @@ -177,6 +187,14 @@ export class MapsPlugin return renderApp(params, UsageTracker); }, }); + + // register wrapper around legacy tile_map and region_map visualizations + plugins.expressions.registerFunction(createRegionMapFn); + plugins.expressions.registerRenderer(regionMapRenderer); + plugins.visualizations.createBaseVisualization(regionMapVisType); + plugins.expressions.registerFunction(createTileMapFn); + plugins.expressions.registerRenderer(tileMapRenderer); + plugins.visualizations.createBaseVisualization(tileMapVisType); } public start(core: CoreStart, plugins: MapsPluginStartDependencies): MapsStartApi { diff --git a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx index 5231aab5d1194..4a2b0fbefad68 100644 --- a/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx +++ b/x-pack/plugins/maps/public/routes/map_page/map_app/map_app.tsx @@ -456,6 +456,7 @@ export class MapApp extends React.Component { title={this.props.savedMap.getAttributes().title} description={this.props.savedMap.getAttributes().description} waitUntilTimeLayersLoad$={waitUntilTimeLayersLoad$(this.props.savedMap.getStore())} + isSharable />
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 68d4482afd92c..aadb73e639402 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3204,37 +3204,6 @@ "management.stackManagement.managementDescription": "Elastic Stack の管理を行うセンターコンソールです。", "management.stackManagement.managementLabel": "スタック管理", "management.stackManagement.title": "スタック管理", - "maps_legacy.advancedSettings.visualization.tileMap.maxPrecision.cellDimensionsLinkText": "ディメンションの説明", - "maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionText": "タイルマップに表示されるジオハッシュの最高精度です。7は高い、10は非常に高い、12は最大です。{cellDimensionsLink}", - "maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionTitle": "タイルマップの最高精度", - "maps_legacy.advancedSettings.visualization.tileMap.wmsDefaults.propertiesLinkText": "プロパティ", - "maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsText": "座標マップのWMSマップサーバーサポートのデフォルトの{propertiesLink}です。", - "maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsTitle": "デフォルトのWMSプロパティ", - "maps_legacy.baseMapsVisualization.childShouldImplementMethodErrorMessage": "子はdata-updateに対応できるようこのメソッドを導入する必要があります", - "maps_legacy.defaultDistributionMessage": "Mapsを入手するには、ElasticsearchとKibanaの{defaultDistribution}にアップグレードしてください。", - "maps_legacy.kibanaMap.leaflet.fitDataBoundsAriaLabel": "データバウンドを合わせる", - "maps_legacy.legacyMapDeprecationMessage": "Mapsを使用すると、複数のレイヤーとインデックスを追加する、個別のドキュメントをプロットする、データ値から特徴を表現する、ヒートマップ、グリッド、クラスターを追加するなど、さまざまなことが可能です。{getMapsMessage}", - "maps_legacy.legacyMapDeprecationTitle": "{label}は8.0でMapsに移行されます。", - "maps_legacy.openInMapsButtonLabel": "Mapsで表示", - "maps_legacy.wmsOptions.attributionStringTip": "右下角の属性文字列", - "maps_legacy.wmsOptions.baseLayerSettingsTitle": "ベースレイヤー設定", - "maps_legacy.wmsOptions.imageFormatToUseTip": "通常、画像/pngまたは画像/jpegです。サーバーが透明レイヤーを返す場合は。pngを使用します。", - "maps_legacy.wmsOptions.layersLabel": "レイヤー", - "maps_legacy.wmsOptions.listOfLayersToUseTip": "使用するレイヤーのコンマ区切りのリストです。", - "maps_legacy.wmsOptions.mapLoadFailDescription": "このパラメーターが正しくないと、マップが正常に読み込まれません。", - "maps_legacy.wmsOptions.urlOfWMSWebServiceTip": "WMS WebサービスのURLです。", - "maps_legacy.wmsOptions.useWMSCompliantMapTileServerTip": "WMS対応のマップタイルサーバーを使用します。上級者向けです。", - "maps_legacy.wmsOptions.versionOfWMSserverSupportsTip": "サーバーがサポートしているWMSのバージョンです。", - "maps_legacy.wmsOptions.wmsAttributionLabel": "WMS属性", - "maps_legacy.wmsOptions.wmsDescription": "WMSは、マップイメージサービスの{wmsLink}です。", - "maps_legacy.wmsOptions.wmsFormatLabel": "WMSフォーマット", - "maps_legacy.wmsOptions.wmsLayersLabel": "WMSレイヤー", - "maps_legacy.wmsOptions.wmsLinkText": "OGCスタンダード", - "maps_legacy.wmsOptions.wmsMapServerLabel": "WMSマップサーバー", - "maps_legacy.wmsOptions.wmsServerSupportedStylesListTip": "WMSサーバーがサポートしている、使用するスタイルのコンマ区切りのリストです。一般的に、空白のままです。", - "maps_legacy.wmsOptions.wmsStylesLabel": "WMSスタイル", - "maps_legacy.wmsOptions.wmsUrlLabel": "WMS URL", - "maps_legacy.wmsOptions.wmsVersionLabel": "WMS バージョン", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "doc['field_name'] 構文を使用して、スクリプトからフィールド値にアクセスします", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "戻らずに値を発行します。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "フィールド「{fieldName}」の値を取得します", @@ -3281,30 +3250,6 @@ "presentationUtil.solutionToolbar.libraryButtonLabel": "ライブラリから追加", "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "新しい{createType}を作成", "presentationUtil.solutionToolbar.quickButton.legendLabel": "クイック作成", - "regionMap.advancedSettings.visualization.showRegionMapWarningsText": "用語がマップの形に合わない場合に地域マップに警告を表示するかどうかです。", - "regionMap.advancedSettings.visualization.showRegionMapWarningsTitle": "地域マップに警告を表示", - "regionMap.choroplethLayer.downloadingVectorData404ErrorMessage": "{name} の取得時にサーバーから「404」が返されます。指定された場所にファイルが存在することを確認してください。", - "regionMap.choroplethLayer.downloadingVectorDataErrorMessage": "{name} ファイルをダウンロードできません。サーバーの CORS 構成で、このホストの Kibana アプリケーションからのリクエストが許可されていることを確認してください。", - "regionMap.choroplethLayer.downloadingVectorDataErrorMessageTitle": "ベクトルデータのダウンロード中にエラーが発生しました", - "regionMap.choroplethLayer.unrecognizedFormatErrorMessage": "認識されないフォーマット {formatType}", - "regionMap.function.help": "地域マップビジュアライゼーション", - "regionMap.mapVis.regionMapDescription": "テーママップにメトリックを表示します。提供されたベースマップを使用するか、独自のマップを追加できます。暗い色は大きな値を意味します。", - "regionMap.mapVis.regionMapEditorConfig.schemas.metricTitle": "値", - "regionMap.mapVis.regionMapEditorConfig.schemas.segmentTitle": "フィールドのシェイプ", - "regionMap.mapVis.regionMapTitle": "地域マップ", - "regionMap.visParams.colorSchemaLabel": "配色", - "regionMap.visParams.displayWarningsLabel": "警告を表示", - "regionMap.visParams.joinFieldLabel": "フィールドを結合", - "regionMap.visParams.layerSettingsTitle": "レイヤー設定", - "regionMap.visParams.outlineWeightLabel": "境界の太さ", - "regionMap.visParams.previewOnEMSLinkText": "EMS でプレビュー", - "regionMap.visParams.previewOnEMSLinkTitle": "Elastic Maps Service で {selectedLayerName} をプレビュー", - "regionMap.visParams.showAllShapesLabel": "すべてのシェイプを表示", - "regionMap.visParams.styleSettingsLabel": "スタイル設定", - "regionMap.visParams.switchWarningsTipText": "警告のオン/オフを切り替えます。オンの場合、結合フィールドに基づきベクトルレイヤーのシェイプと一致しない用語ごとに警告が表示されます。オフにすると、これらの警告がオフになります。", - "regionMap.visParams.turnOffShowingAllShapesTipText": "この設定をオフにすると、対応する用語と一致したシェイプのみが表示されます。", - "regionMap.visParams.vectorMapLabel": "ベクトルマップ", - "regionMap.visualization.unableToShowMismatchesWarningText": "次の各用語がシェイプの結合フィールドのシェイプと一致することを確認してください:{mismatches}", "savedObjects.advancedSettings.listingLimitText": "一覧ページ用に取得するオブジェクトの数です", "savedObjects.advancedSettings.listingLimitTitle": "オブジェクト取得制限", "savedObjects.advancedSettings.perPageText": "読み込みダイアログで表示されるページごとのオブジェクトの数です", @@ -3548,27 +3493,6 @@ "telemetry.welcomeBanner.enableButtonLabel": "有効にする", "telemetry.welcomeBanner.telemetryConfigDetailsDescription.telemetryPrivacyStatementLinkText": "プライバシーポリシー", "telemetry.welcomeBanner.title": "Elastic Stack の改善にご協力ください", - "tileMap.function.help": "タイルマップのビジュアライゼーションです", - "tileMap.geohashLayer.mapTitle": "{mapType} マップタイプが認識されません", - "tileMap.legendPositions.bottomLeftText": "左下", - "tileMap.legendPositions.bottomRightText": "右下", - "tileMap.legendPositions.topLeftText": "左上", - "tileMap.legendPositions.topRightText": "右上", - "tileMap.mapTypes.heatmapText": "ヒートマップ", - "tileMap.mapTypes.scaledCircleMarkersText": "スケーリングされた円マーカー", - "tileMap.mapTypes.shadedCircleMarkersText": "影付き円マーカー", - "tileMap.mapTypes.shadedGeohashGridText": "影付きジオハッシュグリッド", - "tileMap.tooltipFormatter.latitudeLabel": "緯度", - "tileMap.tooltipFormatter.longitudeLabel": "経度", - "tileMap.vis.map.editorConfig.schemas.geoCoordinatesTitle": "座標", - "tileMap.vis.map.editorConfig.schemas.metricTitle": "値", - "tileMap.vis.mapDescription": "マップ上に緯度と経度の座標を表示します。", - "tileMap.vis.mapTitle": "座標マップ", - "tileMap.visParams.clusterSizeLabel": "クラスターサイズ", - "tileMap.visParams.colorSchemaLabel": "配色", - "tileMap.visParams.desaturateTilesLabel": "タイルを不飽和化", - "tileMap.visParams.mapTypeLabel": "マップタイプ", - "tileMap.visParams.reduceVibrancyOfTileColorsTip": "色の鮮明度を下げます。この機能は Internet Explorer ではバージョンにかかわらず利用できません。", "timelion.badge.readOnly.text": "読み取り専用", "timelion.badge.readOnly.tooltip": "Timelion シートを保存できません", "timelion.breadcrumbs.create": "作成", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index fa6e840e023b3..2427a840aff56 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3218,37 +3218,6 @@ "management.stackManagement.managementDescription": "您用于管理 Elastic Stack 的中心控制台。", "management.stackManagement.managementLabel": "Stack Management", "management.stackManagement.title": "Stack Management", - "maps_legacy.advancedSettings.visualization.tileMap.maxPrecision.cellDimensionsLinkText": "单元格维度的解释", - "maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionText": "在磁贴地图上显示的最大 geoHash 精度:7 代表较高,10 代表非常高,12 代表最大值。{cellDimensionsLink}", - "maps_legacy.advancedSettings.visualization.tileMap.maxPrecisionTitle": "最大磁贴地图精度", - "maps_legacy.advancedSettings.visualization.tileMap.wmsDefaults.propertiesLinkText": "属性", - "maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsText": "坐标地图中支持 WMS 地图服务器的默认{propertiesLink}", - "maps_legacy.advancedSettings.visualization.tileMap.wmsDefaultsTitle": "默认 WMS 属性", - "maps_legacy.baseMapsVisualization.childShouldImplementMethodErrorMessage": "子对象应实现此方法以响应数据更新", - "maps_legacy.defaultDistributionMessage": "要获取 Maps,请升级到 {defaultDistribution} 版的 Elasticsearch 和 Kibana。", - "maps_legacy.kibanaMap.leaflet.fitDataBoundsAriaLabel": "适应数据边界", - "maps_legacy.legacyMapDeprecationMessage": "使用 Maps,可以添加多个图层和索引,绘制单个文档,使用数据值表示特征,添加热图、网格和集群,等等。{getMapsMessage}", - "maps_legacy.legacyMapDeprecationTitle": "在 8.0 中,{label} 将迁移到 Maps。", - "maps_legacy.openInMapsButtonLabel": "在 Maps 中查看", - "maps_legacy.wmsOptions.attributionStringTip": "右下角的归因字符串。", - "maps_legacy.wmsOptions.baseLayerSettingsTitle": "基础图层设置", - "maps_legacy.wmsOptions.imageFormatToUseTip": "通常为 image/png 或 image/jpeg。如果服务器将返回透明图层,则请使用 png。", - "maps_legacy.wmsOptions.layersLabel": "图层", - "maps_legacy.wmsOptions.listOfLayersToUseTip": "要使用的图层逗号分隔列表。", - "maps_legacy.wmsOptions.mapLoadFailDescription": "如果此参数不正确,将无法加载地图。", - "maps_legacy.wmsOptions.urlOfWMSWebServiceTip": "WMS Web 服务的 URL。", - "maps_legacy.wmsOptions.useWMSCompliantMapTileServerTip": "使用符合 WMS 规范的地图磁贴服务器。仅适用于高级用户。", - "maps_legacy.wmsOptions.versionOfWMSserverSupportsTip": "服务器支持的 WMS 版本。", - "maps_legacy.wmsOptions.wmsAttributionLabel": "WMS 属性", - "maps_legacy.wmsOptions.wmsDescription": "WMS 是用于地图图像服务的 {wmsLink}。", - "maps_legacy.wmsOptions.wmsFormatLabel": "WMS 格式", - "maps_legacy.wmsOptions.wmsLayersLabel": "WMS 图层", - "maps_legacy.wmsOptions.wmsLinkText": "OGC 标准", - "maps_legacy.wmsOptions.wmsMapServerLabel": "WMS 地图服务器", - "maps_legacy.wmsOptions.wmsServerSupportedStylesListTip": "要使用的 WMS 服务器支持的样式逗号分隔列表。在大部分情况下为空。", - "maps_legacy.wmsOptions.wmsStylesLabel": "WMS 样式", - "maps_legacy.wmsOptions.wmsUrlLabel": "WMS url", - "maps_legacy.wmsOptions.wmsVersionLabel": "WMS 版本", "monaco.painlessLanguage.autocomplete.docKeywordDescription": "使用 doc['field_name'] 语法,从脚本中访问字段值", "monaco.painlessLanguage.autocomplete.emitKeywordDescription": "发出值,而不返回值。", "monaco.painlessLanguage.autocomplete.fieldValueDescription": "检索字段“{fieldName}”的值", @@ -3295,31 +3264,6 @@ "presentationUtil.solutionToolbar.libraryButtonLabel": "从库中添加", "presentationUtil.solutionToolbar.quickButton.ariaButtonLabel": "创建新的 {createType}", "presentationUtil.solutionToolbar.quickButton.legendLabel": "快速创建", - "regionMap.advancedSettings.visualization.showRegionMapWarningsText": "词无法联接到地图上的形状时,区域地图是否显示警告。", - "regionMap.advancedSettings.visualization.showRegionMapWarningsTitle": "显示区域地图警告", - "regionMap.choroplethLayer.downloadingVectorData404ErrorMessage": "尝试提取 {name} 时,服务器响应“404”。请确保文件位于该位置。", - "regionMap.choroplethLayer.downloadingVectorDataErrorMessage": "无法下载 {name} 文件。请确保服务器的 CORS 配置允许来自此主机上的 Kibana 应用程序的请求。", - "regionMap.choroplethLayer.downloadingVectorDataErrorMessageTitle": "下载矢量数据时出错", - "regionMap.choroplethLayer.unrecognizedFormatErrorMessage": "格式 {formatType} 无法识别", - "regionMap.function.help": "地区地图可视化", - "regionMap.mapVis.regionMapDescription": "在主题地图上显示指标。使用一个已提供的基础地图,或添加自己的地图。颜色越深表示值越大。", - "regionMap.mapVis.regionMapEditorConfig.schemas.metricTitle": "值", - "regionMap.mapVis.regionMapEditorConfig.schemas.segmentTitle": "形状字段", - "regionMap.mapVis.regionMapTitle": "区域地图", - "regionMap.visParams.colorSchemaLabel": "颜色方案", - "regionMap.visParams.displayWarningsLabel": "显示警告", - "regionMap.visParams.joinFieldLabel": "联接字段", - "regionMap.visParams.layerSettingsTitle": "图层设置", - "regionMap.visParams.outlineWeightLabel": "边框粗细", - "regionMap.visParams.previewOnEMSLinkText": "在 EMS 上预览", - "regionMap.visParams.previewOnEMSLinkTitle": "在 Elastic Maps Service 上预览“{selectedLayerName}”", - "regionMap.visParams.showAllShapesLabel": "显示所有形状", - "regionMap.visParams.styleSettingsLabel": "样式设置", - "regionMap.visParams.switchWarningsTipText": "打开/关闭警告。打开后,将对根据联接字段与矢量图层中的形状不匹配的每个字词显示警告。关闭后,将不显示这些警告。", - "regionMap.visParams.turnOffShowingAllShapesTipText": "关闭此设置时,将仅显示与相应字词匹配的形状。", - "regionMap.visParams.vectorMapLabel": "矢量地图", - "regionMap.visualization.unableToShowMismatchesWarningText": "确保每个字词与该形状的联接字段匹配:{mismatches}", - "regionMap.visualization.unableToShowMismatchesWarningTitle": "无法在地图上显示 {mismatchesLength} 个{oneMismatch, plural, other {结果}}", "savedObjects.advancedSettings.listingLimitText": "要为列表页面提取的对象数目", "savedObjects.advancedSettings.listingLimitTitle": "对象列表限制", "savedObjects.advancedSettings.perPageText": "加载对话框中每页要显示的对象数目", @@ -3568,27 +3512,6 @@ "telemetry.welcomeBanner.enableButtonLabel": "启用", "telemetry.welcomeBanner.telemetryConfigDetailsDescription.telemetryPrivacyStatementLinkText": "隐私声明", "telemetry.welcomeBanner.title": "帮助我们改进 Elastic Stack", - "tileMap.function.help": "磁贴地图可视化", - "tileMap.geohashLayer.mapTitle": "{mapType} 地图类型无法识别", - "tileMap.legendPositions.bottomLeftText": "左下方", - "tileMap.legendPositions.bottomRightText": "右下方", - "tileMap.legendPositions.topLeftText": "左上方", - "tileMap.legendPositions.topRightText": "右上方", - "tileMap.mapTypes.heatmapText": "热图", - "tileMap.mapTypes.scaledCircleMarkersText": "缩放式圆形标记", - "tileMap.mapTypes.shadedCircleMarkersText": "带阴影圆形标记", - "tileMap.mapTypes.shadedGeohashGridText": "带阴影 geohash 网格", - "tileMap.tooltipFormatter.latitudeLabel": "纬度", - "tileMap.tooltipFormatter.longitudeLabel": "经度", - "tileMap.vis.map.editorConfig.schemas.geoCoordinatesTitle": "地理坐标", - "tileMap.vis.map.editorConfig.schemas.metricTitle": "值", - "tileMap.vis.mapDescription": "在地图上绘制纬度和经度坐标", - "tileMap.vis.mapTitle": "坐标地图", - "tileMap.visParams.clusterSizeLabel": "集群大小", - "tileMap.visParams.colorSchemaLabel": "颜色方案", - "tileMap.visParams.desaturateTilesLabel": "降低平铺地图饱和度", - "tileMap.visParams.mapTypeLabel": "地图类型", - "tileMap.visParams.reduceVibrancyOfTileColorsTip": "降低磁贴颜色的鲜艳度。此设置在任何版本的 Internet Explorer 中均不起作用。", "timelion.badge.readOnly.text": "只读", "timelion.badge.readOnly.tooltip": "无法保存 Timelion 工作表", "timelion.breadcrumbs.create": "创建", diff --git a/x-pack/test/functional/apps/maps/visualize_create_menu.js b/x-pack/test/functional/apps/maps/visualize_create_menu.js index c9044353fbde8..795480ec1c638 100644 --- a/x-pack/test/functional/apps/maps/visualize_create_menu.js +++ b/x-pack/test/functional/apps/maps/visualize_create_menu.js @@ -64,12 +64,12 @@ export default function ({ getService, getPageObjects }) { }); it('should not show legacy region map visualizion in create menu', async () => { - const hasLegecyViz = await PageObjects.visualize.hasRegionMap(); + const hasLegecyViz = await PageObjects.visualize.hasVisType('region_map'); expect(hasLegecyViz).to.equal(false); }); it('should not show legacy tilemap map visualizion in create menu', async () => { - const hasLegecyViz = await PageObjects.visualize.hasTileMap(); + const hasLegecyViz = await PageObjects.visualize.hasVisType('tile_map'); expect(hasLegecyViz).to.equal(false); }); }); diff --git a/yarn.lock b/yarn.lock index e49d7590c21aa..e20c1c4136538 100644 --- a/yarn.lock +++ b/yarn.lock @@ -18271,26 +18271,6 @@ lead@^1.0.0: dependencies: flush-write-stream "^1.0.2" -leaflet-draw@0.4.14: - version "0.4.14" - resolved "https://registry.yarnpkg.com/leaflet-draw/-/leaflet-draw-0.4.14.tgz#1b5b06d570873a015aa96b80d664dab496c45a4a" - integrity sha512-O99KSPjyHNMDE+uD/fpdPydvQfTE8QruaG7ylEEtKCIaSSb60mCWoDdGUqGEHU9PGPu2JxbEfkGTXY9eYv7aEw== - -leaflet-responsive-popup@0.6.4: - version "0.6.4" - resolved "https://registry.yarnpkg.com/leaflet-responsive-popup/-/leaflet-responsive-popup-0.6.4.tgz#b93d9368ef9f96d6dc911cf5b96d90e08601c6b3" - integrity sha512-2D8G9aQA6NHkulDBPN9kqbUCkCpWQQ6dF0xFL11AuEIWIbsL4UC/ZPP5m8GYM0dpU6YTlmyyCh1Tz+cls5Q4dg== - -leaflet.heat@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/leaflet.heat/-/leaflet.heat-0.2.0.tgz#109d8cf586f0adee41f05aff031e27a77fecc229" - integrity sha1-EJ2M9Ybwre5B8Fr/Ax4np3/swik= - -leaflet@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.5.1.tgz#9afb9d963d66c870066b1342e7a06f92840f46bf" - integrity sha512-ekM9KAeG99tYisNBg0IzEywAlp0hYI5XRipsqRXyRTeuU8jcuntilpp+eFf5gaE0xubc9RuSNIVtByEKwqFV0w== - "less@npm:@elastic/less@2.7.3-kibana": version "2.7.3-kibana" resolved "https://registry.yarnpkg.com/@elastic/less/-/less-2.7.3-kibana.tgz#3de5e0b06bb095b1cc1149043d67f8dc36272d23"