From 52ba8a4ddeb78d3f561f113a6f8fc189ed3f8c81 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Fri, 20 Mar 2020 14:19:18 -0600 Subject: [PATCH 01/24] Get legacy maps into basic NP plugin form. Swap out legacy services for NP --- src/plugins/maps_legacy/common/origin.ts | 23 + src/plugins/maps_legacy/kibana.json | 8 + src/plugins/maps_legacy/public/index.ts | 24 + .../maps_legacy/public/kibana_services.js | 26 + .../maps_legacy/public/map/_index.scss | 2 + .../public/map/_leaflet_overrides.scss | 157 ++++ .../maps_legacy/public/map/_legend.scss | 33 + .../maps_legacy/public/map/color_util.js | 36 + .../public/map/convert_to_geojson.js | 121 +++ .../public/map/decode_geo_hash.test.ts | 34 + .../maps_legacy/public/map/decode_geo_hash.ts | 191 +++++ .../maps_legacy/public/map/grid_dimensions.js | 41 + .../maps_legacy/public/map/kibana_map.js | 710 ++++++++++++++++++ .../public/map/kibana_map_layer.js | 49 ++ .../maps_legacy/public/map/map_messages.js | 118 +++ .../public/map/service_settings.d.ts | 51 ++ .../public/map/service_settings.js | 252 +++++++ .../public/map/zoom_to_precision.ts | 60 ++ src/plugins/maps_legacy/public/plugin.ts | 46 ++ 19 files changed, 1982 insertions(+) create mode 100644 src/plugins/maps_legacy/common/origin.ts create mode 100644 src/plugins/maps_legacy/kibana.json create mode 100644 src/plugins/maps_legacy/public/index.ts create mode 100644 src/plugins/maps_legacy/public/kibana_services.js create mode 100644 src/plugins/maps_legacy/public/map/_index.scss create mode 100644 src/plugins/maps_legacy/public/map/_leaflet_overrides.scss create mode 100644 src/plugins/maps_legacy/public/map/_legend.scss create mode 100644 src/plugins/maps_legacy/public/map/color_util.js create mode 100644 src/plugins/maps_legacy/public/map/convert_to_geojson.js create mode 100644 src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts create mode 100644 src/plugins/maps_legacy/public/map/decode_geo_hash.ts create mode 100644 src/plugins/maps_legacy/public/map/grid_dimensions.js create mode 100644 src/plugins/maps_legacy/public/map/kibana_map.js create mode 100644 src/plugins/maps_legacy/public/map/kibana_map_layer.js create mode 100644 src/plugins/maps_legacy/public/map/map_messages.js create mode 100644 src/plugins/maps_legacy/public/map/service_settings.d.ts create mode 100644 src/plugins/maps_legacy/public/map/service_settings.js create mode 100644 src/plugins/maps_legacy/public/map/zoom_to_precision.ts create mode 100644 src/plugins/maps_legacy/public/plugin.ts diff --git a/src/plugins/maps_legacy/common/origin.ts b/src/plugins/maps_legacy/common/origin.ts new file mode 100644 index 0000000000000..7fcf1c659bdf3 --- /dev/null +++ b/src/plugins/maps_legacy/common/origin.ts @@ -0,0 +1,23 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export enum ORIGIN { + EMS = 'elastic_maps_service', + KIBANA_YML = 'self_hosted', +} diff --git a/src/plugins/maps_legacy/kibana.json b/src/plugins/maps_legacy/kibana.json new file mode 100644 index 0000000000000..b90295541e807 --- /dev/null +++ b/src/plugins/maps_legacy/kibana.json @@ -0,0 +1,8 @@ +{ + "id": "maps_legacy", + "version": "8.0.0", + "kibanaVersion": "kibana", + "configPath": ["maps_legacy"], + "ui": true, + "requiredPlugins": [] +} diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts new file mode 100644 index 0000000000000..cec5fc3f0994f --- /dev/null +++ b/src/plugins/maps_legacy/public/index.ts @@ -0,0 +1,24 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { FileUploadPlugin } from './plugin'; + +export function plugin() { + return new FileUploadPlugin(); +} diff --git a/src/plugins/maps_legacy/public/kibana_services.js b/src/plugins/maps_legacy/public/kibana_services.js new file mode 100644 index 0000000000000..55311b8dc395e --- /dev/null +++ b/src/plugins/maps_legacy/public/kibana_services.js @@ -0,0 +1,26 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +let toast; +export const setToasts = notificationToast => (toast = notificationToast); +export const getToasts = () => toast; + +let uiSettings; +export const setUiSettings = coreUiSettings => (uiSettings = coreUiSettings); +export const getUiSettings = () => uiSettings; diff --git a/src/plugins/maps_legacy/public/map/_index.scss b/src/plugins/maps_legacy/public/map/_index.scss new file mode 100644 index 0000000000000..f9fc841b9f868 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/_index.scss @@ -0,0 +1,2 @@ +@import './leaflet_overrides'; +@import './legend'; diff --git a/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss b/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss new file mode 100644 index 0000000000000..3235bb63ca22d --- /dev/null +++ b/src/plugins/maps_legacy/public/map/_leaflet_overrides.scss @@ -0,0 +1,157 @@ +// SASSTODO: Create these tooltip variables in EUI +// And/Or create a tooltip mixin +$temp-euiTooltipBackground: tintOrShade($euiColorFullShade, 25%, 90%); +$temp-euiTooltipText: $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: 0.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: $temp-euiTooltipBackground; + color: $temp-euiTooltipText; + 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(0.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 new file mode 100644 index 0000000000000..2c50e214c248b --- /dev/null +++ b/src/plugins/maps_legacy/public/map/_legend.scss @@ -0,0 +1,33 @@ +.visMapLegend { + @include fontSize(11px); + @include euiBottomShadowMedium($color: $euiShadowColorLarge, $opacity: .1); + 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/color_util.js b/src/plugins/maps_legacy/public/map/color_util.js new file mode 100644 index 0000000000000..fd12496fe783e --- /dev/null +++ b/src/plugins/maps_legacy/public/map/color_util.js @@ -0,0 +1,36 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +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/convert_to_geojson.js b/src/plugins/maps_legacy/public/map/convert_to_geojson.js new file mode 100644 index 0000000000000..2186dbb3fc2a3 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/convert_to_geojson.js @@ -0,0 +1,121 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { decodeGeoHash } from './decode_geo_hash'; +import { gridDimensions } from './grid_dimensions'; + +export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metric }) { + let features; + 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; + 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: rectangle, + }, + value: value, + }, + }; + }) + .filter(row => row); + } + } else { + features = []; + } + + const featureCollection = { + type: 'FeatureCollection', + features: features, + }; + + return { + featureCollection: featureCollection, + meta: { + min: min, + max: max, + geohashPrecision: geohash && geohash.params.precision, + geohashGridDimensionsAtEquator: geohash && gridDimensions(geohash.params.precision), + }, + }; +} + +function clampGrid(val, min, max) { + if (val > max) val = max; + else if (val < min) val = min; + return val; +} diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts new file mode 100644 index 0000000000000..c1ca7e4c80383 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.test.ts @@ -0,0 +1,34 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { geohashColumns, decodeGeoHash } from './decode_geo_hash'; + +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); +}); + +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/maps_legacy/public/map/decode_geo_hash.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts new file mode 100644 index 0000000000000..cf2e2056d97dc --- /dev/null +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts @@ -0,0 +1,191 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; +import { getUiSettings } from '../kibana_services'; + +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, + } as DecodedGeoHash; +} + +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; + } +} + +/** + * 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; +} + +/** + * Get the number of geohash columns (world-wide) for a given precision + * @param precision the geohash precision + * @returns {number} the number of columns + */ +export function geohashColumns(precision: number): number { + return geohashCells(precision, 0); +} + +const config = getUiSettings(); +const defaultPrecision = 2; +const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; +/** + * 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. + */ +export const zoomPrecision: any = {}; +const minGeohashPixels = 16; + +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; + } + } +} + +export function getPrecision(val: string) { + let precision = parseInt(val, 10); + + if (Number.isNaN(precision)) { + precision = defaultPrecision; + } + + if (precision > maxPrecision) { + return maxPrecision; + } + + return precision; +} + +interface GeoBoundingBoxCoordinate { + lat: number; + lon: number; +} + +interface GeoBoundingBox { + top_left: GeoBoundingBoxCoordinate; + bottom_right: GeoBoundingBoxCoordinate; +} + +export function scaleBounds(bounds: GeoBoundingBox): GeoBoundingBox { + const scale = 0.5; // scale bounds by 50% + + const topLeft = bounds.top_left; + const bottomRight = bounds.bottom_right; + let latDiff = _.round(Math.abs(topLeft.lat - bottomRight.lat), 5); + const lonDiff = _.round(Math.abs(bottomRight.lon - topLeft.lon), 5); + // map height can be zero when vis is first created + if (latDiff === 0) latDiff = lonDiff; + + const latDelta = latDiff * scale; + let topLeftLat = _.round(topLeft.lat, 5) + latDelta; + if (topLeftLat > 90) topLeftLat = 90; + let bottomRightLat = _.round(bottomRight.lat, 5) - latDelta; + if (bottomRightLat < -90) bottomRightLat = -90; + const lonDelta = lonDiff * scale; + let topLeftLon = _.round(topLeft.lon, 5) - lonDelta; + if (topLeftLon < -180) topLeftLon = -180; + let bottomRightLon = _.round(bottomRight.lon, 5) + lonDelta; + if (bottomRightLon > 180) bottomRightLon = 180; + + return { + top_left: { lat: topLeftLat, lon: topLeftLon }, + bottom_right: { lat: bottomRightLat, lon: bottomRightLon }, + }; +} + +export function geoContains(collar?: GeoBoundingBox, bounds?: GeoBoundingBox) { + if (!bounds || !collar) return false; + // test if bounds top_left is outside collar + 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/maps_legacy/public/map/grid_dimensions.js b/src/plugins/maps_legacy/public/map/grid_dimensions.js new file mode 100644 index 0000000000000..b3438914d5636 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/grid_dimensions.js @@ -0,0 +1,41 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import _ from 'lodash'; + +// geohash precision mapping of geohash grid cell dimensions (width x height, in meters) at equator. +// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator +const gridAtEquator = { + '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) { + return _.get(gridAtEquator, precision); +} diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js new file mode 100644 index 0000000000000..88412ee645d77 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -0,0 +1,710 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { EventEmitter } from 'events'; +import { createZoomWarningMsg } from './map_messages'; +import L from 'leaflet'; +import $ from 'jquery'; +import _ from 'lodash'; +import { zoomToPrecision } from './zoom_to_precision'; +import { i18n } from '@kbn/i18n'; +import { ORIGIN } from '../../common/origin'; + +function makeFitControl(fitContainer, kibanaMap) { + 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( + 'common.ui.vis.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) { + 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, + renderer: L.canvas(), + zoomAnimation: false, // Desaturate map tiles causes animation rendering artifacts + zoomControl: options.zoomControl === undefined ? true : options.zoomControl, + }; + + 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) { + this._popup = L.responsivePopup({ autoPan: false }); + this._popup.setLatLng(event.position); + this._popup.setContent(event.content); + this._popup.openOn(this._leafletMap); + } 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) { + 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 _.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, + }, + }; + this._leafletDrawControl = new L.Control.Draw(drawOptions); + this._leafletMap.addControl(this._leafletDrawControl); + } + + addFitControl() { + if (this._leafletFitControl || !this._leafletMap) { + return; + } + + 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(); + } + + _addMaxZoomMessage = layer => { + const zoomWarningMsg = createZoomWarningMsg(this.getZoomLevel, this.getMaxZoomLevel); + + this._leafletMap.on('zoomend', zoomWarningMsg); + this._containerNode.setAttribute('data-test-subj', 'zoomWarningEnabled'); + + layer.on('remove', () => { + this._leafletMap.off('zoomend', zoomWarningMsg); + this._containerNode.removeAttribute('data-test-subj'); + }); + }; + + 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; + if (settings.options.showZoomMessage) { + baseLayer.on('add', () => { + this._addMaxZoomMessage(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) { + 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 + ? 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(visualization) { + function persistMapStateInUiState() { + const uiState = visualization.getUiState(); + const centerFromUIState = uiState.get('mapCenter'); + const zoomFromUiState = parseInt(uiState.get('mapZoom')); + + if (isNaN(zoomFromUiState) || this.getZoomLevel() !== zoomFromUiState) { + visualization.uiStateVal('mapZoom', this.getZoomLevel()); + } + const centerFromMap = this.getCenter(); + if ( + !centerFromUIState || + centerFromMap.lon !== centerFromUIState[1] || + centerFromMap.lat !== centerFromUIState[0] + ) { + visualization.uiStateVal('mapCenter', [centerFromMap.lat, centerFromMap.lon]); + } + } + + this._leafletMap.on('resize', () => { + visualization.sessionState.mapBounds = this.getBounds(); + }); + this._leafletMap.on('load', () => { + visualization.sessionState.mapBounds = this.getBounds(); + }); + this.on('dragend', persistMapStateInUiState); + this.on('zoomend', persistMapStateInUiState); + } + + useUiStateFromVisualization(visualization) { + const uiState = visualization.getUiState(); + 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.js b/src/plugins/maps_legacy/public/map/kibana_map_layer.js new file mode 100644 index 0000000000000..e276799ed0e1b --- /dev/null +++ b/src/plugins/maps_legacy/public/map/kibana_map_layer.js @@ -0,0 +1,49 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { 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/map_messages.js b/src/plugins/maps_legacy/public/map/map_messages.js new file mode 100644 index 0000000000000..255aef93b1b72 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/map_messages.js @@ -0,0 +1,118 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getToasts } from '../kibana_services'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; +import { toMountPoint } from '../../../kibana_react/public'; + +export const createZoomWarningMsg = (function() { + let disableZoomMsg = false; + const setZoomMsg = boolDisableMsg => (disableZoomMsg = boolDisableMsg); + + class ZoomWarning extends React.Component { + constructor(props) { + super(props); + this.state = { + disabled: false, + }; + } + + render() { + return ( +
+

+ + {`default distribution `} + + ), + ems: ( + + {`Elastic Maps Service`} + + ), + wms: ( + + {`Custom WMS Configuration`} + + ), + configSettings: ( + + {`Custom TMS Using Config Settings`} + + ), + }} + /> +

+ + { + this.setState( + { + disabled: true, + }, + () => this.props.onChange(this.state.disabled) + ); + }} + data-test-subj="suppressZoomWarnings" + > + {`Don't show again`} + +
+ ); + } + } + + const zoomToast = { + title: 'No additional zoom levels', + text: toMountPoint(), + 'data-test-subj': 'maxZoomWarning', + }; + + const toasts = getToasts(); + return (getZoomLevel, getMaxZoomLevel) => { + return () => { + const zoomLevel = getZoomLevel(); + const maxMapZoom = getMaxZoomLevel(); + if (!disableZoomMsg && zoomLevel === maxMapZoom) { + toasts.addDanger(zoomToast); + } + }; + }; +})(); diff --git a/src/plugins/maps_legacy/public/map/service_settings.d.ts b/src/plugins/maps_legacy/public/map/service_settings.d.ts new file mode 100644 index 0000000000000..6766000861e47 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/service_settings.d.ts @@ -0,0 +1,51 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +export interface TmsLayer { + id: string; + origin: string; + minZoom: string; + maxZoom: number; + attribution: string; +} + +export interface FileLayer { + name: string; + origin: string; + id: string; + format: string | { type: string }; + fields: FileLayerField[]; +} + +export interface FileLayerField { + name: string; + description: string; + type: string; +} + +export interface VectorLayer extends FileLayer { + layerId: string; + isEMS: boolean; +} + +export interface ServiceSettings { + getEMSHotLink(layer: FileLayer): Promise; + getTMSServices(): Promise; + getFileLayers(): Promise; +} diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js new file mode 100644 index 0000000000000..d7fb8fde54893 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/service_settings.js @@ -0,0 +1,252 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { uiModules } from '../../modules'; +import _ from 'lodash'; +import MarkdownIt from 'markdown-it'; +import { ORIGIN } from '../../common/origin'; +import { EMSClient } from '@elastic/ems-client'; +import { i18n } from '@kbn/i18n'; +import 'angular-sanitize'; + +const markdownIt = new MarkdownIt({ + html: false, + linkify: true, +}); + +const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; + +uiModules + .get('kibana', ['ngSanitize']) + .service('serviceSettings', function($sanitize, mapConfig, tilemapsConfig, kbnVersion) { + const attributionFromConfig = $sanitize( + markdownIt.render(tilemapsConfig.deprecated.config.options.attribution || '') + ); + const tmsOptionsFromConfig = _.assign({}, tilemapsConfig.deprecated.config.options, { + attribution: attributionFromConfig, + }); + + class ServiceSettings { + constructor() { + this._showZoomMessage = true; + this._emsClient = new EMSClient({ + language: i18n.getLocale(), + appVersion: kbnVersion, + appName: 'kibana', + fileApiUrl: mapConfig.emsFileApiUrl, + tileApiUrl: mapConfig.emsTileApiUrl, + htmlSanitizer: $sanitize, + landingPageUrl: mapConfig.emsLandingPageUrl, + }); + } + + shouldShowZoomMessage({ origin }) { + return origin === ORIGIN.EMS && this._showZoomMessage; + } + + disableZoomMessage() { + this._showZoomMessage = false; + } + + __debugStubManifestCalls(manifestRetrieval) { + const oldGetManifest = this._emsClient.getManifest; + this._emsClient.getManifest = manifestRetrieval; + return { + removeStub: () => { + delete this._emsClient.getManifest; + //not strictly necessary since this is prototype method + if (this._emsClient.getManifest !== oldGetManifest) { + this._emsClient.getManifest = oldGetManifest; + } + }, + }; + } + + async getFileLayers() { + if (!mapConfig.includeElasticMapsService) { + return []; + } + + const fileLayers = await this._emsClient.getFileLayers(); + return fileLayers.map(fileLayer => { + //backfill to older settings + const format = fileLayer.getDefaultFormatType(); + const meta = fileLayer.getDefaultFormatMeta(); + + return { + name: fileLayer.getDisplayName(), + origin: fileLayer.getOrigin(), + id: fileLayer.getId(), + created_at: fileLayer.getCreatedAt(), + attribution: fileLayer.getHTMLAttribution(), + fields: fileLayer.getFieldsInLanguage(), + format: format, //legacy: format and meta are split up + meta: meta, //legacy, format and meta are split up + }; + }); + } + + /** + * Returns all the services published by EMS (if configures) + * It also includes the service configured in tilemap (override) + */ + async getTMSServices() { + let allServices = []; + if (tilemapsConfig.deprecated.isOverridden) { + //use tilemap.* settings from yml + const tmsService = _.cloneDeep(tmsOptionsFromConfig); + tmsService.id = TMS_IN_YML_ID; + tmsService.origin = ORIGIN.KIBANA_YML; + allServices.push(tmsService); + } + + if (mapConfig.includeElasticMapsService) { + const servicesFromManifest = await this._emsClient.getTMSServices(); + const strippedServiceFromManifest = await Promise.all( + servicesFromManifest + .filter(tmsService => tmsService.getId() === mapConfig.emsTileLayerId.bright) + .map(async tmsService => { + //shim for compatibility + const shim = { + origin: tmsService.getOrigin(), + id: tmsService.getId(), + minZoom: await tmsService.getMinZoom(), + maxZoom: await tmsService.getMaxZoom(), + attribution: tmsService.getHTMLAttribution(), + }; + return shim; + }) + ); + allServices = allServices.concat(strippedServiceFromManifest); + } + + return allServices; + } + + /** + * Add optional query-parameters to all requests + * + * @param additionalQueryParams + */ + addQueryParams(additionalQueryParams) { + this._emsClient.addQueryParams(additionalQueryParams); + } + + async getEMSHotLink(fileLayerConfig) { + const fileLayers = await this._emsClient.getFileLayers(); + const layer = fileLayers.find(fileLayer => { + const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy + const hasIdById = fileLayer.hasId(fileLayerConfig.id); + return hasIdByName || hasIdById; + }); + return layer ? layer.getEMSHotLink() : null; + } + + async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) { + const tmsServices = await this._emsClient.getTMSServices(); + const emsTileLayerId = mapConfig.emsTileLayerId; + let serviceId; + if (isDarkMode) { + serviceId = emsTileLayerId.dark; + } else { + if (isDesaturated) { + serviceId = emsTileLayerId.desaturated; + } else { + serviceId = emsTileLayerId.bright; + } + } + const tmsService = tmsServices.find(service => { + return service.getId() === serviceId; + }); + return { + url: await tmsService.getUrlTemplate(), + minZoom: await tmsService.getMinZoom(), + maxZoom: await tmsService.getMaxZoom(), + attribution: await tmsService.getHTMLAttribution(), + origin: ORIGIN.EMS, + }; + } + + async getAttributesForTMSLayer(tmsServiceConfig, isDesaturated, isDarkMode) { + if (tmsServiceConfig.origin === ORIGIN.EMS) { + return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); + } else if (tmsServiceConfig.origin === ORIGIN.KIBANA_YML) { + const config = tilemapsConfig.deprecated.config; + const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); + return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; + } else { + //this is an older config. need to resolve this dynamically. + if (tmsServiceConfig.id === TMS_IN_YML_ID) { + const config = tilemapsConfig.deprecated.config; + const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); + return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; + } else { + //assume ems + return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); + } + } + } + + async _getFileUrlFromEMS(fileLayerConfig) { + const fileLayers = await this._emsClient.getFileLayers(); + const layer = fileLayers.find(fileLayer => { + const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy + const hasIdById = fileLayer.hasId(fileLayerConfig.id); + return hasIdByName || hasIdById; + }); + + if (layer) { + return layer.getDefaultFormatUrl(); + } else { + throw new Error(`File ${fileLayerConfig.name} not recognized`); + } + } + + async getUrlForRegionLayer(fileLayerConfig) { + let url; + if (fileLayerConfig.origin === ORIGIN.EMS) { + url = this._getFileUrlFromEMS(fileLayerConfig); + } else if ( + fileLayerConfig.layerId && + fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`) + ) { + //fallback for older saved objects + url = this._getFileUrlFromEMS(fileLayerConfig); + } else if ( + fileLayerConfig.layerId && + fileLayerConfig.layerId.startsWith(`${ORIGIN.KIBANA_YML}.`) + ) { + //fallback for older saved objects + url = fileLayerConfig.url; + } else { + //generic fallback + url = fileLayerConfig.url; + } + return url; + } + + async getJsonForRegionLayer(fileLayerConfig) { + const url = await this.getUrlForRegionLayer(fileLayerConfig); + const response = await fetch(url); + return await response.json(); + } + } + + return new ServiceSettings(); + }); diff --git a/src/plugins/maps_legacy/public/map/zoom_to_precision.ts b/src/plugins/maps_legacy/public/map/zoom_to_precision.ts new file mode 100644 index 0000000000000..552c509590286 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/zoom_to_precision.ts @@ -0,0 +1,60 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { geohashColumns } from './decode_geo_hash'; + +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 new file mode 100644 index 0000000000000..473c2b1542469 --- /dev/null +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -0,0 +1,46 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +// @ts-ignore +import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; +// @ts-ignore +import { setToasts, setUiSettings } from './kibana_services'; + +/** + * These are the interfaces with your public contracts. You should export these + * for other plugins to use in _their_ `SetupDeps`/`StartDeps` interfaces. + * @public + */ + +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface MapsLegacySetupDependencies {} +// eslint-disable-next-line @typescript-eslint/no-empty-interface +export interface MapsLegacyStartDependencies {} + +export type MapsLegacyPluginSetup = ReturnType; +export type MapsLegacyPluginStart = ReturnType; + +export class MapsLegacyPlugin implements Plugin { + public setup(core: CoreSetup, plugins: MapsLegacySetupDependencies) { + setToasts(core.notifications.toasts); + setUiSettings(core.uiSettings); + } + + public start(core: CoreStart, plugins: MapsLegacyStartDependencies) {} +} From 2b14538e4cde5fc3cc718c8374bf2f0bbc5b0a24 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Mon, 23 Mar 2020 09:58:12 -0600 Subject: [PATCH 02/24] Pull service settings from injected vars. Return new instance of service settings from setup --- src/plugins/maps_legacy/kibana.json | 4 +- src/plugins/maps_legacy/public/index.ts | 7 +- .../maps_legacy/public/kibana_services.js | 4 + .../public/map/service_settings.js | 425 +++++++++--------- src/plugins/maps_legacy/public/plugin.ts | 12 +- 5 files changed, 232 insertions(+), 220 deletions(-) diff --git a/src/plugins/maps_legacy/kibana.json b/src/plugins/maps_legacy/kibana.json index b90295541e807..de11f58bad7e1 100644 --- a/src/plugins/maps_legacy/kibana.json +++ b/src/plugins/maps_legacy/kibana.json @@ -2,7 +2,7 @@ "id": "maps_legacy", "version": "8.0.0", "kibanaVersion": "kibana", - "configPath": ["maps_legacy"], "ui": true, - "requiredPlugins": [] + "configPath": ["map"], + "requiredPlugins": ["kibanaLegacy"] } diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index cec5fc3f0994f..1b0a438e021f5 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -17,8 +17,9 @@ * under the License. */ -import { FileUploadPlugin } from './plugin'; +import { PluginInitializerContext } from 'src/core/public'; +import { MapsLegacyPlugin } from './plugin'; -export function plugin() { - return new FileUploadPlugin(); +export function plugin(initializerContext: PluginInitializerContext) { + return new MapsLegacyPlugin(initializerContext); } diff --git a/src/plugins/maps_legacy/public/kibana_services.js b/src/plugins/maps_legacy/public/kibana_services.js index 55311b8dc395e..815c6f9e5651f 100644 --- a/src/plugins/maps_legacy/public/kibana_services.js +++ b/src/plugins/maps_legacy/public/kibana_services.js @@ -24,3 +24,7 @@ export const getToasts = () => toast; let uiSettings; export const setUiSettings = coreUiSettings => (uiSettings = coreUiSettings); export const getUiSettings = () => uiSettings; + +let getInjectedVar; +export const setInjectedVarFunc = getInjectedVarFunc => (getInjectedVar = getInjectedVarFunc); +export const getInjectedVarFunc = () => getInjectedVar; diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js index d7fb8fde54893..4d61b90fb0b91 100644 --- a/src/plugins/maps_legacy/public/map/service_settings.js +++ b/src/plugins/maps_legacy/public/map/service_settings.js @@ -17,236 +17,235 @@ * under the License. */ -import { uiModules } from '../../modules'; import _ from 'lodash'; import MarkdownIt from 'markdown-it'; import { ORIGIN } from '../../common/origin'; import { EMSClient } from '@elastic/ems-client'; import { i18n } from '@kbn/i18n'; -import 'angular-sanitize'; - -const markdownIt = new MarkdownIt({ - html: false, - linkify: true, -}); +import { getInjectedVarFunc } from '../kibana_services'; const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; -uiModules - .get('kibana', ['ngSanitize']) - .service('serviceSettings', function($sanitize, mapConfig, tilemapsConfig, kbnVersion) { - const attributionFromConfig = $sanitize( - markdownIt.render(tilemapsConfig.deprecated.config.options.attribution || '') - ); - const tmsOptionsFromConfig = _.assign({}, tilemapsConfig.deprecated.config.options, { - attribution: attributionFromConfig, +export class ServiceSettings { + constructor() { + const getInjectedVar = getInjectedVarFunc(); + this.mapConfig = getInjectedVar('mapConfig'); + this.tilemapsConfig = getInjectedVar('tilemapsConfig'); + const kbnVersion = getInjectedVar('version'); + + this._showZoomMessage = true; + this._emsClient = new EMSClient({ + language: i18n.getLocale(), + appVersion: kbnVersion, + appName: 'kibana', + fileApiUrl: this.mapConfig.emsFileApiUrl, + tileApiUrl: this.mapConfig.emsTileApiUrl, + htmlSanitizer: _.escape, + landingPageUrl: this.mapConfig.emsLandingPageUrl, }); + this.getTMSOptions(); + } - class ServiceSettings { - constructor() { - this._showZoomMessage = true; - this._emsClient = new EMSClient({ - language: i18n.getLocale(), - appVersion: kbnVersion, - appName: 'kibana', - fileApiUrl: mapConfig.emsFileApiUrl, - tileApiUrl: mapConfig.emsTileApiUrl, - htmlSanitizer: $sanitize, - landingPageUrl: mapConfig.emsLandingPageUrl, - }); - } - - shouldShowZoomMessage({ origin }) { - return origin === ORIGIN.EMS && this._showZoomMessage; - } - - disableZoomMessage() { - this._showZoomMessage = false; - } - - __debugStubManifestCalls(manifestRetrieval) { - const oldGetManifest = this._emsClient.getManifest; - this._emsClient.getManifest = manifestRetrieval; - return { - removeStub: () => { - delete this._emsClient.getManifest; - //not strictly necessary since this is prototype method - if (this._emsClient.getManifest !== oldGetManifest) { - this._emsClient.getManifest = oldGetManifest; - } - }, - }; - } - - async getFileLayers() { - if (!mapConfig.includeElasticMapsService) { - return []; - } - - const fileLayers = await this._emsClient.getFileLayers(); - return fileLayers.map(fileLayer => { - //backfill to older settings - const format = fileLayer.getDefaultFormatType(); - const meta = fileLayer.getDefaultFormatMeta(); - - return { - name: fileLayer.getDisplayName(), - origin: fileLayer.getOrigin(), - id: fileLayer.getId(), - created_at: fileLayer.getCreatedAt(), - attribution: fileLayer.getHTMLAttribution(), - fields: fileLayer.getFieldsInLanguage(), - format: format, //legacy: format and meta are split up - meta: meta, //legacy, format and meta are split up - }; - }); - } - - /** - * Returns all the services published by EMS (if configures) - * It also includes the service configured in tilemap (override) - */ - async getTMSServices() { - let allServices = []; - if (tilemapsConfig.deprecated.isOverridden) { - //use tilemap.* settings from yml - const tmsService = _.cloneDeep(tmsOptionsFromConfig); - tmsService.id = TMS_IN_YML_ID; - tmsService.origin = ORIGIN.KIBANA_YML; - allServices.push(tmsService); - } + getTMSOptions() { + const markdownIt = new MarkdownIt({ + html: false, + linkify: true, + }); - if (mapConfig.includeElasticMapsService) { - const servicesFromManifest = await this._emsClient.getTMSServices(); - const strippedServiceFromManifest = await Promise.all( - servicesFromManifest - .filter(tmsService => tmsService.getId() === mapConfig.emsTileLayerId.bright) - .map(async tmsService => { - //shim for compatibility - const shim = { - origin: tmsService.getOrigin(), - id: tmsService.getId(), - minZoom: await tmsService.getMinZoom(), - maxZoom: await tmsService.getMaxZoom(), - attribution: tmsService.getHTMLAttribution(), - }; - return shim; - }) - ); - allServices = allServices.concat(strippedServiceFromManifest); + // TMS attribution + const attributionFromConfig = _.escape( + markdownIt.render(this.tilemapsConfig.deprecated.config.options.attribution || '') + ); + // TMS Options + this.tmsOptionsFromConfig = _.assign({}, this.tilemapsConfig.deprecated.config.options, { + attribution: attributionFromConfig, + }); + } + + shouldShowZoomMessage({ origin }) { + return origin === ORIGIN.EMS && this._showZoomMessage; + } + + disableZoomMessage() { + this._showZoomMessage = false; + } + + __debugStubManifestCalls(manifestRetrieval) { + const oldGetManifest = this._emsClient.getManifest; + this._emsClient.getManifest = manifestRetrieval; + return { + removeStub: () => { + delete this._emsClient.getManifest; + //not strictly necessary since this is prototype method + if (this._emsClient.getManifest !== oldGetManifest) { + this._emsClient.getManifest = oldGetManifest; } + }, + }; + } - return allServices; - } - - /** - * Add optional query-parameters to all requests - * - * @param additionalQueryParams - */ - addQueryParams(additionalQueryParams) { - this._emsClient.addQueryParams(additionalQueryParams); - } - - async getEMSHotLink(fileLayerConfig) { - const fileLayers = await this._emsClient.getFileLayers(); - const layer = fileLayers.find(fileLayer => { - const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy - const hasIdById = fileLayer.hasId(fileLayerConfig.id); - return hasIdByName || hasIdById; - }); - return layer ? layer.getEMSHotLink() : null; - } - - async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) { - const tmsServices = await this._emsClient.getTMSServices(); - const emsTileLayerId = mapConfig.emsTileLayerId; - let serviceId; - if (isDarkMode) { - serviceId = emsTileLayerId.dark; - } else { - if (isDesaturated) { - serviceId = emsTileLayerId.desaturated; - } else { - serviceId = emsTileLayerId.bright; - } - } - const tmsService = tmsServices.find(service => { - return service.getId() === serviceId; - }); - return { - url: await tmsService.getUrlTemplate(), - minZoom: await tmsService.getMinZoom(), - maxZoom: await tmsService.getMaxZoom(), - attribution: await tmsService.getHTMLAttribution(), - origin: ORIGIN.EMS, - }; - } + async getFileLayers() { + if (!this.mapConfig.includeElasticMapsService) { + return []; + } - async getAttributesForTMSLayer(tmsServiceConfig, isDesaturated, isDarkMode) { - if (tmsServiceConfig.origin === ORIGIN.EMS) { - return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); - } else if (tmsServiceConfig.origin === ORIGIN.KIBANA_YML) { - const config = tilemapsConfig.deprecated.config; - const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); - return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; - } else { - //this is an older config. need to resolve this dynamically. - if (tmsServiceConfig.id === TMS_IN_YML_ID) { - const config = tilemapsConfig.deprecated.config; - const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); - return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; - } else { - //assume ems - return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); - } - } - } + const fileLayers = await this._emsClient.getFileLayers(); + return fileLayers.map(fileLayer => { + //backfill to older settings + const format = fileLayer.getDefaultFormatType(); + const meta = fileLayer.getDefaultFormatMeta(); + + return { + name: fileLayer.getDisplayName(), + origin: fileLayer.getOrigin(), + id: fileLayer.getId(), + created_at: fileLayer.getCreatedAt(), + attribution: fileLayer.getHTMLAttribution(), + fields: fileLayer.getFieldsInLanguage(), + format: format, //legacy: format and meta are split up + meta: meta, //legacy, format and meta are split up + }; + }); + } + + /** + * Returns all the services published by EMS (if configures) + * It also includes the service configured in tilemap (override) + */ + async getTMSServices() { + let allServices = []; + if (this.tilemapsConfig.deprecated.isOverridden) { + //use tilemap.* settings from yml + const tmsService = _.cloneDeep(this.tmsOptionsFromConfig); + tmsService.id = TMS_IN_YML_ID; + tmsService.origin = ORIGIN.KIBANA_YML; + allServices.push(tmsService); + } - async _getFileUrlFromEMS(fileLayerConfig) { - const fileLayers = await this._emsClient.getFileLayers(); - const layer = fileLayers.find(fileLayer => { - const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy - const hasIdById = fileLayer.hasId(fileLayerConfig.id); - return hasIdByName || hasIdById; - }); - - if (layer) { - return layer.getDefaultFormatUrl(); - } else { - throw new Error(`File ${fileLayerConfig.name} not recognized`); - } - } + if (this.mapConfig.includeElasticMapsService) { + const servicesFromManifest = await this._emsClient.getTMSServices(); + const strippedServiceFromManifest = await Promise.all( + servicesFromManifest + .filter(tmsService => tmsService.getId() === this.mapConfig.emsTileLayerId.bright) + .map(async tmsService => { + //shim for compatibility + return { + origin: tmsService.getOrigin(), + id: tmsService.getId(), + minZoom: await tmsService.getMinZoom(), + maxZoom: await tmsService.getMaxZoom(), + attribution: tmsService.getHTMLAttribution(), + }; + }) + ); + allServices = allServices.concat(strippedServiceFromManifest); + } - async getUrlForRegionLayer(fileLayerConfig) { - let url; - if (fileLayerConfig.origin === ORIGIN.EMS) { - url = this._getFileUrlFromEMS(fileLayerConfig); - } else if ( - fileLayerConfig.layerId && - fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`) - ) { - //fallback for older saved objects - url = this._getFileUrlFromEMS(fileLayerConfig); - } else if ( - fileLayerConfig.layerId && - fileLayerConfig.layerId.startsWith(`${ORIGIN.KIBANA_YML}.`) - ) { - //fallback for older saved objects - url = fileLayerConfig.url; - } else { - //generic fallback - url = fileLayerConfig.url; - } - return url; + return allServices; + } + + /** + * Add optional query-parameters to all requests + * + * @param additionalQueryParams + */ + addQueryParams(additionalQueryParams) { + this._emsClient.addQueryParams(additionalQueryParams); + } + + async getEMSHotLink(fileLayerConfig) { + const fileLayers = await this._emsClient.getFileLayers(); + const layer = fileLayers.find(fileLayer => { + const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy + const hasIdById = fileLayer.hasId(fileLayerConfig.id); + return hasIdByName || hasIdById; + }); + return layer ? layer.getEMSHotLink() : null; + } + + async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) { + const tmsServices = await this._emsClient.getTMSServices(); + const emsTileLayerId = this.mapConfig.emsTileLayerId; + let serviceId; + if (isDarkMode) { + serviceId = emsTileLayerId.dark; + } else { + if (isDesaturated) { + serviceId = emsTileLayerId.desaturated; + } else { + serviceId = emsTileLayerId.bright; } - - async getJsonForRegionLayer(fileLayerConfig) { - const url = await this.getUrlForRegionLayer(fileLayerConfig); - const response = await fetch(url); - return await response.json(); + } + const tmsService = tmsServices.find(service => { + return service.getId() === serviceId; + }); + return { + url: await tmsService.getUrlTemplate(), + minZoom: await tmsService.getMinZoom(), + maxZoom: await tmsService.getMaxZoom(), + attribution: await tmsService.getHTMLAttribution(), + origin: ORIGIN.EMS, + }; + } + + async getAttributesForTMSLayer(tmsServiceConfig, isDesaturated, isDarkMode) { + if (tmsServiceConfig.origin === ORIGIN.EMS) { + return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); + } else if (tmsServiceConfig.origin === ORIGIN.KIBANA_YML) { + const config = this.tilemapsConfig.deprecated.config; + const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); + return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; + } else { + //this is an older config. need to resolve this dynamically. + if (tmsServiceConfig.id === TMS_IN_YML_ID) { + const config = this.tilemapsConfig.deprecated.config; + const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); + return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; + } else { + //assume ems + return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); } } + } + + async _getFileUrlFromEMS(fileLayerConfig) { + const fileLayers = await this._emsClient.getFileLayers(); + const layer = fileLayers.find(fileLayer => { + const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy + const hasIdById = fileLayer.hasId(fileLayerConfig.id); + return hasIdByName || hasIdById; + }); - return new ServiceSettings(); - }); + if (layer) { + return layer.getDefaultFormatUrl(); + } else { + throw new Error(`File ${fileLayerConfig.name} not recognized`); + } + } + + async getUrlForRegionLayer(fileLayerConfig) { + let url; + if (fileLayerConfig.origin === ORIGIN.EMS) { + url = this._getFileUrlFromEMS(fileLayerConfig); + } else if (fileLayerConfig.layerId && fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`)) { + //fallback for older saved objects + url = this._getFileUrlFromEMS(fileLayerConfig); + } else if ( + fileLayerConfig.layerId && + fileLayerConfig.layerId.startsWith(`${ORIGIN.KIBANA_YML}.`) + ) { + //fallback for older saved objects + url = fileLayerConfig.url; + } else { + //generic fallback + url = fileLayerConfig.url; + } + return url; + } + + async getJsonForRegionLayer(fileLayerConfig) { + const url = await this.getUrlForRegionLayer(fileLayerConfig); + const response = await fetch(url); + return await response.json(); + } +} diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index 473c2b1542469..7af8c3050e3e9 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -18,9 +18,10 @@ */ // @ts-ignore -import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; +import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public'; // @ts-ignore -import { setToasts, setUiSettings } from './kibana_services'; +import { setToasts, setUiSettings, setInjectedVarFunc } from './kibana_services'; +import { ServiceSettings } from './map/service_settings'; /** * These are the interfaces with your public contracts. You should export these @@ -37,9 +38,16 @@ export type MapsLegacyPluginSetup = ReturnType; export type MapsLegacyPluginStart = ReturnType; export class MapsLegacyPlugin implements Plugin { + constructor(private readonly initializerContext: PluginInitializerContext) {} + public setup(core: CoreSetup, plugins: MapsLegacySetupDependencies) { setToasts(core.notifications.toasts); setUiSettings(core.uiSettings); + setInjectedVarFunc(core.injectedMetadata.getInjectedVar); + + return { + serviceSettings: new ServiceSettings(), + }; } public start(core: CoreStart, plugins: MapsLegacyStartDependencies) {} From ccb2333fdaa64f2c4247a45343fc0e6a47f602ed Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Mon, 23 Mar 2020 14:42:57 -0600 Subject: [PATCH 03/24] Use NP service settings in vega maps. Clean up legacy shim --- .../vis_type_vega/public/legacy.ts | 5 -- .../vis_type_vega/public/plugin.ts | 21 ++++---- .../vis_type_vega/public/shim/index.ts | 20 -------- .../public/shim/legacy_dependencies_plugin.ts | 49 ------------------- src/plugins/maps_legacy/public/_index.scss | 1 + 5 files changed, 10 insertions(+), 86 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/shim/index.ts delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts create mode 100644 src/plugins/maps_legacy/public/_index.scss diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts index 38ce706ed13ef..11b1ab6c38783 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts @@ -22,16 +22,11 @@ import { npSetup, npStart } from 'ui/new_platform'; import { setup as visualizationsSetup } from '../../visualizations/public/np_ready/public/legacy'; import { VegaPluginSetupDependencies, VegaPluginStartDependencies } from './plugin'; -import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; const setupPlugins: Readonly = { ...npSetup.plugins, visualizations: visualizationsSetup, - - // Temporary solution - // It will be removed when all dependent services are migrated to the new platform. - __LEGACY: new LegacyDependenciesPlugin(), }; const startPlugins: Readonly = { diff --git a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts index 3b01d9ceca5a6..0fa62f4e555fc 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts @@ -17,7 +17,6 @@ * under the License. */ import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '../../../../core/public'; -import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim'; import { Plugin as ExpressionsPublicPlugin } from '../../../../plugins/expressions/public'; import { Plugin as DataPublicPlugin } from '../../../../plugins/data/public'; import { VisualizationsSetup } from '../../visualizations/public'; @@ -33,21 +32,12 @@ import { createVegaFn } from './vega_fn'; import { createVegaTypeDefinition } from './vega_type'; import { VisTypeVegaSetup } from '../../../../plugins/vis_type_vega/public'; -/** @internal */ -export interface VegaVisualizationDependencies extends LegacyDependenciesPluginSetup { - core: CoreSetup; - plugins: { - data: ReturnType; - }; -} - /** @internal */ export interface VegaPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; data: ReturnType; visTypeVega: VisTypeVegaSetup; - __LEGACY: LegacyDependenciesPlugin; } /** @internal */ @@ -65,7 +55,14 @@ export class VegaPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { data, expressions, visualizations, visTypeVega, __LEGACY }: VegaPluginSetupDependencies + { + data, + expressions, + visualizations, + visTypeVega, + maps_legacy, + __LEGACY, + }: VegaPluginSetupDependencies ) { setInjectedVars({ enableExternalUrls: visTypeVega.config.enableExternalUrls, @@ -79,7 +76,7 @@ export class VegaPlugin implements Plugin, void> { plugins: { data, }, - ...(await __LEGACY.setup()), + serviceSettings: maps_legacy.serviceSettings, }; expressions.registerFunction(() => createVegaFn(visualizationDependencies)); diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/index.ts b/src/legacy/core_plugins/vis_type_vega/public/shim/index.ts deleted file mode 100644 index cfc7b62ff4f86..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export * from './legacy_dependencies_plugin'; diff --git a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts deleted file mode 100644 index 8925f76cffa43..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/shim/legacy_dependencies_plugin.ts +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// TODO remove this file as soon as serviceSettings is exposed in the new platform -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import chrome from 'ui/chrome'; -// eslint-disable-next-line @kbn/eslint/no-restricted-paths -import 'ui/vis/map/service_settings'; -import { CoreStart, Plugin } from 'kibana/public'; - -/** @internal */ -export interface LegacyDependenciesPluginSetup { - serviceSettings: any; -} - -export class LegacyDependenciesPlugin - implements Plugin, void> { - public async setup() { - const $injector = await chrome.dangerouslyGetActiveInjector(); - - return { - // Settings for EMSClient. - // EMSClient, which currently lives in the tile_map vis, - // will probably end up being exposed from the future vis_type_maps plugin, - // which would register both the tile_map and the region_map vis plugins. - serviceSettings: $injector.get('serviceSettings'), - } as LegacyDependenciesPluginSetup; - } - - public start(core: CoreStart) { - // nothing to do here yet - } -} diff --git a/src/plugins/maps_legacy/public/_index.scss b/src/plugins/maps_legacy/public/_index.scss new file mode 100644 index 0000000000000..28cf4289bb048 --- /dev/null +++ b/src/plugins/maps_legacy/public/_index.scss @@ -0,0 +1 @@ +@import './map/index'; From f4598cf529fa1f97d91997a50956e3674598c5a1 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Tue, 24 Mar 2020 10:06:18 -0600 Subject: [PATCH 04/24] Use NP maps service in region maps. Clean up shim. Add exports to NP service --- .../region_map/public/choropleth_layer.js | 4 +-- .../core_plugins/region_map/public/legacy.ts | 1 + .../core_plugins/region_map/public/plugin.ts | 8 +++++- .../public/shim/legacy_dependencies_plugin.ts | 7 ----- .../core_plugins/region_map/public/types.ts | 2 +- src/plugins/maps_legacy/public/index.ts | 27 ++++++++++++++++--- src/plugins/maps_legacy/public/plugin.ts | 5 ++-- 7 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/choropleth_layer.js b/src/legacy/core_plugins/region_map/public/choropleth_layer.js index e637a217bfbc3..df368abca1b16 100644 --- a/src/legacy/core_plugins/region_map/public/choropleth_layer.js +++ b/src/legacy/core_plugins/region_map/public/choropleth_layer.js @@ -22,11 +22,9 @@ import L from 'leaflet'; import _ from 'lodash'; import d3 from 'd3'; import { i18n } from '@kbn/i18n'; -import { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; import * as topojson from 'topojson-client'; import { toastNotifications } from 'ui/notify'; -import * as colorUtil from 'ui/vis/map/color_util'; - +import { colorUtil, KibanaMapLayer } from '../../../../plugins/maps_legacy/public' import { truncatedColorMaps } from '../../../../plugins/charts/public'; const EMPTY_STYLE = { diff --git a/src/legacy/core_plugins/region_map/public/legacy.ts b/src/legacy/core_plugins/region_map/public/legacy.ts index 495e558e29dd7..3625b46e94dc1 100644 --- a/src/legacy/core_plugins/region_map/public/legacy.ts +++ b/src/legacy/core_plugins/region_map/public/legacy.ts @@ -32,6 +32,7 @@ const regionmapsConfig = npSetup.core.injectedMetadata.getInjectedVar( const plugins: Readonly = { expressions: npSetup.plugins.expressions, visualizations: visualizationsSetup, + maps_legacy: npSetup.plugins.maps_legacy, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index 98fb5604c3d65..a01fe9940bd65 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -32,10 +32,13 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createRegionMapFn } from './region_map_fn'; // @ts-ignore import { createRegionMapTypeDefinition } from './region_map_type'; +import { ServiceSettingsSetupContract } from '../../../../plugins/maps_legacy/public'; /** @private */ interface RegionMapVisualizationDependencies extends LegacyDependenciesPluginSetup { uiSettings: IUiSettingsClient; + regionmapsConfig: RegionMapsConfig; + serviceSettings: ServiceSettingsSetupContract } /** @internal */ @@ -43,6 +46,7 @@ export interface RegionMapPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; __LEGACY: LegacyDependenciesPlugin; + maps_legacy: any; } /** @internal */ @@ -61,10 +65,12 @@ export class RegionMapPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations, __LEGACY }: RegionMapPluginSetupDependencies + { expressions, visualizations, maps_legacy, __LEGACY }: RegionMapPluginSetupDependencies ) { const visualizationDependencies: Readonly = { uiSettings: core.uiSettings, + regionmapsConfig: core.injectedMetadata.getInjectedVar('regionmapsConfig'), + serviceSettings: maps_legacy.serviceSettings, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts index c47fc40fbacd7..35bdff415306e 100644 --- a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts @@ -31,19 +31,12 @@ export interface LegacyDependenciesPluginSetup { export class LegacyDependenciesPlugin implements Plugin, void> { - constructor(private readonly regionmapsConfig: RegionMapsConfig) {} public async setup() { const $injector = await chrome.dangerouslyGetActiveInjector(); return { $injector, - regionmapsConfig: this.regionmapsConfig, - // Settings for EMSClient. - // EMSClient, which currently lives in the tile_map vis, - // will probably end up being exposed from the future vis_type_maps plugin, - // which would register both the tile_map and the region_map vis plugins. - serviceSettings: $injector.get('serviceSettings'), } as LegacyDependenciesPluginSetup; } diff --git a/src/legacy/core_plugins/region_map/public/types.ts b/src/legacy/core_plugins/region_map/public/types.ts index 2097aebd27ce0..8585bf720e0cf 100644 --- a/src/legacy/core_plugins/region_map/public/types.ts +++ b/src/legacy/core_plugins/region_map/public/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { VectorLayer, FileLayerField } from 'ui/vis/map/service_settings'; +import { VectorLayer, FileLayerField } from '../../../../plugins/maps_legacy/public'; import { WMSOptions } from '../../tile_map/public/types'; export interface RegionMapVisParams { diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 1b0a438e021f5..9157ac43e7d51 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -17,9 +17,30 @@ * under the License. */ -import { PluginInitializerContext } from 'src/core/public'; import { MapsLegacyPlugin } from './plugin'; +// @ts-ignore +import * as colorUtil from './map/color_util' +// @ts-ignore +import { KibanaMapLayer } from './map/kibana_map_layer'; +// @ts-ignore +import { + VectorLayer, + FileLayerField, + FileLayer, + ServiceSettingsSetupContract +} from './map/service_settings'; -export function plugin(initializerContext: PluginInitializerContext) { - return new MapsLegacyPlugin(initializerContext); + +export function plugin() { + return new MapsLegacyPlugin(); +} + +/** @public */ +export { + colorUtil, + KibanaMapLayer, + VectorLayer, + FileLayerField, + FileLayer, + ServiceSettingsSetupContract } diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index 7af8c3050e3e9..98c61415202fe 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -18,9 +18,10 @@ */ // @ts-ignore -import { CoreSetup, CoreStart, Plugin, PluginInitializerContext } from 'kibana/public'; +import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; // @ts-ignore import { setToasts, setUiSettings, setInjectedVarFunc } from './kibana_services'; +// @ts-ignore import { ServiceSettings } from './map/service_settings'; /** @@ -38,7 +39,7 @@ export type MapsLegacyPluginSetup = ReturnType; export type MapsLegacyPluginStart = ReturnType; export class MapsLegacyPlugin implements Plugin { - constructor(private readonly initializerContext: PluginInitializerContext) {} + constructor() {} public setup(core: CoreSetup, plugins: MapsLegacySetupDependencies) { setToasts(core.notifications.toasts); From 1556d404d98e2c3c97fe843bc3036921a57dab7b Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Tue, 24 Mar 2020 16:25:57 -0600 Subject: [PATCH 05/24] Pull zoom precision out to separate module since it's dependent on config --- src/plugins/maps_legacy/public/index.ts | 22 ++++++-- .../maps_legacy/public/map/decode_geo_hash.ts | 33 ----------- .../maps_legacy/public/map/zoom_precision.ts | 56 +++++++++++++++++++ src/plugins/maps_legacy/public/plugin.ts | 3 + 4 files changed, 76 insertions(+), 38 deletions(-) create mode 100644 src/plugins/maps_legacy/public/map/zoom_precision.ts diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 9157ac43e7d51..9168c87ef6c72 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -19,28 +19,40 @@ import { MapsLegacyPlugin } from './plugin'; // @ts-ignore -import * as colorUtil from './map/color_util' +import * as colorUtil from './map/color_util'; +// @ts-ignore +import { KibanaMap } from './map/kibana_map'; // @ts-ignore import { KibanaMapLayer } from './map/kibana_map_layer'; // @ts-ignore +import { convertToGeoJson } from './map/convert_to_geojson'; +// @ts-ignore +import { scaleBounds, getPrecision, geoContains } from './map/decode_geo_hash'; +// @ts-ignore import { VectorLayer, FileLayerField, FileLayer, - ServiceSettingsSetupContract + ServiceSettingsSetupContract, + TmsLayer, } from './map/service_settings'; - export function plugin() { return new MapsLegacyPlugin(); } /** @public */ export { + scaleBounds, + getPrecision, + geoContains, colorUtil, + convertToGeoJson, + KibanaMap, KibanaMapLayer, VectorLayer, FileLayerField, FileLayer, - ServiceSettingsSetupContract -} + ServiceSettingsSetupContract, + TmsLayer, +}; diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts index cf2e2056d97dc..5afcad7ec5bf2 100644 --- a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts @@ -18,7 +18,6 @@ */ import _ from 'lodash'; -import { getUiSettings } from '../kibana_services'; interface DecodedGeoHash { latitude: number[]; @@ -88,38 +87,6 @@ function geohashCells(precision: number, axis: number) { return cells; } -/** - * Get the number of geohash columns (world-wide) for a given precision - * @param precision the geohash precision - * @returns {number} the number of columns - */ -export function geohashColumns(precision: number): number { - return geohashCells(precision, 0); -} - -const config = getUiSettings(); -const defaultPrecision = 2; -const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; -/** - * 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. - */ -export const zoomPrecision: any = {}; -const minGeohashPixels = 16; - -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; - } - } -} - export function getPrecision(val: string) { let precision = parseInt(val, 10); diff --git a/src/plugins/maps_legacy/public/map/zoom_precision.ts b/src/plugins/maps_legacy/public/map/zoom_precision.ts new file mode 100644 index 0000000000000..38e80271397a1 --- /dev/null +++ b/src/plugins/maps_legacy/public/map/zoom_precision.ts @@ -0,0 +1,56 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { getUiSettings } from '../kibana_services'; + +/** + * Get the number of geohash columns (world-wide) for a given precision + * @param precision the geohash precision + * @returns {number} the number of columns + */ +export function geohashColumns(precision: number): number { + return geohashCells(precision, 0); +} + +export function getZoomPrecision() { + const config = getUiSettings(); + const defaultPrecision = 2; + const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; + + /** + * 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; + + 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; +} diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index 98c61415202fe..bb48f84969076 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -23,6 +23,8 @@ import { CoreSetup, CoreStart, Plugin } from 'kibana/public'; import { setToasts, setUiSettings, setInjectedVarFunc } from './kibana_services'; // @ts-ignore import { ServiceSettings } from './map/service_settings'; +// @ts-ignore +import { getZoomPrecision } from './map/zoom_precision'; /** * These are the interfaces with your public contracts. You should export these @@ -48,6 +50,7 @@ export class MapsLegacyPlugin implements Plugin Date: Wed, 25 Mar 2020 16:07:25 -0600 Subject: [PATCH 06/24] Update paths to point to NP resources --- src/legacy/core_plugins/region_map/public/choropleth_layer.js | 2 +- src/legacy/core_plugins/region_map/public/plugin.ts | 4 ++-- .../region_map/public/shim/legacy_dependencies_plugin.ts | 2 -- .../core_plugins/tile_map/public/__tests__/geohash_layer.js | 2 +- .../core_plugins/tile_map/public/base_maps_visualization.js | 3 +-- .../core_plugins/tile_map/public/components/wms_options.tsx | 3 +-- src/legacy/core_plugins/tile_map/public/geohash_layer.js | 3 +-- .../core_plugins/tile_map/public/markers/scaled_circles.js | 3 +-- src/legacy/core_plugins/tile_map/public/tile_map_fn.js | 2 +- src/legacy/core_plugins/tile_map/public/tile_map_type.js | 4 +--- src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js | 2 +- src/legacy/core_plugins/tile_map/public/types.ts | 2 +- .../timelion/public/shim/timelion_legacy_module.ts | 1 - .../vis_type_vega/public/vega_view/vega_map_layer.js | 2 +- .../vis_type_vega/public/vega_view/vega_map_view.js | 2 +- 15 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/choropleth_layer.js b/src/legacy/core_plugins/region_map/public/choropleth_layer.js index df368abca1b16..4ea9cc1f7bfbf 100644 --- a/src/legacy/core_plugins/region_map/public/choropleth_layer.js +++ b/src/legacy/core_plugins/region_map/public/choropleth_layer.js @@ -24,7 +24,7 @@ import d3 from 'd3'; import { i18n } from '@kbn/i18n'; import * as topojson from 'topojson-client'; import { toastNotifications } from 'ui/notify'; -import { colorUtil, KibanaMapLayer } from '../../../../plugins/maps_legacy/public' +import { colorUtil, KibanaMapLayer } from '../../../../plugins/maps_legacy/public'; import { truncatedColorMaps } from '../../../../plugins/charts/public'; const EMPTY_STYLE = { diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index a01fe9940bd65..d3cbbcfcaae4f 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -38,7 +38,7 @@ import { ServiceSettingsSetupContract } from '../../../../plugins/maps_legacy/pu interface RegionMapVisualizationDependencies extends LegacyDependenciesPluginSetup { uiSettings: IUiSettingsClient; regionmapsConfig: RegionMapsConfig; - serviceSettings: ServiceSettingsSetupContract + serviceSettings: ServiceSettingsSetupContract; } /** @internal */ @@ -65,7 +65,7 @@ export class RegionMapPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations, maps_legacy, __LEGACY }: RegionMapPluginSetupDependencies + { expressions, visualizations, maps_legacy, __LEGACY }: RegionMapPluginSetupDependencies ) { const visualizationDependencies: Readonly = { uiSettings: core.uiSettings, diff --git a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts index 35bdff415306e..a952ea08ec6b3 100644 --- a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts @@ -19,7 +19,6 @@ import chrome from 'ui/chrome'; import { CoreStart, Plugin } from 'kibana/public'; -import 'ui/vis/map/service_settings'; import { RegionMapsConfig } from '../plugin'; /** @internal */ @@ -31,7 +30,6 @@ export interface LegacyDependenciesPluginSetup { export class LegacyDependenciesPlugin implements Plugin, void> { - public async setup() { const $injector = await chrome.dangerouslyGetActiveInjector(); diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js b/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js index 857432079e376..fc029d6bccb6e 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/geohash_layer.js @@ -18,13 +18,13 @@ */ import expect from '@kbn/expect'; -import { KibanaMap } from 'ui/vis/map/kibana_map'; import { GeohashLayer } from '../geohash_layer'; // import heatmapPng from './heatmap.png'; import scaledCircleMarkersPng from './scaledCircleMarkers.png'; // import shadedCircleMarkersPng from './shadedCircleMarkers.png'; import { ImageComparator } from 'test_utils/image_comparator'; import GeoHashSampleData from './dummy_es_response.json'; +import { KibanaMap } from '../../../../../plugins/maps_legacy/public'; describe('geohash_layer', function() { let domNode; diff --git a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js index d38159c91ef9f..5b21db582be7b 100644 --- a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js @@ -19,10 +19,9 @@ import _ from 'lodash'; import { i18n } from '@kbn/i18n'; -import { KibanaMap } from 'ui/vis/map/kibana_map'; +import { KibanaMap } from '../../../../plugins/maps_legacy/public'; import * as Rx from 'rxjs'; import { filter, first } from 'rxjs/operators'; -import 'ui/vis/map/service_settings'; import { toastNotifications } from 'ui/notify'; import chrome from 'ui/chrome'; diff --git a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx index 204ad5efa9b40..ed8f6950f287b 100644 --- a/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx +++ b/src/legacy/core_plugins/tile_map/public/components/wms_options.tsx @@ -21,8 +21,7 @@ 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 'ui/vis/map/service_settings'; +import { TmsLayer } from '../../../../../plugins/maps_legacy/public'; import { Vis } from '../../../visualizations/public'; import { RegionMapVisParams } from '../../../region_map/public/types'; import { SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; diff --git a/src/legacy/core_plugins/tile_map/public/geohash_layer.js b/src/legacy/core_plugins/tile_map/public/geohash_layer.js index a604e02be7c8c..b9acf1a15208f 100644 --- a/src/legacy/core_plugins/tile_map/public/geohash_layer.js +++ b/src/legacy/core_plugins/tile_map/public/geohash_layer.js @@ -20,8 +20,7 @@ import L from 'leaflet'; import { min, isEqual } from 'lodash'; import { i18n } from '@kbn/i18n'; - -import { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; +import { KibanaMapLayer } from '../../../../plugins/maps_legacy/public'; import { HeatmapMarkers } from './markers/heatmap'; import { ScaledCirclesMarkers } from './markers/scaled_circles'; import { ShadedCirclesMarkers } from './markers/shaded_circles'; diff --git a/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js b/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js index 88d6db82946c7..f39de6ca7d179 100644 --- a/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js +++ b/src/legacy/core_plugins/tile_map/public/markers/scaled_circles.js @@ -22,8 +22,7 @@ import _ from 'lodash'; import d3 from 'd3'; import $ from 'jquery'; import { EventEmitter } from 'events'; -import * as colorUtil from 'ui/vis/map/color_util'; - +import { colorUtil } from '../../../../../plugins/maps_legacy/public'; import { truncatedColorMaps } from '../../../../../plugins/charts/public'; export class ScaledCirclesMarkers extends EventEmitter { diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_fn.js b/src/legacy/core_plugins/tile_map/public/tile_map_fn.js index 2f54d23590c33..5ad4a2c33db25 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_fn.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_fn.js @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; +import { convertToGeoJson } from '../../../../plugins/maps_legacy/public'; import { i18n } from '@kbn/i18n'; export const createTileMapFn = () => ({ diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_type.js b/src/legacy/core_plugins/tile_map/public/tile_map_type.js index 39d39a4c8f8fc..4efe8283c6879 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_type.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_type.js @@ -19,9 +19,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; - -import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; - +import { convertToGeoJson } from '../../../../plugins/maps_legacy/public'; import { Schemas } from '../../vis_default_editor/public'; import { createTileMapVisualization } from './tile_map_visualization'; import { TileMapOptions } from './components/tile_map_options'; diff --git a/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js b/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js index 0913d6fc92e8a..4f30b2aa1f24c 100644 --- a/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js +++ b/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js @@ -37,7 +37,7 @@ jest.mock('ui/vis/map/convert_to_geojson', () => ({ }), })); -import { convertToGeoJson } from 'ui/vis/map/convert_to_geojson'; +import { convertToGeoJson } from '../../../../plugins/maps_legacy/public'; describe('interpreter/functions#tilemap', () => { const fn = functionWrapper(createTileMapFn()); diff --git a/src/legacy/core_plugins/tile_map/public/types.ts b/src/legacy/core_plugins/tile_map/public/types.ts index 5f1c3f9b03c9e..e1b4c27319123 100644 --- a/src/legacy/core_plugins/tile_map/public/types.ts +++ b/src/legacy/core_plugins/tile_map/public/types.ts @@ -17,7 +17,7 @@ * under the License. */ -import { TmsLayer } from 'ui/vis/map/service_settings'; +import { TmsLayer } from '../../../../plugins/maps_legacy/public'; import { MapTypes } from './map_types'; export interface WMSOptions { diff --git a/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts b/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts index 9de8477e3978c..8fadf223e1807 100644 --- a/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts +++ b/src/legacy/core_plugins/timelion/public/shim/timelion_legacy_module.ts @@ -21,7 +21,6 @@ import 'ngreact'; import 'brace/mode/hjson'; import 'brace/ext/searchbox'; import 'ui/accessibility/kbn_ui_ace_keyboard_mode'; -import 'ui/vis/map/service_settings'; import { once } from 'lodash'; // @ts-ignore diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js index 38540e9f218fb..d43eb9c3351ea 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_layer.js @@ -19,7 +19,7 @@ import L from 'leaflet'; import 'leaflet-vega'; -import { KibanaMapLayer } from '../legacy_imports'; +import { KibanaMapLayer } from '../../../../../plugins/maps_legacy/public'; export class VegaMapLayer extends KibanaMapLayer { constructor(spec, options) { diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js index 487c90d01ada3..74c8588f10d17 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js @@ -21,7 +21,7 @@ import * as vega from 'vega-lib'; import { i18n } from '@kbn/i18n'; import { VegaBaseView } from './vega_base_view'; import { VegaMapLayer } from './vega_map_layer'; -import { KibanaMap } from '../legacy_imports'; +import { KibanaMap } from '../../../../../plugins/maps_legacy/public'; import { getEmsTileLayerId, getUISettings } from '../services'; export class VegaMapView extends VegaBaseView { From 86b62e2be8dfdb42eb0dc1a6d713981cfbabc073 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 26 Mar 2020 11:46:22 -0600 Subject: [PATCH 07/24] More path updates, clean up, use IServiceSettings --- .../public/components/region_map_options.tsx | 9 +++++--- .../core_plugins/region_map/public/plugin.ts | 4 ++-- .../core_plugins/region_map/public/util.ts | 2 +- .../core_plugins/tile_map/public/legacy.ts | 1 + .../core_plugins/tile_map/public/plugin.ts | 14 ++++++++++- .../public/shim/legacy_dependencies_plugin.ts | 6 ----- .../vis_type_vega/public/legacy_imports.ts | 23 ------------------- src/plugins/maps_legacy/public/index.ts | 4 ++-- .../update_tilemap_settings.js | 1 - 9 files changed, 25 insertions(+), 39 deletions(-) delete mode 100644 src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts diff --git a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx index 4219e2e715150..e8307f46dbe59 100644 --- a/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx +++ b/src/legacy/core_plugins/region_map/public/components/region_map_options.tsx @@ -21,9 +21,12 @@ 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 { FileLayerField, VectorLayer, ServiceSettings } from 'ui/vis/map/service_settings'; import { VisOptionsProps } from 'src/legacy/core_plugins/vis_default_editor/public'; +import { + FileLayerField, + VectorLayer, + IServiceSettings, +} from '../../../../../plugins/maps_legacy/public'; import { NumberInputOption, SelectOption, SwitchOption } from '../../../vis_type_vislib/public'; import { WmsOptions } from '../../../tile_map/public/components/wms_options'; import { RegionMapVisParams } from '../types'; @@ -39,7 +42,7 @@ const mapFieldForOption = ({ description, name }: FileLayerField) => ({ }); export type RegionMapOptionsProps = { - serviceSettings: ServiceSettings; + serviceSettings: IServiceSettings; } & VisOptionsProps; function RegionMapOptions(props: RegionMapOptionsProps) { diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index d3cbbcfcaae4f..6b3c5c61ff020 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -32,13 +32,13 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createRegionMapFn } from './region_map_fn'; // @ts-ignore import { createRegionMapTypeDefinition } from './region_map_type'; -import { ServiceSettingsSetupContract } from '../../../../plugins/maps_legacy/public'; +import { IServiceSettings } from '../../../../plugins/maps_legacy/public'; /** @private */ interface RegionMapVisualizationDependencies extends LegacyDependenciesPluginSetup { uiSettings: IUiSettingsClient; regionmapsConfig: RegionMapsConfig; - serviceSettings: ServiceSettingsSetupContract; + serviceSettings: IServiceSettings; } /** @internal */ diff --git a/src/legacy/core_plugins/region_map/public/util.ts b/src/legacy/core_plugins/region_map/public/util.ts index 69a7a1815bc8e..24c721da1f31a 100644 --- a/src/legacy/core_plugins/region_map/public/util.ts +++ b/src/legacy/core_plugins/region_map/public/util.ts @@ -17,7 +17,7 @@ * under the License. */ -import { FileLayer, VectorLayer } from 'ui/vis/map/service_settings'; +import { FileLayer, VectorLayer } from '../../../../plugins/maps_legacy/public'; // TODO: reference to TILE_MAP plugin should be removed import { ORIGIN } from '../../../../legacy/core_plugins/tile_map/common/origin'; diff --git a/src/legacy/core_plugins/tile_map/public/legacy.ts b/src/legacy/core_plugins/tile_map/public/legacy.ts index 74be8482bfd30..93ee46a204e63 100644 --- a/src/legacy/core_plugins/tile_map/public/legacy.ts +++ b/src/legacy/core_plugins/tile_map/public/legacy.ts @@ -28,6 +28,7 @@ import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, visualizations: visualizationsSetup, + maps_legacy: npSetup.plugins.maps_legacy, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index a12c2753cc525..c8dd2ff833241 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -32,16 +32,20 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createTileMapFn } from './tile_map_fn'; // @ts-ignore import { createTileMapTypeDefinition } from './tile_map_type'; +import { IServiceSettings } from '../../../../plugins/maps_legacy/public'; /** @private */ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup { + serviceSettings: IServiceSettings; uiSettings: IUiSettingsClient; + getZoomPrecision: any; } /** @internal */ export interface TileMapPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; + maps_legacy: any; __LEGACY: LegacyDependenciesPlugin; } @@ -55,9 +59,17 @@ export class TileMapPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations, __LEGACY }: TileMapPluginSetupDependencies + { + expressions, + visualizations, + maps_legacy: mapsLegacy, + __LEGACY, + }: TileMapPluginSetupDependencies ) { + const { getZoomPrecision, serviceSettings } = mapsLegacy; const visualizationDependencies: Readonly = { + serviceSettings, + getZoomPrecision, uiSettings: core.uiSettings, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts index 063b12bf0a2db..9a87035fbcf22 100644 --- a/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts @@ -23,7 +23,6 @@ import { CoreStart, Plugin } from 'kibana/public'; /** @internal */ export interface LegacyDependenciesPluginSetup { - serviceSettings: any; $injector: any; } @@ -34,11 +33,6 @@ export class LegacyDependenciesPlugin return { $injector, - // Settings for EMSClient. - // EMSClient, which currently lives in the tile_map vis, - // will probably end up being exposed from the future vis_type_maps plugin, - // which would register both the tile_map and the region_map vis plugins. - serviceSettings: $injector.get('serviceSettings'), } as LegacyDependenciesPluginSetup; } diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts deleted file mode 100644 index b868321d6310f..0000000000000 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy_imports.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -// @ts-ignore -export { KibanaMapLayer } from 'ui/vis/map/kibana_map_layer'; -// @ts-ignore -export { KibanaMap } from 'ui/vis/map/kibana_map'; diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 9168c87ef6c72..7c06d4965fdc1 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -33,8 +33,8 @@ import { VectorLayer, FileLayerField, FileLayer, - ServiceSettingsSetupContract, TmsLayer, + IServiceSettings, } from './map/service_settings'; export function plugin() { @@ -48,11 +48,11 @@ export { geoContains, colorUtil, convertToGeoJson, + IServiceSettings, KibanaMap, KibanaMapLayer, VectorLayer, FileLayerField, FileLayer, - ServiceSettingsSetupContract, TmsLayer, }; diff --git a/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js b/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js index 45764016f0311..51a53e8a3ed3f 100644 --- a/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js +++ b/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js @@ -6,7 +6,6 @@ import uiRoutes from 'ui/routes'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; -import 'ui/vis/map/service_settings'; uiRoutes.addSetupWork(function($injector, serviceSettings) { const tileMapPluginInfo = xpackInfo.get('features.tilemap'); From 2a37f30031d8d2e1e513d4b4ecba51f60e7f3150 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 26 Mar 2020 12:23:14 -0600 Subject: [PATCH 08/24] Remove dependency on legacy service settings. Add tile_map dependency ng-sanitize --- .../public/shim/legacy_dependencies_plugin.ts | 3 +- src/legacy/ui/public/vis/_index.scss | 1 - src/legacy/ui/public/vis/map/_index.scss | 2 - .../ui/public/vis/map/_leaflet_overrides.scss | 157 ---- src/legacy/ui/public/vis/map/_legend.scss | 33 - src/legacy/ui/public/vis/map/color_util.js | 36 - .../ui/public/vis/map/convert_to_geojson.js | 121 --- .../ui/public/vis/map/decode_geo_hash.test.ts | 34 - .../ui/public/vis/map/decode_geo_hash.ts | 192 ----- .../ui/public/vis/map/grid_dimensions.js | 41 - src/legacy/ui/public/vis/map/kibana_map.js | 710 ------------------ .../ui/public/vis/map/kibana_map_layer.js | 49 -- src/legacy/ui/public/vis/map/map_messages.js | 117 --- .../ui/public/vis/map/service_settings.d.ts | 51 -- .../ui/public/vis/map/service_settings.js | 252 ------- .../ui/public/vis/map/zoom_to_precision.ts | 60 -- 16 files changed, 2 insertions(+), 1857 deletions(-) delete mode 100644 src/legacy/ui/public/vis/_index.scss delete mode 100644 src/legacy/ui/public/vis/map/_index.scss delete mode 100644 src/legacy/ui/public/vis/map/_leaflet_overrides.scss delete mode 100644 src/legacy/ui/public/vis/map/_legend.scss delete mode 100644 src/legacy/ui/public/vis/map/color_util.js delete mode 100644 src/legacy/ui/public/vis/map/convert_to_geojson.js delete mode 100644 src/legacy/ui/public/vis/map/decode_geo_hash.test.ts delete mode 100644 src/legacy/ui/public/vis/map/decode_geo_hash.ts delete mode 100644 src/legacy/ui/public/vis/map/grid_dimensions.js delete mode 100644 src/legacy/ui/public/vis/map/kibana_map.js delete mode 100644 src/legacy/ui/public/vis/map/kibana_map_layer.js delete mode 100644 src/legacy/ui/public/vis/map/map_messages.js delete mode 100644 src/legacy/ui/public/vis/map/service_settings.d.ts delete mode 100644 src/legacy/ui/public/vis/map/service_settings.js delete mode 100644 src/legacy/ui/public/vis/map/zoom_to_precision.ts diff --git a/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts index 9a87035fbcf22..5296e98b09efe 100644 --- a/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/shim/legacy_dependencies_plugin.ts @@ -18,8 +18,9 @@ */ import chrome from 'ui/chrome'; -import 'ui/vis/map/service_settings'; import { CoreStart, Plugin } from 'kibana/public'; +// TODO: Determine why visualizations don't populate without this +import 'angular-sanitize'; /** @internal */ export interface LegacyDependenciesPluginSetup { diff --git a/src/legacy/ui/public/vis/_index.scss b/src/legacy/ui/public/vis/_index.scss deleted file mode 100644 index 28cf4289bb048..0000000000000 --- a/src/legacy/ui/public/vis/_index.scss +++ /dev/null @@ -1 +0,0 @@ -@import './map/index'; diff --git a/src/legacy/ui/public/vis/map/_index.scss b/src/legacy/ui/public/vis/map/_index.scss deleted file mode 100644 index f9fc841b9f868..0000000000000 --- a/src/legacy/ui/public/vis/map/_index.scss +++ /dev/null @@ -1,2 +0,0 @@ -@import './leaflet_overrides'; -@import './legend'; diff --git a/src/legacy/ui/public/vis/map/_leaflet_overrides.scss b/src/legacy/ui/public/vis/map/_leaflet_overrides.scss deleted file mode 100644 index 3235bb63ca22d..0000000000000 --- a/src/legacy/ui/public/vis/map/_leaflet_overrides.scss +++ /dev/null @@ -1,157 +0,0 @@ -// SASSTODO: Create these tooltip variables in EUI -// And/Or create a tooltip mixin -$temp-euiTooltipBackground: tintOrShade($euiColorFullShade, 25%, 90%); -$temp-euiTooltipText: $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: 0.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: $temp-euiTooltipBackground; - color: $temp-euiTooltipText; - 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(0.73); - } @else { - filter: invert(1) brightness(1.75) grayscale(1); - } -} - -img.leaflet-tile.filters-off { - filter: none; -} diff --git a/src/legacy/ui/public/vis/map/_legend.scss b/src/legacy/ui/public/vis/map/_legend.scss deleted file mode 100644 index 2c50e214c248b..0000000000000 --- a/src/legacy/ui/public/vis/map/_legend.scss +++ /dev/null @@ -1,33 +0,0 @@ -.visMapLegend { - @include fontSize(11px); - @include euiBottomShadowMedium($color: $euiShadowColorLarge, $opacity: .1); - 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/legacy/ui/public/vis/map/color_util.js b/src/legacy/ui/public/vis/map/color_util.js deleted file mode 100644 index fd12496fe783e..0000000000000 --- a/src/legacy/ui/public/vis/map/color_util.js +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -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/legacy/ui/public/vis/map/convert_to_geojson.js b/src/legacy/ui/public/vis/map/convert_to_geojson.js deleted file mode 100644 index 2186dbb3fc2a3..0000000000000 --- a/src/legacy/ui/public/vis/map/convert_to_geojson.js +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { decodeGeoHash } from './decode_geo_hash'; -import { gridDimensions } from './grid_dimensions'; - -export function convertToGeoJson(tabifiedResponse, { geohash, geocentroid, metric }) { - let features; - 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; - 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: rectangle, - }, - value: value, - }, - }; - }) - .filter(row => row); - } - } else { - features = []; - } - - const featureCollection = { - type: 'FeatureCollection', - features: features, - }; - - return { - featureCollection: featureCollection, - meta: { - min: min, - max: max, - geohashPrecision: geohash && geohash.params.precision, - geohashGridDimensionsAtEquator: geohash && gridDimensions(geohash.params.precision), - }, - }; -} - -function clampGrid(val, min, max) { - if (val > max) val = max; - else if (val < min) val = min; - return val; -} diff --git a/src/legacy/ui/public/vis/map/decode_geo_hash.test.ts b/src/legacy/ui/public/vis/map/decode_geo_hash.test.ts deleted file mode 100644 index c1ca7e4c80383..0000000000000 --- a/src/legacy/ui/public/vis/map/decode_geo_hash.test.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { geohashColumns, decodeGeoHash } from './decode_geo_hash'; - -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); -}); - -test('decodeGeoHash', () => { - expect(decodeGeoHash('drm3btev3e86')).toEqual({ - latitude: [41.119999922811985, 41.12000009045005, 41.12000000663102], - longitude: [-71.34000029414892, -71.3399999588728, -71.34000012651086], - }); -}); diff --git a/src/legacy/ui/public/vis/map/decode_geo_hash.ts b/src/legacy/ui/public/vis/map/decode_geo_hash.ts deleted file mode 100644 index 3f8430b8628d7..0000000000000 --- a/src/legacy/ui/public/vis/map/decode_geo_hash.ts +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import chrome from 'ui/chrome'; -import _ from 'lodash'; - -const config = chrome.getUiSettingsClient(); - -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, - } as DecodedGeoHash; -} - -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; - } -} - -/** - * 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; -} - -/** - * Get the number of geohash columns (world-wide) for a given precision - * @param precision the geohash precision - * @returns {number} the number of columns - */ -export function geohashColumns(precision: number): number { - return geohashCells(precision, 0); -} - -const defaultPrecision = 2; -const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; -/** - * 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. - */ -export const zoomPrecision: any = {}; -const minGeohashPixels = 16; - -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; - } - } -} - -export function getPrecision(val: string) { - let precision = parseInt(val, 10); - - if (Number.isNaN(precision)) { - precision = defaultPrecision; - } - - if (precision > maxPrecision) { - return maxPrecision; - } - - return precision; -} - -interface GeoBoundingBoxCoordinate { - lat: number; - lon: number; -} - -interface GeoBoundingBox { - top_left: GeoBoundingBoxCoordinate; - bottom_right: GeoBoundingBoxCoordinate; -} - -export function scaleBounds(bounds: GeoBoundingBox): GeoBoundingBox { - const scale = 0.5; // scale bounds by 50% - - const topLeft = bounds.top_left; - const bottomRight = bounds.bottom_right; - let latDiff = _.round(Math.abs(topLeft.lat - bottomRight.lat), 5); - const lonDiff = _.round(Math.abs(bottomRight.lon - topLeft.lon), 5); - // map height can be zero when vis is first created - if (latDiff === 0) latDiff = lonDiff; - - const latDelta = latDiff * scale; - let topLeftLat = _.round(topLeft.lat, 5) + latDelta; - if (topLeftLat > 90) topLeftLat = 90; - let bottomRightLat = _.round(bottomRight.lat, 5) - latDelta; - if (bottomRightLat < -90) bottomRightLat = -90; - const lonDelta = lonDiff * scale; - let topLeftLon = _.round(topLeft.lon, 5) - lonDelta; - if (topLeftLon < -180) topLeftLon = -180; - let bottomRightLon = _.round(bottomRight.lon, 5) + lonDelta; - if (bottomRightLon > 180) bottomRightLon = 180; - - return { - top_left: { lat: topLeftLat, lon: topLeftLon }, - bottom_right: { lat: bottomRightLat, lon: bottomRightLon }, - }; -} - -export function geoContains(collar?: GeoBoundingBox, bounds?: GeoBoundingBox) { - if (!bounds || !collar) return false; - // test if bounds top_left is outside collar - 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/legacy/ui/public/vis/map/grid_dimensions.js b/src/legacy/ui/public/vis/map/grid_dimensions.js deleted file mode 100644 index b3438914d5636..0000000000000 --- a/src/legacy/ui/public/vis/map/grid_dimensions.js +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import _ from 'lodash'; - -// geohash precision mapping of geohash grid cell dimensions (width x height, in meters) at equator. -// https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geohashgrid-aggregation.html#_cell_dimensions_at_the_equator -const gridAtEquator = { - '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) { - return _.get(gridAtEquator, precision); -} diff --git a/src/legacy/ui/public/vis/map/kibana_map.js b/src/legacy/ui/public/vis/map/kibana_map.js deleted file mode 100644 index bc581b1a8fbaf..0000000000000 --- a/src/legacy/ui/public/vis/map/kibana_map.js +++ /dev/null @@ -1,710 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { EventEmitter } from 'events'; -import { createZoomWarningMsg } from './map_messages'; -import L from 'leaflet'; -import $ from 'jquery'; -import _ from 'lodash'; -import { zoomToPrecision } from './zoom_to_precision'; -import { i18n } from '@kbn/i18n'; -import { ORIGIN } from '../../../../core_plugins/tile_map/common/origin'; - -function makeFitControl(fitContainer, kibanaMap) { - 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( - 'common.ui.vis.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) { - 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, - renderer: L.canvas(), - zoomAnimation: false, // Desaturate map tiles causes animation rendering artifacts - zoomControl: options.zoomControl === undefined ? true : options.zoomControl, - }; - - 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) { - this._popup = L.responsivePopup({ autoPan: false }); - this._popup.setLatLng(event.position); - this._popup.setContent(event.content); - this._popup.openOn(this._leafletMap); - } 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) { - 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 _.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, - }, - }; - this._leafletDrawControl = new L.Control.Draw(drawOptions); - this._leafletMap.addControl(this._leafletDrawControl); - } - - addFitControl() { - if (this._leafletFitControl || !this._leafletMap) { - return; - } - - 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(); - } - - _addMaxZoomMessage = layer => { - const zoomWarningMsg = createZoomWarningMsg(this.getZoomLevel, this.getMaxZoomLevel); - - this._leafletMap.on('zoomend', zoomWarningMsg); - this._containerNode.setAttribute('data-test-subj', 'zoomWarningEnabled'); - - layer.on('remove', () => { - this._leafletMap.off('zoomend', zoomWarningMsg); - this._containerNode.removeAttribute('data-test-subj'); - }); - }; - - 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; - if (settings.options.showZoomMessage) { - baseLayer.on('add', () => { - this._addMaxZoomMessage(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) { - 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 - ? 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(visualization) { - function persistMapStateInUiState() { - const uiState = visualization.getUiState(); - const centerFromUIState = uiState.get('mapCenter'); - const zoomFromUiState = parseInt(uiState.get('mapZoom')); - - if (isNaN(zoomFromUiState) || this.getZoomLevel() !== zoomFromUiState) { - visualization.uiStateVal('mapZoom', this.getZoomLevel()); - } - const centerFromMap = this.getCenter(); - if ( - !centerFromUIState || - centerFromMap.lon !== centerFromUIState[1] || - centerFromMap.lat !== centerFromUIState[0] - ) { - visualization.uiStateVal('mapCenter', [centerFromMap.lat, centerFromMap.lon]); - } - } - - this._leafletMap.on('resize', () => { - visualization.sessionState.mapBounds = this.getBounds(); - }); - this._leafletMap.on('load', () => { - visualization.sessionState.mapBounds = this.getBounds(); - }); - this.on('dragend', persistMapStateInUiState); - this.on('zoomend', persistMapStateInUiState); - } - - useUiStateFromVisualization(visualization) { - const uiState = visualization.getUiState(); - 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/legacy/ui/public/vis/map/kibana_map_layer.js b/src/legacy/ui/public/vis/map/kibana_map_layer.js deleted file mode 100644 index e276799ed0e1b..0000000000000 --- a/src/legacy/ui/public/vis/map/kibana_map_layer.js +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { 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/legacy/ui/public/vis/map/map_messages.js b/src/legacy/ui/public/vis/map/map_messages.js deleted file mode 100644 index 211796d734958..0000000000000 --- a/src/legacy/ui/public/vis/map/map_messages.js +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { toastNotifications } from 'ui/notify'; -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; -import { toMountPoint } from '../../../../../plugins/kibana_react/public'; - -export const createZoomWarningMsg = (function() { - let disableZoomMsg = false; - const setZoomMsg = boolDisableMsg => (disableZoomMsg = boolDisableMsg); - - class ZoomWarning extends React.Component { - constructor(props) { - super(props); - this.state = { - disabled: false, - }; - } - - render() { - return ( -
-

- - {`default distribution `} - - ), - ems: ( - - {`Elastic Maps Service`} - - ), - wms: ( - - {`Custom WMS Configuration`} - - ), - configSettings: ( - - {`Custom TMS Using Config Settings`} - - ), - }} - /> -

- - { - this.setState( - { - disabled: true, - }, - () => this.props.onChange(this.state.disabled) - ); - }} - data-test-subj="suppressZoomWarnings" - > - {`Don't show again`} - -
- ); - } - } - - const zoomToast = { - title: 'No additional zoom levels', - text: toMountPoint(), - 'data-test-subj': 'maxZoomWarning', - }; - - return (getZoomLevel, getMaxZoomLevel) => { - return () => { - const zoomLevel = getZoomLevel(); - const maxMapZoom = getMaxZoomLevel(); - if (!disableZoomMsg && zoomLevel === maxMapZoom) { - toastNotifications.addDanger(zoomToast); - } - }; - }; -})(); diff --git a/src/legacy/ui/public/vis/map/service_settings.d.ts b/src/legacy/ui/public/vis/map/service_settings.d.ts deleted file mode 100644 index 6766000861e47..0000000000000 --- a/src/legacy/ui/public/vis/map/service_settings.d.ts +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -export interface TmsLayer { - id: string; - origin: string; - minZoom: string; - maxZoom: number; - attribution: string; -} - -export interface FileLayer { - name: string; - origin: string; - id: string; - format: string | { type: string }; - fields: FileLayerField[]; -} - -export interface FileLayerField { - name: string; - description: string; - type: string; -} - -export interface VectorLayer extends FileLayer { - layerId: string; - isEMS: boolean; -} - -export interface ServiceSettings { - getEMSHotLink(layer: FileLayer): Promise; - getTMSServices(): Promise; - getFileLayers(): Promise; -} diff --git a/src/legacy/ui/public/vis/map/service_settings.js b/src/legacy/ui/public/vis/map/service_settings.js deleted file mode 100644 index 9f3d21831e3da..0000000000000 --- a/src/legacy/ui/public/vis/map/service_settings.js +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { uiModules } from '../../modules'; -import _ from 'lodash'; -import MarkdownIt from 'markdown-it'; -import { ORIGIN } from '../../../../core_plugins/tile_map/common/origin'; -import { EMSClient } from '@elastic/ems-client'; -import { i18n } from '@kbn/i18n'; -import 'angular-sanitize'; - -const markdownIt = new MarkdownIt({ - html: false, - linkify: true, -}); - -const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; - -uiModules - .get('kibana', ['ngSanitize']) - .service('serviceSettings', function($sanitize, mapConfig, tilemapsConfig, kbnVersion) { - const attributionFromConfig = $sanitize( - markdownIt.render(tilemapsConfig.deprecated.config.options.attribution || '') - ); - const tmsOptionsFromConfig = _.assign({}, tilemapsConfig.deprecated.config.options, { - attribution: attributionFromConfig, - }); - - class ServiceSettings { - constructor() { - this._showZoomMessage = true; - this._emsClient = new EMSClient({ - language: i18n.getLocale(), - appVersion: kbnVersion, - appName: 'kibana', - fileApiUrl: mapConfig.emsFileApiUrl, - tileApiUrl: mapConfig.emsTileApiUrl, - htmlSanitizer: $sanitize, - landingPageUrl: mapConfig.emsLandingPageUrl, - }); - } - - shouldShowZoomMessage({ origin }) { - return origin === ORIGIN.EMS && this._showZoomMessage; - } - - disableZoomMessage() { - this._showZoomMessage = false; - } - - __debugStubManifestCalls(manifestRetrieval) { - const oldGetManifest = this._emsClient.getManifest; - this._emsClient.getManifest = manifestRetrieval; - return { - removeStub: () => { - delete this._emsClient.getManifest; - //not strictly necessary since this is prototype method - if (this._emsClient.getManifest !== oldGetManifest) { - this._emsClient.getManifest = oldGetManifest; - } - }, - }; - } - - async getFileLayers() { - if (!mapConfig.includeElasticMapsService) { - return []; - } - - const fileLayers = await this._emsClient.getFileLayers(); - return fileLayers.map(fileLayer => { - //backfill to older settings - const format = fileLayer.getDefaultFormatType(); - const meta = fileLayer.getDefaultFormatMeta(); - - return { - name: fileLayer.getDisplayName(), - origin: fileLayer.getOrigin(), - id: fileLayer.getId(), - created_at: fileLayer.getCreatedAt(), - attribution: fileLayer.getHTMLAttribution(), - fields: fileLayer.getFieldsInLanguage(), - format: format, //legacy: format and meta are split up - meta: meta, //legacy, format and meta are split up - }; - }); - } - - /** - * Returns all the services published by EMS (if configures) - * It also includes the service configured in tilemap (override) - */ - async getTMSServices() { - let allServices = []; - if (tilemapsConfig.deprecated.isOverridden) { - //use tilemap.* settings from yml - const tmsService = _.cloneDeep(tmsOptionsFromConfig); - tmsService.id = TMS_IN_YML_ID; - tmsService.origin = ORIGIN.KIBANA_YML; - allServices.push(tmsService); - } - - if (mapConfig.includeElasticMapsService) { - const servicesFromManifest = await this._emsClient.getTMSServices(); - const strippedServiceFromManifest = await Promise.all( - servicesFromManifest - .filter(tmsService => tmsService.getId() === mapConfig.emsTileLayerId.bright) - .map(async tmsService => { - //shim for compatibility - const shim = { - origin: tmsService.getOrigin(), - id: tmsService.getId(), - minZoom: await tmsService.getMinZoom(), - maxZoom: await tmsService.getMaxZoom(), - attribution: tmsService.getHTMLAttribution(), - }; - return shim; - }) - ); - allServices = allServices.concat(strippedServiceFromManifest); - } - - return allServices; - } - - /** - * Add optional query-parameters to all requests - * - * @param additionalQueryParams - */ - addQueryParams(additionalQueryParams) { - this._emsClient.addQueryParams(additionalQueryParams); - } - - async getEMSHotLink(fileLayerConfig) { - const fileLayers = await this._emsClient.getFileLayers(); - const layer = fileLayers.find(fileLayer => { - const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy - const hasIdById = fileLayer.hasId(fileLayerConfig.id); - return hasIdByName || hasIdById; - }); - return layer ? layer.getEMSHotLink() : null; - } - - async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) { - const tmsServices = await this._emsClient.getTMSServices(); - const emsTileLayerId = mapConfig.emsTileLayerId; - let serviceId; - if (isDarkMode) { - serviceId = emsTileLayerId.dark; - } else { - if (isDesaturated) { - serviceId = emsTileLayerId.desaturated; - } else { - serviceId = emsTileLayerId.bright; - } - } - const tmsService = tmsServices.find(service => { - return service.getId() === serviceId; - }); - return { - url: await tmsService.getUrlTemplate(), - minZoom: await tmsService.getMinZoom(), - maxZoom: await tmsService.getMaxZoom(), - attribution: await tmsService.getHTMLAttribution(), - origin: ORIGIN.EMS, - }; - } - - async getAttributesForTMSLayer(tmsServiceConfig, isDesaturated, isDarkMode) { - if (tmsServiceConfig.origin === ORIGIN.EMS) { - return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); - } else if (tmsServiceConfig.origin === ORIGIN.KIBANA_YML) { - const config = tilemapsConfig.deprecated.config; - const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); - return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; - } else { - //this is an older config. need to resolve this dynamically. - if (tmsServiceConfig.id === TMS_IN_YML_ID) { - const config = tilemapsConfig.deprecated.config; - const attrs = _.pick(config, ['url', 'minzoom', 'maxzoom', 'attribution']); - return { ...attrs, ...{ origin: ORIGIN.KIBANA_YML } }; - } else { - //assume ems - return this._getAttributesForEMSTMSLayer(isDesaturated, isDarkMode); - } - } - } - - async _getFileUrlFromEMS(fileLayerConfig) { - const fileLayers = await this._emsClient.getFileLayers(); - const layer = fileLayers.find(fileLayer => { - const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy - const hasIdById = fileLayer.hasId(fileLayerConfig.id); - return hasIdByName || hasIdById; - }); - - if (layer) { - return layer.getDefaultFormatUrl(); - } else { - throw new Error(`File ${fileLayerConfig.name} not recognized`); - } - } - - async getUrlForRegionLayer(fileLayerConfig) { - let url; - if (fileLayerConfig.origin === ORIGIN.EMS) { - url = this._getFileUrlFromEMS(fileLayerConfig); - } else if ( - fileLayerConfig.layerId && - fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`) - ) { - //fallback for older saved objects - url = this._getFileUrlFromEMS(fileLayerConfig); - } else if ( - fileLayerConfig.layerId && - fileLayerConfig.layerId.startsWith(`${ORIGIN.KIBANA_YML}.`) - ) { - //fallback for older saved objects - url = fileLayerConfig.url; - } else { - //generic fallback - url = fileLayerConfig.url; - } - return url; - } - - async getJsonForRegionLayer(fileLayerConfig) { - const url = await this.getUrlForRegionLayer(fileLayerConfig); - const response = await fetch(url); - return await response.json(); - } - } - - return new ServiceSettings(); - }); diff --git a/src/legacy/ui/public/vis/map/zoom_to_precision.ts b/src/legacy/ui/public/vis/map/zoom_to_precision.ts deleted file mode 100644 index 552c509590286..0000000000000 --- a/src/legacy/ui/public/vis/map/zoom_to_precision.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { geohashColumns } from './decode_geo_hash'; - -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; -} From 159d592d36f5481fc11e9661612c1146b635e818 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 26 Mar 2020 12:27:14 -0600 Subject: [PATCH 09/24] More path cleanup. Use zoomPrecision provided through plugin inteface --- .../tile_map/public/tile_map_visualization.js | 12 ++++-------- .../maps_legacy/public/map/service_settings.d.ts | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js index 910def8a0c78e..8985a625d8262 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js @@ -23,14 +23,9 @@ import { BaseMapsVisualizationProvider } from './base_maps_visualization'; import { TileMapTooltipFormatterProvider } from './editors/_tooltip_formatter'; import { npStart } from 'ui/new_platform'; import { getFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities'; -import { - scaleBounds, - zoomPrecision, - getPrecision, - geoContains, -} from '../../../ui/public/vis/map/decode_geo_hash'; - -export const createTileMapVisualization = ({ serviceSettings, $injector }) => { +import { scaleBounds, getPrecision, geoContains } from '../../../../plugins/maps_legacy/public'; + +export const createTileMapVisualization = ({ serviceSettings, $injector, getZoomPrecision }) => { const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings); const tooltipFormatter = new TileMapTooltipFormatterProvider($injector); @@ -59,6 +54,7 @@ export const createTileMapVisualization = ({ serviceSettings, $injector }) => { updateVarsObject.data.boundingBox = geohashAgg.aggConfigParams.boundingBox; } // todo: autoPrecision should be vis parameter, not aggConfig one + const zoomPrecision = getZoomPrecision(); updateVarsObject.data.precision = geohashAgg.aggConfigParams.autoPrecision ? zoomPrecision[this.vis.getUiState().get('mapZoom')] : getPrecision(geohashAgg.aggConfigParams.precision); diff --git a/src/plugins/maps_legacy/public/map/service_settings.d.ts b/src/plugins/maps_legacy/public/map/service_settings.d.ts index 6766000861e47..e265accaeb8fd 100644 --- a/src/plugins/maps_legacy/public/map/service_settings.d.ts +++ b/src/plugins/maps_legacy/public/map/service_settings.d.ts @@ -44,7 +44,7 @@ export interface VectorLayer extends FileLayer { isEMS: boolean; } -export interface ServiceSettings { +export interface IServiceSettings { getEMSHotLink(layer: FileLayer): Promise; getTMSServices(): Promise; getFileLayers(): Promise; From 78c6d89e708097d5a606ca069d079e8c3af9ea72 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Fri, 27 Mar 2020 09:45:04 -0600 Subject: [PATCH 10/24] Move getPrecision into contract-provided function since it depends on config --- .../core_plugins/tile_map/public/plugin.ts | 4 ++- .../tile_map/public/tile_map_visualization.js | 11 +++++-- .../maps_legacy/public/map/decode_geo_hash.ts | 18 +++--------- .../map/{zoom_precision.ts => precision.ts} | 29 +++++++++++++++---- src/plugins/maps_legacy/public/plugin.ts | 3 +- 5 files changed, 40 insertions(+), 25 deletions(-) rename src/plugins/maps_legacy/public/map/{zoom_precision.ts => precision.ts} (77%) diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index c8dd2ff833241..741750d10e498 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -39,6 +39,7 @@ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup serviceSettings: IServiceSettings; uiSettings: IUiSettingsClient; getZoomPrecision: any; + getPrecision: any; } /** @internal */ @@ -66,10 +67,11 @@ export class TileMapPlugin implements Plugin, void> { __LEGACY, }: TileMapPluginSetupDependencies ) { - const { getZoomPrecision, serviceSettings } = mapsLegacy; + const { getZoomPrecision, getPrecision, serviceSettings } = mapsLegacy; const visualizationDependencies: Readonly = { serviceSettings, getZoomPrecision, + getPrecision, uiSettings: core.uiSettings, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js index 8985a625d8262..d866b28a146dd 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js @@ -23,9 +23,14 @@ import { BaseMapsVisualizationProvider } from './base_maps_visualization'; import { TileMapTooltipFormatterProvider } from './editors/_tooltip_formatter'; import { npStart } from 'ui/new_platform'; import { getFormat } from '../../../ui/public/visualize/loader/pipeline_helpers/utilities'; -import { scaleBounds, getPrecision, geoContains } from '../../../../plugins/maps_legacy/public'; - -export const createTileMapVisualization = ({ serviceSettings, $injector, getZoomPrecision }) => { +import { scaleBounds, geoContains } from '../../../../plugins/maps_legacy/public'; + +export const createTileMapVisualization = ({ + serviceSettings, + $injector, + getZoomPrecision, + getPrecision, +}) => { const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings); const tooltipFormatter = new TileMapTooltipFormatterProvider($injector); diff --git a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts index 5afcad7ec5bf2..8c39ada03a46b 100644 --- a/src/plugins/maps_legacy/public/map/decode_geo_hash.ts +++ b/src/plugins/maps_legacy/public/map/decode_geo_hash.ts @@ -71,6 +71,10 @@ function refineInterval(interval: number[], cd: number, mask: number) { } } +export function geohashColumns(precision: number): number { + return geohashCells(precision, 0); +} + /** * Get the number of geohash cells for a given precision * @@ -87,20 +91,6 @@ function geohashCells(precision: number, axis: number) { return cells; } -export function getPrecision(val: string) { - let precision = parseInt(val, 10); - - if (Number.isNaN(precision)) { - precision = defaultPrecision; - } - - if (precision > maxPrecision) { - return maxPrecision; - } - - return precision; -} - interface GeoBoundingBoxCoordinate { lat: number; lon: number; diff --git a/src/plugins/maps_legacy/public/map/zoom_precision.ts b/src/plugins/maps_legacy/public/map/precision.ts similarity index 77% rename from src/plugins/maps_legacy/public/map/zoom_precision.ts rename to src/plugins/maps_legacy/public/map/precision.ts index 38e80271397a1..7d5ebea948f3e 100644 --- a/src/plugins/maps_legacy/public/map/zoom_precision.ts +++ b/src/plugins/maps_legacy/public/map/precision.ts @@ -18,27 +18,29 @@ */ import { getUiSettings } from '../kibana_services'; +import { geohashColumns } from './decode_geo_hash'; /** * Get the number of geohash columns (world-wide) for a given precision * @param precision the geohash precision * @returns {number} the number of columns */ -export function geohashColumns(precision: number): number { - return geohashCells(precision, 0); -} -export function getZoomPrecision() { +const DEFAULT_PRECISION = 2; + +function getMaxPrecision() { const config = getUiSettings(); - const defaultPrecision = 2; - const maxPrecision = parseInt(config.get('visualization:tileMap:maxPrecision'), 10) || 12; + 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); @@ -54,3 +56,18 @@ export function getZoomPrecision() { } 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/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index bb48f84969076..7c096d8a5661f 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -24,7 +24,7 @@ import { setToasts, setUiSettings, setInjectedVarFunc } from './kibana_services' // @ts-ignore import { ServiceSettings } from './map/service_settings'; // @ts-ignore -import { getZoomPrecision } from './map/zoom_precision'; +import { getPrecision, getZoomPrecision } from './map/precision'; /** * These are the interfaces with your public contracts. You should export these @@ -51,6 +51,7 @@ export class MapsLegacyPlugin implements Plugin Date: Fri, 27 Mar 2020 10:40:22 -0600 Subject: [PATCH 11/24] Move tests to new service location, remove vis dir --- .../public}/__tests__/map/ems_mocks/sample_files.json | 0 .../public}/__tests__/map/ems_mocks/sample_manifest.json | 0 .../public}/__tests__/map/ems_mocks/sample_style_bright.json | 0 .../__tests__/map/ems_mocks/sample_style_bright_vector.json | 0 .../map/ems_mocks/sample_style_bright_vector_source.json | 0 .../public}/__tests__/map/ems_mocks/sample_style_dark.json | 0 .../__tests__/map/ems_mocks/sample_style_desaturated.json | 0 .../public}/__tests__/map/ems_mocks/sample_tiles.json | 0 .../maps_legacy/public}/__tests__/map/kibana_map.js | 0 .../maps_legacy/public}/__tests__/map/service_settings.js | 2 +- 10 files changed, 1 insertion(+), 1 deletion(-) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_files.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_manifest.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_bright.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_bright_vector.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_bright_vector_source.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_dark.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_style_desaturated.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/ems_mocks/sample_tiles.json (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/kibana_map.js (100%) rename src/{legacy/ui/public/vis => plugins/maps_legacy/public}/__tests__/map/service_settings.js (99%) diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_files.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_files.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector_source.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector_source.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_bright_vector_source.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright_vector_source.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_dark.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_dark.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated.json diff --git a/src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json b/src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json rename to src/plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json diff --git a/src/legacy/ui/public/vis/__tests__/map/kibana_map.js b/src/plugins/maps_legacy/public/__tests__/map/kibana_map.js similarity index 100% rename from src/legacy/ui/public/vis/__tests__/map/kibana_map.js rename to src/plugins/maps_legacy/public/__tests__/map/kibana_map.js diff --git a/src/legacy/ui/public/vis/__tests__/map/service_settings.js b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js similarity index 99% rename from src/legacy/ui/public/vis/__tests__/map/service_settings.js rename to src/plugins/maps_legacy/public/__tests__/map/service_settings.js index 61925760457c6..c9299c3c15442 100644 --- a/src/legacy/ui/public/vis/__tests__/map/service_settings.js +++ b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js @@ -26,7 +26,7 @@ import EMS_TILES from './ems_mocks/sample_tiles.json'; import EMS_STYLE_ROAD_MAP_BRIGHT from './ems_mocks/sample_style_bright'; import EMS_STYLE_ROAD_MAP_DESATURATED from './ems_mocks/sample_style_desaturated'; import EMS_STYLE_DARK_MAP from './ems_mocks/sample_style_dark'; -import { ORIGIN } from '../../../../../core_plugins/tile_map/common/origin'; +import { ORIGIN } from '../../../common/origin'; describe('service_settings (FKA tilemaptest)', function() { let serviceSettings; From 3a2a2f62d8a3bb4f85f6334a9abdbc79d98e5c08 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Fri, 27 Mar 2020 12:15:29 -0600 Subject: [PATCH 12/24] Update test paths. Move origin const declaration into public --- .../__tests__/region_map_visualization.js | 18 ++++++++++++------ .../__tests__/coordinate_maps_visualization.js | 18 ++++++++++++------ .../public/__tests__/map/service_settings.js | 2 +- .../maps_legacy/{ => public}/common/origin.ts | 0 .../maps_legacy/public/map/kibana_map.js | 2 +- .../maps_legacy/public/map/service_settings.js | 2 +- 6 files changed, 27 insertions(+), 15 deletions(-) rename src/plugins/maps_legacy/{ => public}/common/origin.ts (100%) diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index 3880f42d52561..e9c9fe02626d7 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -23,12 +23,18 @@ import _ from 'lodash'; import ChoroplethLayer from '../choropleth_layer'; import { ImageComparator } from 'test_utils/image_comparator'; import worldJson from './world.json'; -import EMS_CATALOGUE from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json'; -import EMS_FILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_files.json'; -import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json'; -import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; -import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; -import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_CATALOGUE from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_FILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_TILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_DARK_MAP from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark'; import initialPng from './initial.png'; import toiso3Png from './toiso3.png'; diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index 2c142b19d9096..1450728f81bb5 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -25,12 +25,18 @@ import initial from './initial.png'; import blues from './blues.png'; import shadedGeohashGrid from './shadedGeohashGrid.png'; import heatmapRaw from './heatmap_raw.png'; -import EMS_CATALOGUE from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_manifest.json'; -import EMS_FILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_files.json'; -import EMS_TILES from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_tiles.json'; -import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_bright'; -import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_desaturated'; -import EMS_STYLE_DARK_MAP from '../../../../ui/public/vis/__tests__/map/ems_mocks/sample_style_dark'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_CATALOGUE from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_manifest.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_FILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_files.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_TILES from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_tiles.json'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_BRIGHT from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_bright'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_ROAD_MAP_DESATURATED from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_desaturated'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import EMS_STYLE_DARK_MAP from '../../../../../plugins/maps_legacy/public/__tests__/map/ems_mocks/sample_style_dark'; import { createTileMapVisualization } from '../tile_map_visualization'; import { createTileMapTypeDefinition } from '../tile_map_type'; diff --git a/src/plugins/maps_legacy/public/__tests__/map/service_settings.js b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js index c9299c3c15442..a9272ea396639 100644 --- a/src/plugins/maps_legacy/public/__tests__/map/service_settings.js +++ b/src/plugins/maps_legacy/public/__tests__/map/service_settings.js @@ -26,7 +26,7 @@ import EMS_TILES from './ems_mocks/sample_tiles.json'; import EMS_STYLE_ROAD_MAP_BRIGHT from './ems_mocks/sample_style_bright'; import EMS_STYLE_ROAD_MAP_DESATURATED from './ems_mocks/sample_style_desaturated'; import EMS_STYLE_DARK_MAP from './ems_mocks/sample_style_dark'; -import { ORIGIN } from '../../../common/origin'; +import { ORIGIN } from '../../common/origin'; describe('service_settings (FKA tilemaptest)', function() { let serviceSettings; diff --git a/src/plugins/maps_legacy/common/origin.ts b/src/plugins/maps_legacy/public/common/origin.ts similarity index 100% rename from src/plugins/maps_legacy/common/origin.ts rename to src/plugins/maps_legacy/public/common/origin.ts diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index 88412ee645d77..cdeecc7c45011 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -24,7 +24,7 @@ import $ from 'jquery'; import _ from 'lodash'; import { zoomToPrecision } from './zoom_to_precision'; import { i18n } from '@kbn/i18n'; -import { ORIGIN } from '../../common/origin'; +import { ORIGIN } from '../common/origin'; function makeFitControl(fitContainer, kibanaMap) { const FitControl = L.Control.extend({ diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js index 4d61b90fb0b91..cbc8349a6298c 100644 --- a/src/plugins/maps_legacy/public/map/service_settings.js +++ b/src/plugins/maps_legacy/public/map/service_settings.js @@ -19,7 +19,7 @@ import _ from 'lodash'; import MarkdownIt from 'markdown-it'; -import { ORIGIN } from '../../common/origin'; +import { ORIGIN } from '../common/origin'; import { EMSClient } from '@elastic/ems-client'; import { i18n } from '@kbn/i18n'; import { getInjectedVarFunc } from '../kibana_services'; From dd13bf4144018b5cc873fc1704c5ebfa8047ef72 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Wed, 1 Apr 2020 15:14:14 -0600 Subject: [PATCH 13/24] Clean up, fixes --- .../core_plugins/kibana/public/index.scss | 2 +- .../vis_type_vega/public/legacy.ts | 5 +---- .../vis_type_vega/public/plugin.ts | 20 +++++++++++-------- src/plugins/maps_legacy/kibana.json | 4 +--- .../maps_legacy/public/common/origin.ts | 8 ++++---- .../public/map/service_settings.js | 2 +- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/index.scss b/src/legacy/core_plugins/kibana/public/index.scss index 547f44652cf2b..bd05ca0bc307c 100644 --- a/src/legacy/core_plugins/kibana/public/index.scss +++ b/src/legacy/core_plugins/kibana/public/index.scss @@ -17,7 +17,7 @@ @import './visualize/index'; // Has to come after visualize because of some // bad cascading in the Editor layout -@import 'src/legacy/ui/public/vis/index'; +@import '../../../../plugins/maps_legacy/public/index'; // Home styles @import '../../../../plugins/home/public/application/index'; diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts index 445fb4b635eb5..ad261ef6f859d 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts @@ -25,10 +25,7 @@ import { plugin } from '.'; const setupPlugins: Readonly = { ...npSetup.plugins, visualizations: npSetup.plugins.visualizations, - - // Temporary solution - // It will be removed when all dependent services are migrated to the new platform. - __LEGACY: new LegacyDependenciesPlugin(), + maps_legacy: npSetup.plugins.maps_legacy, }; const startPlugins: Readonly = { diff --git a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts index 75348154c2e06..4283633cdacf7 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts @@ -31,6 +31,16 @@ import { import { createVegaFn } from './vega_fn'; import { createVegaTypeDefinition } from './vega_type'; import { VisTypeVegaSetup } from '../../../../plugins/vis_type_vega/public'; +import { IServiceSettings } from '../../../../plugins/maps_legacy/public'; + +/** @internal */ +export interface VegaVisualizationDependencies { + core: CoreSetup; + plugins: { + data: ReturnType; + }; + serviceSettings: IServiceSettings; +} /** @internal */ export interface VegaPluginSetupDependencies { @@ -38,6 +48,7 @@ export interface VegaPluginSetupDependencies { visualizations: VisualizationsSetup; data: ReturnType; visTypeVega: VisTypeVegaSetup; + maps_legacy: any; } /** @internal */ @@ -55,14 +66,7 @@ export class VegaPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { - data, - expressions, - visualizations, - visTypeVega, - maps_legacy, - __LEGACY, - }: VegaPluginSetupDependencies + { data, expressions, visualizations, visTypeVega, maps_legacy }: VegaPluginSetupDependencies ) { setInjectedVars({ enableExternalUrls: visTypeVega.config.enableExternalUrls, diff --git a/src/plugins/maps_legacy/kibana.json b/src/plugins/maps_legacy/kibana.json index de11f58bad7e1..69e18db10d5f8 100644 --- a/src/plugins/maps_legacy/kibana.json +++ b/src/plugins/maps_legacy/kibana.json @@ -2,7 +2,5 @@ "id": "maps_legacy", "version": "8.0.0", "kibanaVersion": "kibana", - "ui": true, - "configPath": ["map"], - "requiredPlugins": ["kibanaLegacy"] + "ui": true } diff --git a/src/plugins/maps_legacy/public/common/origin.ts b/src/plugins/maps_legacy/public/common/origin.ts index 7fcf1c659bdf3..fdf74cae4ba68 100644 --- a/src/plugins/maps_legacy/public/common/origin.ts +++ b/src/plugins/maps_legacy/public/common/origin.ts @@ -17,7 +17,7 @@ * under the License. */ -export enum ORIGIN { - EMS = 'elastic_maps_service', - KIBANA_YML = 'self_hosted', -} +export const ORIGIN = { + EMS: 'elastic_maps_service', + KIBANA_YML: 'self_hosted', +}; diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js index 0473a36fb24ca..70e5c1aa3c02a 100644 --- a/src/plugins/maps_legacy/public/map/service_settings.js +++ b/src/plugins/maps_legacy/public/map/service_settings.js @@ -19,10 +19,10 @@ import _ from 'lodash'; import MarkdownIt from 'markdown-it'; -import { ORIGIN } from '../common/origin'; import { EMSClient } from '@elastic/ems-client'; import { i18n } from '@kbn/i18n'; import { getInjectedVarFunc } from '../kibana_services'; +import { ORIGIN } from '../common/origin'; const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; From 7adb212aa81b48bcf02ed25d1186a87bd228a8d6 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Wed, 1 Apr 2020 17:13:56 -0600 Subject: [PATCH 14/24] Fix type errors. General cleaning --- src/legacy/core_plugins/region_map/public/legacy.ts | 10 +++------- src/legacy/core_plugins/region_map/public/plugin.ts | 10 ++++++---- .../public/shim/legacy_dependencies_plugin.ts | 2 -- src/legacy/core_plugins/tile_map/public/legacy.ts | 2 +- src/legacy/core_plugins/tile_map/public/plugin.ts | 9 ++------- src/legacy/core_plugins/vis_type_vega/public/legacy.ts | 2 +- src/legacy/core_plugins/vis_type_vega/public/plugin.ts | 6 +++--- src/legacy/ui/public/new_platform/new_platform.ts | 2 ++ src/plugins/maps_legacy/kibana.json | 2 +- src/plugins/maps_legacy/public/index.ts | 3 +++ src/plugins/maps_legacy/public/map/precision.ts | 1 + src/plugins/maps_legacy/public/plugin.ts | 4 +--- 12 files changed, 24 insertions(+), 29 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/legacy.ts b/src/legacy/core_plugins/region_map/public/legacy.ts index 15c385afb122e..b0cc767a044e8 100644 --- a/src/legacy/core_plugins/region_map/public/legacy.ts +++ b/src/legacy/core_plugins/region_map/public/legacy.ts @@ -20,22 +20,18 @@ import { PluginInitializerContext } from 'kibana/public'; import { npSetup, npStart } from 'ui/new_platform'; -import { RegionMapPluginSetupDependencies, RegionMapsConfig } from './plugin'; +import { RegionMapPluginSetupDependencies } from './plugin'; import { LegacyDependenciesPlugin } from './shim'; import { plugin } from '.'; -const regionmapsConfig = npSetup.core.injectedMetadata.getInjectedVar( - 'regionmap' -) as RegionMapsConfig; - const plugins: Readonly = { expressions: npSetup.plugins.expressions, visualizations: npSetup.plugins.visualizations, - maps_legacy: npSetup.plugins.maps_legacy, + mapsLegacy: npSetup.plugins.mapsLegacy, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. - __LEGACY: new LegacyDependenciesPlugin(regionmapsConfig), + __LEGACY: new LegacyDependenciesPlugin(), }; const pluginInstance = plugin({} as PluginInitializerContext); diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index da8ce62913224..e9c3ea1adb45a 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -46,7 +46,7 @@ export interface RegionMapPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; __LEGACY: LegacyDependenciesPlugin; - maps_legacy: any; + mapsLegacy: any; } /** @internal */ @@ -65,12 +65,14 @@ export class RegionMapPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { expressions, visualizations, maps_legacy, __LEGACY }: RegionMapPluginSetupDependencies + { expressions, visualizations, mapsLegacy, __LEGACY }: RegionMapPluginSetupDependencies ) { const visualizationDependencies: Readonly = { uiSettings: core.uiSettings, - regionmapsConfig: core.injectedMetadata.getInjectedVar('regionmapsConfig'), - serviceSettings: maps_legacy.serviceSettings, + regionmapsConfig: core.injectedMetadata.getInjectedVar( + 'regionmapsConfig' + ) as RegionMapsConfig, + serviceSettings: mapsLegacy.serviceSettings, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts index a952ea08ec6b3..3a7615e83f281 100644 --- a/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts +++ b/src/legacy/core_plugins/region_map/public/shim/legacy_dependencies_plugin.ts @@ -19,13 +19,11 @@ import chrome from 'ui/chrome'; import { CoreStart, Plugin } from 'kibana/public'; -import { RegionMapsConfig } from '../plugin'; /** @internal */ export interface LegacyDependenciesPluginSetup { $injector: any; serviceSettings: any; - regionmapsConfig: RegionMapsConfig; } export class LegacyDependenciesPlugin diff --git a/src/legacy/core_plugins/tile_map/public/legacy.ts b/src/legacy/core_plugins/tile_map/public/legacy.ts index 3cf807ceecc18..741e118750f32 100644 --- a/src/legacy/core_plugins/tile_map/public/legacy.ts +++ b/src/legacy/core_plugins/tile_map/public/legacy.ts @@ -27,7 +27,7 @@ import { plugin } from '.'; const plugins: Readonly = { expressions: npSetup.plugins.expressions, visualizations: npSetup.plugins.visualizations, - maps_legacy: npSetup.plugins.maps_legacy, + mapsLegacy: npSetup.plugins.mapsLegacy, // Temporary solution // It will be removed when all dependent services are migrated to the new platform. diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index 88cc25ee65d28..8fd00ec073d1e 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -46,7 +46,7 @@ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup export interface TileMapPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; - maps_legacy: any; + mapsLegacy: any; __LEGACY: LegacyDependenciesPlugin; } @@ -60,12 +60,7 @@ export class TileMapPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { - expressions, - visualizations, - maps_legacy: mapsLegacy, - __LEGACY, - }: TileMapPluginSetupDependencies + { expressions, visualizations, mapsLegacy, __LEGACY }: TileMapPluginSetupDependencies ) { const { getZoomPrecision, getPrecision, serviceSettings } = mapsLegacy; const visualizationDependencies: Readonly = { diff --git a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts index ad261ef6f859d..450af4a6f253e 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/legacy.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/legacy.ts @@ -25,7 +25,7 @@ import { plugin } from '.'; const setupPlugins: Readonly = { ...npSetup.plugins, visualizations: npSetup.plugins.visualizations, - maps_legacy: npSetup.plugins.maps_legacy, + mapsLegacy: npSetup.plugins.mapsLegacy, }; const startPlugins: Readonly = { diff --git a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts index 4283633cdacf7..9fa77d28fbbfa 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/plugin.ts +++ b/src/legacy/core_plugins/vis_type_vega/public/plugin.ts @@ -48,7 +48,7 @@ export interface VegaPluginSetupDependencies { visualizations: VisualizationsSetup; data: ReturnType; visTypeVega: VisTypeVegaSetup; - maps_legacy: any; + mapsLegacy: any; } /** @internal */ @@ -66,7 +66,7 @@ export class VegaPlugin implements Plugin, void> { public async setup( core: CoreSetup, - { data, expressions, visualizations, visTypeVega, maps_legacy }: VegaPluginSetupDependencies + { data, expressions, visualizations, visTypeVega, mapsLegacy }: VegaPluginSetupDependencies ) { setInjectedVars({ enableExternalUrls: visTypeVega.config.enableExternalUrls, @@ -80,7 +80,7 @@ export class VegaPlugin implements Plugin, void> { plugins: { data, }, - serviceSettings: maps_legacy.serviceSettings, + serviceSettings: mapsLegacy.serviceSettings, }; expressions.registerFunction(() => createVegaFn(visualizationDependencies)); diff --git a/src/legacy/ui/public/new_platform/new_platform.ts b/src/legacy/ui/public/new_platform/new_platform.ts index b4b5099081759..13c803113e0f4 100644 --- a/src/legacy/ui/public/new_platform/new_platform.ts +++ b/src/legacy/ui/public/new_platform/new_platform.ts @@ -64,6 +64,7 @@ import { VisualizationsSetup, VisualizationsStart, } from '../../../../plugins/visualizations/public'; +import { MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; export interface PluginsSetup { bfetch: BfetchPublicSetup; @@ -86,6 +87,7 @@ export interface PluginsSetup { visualizations: VisualizationsSetup; telemetry?: TelemetryPluginSetup; savedObjectsManagement: SavedObjectsManagementPluginSetup; + mapsLegacy: MapsLegacyPluginSetup; } export interface PluginsStart { diff --git a/src/plugins/maps_legacy/kibana.json b/src/plugins/maps_legacy/kibana.json index 69e18db10d5f8..d66be2b156bb9 100644 --- a/src/plugins/maps_legacy/kibana.json +++ b/src/plugins/maps_legacy/kibana.json @@ -1,5 +1,5 @@ { - "id": "maps_legacy", + "id": "mapsLegacy", "version": "8.0.0", "kibanaVersion": "kibana", "ui": true diff --git a/src/plugins/maps_legacy/public/index.ts b/src/plugins/maps_legacy/public/index.ts index 7c06d4965fdc1..861f67006ad83 100644 --- a/src/plugins/maps_legacy/public/index.ts +++ b/src/plugins/maps_legacy/public/index.ts @@ -56,3 +56,6 @@ export { FileLayer, TmsLayer, }; + +export type MapsLegacyPluginSetup = ReturnType; +export type MapsLegacyPluginStart = ReturnType; diff --git a/src/plugins/maps_legacy/public/map/precision.ts b/src/plugins/maps_legacy/public/map/precision.ts index 7d5ebea948f3e..a1b3b72f201a4 100644 --- a/src/plugins/maps_legacy/public/map/precision.ts +++ b/src/plugins/maps_legacy/public/map/precision.ts @@ -17,6 +17,7 @@ * under the License. */ +// @ts-ignore import { getUiSettings } from '../kibana_services'; import { geohashColumns } from './decode_geo_hash'; diff --git a/src/plugins/maps_legacy/public/plugin.ts b/src/plugins/maps_legacy/public/plugin.ts index 7c096d8a5661f..751be65e1dbf6 100644 --- a/src/plugins/maps_legacy/public/plugin.ts +++ b/src/plugins/maps_legacy/public/plugin.ts @@ -25,6 +25,7 @@ import { setToasts, setUiSettings, setInjectedVarFunc } from './kibana_services' import { ServiceSettings } from './map/service_settings'; // @ts-ignore import { getPrecision, getZoomPrecision } from './map/precision'; +import { MapsLegacyPluginSetup, MapsLegacyPluginStart } from './index'; /** * These are the interfaces with your public contracts. You should export these @@ -37,9 +38,6 @@ export interface MapsLegacySetupDependencies {} // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface MapsLegacyStartDependencies {} -export type MapsLegacyPluginSetup = ReturnType; -export type MapsLegacyPluginStart = ReturnType; - export class MapsLegacyPlugin implements Plugin { constructor() {} From f1564bb6f2366ee4ba523d16e2d31c8236f74fc5 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 2 Apr 2020 16:42:31 -0600 Subject: [PATCH 15/24] Inject toast service into map when needed --- .../core_plugins/region_map/public/plugin.ts | 2 ++ .../public/region_map_visualization.js | 12 +++++++-- .../public/base_maps_visualization.js | 9 +++++-- .../core_plugins/tile_map/public/plugin.ts | 2 ++ .../tile_map/public/tile_map_visualization.js | 6 ++++- .../public/vega_view/vega_map_view.js | 25 +++++++++++++------ .../public/vega_visualization.js | 3 ++- .../maps_legacy/public/map/kibana_map.js | 23 +++++++++++------ .../maps_legacy/public/map/map_messages.js | 6 ++--- 9 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index e9c3ea1adb45a..b824c0b8cd5ce 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -39,6 +39,7 @@ interface RegionMapVisualizationDependencies extends LegacyDependenciesPluginSet uiSettings: IUiSettingsClient; regionmapsConfig: RegionMapsConfig; serviceSettings: IServiceSettings; + notificationService: any; } /** @internal */ @@ -73,6 +74,7 @@ export class RegionMapPlugin implements Plugin, void> { 'regionmapsConfig' ) as RegionMapsConfig, serviceSettings: mapsLegacy.serviceSettings, + notificationService: core.notifications.toasts, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/region_map/public/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/region_map_visualization.js index 25641ea76809d..2cc2a886657a1 100644 --- a/src/legacy/core_plugins/region_map/public/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/region_map_visualization.js @@ -28,8 +28,16 @@ import { truncatedColorMaps } from '../../../../plugins/charts/public'; // TODO: reference to TILE_MAP plugin should be removed import { BaseMapsVisualizationProvider } from '../../tile_map/public/base_maps_visualization'; -export function createRegionMapVisualization({ serviceSettings, $injector, uiSettings }) { - const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings); +export function createRegionMapVisualization({ + serviceSettings, + $injector, + uiSettings, + notificationService, +}) { + const BaseMapsVisualization = new BaseMapsVisualizationProvider( + serviceSettings, + notificationService + ); const tooltipFormatter = new TileMapTooltipFormatter($injector); return class RegionMapsVisualization extends BaseMapsVisualization { diff --git a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js index 5b21db582be7b..1dac4607280cc 100644 --- a/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/base_maps_visualization.js @@ -28,12 +28,16 @@ import chrome from 'ui/chrome'; const WMS_MINZOOM = 0; const WMS_MAXZOOM = 22; //increase this to 22. Better for WMS -export function BaseMapsVisualizationProvider(serviceSettings) { +export function BaseMapsVisualizationProvider(mapServiceSettings, notificationService) { /** * Abstract base class for a visualization consisting of a map with a single baselayer. * @class BaseMapsVisualization * @constructor */ + + const serviceSettings = mapServiceSettings; + const toastService = notificationService; + return class BaseMapsVisualization { constructor(element, vis) { this.vis = vis; @@ -93,8 +97,9 @@ export function BaseMapsVisualizationProvider(serviceSettings) { const centerFromUIState = uiState.get('mapCenter'); options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : this.vis.params.mapZoom; options.center = centerFromUIState ? centerFromUIState : this.vis.params.mapCenter; + const services = { toastService }; - this._kibanaMap = new KibanaMap(this._container, options); + this._kibanaMap = new KibanaMap(this._container, options, services); this._kibanaMap.setMinZoom(WMS_MINZOOM); //use a default this._kibanaMap.setMaxZoom(WMS_MAXZOOM); //use a default diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index 8fd00ec073d1e..e65bf857d30aa 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -40,6 +40,7 @@ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup uiSettings: IUiSettingsClient; getZoomPrecision: any; getPrecision: any; + notificationService: any; } /** @internal */ @@ -67,6 +68,7 @@ export class TileMapPlugin implements Plugin, void> { serviceSettings, getZoomPrecision, getPrecision, + notificationService: core.notifications.toasts, uiSettings: core.uiSettings, ...(await __LEGACY.setup()), }; diff --git a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js index d866b28a146dd..fdce8bc51fe86 100644 --- a/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/tile_map_visualization.js @@ -30,8 +30,12 @@ export const createTileMapVisualization = ({ $injector, getZoomPrecision, getPrecision, + notificationService, }) => { - const BaseMapsVisualization = new BaseMapsVisualizationProvider(serviceSettings); + const BaseMapsVisualization = new BaseMapsVisualizationProvider( + serviceSettings, + notificationService + ); const tooltipFormatter = new TileMapTooltipFormatterProvider($injector); return class CoordinateMapsVisualization extends BaseMapsVisualization { diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js index 74c8588f10d17..03aef29dc5739 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_view/vega_map_view.js @@ -25,6 +25,11 @@ import { KibanaMap } from '../../../../../plugins/maps_legacy/public'; import { getEmsTileLayerId, getUISettings } from '../services'; export class VegaMapView extends VegaBaseView { + constructor(opts, services) { + super(opts); + this.services = services; + } + async _initViewCustomizations() { const mapConfig = this._parser.mapConfig; let baseMapOpts; @@ -102,14 +107,18 @@ export class VegaMapView extends VegaBaseView { // maxBounds = L.latLngBounds(L.latLng(b[1], b[0]), L.latLng(b[3], b[2])); // } - this._kibanaMap = new KibanaMap(this._$container.get(0), { - zoom, - minZoom, - maxZoom, - center: [mapConfig.latitude, mapConfig.longitude], - zoomControl: mapConfig.zoomControl, - scrollWheelZoom: mapConfig.scrollWheelZoom, - }); + this._kibanaMap = new KibanaMap( + this._$container.get(0), + { + zoom, + minZoom, + maxZoom, + center: [mapConfig.latitude, mapConfig.longitude], + zoomControl: mapConfig.zoomControl, + scrollWheelZoom: mapConfig.scrollWheelZoom, + }, + this.services + ); if (baseMapOpts) { this._kibanaMap.setBaseLayer({ diff --git a/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js index 96835ef3b10bc..a6e911de7f0cb 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/vega_visualization.js @@ -116,7 +116,8 @@ export const createVegaVisualization = ({ serviceSettings }) => }; if (vegaParser.useMap) { - this._vegaView = new VegaMapView(vegaViewParams); + const services = { toastService: getNotifications().toasts }; + this._vegaView = new VegaMapView(vegaViewParams, services); } else { this._vegaView = new VegaView(vegaViewParams); } diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index cdeecc7c45011..a5d8137170afe 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -101,7 +101,7 @@ function makeLegendControl(container, kibanaMap, position) { * Serves as simple abstraction for leaflet as well. */ export class KibanaMap extends EventEmitter { - constructor(containerNode, options) { + constructor(containerNode, options, services) { super(); this._containerNode = containerNode; this._leafletBaseLayer = null; @@ -116,6 +116,7 @@ export class KibanaMap extends EventEmitter { this._layers = []; this._listeners = []; this._showTooltip = false; + this.toastService = services.toastService; const leafletOptions = { minZoom: options.minZoom, @@ -482,15 +483,21 @@ export class KibanaMap extends EventEmitter { } _addMaxZoomMessage = layer => { - const zoomWarningMsg = createZoomWarningMsg(this.getZoomLevel, this.getMaxZoomLevel); + if (this.toastService) { + const zoomWarningMsg = createZoomWarningMsg( + this.toastService, + this.getZoomLevel, + this.getMaxZoomLevel + ); - this._leafletMap.on('zoomend', zoomWarningMsg); - this._containerNode.setAttribute('data-test-subj', 'zoomWarningEnabled'); + this._leafletMap.on('zoomend', zoomWarningMsg); + this._containerNode.setAttribute('data-test-subj', 'zoomWarningEnabled'); - layer.on('remove', () => { - this._leafletMap.off('zoomend', zoomWarningMsg); - this._containerNode.removeAttribute('data-test-subj'); - }); + layer.on('remove', () => { + this._leafletMap.off('zoomend', zoomWarningMsg); + this._containerNode.removeAttribute('data-test-subj'); + }); + } }; setLegendPosition(position) { diff --git a/src/plugins/maps_legacy/public/map/map_messages.js b/src/plugins/maps_legacy/public/map/map_messages.js index 255aef93b1b72..2fd25701f26a6 100644 --- a/src/plugins/maps_legacy/public/map/map_messages.js +++ b/src/plugins/maps_legacy/public/map/map_messages.js @@ -17,7 +17,6 @@ * under the License. */ -import { getToasts } from '../kibana_services'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiSpacer, EuiButtonEmpty } from '@elastic/eui'; @@ -105,13 +104,12 @@ export const createZoomWarningMsg = (function() { 'data-test-subj': 'maxZoomWarning', }; - const toasts = getToasts(); - return (getZoomLevel, getMaxZoomLevel) => { + return (toastService, getZoomLevel, getMaxZoomLevel) => { return () => { const zoomLevel = getZoomLevel(); const maxMapZoom = getMaxZoomLevel(); if (!disableZoomMsg && zoomLevel === maxMapZoom) { - toasts.addDanger(zoomToast); + toastService.addDanger(zoomToast); } }; }; From 8a6849a92a527790e8a25abb740e1e5d0608ffac Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Fri, 3 Apr 2020 09:12:49 -0600 Subject: [PATCH 16/24] Fix typo in regionmap config --- src/legacy/core_plugins/region_map/public/plugin.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index b824c0b8cd5ce..330e5ec126987 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -70,9 +70,7 @@ export class RegionMapPlugin implements Plugin, void> { ) { const visualizationDependencies: Readonly = { uiSettings: core.uiSettings, - regionmapsConfig: core.injectedMetadata.getInjectedVar( - 'regionmapsConfig' - ) as RegionMapsConfig, + regionmapsConfig: core.injectedMetadata.getInjectedVar('regionmap') as RegionMapsConfig, serviceSettings: mapsLegacy.serviceSettings, notificationService: core.notifications.toasts, ...(await __LEGACY.setup()), From d33b9d3582a58a292b433d997e066727a5374edb Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Fri, 3 Apr 2020 09:26:22 -0600 Subject: [PATCH 17/24] i18n fixes --- .i18nrc.json | 1 + src/plugins/maps_legacy/public/map/kibana_map.js | 2 +- src/plugins/maps_legacy/public/map/map_messages.js | 2 +- x-pack/plugins/translations/translations/ja-JP.json | 2 -- x-pack/plugins/translations/translations/zh-CN.json | 2 -- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.i18nrc.json b/.i18nrc.json index c293b3103a39c..7fbd1d55d8405 100644 --- a/.i18nrc.json +++ b/.i18nrc.json @@ -24,6 +24,7 @@ "src/legacy/core_plugins/management", "src/plugins/management" ], + "maps_legacy": "src/plugins/maps_legacy", "advancedSettings": "src/plugins/advanced_settings", "kibana_legacy": "src/plugins/kibana_legacy", "kibana_react": "src/legacy/core_plugins/kibana_react", diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index a5d8137170afe..c29e8bf6d5b92 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -39,7 +39,7 @@ function makeFitControl(fitContainer, kibanaMap) { onAdd: function(leafletMap) { this._leafletMap = leafletMap; const fitDatBoundsLabel = i18n.translate( - 'common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel', + 'maps_legacy.kibanaMap.leaflet.fitDataBoundsAriaLabel', { defaultMessage: 'Fit Data Bounds' } ); $(this._fitContainer) diff --git a/src/plugins/maps_legacy/public/map/map_messages.js b/src/plugins/maps_legacy/public/map/map_messages.js index 2fd25701f26a6..7422fa71280fb 100644 --- a/src/plugins/maps_legacy/public/map/map_messages.js +++ b/src/plugins/maps_legacy/public/map/map_messages.js @@ -39,7 +39,7 @@ export const createZoomWarningMsg = (function() {

Date: Fri, 3 Apr 2020 11:08:46 -0600 Subject: [PATCH 18/24] Update jest test path --- src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js b/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js index 4f30b2aa1f24c..6da37f4c5ef86 100644 --- a/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js +++ b/src/legacy/core_plugins/tile_map/public/tilemap_fn.test.js @@ -22,7 +22,7 @@ import { functionWrapper } from '../../../../plugins/expressions/common/expressi import { createTileMapFn } from './tile_map_fn'; jest.mock('ui/new_platform'); -jest.mock('ui/vis/map/convert_to_geojson', () => ({ +jest.mock('../../../../plugins/maps_legacy/public', () => ({ convertToGeoJson: jest.fn().mockReturnValue({ featureCollection: { type: 'FeatureCollection', From 128d952cdbb37705d9dab466498f5a430cd379bf Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Mon, 6 Apr 2020 09:45:41 -0600 Subject: [PATCH 19/24] Fix karma tests --- .../__tests__/region_map_visualization.js | 30 ++++++++++++++- .../coordinate_maps_visualization.js | 37 ++++++++++++++++++- .../maps_legacy/public/map/kibana_map.js | 2 +- 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js index e9c9fe02626d7..6e1b0b7160941 100644 --- a/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js +++ b/src/legacy/core_plugins/region_map/public/__tests__/region_map_visualization.js @@ -50,6 +50,10 @@ import { createRegionMapTypeDefinition } from '../region_map_type'; import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings'; const THRESHOLD = 0.45; const PIXEL_DIFF = 96; @@ -98,7 +102,31 @@ describe('RegionMapsVisualizationTests', function() { let getManifestStub; beforeEach( ngMock.inject((Private, $injector) => { - const serviceSettings = $injector.get('serviceSettings'); + setInjectedVarFunc(injectedVar => { + switch (injectedVar) { + case 'mapConfig': + return { + emsFileApiUrl: '', + emsTileApiUrl: '', + emsLandingPageUrl: '', + }; + case 'tilemapsConfig': + return { + deprecated: { + config: { + options: { + attribution: '123', + }, + }, + }, + }; + case 'version': + return '123'; + default: + return 'not found'; + } + }); + const serviceSettings = new ServiceSettings(); const uiSettings = $injector.get('config'); const regionmapsConfig = { includeElasticMapsService: true, diff --git a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js index 1450728f81bb5..3904c43707906 100644 --- a/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js +++ b/src/legacy/core_plugins/tile_map/public/__tests__/coordinate_maps_visualization.js @@ -44,6 +44,15 @@ import { createTileMapTypeDefinition } from '../tile_map_type'; import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_types/base_vis_type'; +import { + getPrecision, + getZoomPrecision, + // eslint-disable-next-line @kbn/eslint/no-restricted-paths +} from '../../../../../plugins/maps_legacy/public/map/precision'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services'; function mockRawData() { const stack = [dummyESResponse]; @@ -81,13 +90,39 @@ describe('CoordinateMapsVisualizationTest', function() { beforeEach(ngMock.module('kibana')); beforeEach( ngMock.inject((Private, $injector) => { - const serviceSettings = $injector.get('serviceSettings'); + setInjectedVarFunc(injectedVar => { + switch (injectedVar) { + case 'mapConfig': + return { + emsFileApiUrl: '', + emsTileApiUrl: '', + emsLandingPageUrl: '', + }; + case 'tilemapsConfig': + return { + deprecated: { + config: { + options: { + attribution: '123', + }, + }, + }, + }; + case 'version': + return '123'; + default: + return 'not found'; + } + }); + const serviceSettings = new ServiceSettings(); const uiSettings = $injector.get('config'); dependencies = { serviceSettings, uiSettings, $injector, + getPrecision, + getZoomPrecision, }; visType = new BaseVisType(createTileMapTypeDefinition(dependencies)); diff --git a/src/plugins/maps_legacy/public/map/kibana_map.js b/src/plugins/maps_legacy/public/map/kibana_map.js index c29e8bf6d5b92..1c4d0882cb7da 100644 --- a/src/plugins/maps_legacy/public/map/kibana_map.js +++ b/src/plugins/maps_legacy/public/map/kibana_map.js @@ -116,7 +116,7 @@ export class KibanaMap extends EventEmitter { this._layers = []; this._listeners = []; this._showTooltip = false; - this.toastService = services.toastService; + this.toastService = services ? services.toastService : null; const leafletOptions = { minZoom: options.minZoom, From d2b0433c74daef9bee78d162955b720ca5e7895b Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Mon, 6 Apr 2020 09:57:48 -0600 Subject: [PATCH 20/24] i18n fixes --- x-pack/plugins/translations/translations/ja-JP.json | 2 -- x-pack/plugins/translations/translations/zh-CN.json | 2 -- 2 files changed, 4 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 023a97274b957..68034f4045e3d 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -312,8 +312,6 @@ "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "セッションがいっぱいで安全に削除できるアイテムが見つからないため、Kibana は履歴アイテムを保存できません。\n\nこれは大抵新規タブに移動することで解決されますが、より大きな問題が原因である可能性もあります。このメッセージが定期的に表示される場合は、{gitHubIssuesUrl} で問題を報告してください。", "common.ui.url.replacementFailedErrorMessage": "置換に失敗、未解決の表現式: {expr}", "common.ui.url.savedObjectIsMissingNotificationMessage": "保存されたオブジェクトがありません", - "common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel": "データバウンドを合わせる", - "common.ui.vis.kibanaMap.zoomWarning": "ズームレベルが最大に達しました。完全にズームインするには、Elasticsearch と Kibana の {defaultDistribution} にアップグレードしてください。{ems} でより多くのズームレベルが利用できます。または、独自のマップサーバーを構成できます。詳細は { wms } または { configSettings} をご覧ください。", "console.autocomplete.addMethodMetaText": "メソド", "console.consoleDisplayName": "コンソール", "console.consoleMenu.copyAsCurlMessage": "リクエストが URL としてコピーされました", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b359014e95e70..f68f7ca706009 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -312,8 +312,6 @@ "common.ui.stateManagement.unableToStoreHistoryInSessionErrorMessage": "Kibana 无法将历史记录项存储在您的会话中,因为其已满,并且似乎没有任何可安全删除的项。\n\n通常可通过移至新的标签页来解决此问题,但这会导致更大的问题。如果您有规律地看到此消息,请在 {gitHubIssuesUrl} 提交问题。", "common.ui.url.replacementFailedErrorMessage": "替换失败,未解析的表达式:{expr}", "common.ui.url.savedObjectIsMissingNotificationMessage": "已保存对象缺失", - "common.ui.vis.kibanaMap.leaflet.fitDataBoundsAriaLabel": "适应数据边界", - "common.ui.vis.kibanaMap.zoomWarning": "已达到缩放级别最大数目。要一直放大,请升级到 Elasticsearch 和 Kibana 的 {defaultDistribution}。您可以通过 {ems} 免费使用其他缩放级别。或者,您可以配置自己的地图服务器。请前往 { wms } 或 { configSettings} 以获取详细信息。", "console.autocomplete.addMethodMetaText": "方法", "console.consoleDisplayName": "控制台", "console.consoleMenu.copyAsCurlMessage": "请求已复制为 cURL", From d9534234194e7def2b03086c4d78f08a81340c74 Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Tue, 7 Apr 2020 09:47:46 -0600 Subject: [PATCH 21/24] Type updates. Add mapsLegacy to np karma mock --- src/legacy/core_plugins/region_map/public/plugin.ts | 4 ++-- src/legacy/core_plugins/tile_map/public/plugin.ts | 4 ++-- .../ui/public/new_platform/new_platform.karma_mock.js | 6 ++++++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/legacy/core_plugins/region_map/public/plugin.ts b/src/legacy/core_plugins/region_map/public/plugin.ts index 330e5ec126987..1453c2155e2d6 100644 --- a/src/legacy/core_plugins/region_map/public/plugin.ts +++ b/src/legacy/core_plugins/region_map/public/plugin.ts @@ -32,7 +32,7 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createRegionMapFn } from './region_map_fn'; // @ts-ignore import { createRegionMapTypeDefinition } from './region_map_type'; -import { IServiceSettings } from '../../../../plugins/maps_legacy/public'; +import { IServiceSettings, MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; /** @private */ interface RegionMapVisualizationDependencies extends LegacyDependenciesPluginSetup { @@ -47,7 +47,7 @@ export interface RegionMapPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; __LEGACY: LegacyDependenciesPlugin; - mapsLegacy: any; + mapsLegacy: MapsLegacyPluginSetup; } /** @internal */ diff --git a/src/legacy/core_plugins/tile_map/public/plugin.ts b/src/legacy/core_plugins/tile_map/public/plugin.ts index e65bf857d30aa..2b97407b17b38 100644 --- a/src/legacy/core_plugins/tile_map/public/plugin.ts +++ b/src/legacy/core_plugins/tile_map/public/plugin.ts @@ -32,7 +32,7 @@ import { LegacyDependenciesPlugin, LegacyDependenciesPluginSetup } from './shim' import { createTileMapFn } from './tile_map_fn'; // @ts-ignore import { createTileMapTypeDefinition } from './tile_map_type'; -import { IServiceSettings } from '../../../../plugins/maps_legacy/public'; +import { IServiceSettings, MapsLegacyPluginSetup } from '../../../../plugins/maps_legacy/public'; /** @private */ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup { @@ -47,7 +47,7 @@ interface TileMapVisualizationDependencies extends LegacyDependenciesPluginSetup export interface TileMapPluginSetupDependencies { expressions: ReturnType; visualizations: VisualizationsSetup; - mapsLegacy: any; + mapsLegacy: MapsLegacyPluginSetup; __LEGACY: LegacyDependenciesPlugin; } diff --git a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js index 25647e4a08897..297ea613df39f 100644 --- a/src/legacy/ui/public/new_platform/new_platform.karma_mock.js +++ b/src/legacy/ui/public/new_platform/new_platform.karma_mock.js @@ -299,6 +299,12 @@ export const npSetup = { registerAlias: sinon.fake(), hideTypes: sinon.fake(), }, + + mapsLegacy: { + serviceSettings: sinon.fake(), + getPrecision: sinon.fake(), + getZoomPrecision: sinon.fake(), + }, }, }; From a3278ca99e4ee9b46736f59d71a3f70dc754ea8a Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Tue, 7 Apr 2020 14:37:40 -0600 Subject: [PATCH 22/24] Remove html sanitizer --- src/plugins/maps_legacy/public/map/service_settings.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/maps_legacy/public/map/service_settings.js b/src/plugins/maps_legacy/public/map/service_settings.js index 70e5c1aa3c02a..11c853d39e107 100644 --- a/src/plugins/maps_legacy/public/map/service_settings.js +++ b/src/plugins/maps_legacy/public/map/service_settings.js @@ -40,7 +40,6 @@ export class ServiceSettings { appName: 'kibana', fileApiUrl: this.mapConfig.emsFileApiUrl, tileApiUrl: this.mapConfig.emsTileApiUrl, - htmlSanitizer: _.escape, landingPageUrl: this.mapConfig.emsLandingPageUrl, // Wrap to avoid errors passing window fetch fetchFunction: function(...args) { From b14ad08888459105742c8a23f705e7ed09f2a46d Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Wed, 8 Apr 2020 10:03:48 -0600 Subject: [PATCH 23/24] Fix vega test that depends on serviceSettings --- .../public/__tests__/vega_visualization.js | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js index c7fbc0815b07c..6412d8a569b2a 100644 --- a/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js +++ b/src/legacy/core_plugins/vis_type_vega/public/__tests__/vega_visualization.js @@ -49,6 +49,10 @@ import { BaseVisType } from '../../../../../plugins/visualizations/public/vis_ty // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ExprVis } from '../../../../../plugins/visualizations/public/expressions/vis'; import { setInjectedVars } from '../services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { setInjectedVarFunc } from '../../../../../plugins/maps_legacy/public/kibana_services'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import { ServiceSettings } from '../../../../../plugins/maps_legacy/public/map/service_settings'; const THRESHOLD = 0.1; const PIXEL_DIFF = 30; @@ -69,9 +73,34 @@ describe('VegaVisualizations', () => { beforeEach(ngMock.module('kibana')); beforeEach( - ngMock.inject($injector => { + ngMock.inject(() => { + setInjectedVarFunc(injectedVar => { + switch (injectedVar) { + case 'mapConfig': + return { + emsFileApiUrl: '', + emsTileApiUrl: '', + emsLandingPageUrl: '', + }; + case 'tilemapsConfig': + return { + deprecated: { + config: { + options: { + attribution: '123', + }, + }, + }, + }; + case 'version': + return '123'; + default: + return 'not found'; + } + }); + const serviceSettings = new ServiceSettings(); vegaVisualizationDependencies = { - serviceSettings: $injector.get('serviceSettings'), + serviceSettings, core: { uiSettings: npStart.core.uiSettings, }, From f9a41e93b0359bb59877ba590f65212d2aecd5bd Mon Sep 17 00:00:00 2001 From: Aaron Caldwell Date: Thu, 9 Apr 2020 08:11:50 -0600 Subject: [PATCH 24/24] Revise xpack license handling to use NP serviceSettings. Remove angular bindings --- .../update_tilemap_settings.js | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js b/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js index 51a53e8a3ed3f..294bc31e3893e 100644 --- a/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js +++ b/x-pack/legacy/plugins/tilemap/public/vis_type_enhancers/update_tilemap_settings.js @@ -4,19 +4,13 @@ * you may not use this file except in compliance with the Elastic License. */ -import uiRoutes from 'ui/routes'; import { xpackInfo } from 'plugins/xpack_main/services/xpack_info'; +import { npSetup } from 'ui/new_platform'; -uiRoutes.addSetupWork(function($injector, serviceSettings) { - const tileMapPluginInfo = xpackInfo.get('features.tilemap'); +const tileMapPluginInfo = xpackInfo.get('features.tilemap'); - if (!tileMapPluginInfo) { - return; - } - - if (!tileMapPluginInfo.license.active || !tileMapPluginInfo.license.valid) { - return; - } +if (tileMapPluginInfo && (tileMapPluginInfo.license.active || tileMapPluginInfo.license.valid)) { + const { serviceSettings } = npSetup.plugins.mapsLegacy; serviceSettings.addQueryParams({ license: tileMapPluginInfo.license.uid }); serviceSettings.disableZoomMessage(); -}); +}