From c56360b9089c974f32b1c917f72011ef1cc60ba0 Mon Sep 17 00:00:00 2001 From: Peter Pisljar Date: Tue, 21 Nov 2017 08:27:39 +0100 Subject: [PATCH] Improve Region Maps for use without network connection (#15056) * enable turning on/off of warnings * add tooltip * add server setting so users can opt out of connecting to the EMS service * replace WMS options with custom directive, so we can reuse it in region maps * add wms settings form to Region Map * no need to recreate map after leaflet upgrade * add WMS map to region map * linting issues * fix rebase * improve wording * add global config * fix typo --- docs/setup/settings.asciidoc | 3 + .../public/region_map_controller.js | 48 ++++++++---- .../region_map/public/region_map_vis.js | 6 +- .../public/region_map_vis_params.html | 18 ++++- .../public/region_map_vis_params.js | 71 ++++++++++------- .../tile_map/public/editors/tile_map.html | 74 +----------------- .../tile_map/public/editors/wms_options.html | 76 +++++++++++++++++++ .../tile_map/public/editors/wms_options.js | 11 +++ .../tile_map/public/kibana_map.js | 7 ++ .../tile_map/public/maps_visualization.js | 19 +++-- src/server/config/schema.js | 1 + 11 files changed, 209 insertions(+), 125 deletions(-) create mode 100644 src/core_plugins/tile_map/public/editors/wms_options.html create mode 100644 src/core_plugins/tile_map/public/editors/wms_options.js diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 9748a70be5dd..6e5a56d8ae10 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -97,6 +97,9 @@ The following example shows a valid regionmap configuration. description: "Full department name" - name: "INSEE" description: "INSEE numeric identifier" + +`regionmap.includeElasticMapsService`:: turns on or off whether layers from the Elastic Maps Service should be included in the vector layer option list. +By turning this off, only the layers that are configured here will be included. `server.basePath:`:: Enables you to specify a path to mount Kibana at if you are running behind a proxy. This only affects the URLs generated by Kibana, your proxy is expected to remove the basePath value before forwarding requests diff --git a/src/core_plugins/region_map/public/region_map_controller.js b/src/core_plugins/region_map/public/region_map_controller.js index 61d52ed55a0f..9af4351fbbfe 100644 --- a/src/core_plugins/region_map/public/region_map_controller.js +++ b/src/core_plugins/region_map/public/region_map_controller.js @@ -32,7 +32,6 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private, }); $scope.$watch('esResponse', async function (tableGroup) { - kibanaMapReady.then(() => { let results; @@ -52,7 +51,6 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private, } updateChoroplethLayer($scope.vis.params.selectedLayer.url, $scope.vis.params.selectedLayer.attribution); - const metricsAgg = _.first($scope.vis.getAggConfig().bySchemaName.metric); choroplethLayer.setMetrics(results, metricsAgg); setTooltipFormatter(); @@ -78,6 +76,10 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private, choroplethLayer.setColorRamp(truncatedColorMaps[visParams.colorSchema]); setTooltipFormatter(); + + updateBaseLayer(visParams); + + kibanaMap.setShowTooltip(visParams.addTooltip); kibanaMap.setLegendPosition(visParams.legendPosition); kibanaMap.useUiStateFromVisualization($scope.vis); @@ -86,25 +88,44 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private, }); }); - async function makeKibanaMap() { + async function updateBaseLayer(visParams) { const tmsSettings = await serviceSettings.getTMSService(); - const minMaxZoom = tmsSettings.getMinMaxZoom(false); + let baseLayerOptions; + let minMaxZoom; + if (visParams.wms.enabled) { + minMaxZoom = tmsSettings.getMinMaxZoom(true); + baseLayerOptions = { + baseLayerType: 'wms', + options: { + minZoom: minMaxZoom.minZoom, + maxZoom: minMaxZoom.maxZoom, + url: visParams.wms.url, + ...visParams.wms.options + } + }; + } else { + minMaxZoom = tmsSettings.getMinMaxZoom(false); + const tmsUrl = tmsSettings.getUrl(); + const tmsOptions = tmsSettings.getTMSOptions(); + baseLayerOptions = { baseLayerType: 'tms', options: { tmsUrl, ...tmsOptions } }; + } + kibanaMap.setMinZoom(minMaxZoom.minZoom); + kibanaMap.setMaxZoom(minMaxZoom.maxZoom); + kibanaMap.setBaseLayer(baseLayerOptions); + } - const options = { ...minMaxZoom }; + async function makeKibanaMap() { + const options = {}; const uiState = $scope.vis.getUiState(); const zoomFromUiState = parseInt(uiState.get('mapZoom')); const centerFromUIState = uiState.get('mapCenter'); options.zoom = !isNaN(zoomFromUiState) ? zoomFromUiState : DEFAULT_ZOOM_SETTINGS.zoom; options.center = centerFromUIState ? centerFromUIState : DEFAULT_ZOOM_SETTINGS.mapCenter; kibanaMap = new KibanaMap($element[0], options); - - - const tmsUrl = tmsSettings.getUrl(); - const tmsOptions = tmsSettings.getTMSOptions(); - kibanaMap.setBaseLayer({ baseLayerType: 'tms', options: { tmsUrl, ...tmsOptions } }); kibanaMap.addLegendControl(); kibanaMap.addFitControl(); kibanaMap.persistUiStateForVisualization($scope.vis); + await updateBaseLayer($scope.vis.params); } function setTooltipFormatter() { @@ -136,11 +157,12 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private, $scope.vis.API.events.filter({ point: { aggConfigResult: aggConfigResult } }); }); choroplethLayer.on('styleChanged', function (event) { - if (event.mismatches.length > 0 && config.get('visualization:regionmap:showWarnings')) { + const shouldShowWarning = $scope.vis.params.isDisplayWarning && config.get('visualization:regionmap:showWarnings'); + if (event.mismatches.length > 0 && shouldShowWarning) { notify.warning( `Could not show ${event.mismatches.length} ${event.mismatches.length > 1 ? 'results' : 'result'} on the map.` - + ` To avoid this, ensure that each term can be joined to a corresponding shape on that shape's join field.` - + ` Could not join following terms: ${event.mismatches.join(',')}` + + ` To avoid this, ensure that each term can be matched to a corresponding shape on that shape's join field.` + + ` Could not match following terms: ${event.mismatches.join(',')}` ); } }); diff --git a/src/core_plugins/region_map/public/region_map_vis.js b/src/core_plugins/region_map/public/region_map_vis.js index cc6a44d23f5a..37cfb85fb749 100644 --- a/src/core_plugins/region_map/public/region_map_vis.js +++ b/src/core_plugins/region_map/public/region_map_vis.js @@ -10,7 +10,7 @@ import { VisTypesRegistryProvider } from 'ui/registry/vis_types'; import { truncatedColorMaps } from 'ui/vislib/components/color/truncated_colormaps'; import { mapToLayerWithId } from './util'; -VisTypesRegistryProvider.register(function RegionMapProvider(Private, regionmapsConfig) { +VisTypesRegistryProvider.register(function RegionMapProvider(Private, regionmapsConfig, config) { const VisFactory = Private(VisFactoryProvider); const Schemas = Private(VisSchemasProvider); @@ -32,7 +32,9 @@ VisTypesRegistryProvider.register(function RegionMapProvider(Private, regionmaps addTooltip: true, colorSchema: 'Yellow to Red', selectedLayer: selectedLayer, - selectedJoinField: selectedJoinField + selectedJoinField: selectedJoinField, + isDisplayWarning: true, + wms: config.get('visualization:tileMap:WMSdefaults') }, template: regionTemplate, }, diff --git a/src/core_plugins/region_map/public/region_map_vis_params.html b/src/core_plugins/region_map/public/region_map_vis_params.html index 7e5c1dff0231..2a454765b890 100644 --- a/src/core_plugins/region_map/public/region_map_vis_params.html +++ b/src/core_plugins/region_map/public/region_map_vis_params.html @@ -34,10 +34,21 @@ +
+ + +
+ +
+
+
Style settings
@@ -56,9 +67,12 @@
+
-
Basic settings
+
+ Base Layer Settings +
- +
diff --git a/src/core_plugins/region_map/public/region_map_vis_params.js b/src/core_plugins/region_map/public/region_map_vis_params.js index 9729f359509b..386311d46719 100644 --- a/src/core_plugins/region_map/public/region_map_vis_params.js +++ b/src/core_plugins/region_map/public/region_map_vis_params.js @@ -1,10 +1,10 @@ import { uiModules } from 'ui/modules'; import regionMapVisParamsTemplate from './region_map_vis_params.html'; import { mapToLayerWithId } from './util'; +import '../../tile_map/public/editors/wms_options'; uiModules.get('kibana/region_map') - .directive('regionMapVisParams', function (serviceSettings, Notifier) { - + .directive('regionMapVisParams', function (serviceSettings, regionmapsConfig, Notifier) { const notify = new Notifier({ location: 'Region map' }); @@ -14,37 +14,54 @@ uiModules.get('kibana/region_map') link: function ($scope) { $scope.collections = $scope.vis.type.editorConfig.collections; - $scope.onLayerChange = onLayerChange; - serviceSettings.getFileLayers() - .then(function (layersFromService) { - layersFromService = layersFromService.map(mapToLayerWithId.bind(null, 'elastic_maps_service')); - const newVectorLayers = $scope.collections.vectorLayers.slice(); - for (let i = 0; i < layersFromService.length; i += 1) { - const layerFromService = layersFromService[i]; - const alreadyAdded = newVectorLayers.some((layer) => layerFromService.layerId === layer.layerId); - if (!alreadyAdded) { - newVectorLayers.push(layerFromService); + if (regionmapsConfig.includeElasticMapsService) { + + serviceSettings.getFileLayers() + .then(function (layersFromService) { + + layersFromService = layersFromService.map(mapToLayerWithId.bind(null, 'elastic_maps_service')); + const newVectorLayers = $scope.collections.vectorLayers.slice(); + for (let i = 0; i < layersFromService.length; i += 1) { + const layerFromService = layersFromService[i]; + const alreadyAdded = newVectorLayers.some((layer) => layerFromService.layerId === layer.layerId); + if (!alreadyAdded) { + newVectorLayers.push(layerFromService); + } } - } - $scope.collections.vectorLayers = newVectorLayers; - if ($scope.collections.vectorLayers[0] && !$scope.vis.params.selectedLayer) { - $scope.vis.params.selectedLayer = $scope.collections.vectorLayers[0]; - onLayerChange(); - } + $scope.collections.vectorLayers = newVectorLayers; + if ($scope.collections.vectorLayers[0] && !$scope.vis.params.selectedLayer) { + $scope.vis.params.selectedLayer = $scope.collections.vectorLayers[0]; + onLayerChange(); + } - //the dirty flag is set to true because the change in vector layers config causes an update of the scope.params - //temp work-around. addressing this issue with the visualize refactor for 6.0 - setTimeout(function () { - $scope.dirty = false; - }, 0); + //the dirty flag is set to true because the change in vector layers config causes an update of the scope.params + //temp work-around. addressing this issue with the visualize refactor for 6.0 + setTimeout(function () { + $scope.dirty = false; + }, 0); + $scope.collections.vectorLayers = newVectorLayers; - }) - .catch(function (error) { - notify.warning(error.message); - }); + if ($scope.collections.vectorLayers[0] && !$scope.vis.params.selectedLayer) { + $scope.vis.params.selectedLayer = $scope.collections.vectorLayers[0]; + onLayerChange(); + } + + + //the dirty flag is set to true because the change in vector layers config causes an update of the scope.params + //temp work-around. addressing this issue with the visualize refactor for 6.0 + setTimeout(function () { + $scope.dirty = false; + }, 0); + + + }) + .catch(function (error) { + notify.warning(error.message); + }); + } function onLayerChange() { $scope.vis.params.selectedJoinField = $scope.vis.params.selectedLayer.fields[0]; diff --git a/src/core_plugins/tile_map/public/editors/tile_map.html b/src/core_plugins/tile_map/public/editors/tile_map.html index 903dfd24ad41..378fc891401c 100644 --- a/src/core_plugins/tile_map/public/editors/tile_map.html +++ b/src/core_plugins/tile_map/public/editors/tile_map.html @@ -53,77 +53,5 @@ -
- -
- -
-
-

WMS is an OGC standard for map image services. For more information, go here.

- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -

* if this parameter is incorrect, maps will fail to load.

- - -
+ diff --git a/src/core_plugins/tile_map/public/editors/wms_options.html b/src/core_plugins/tile_map/public/editors/wms_options.html new file mode 100644 index 000000000000..c23ac730c4ea --- /dev/null +++ b/src/core_plugins/tile_map/public/editors/wms_options.html @@ -0,0 +1,76 @@ +
+ +
+ +
+ +
+
+

WMS is an OGC standard for map image services. For more information, go here.

+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +

* if this parameter is incorrect, maps will fail to load.

+ + +
+
diff --git a/src/core_plugins/tile_map/public/editors/wms_options.js b/src/core_plugins/tile_map/public/editors/wms_options.js new file mode 100644 index 000000000000..22084308d5e1 --- /dev/null +++ b/src/core_plugins/tile_map/public/editors/wms_options.js @@ -0,0 +1,11 @@ +import { uiModules } from 'ui/modules'; +import wmsOptionsTemplate from './wms_options.html'; +const module = uiModules.get('kibana'); + +module.directive('wmsOptions', function () { + return { + restrict: 'E', + template: wmsOptionsTemplate, + replace: true, + }; +}); diff --git a/src/core_plugins/tile_map/public/kibana_map.js b/src/core_plugins/tile_map/public/kibana_map.js index e5626e8845c8..3afb5f34102c 100644 --- a/src/core_plugins/tile_map/public/kibana_map.js +++ b/src/core_plugins/tile_map/public/kibana_map.js @@ -528,6 +528,13 @@ export class KibanaMap extends EventEmitter { this._updateExtent(); } + setMinZoom(zoom) { + this._leafletMap.setMinZoom(zoom); + } + + setMaxZoom(zoom) { + this._leafletMap.setMaxZoom(zoom); + } getLeafletBaseLayer() { return this._leafletBaseLayer; diff --git a/src/core_plugins/tile_map/public/maps_visualization.js b/src/core_plugins/tile_map/public/maps_visualization.js index f6e082ed1893..623cde614d35 100644 --- a/src/core_plugins/tile_map/public/maps_visualization.js +++ b/src/core_plugins/tile_map/public/maps_visualization.js @@ -1,12 +1,12 @@ import 'ui/vislib'; import 'plugins/kbn_vislib_vis_types/controls/vislib_basic_options'; +import './editors/wms_options'; import $ from 'jquery'; import _ from 'lodash'; import { KibanaMap } from './kibana_map'; import { GeohashLayer } from './geohash_layer'; import { SearchSourceProvider } from 'ui/courier/data_source/search_source'; import { VisAggConfigProvider } from 'ui/vis/agg_config'; -// import './lib/service_settings'; import 'ui/vis/map/service_settings'; import './styles/_tilemap.less'; @@ -172,6 +172,7 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState * called on options change (vis.params change) */ async _updateParams() { + const mapParams = this._getMapsParams(); if (_.eq(this._currentParams, mapParams)) { return; @@ -181,12 +182,13 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState const { minZoom, maxZoom } = this._getMinMaxZoom(); if (mapParams.wms.enabled) { - //Switch to WMS + // Switch to WMS if (maxZoom > this._kibanaMap.getMaxZoomLevel()) { //need to recreate the map with less restrictive zoom + this._kibanaMap.removeLayer(this._geohashLayer); this._geohashLayer = null; - this._kibanaMapReady = this._makeKibanaMap(); - await this._kibanaMapReady; + this._kibanaMap.setMinZoom(minZoom); + this._kibanaMap.setMaxZoom(maxZoom); } this._kibanaMap.setBaseLayer({ @@ -200,13 +202,13 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState }); } else { - //switch to regular + // switch to tms if (maxZoom < this._kibanaMap.getMaxZoomLevel()) { //need to recreate the map with more restrictive zoom level + this._kibanaMap.removeLayer(this._geohashLayer); this._geohashLayer = null; - this._kibanaMapReady = this._makeKibanaMap(); - await this._kibanaMapReady; - + this._kibanaMap.setMinZoom(minZoom); + this._kibanaMap.setMaxZoom(maxZoom); if (this._kibanaMap.getZoomLevel() > maxZoom) { this._kibanaMap.setZoomLevel(maxZoom); } @@ -221,6 +223,7 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState }); } } + const geohashOptions = this._getGeohashOptions(); if (!this._geohashLayer || !this._geohashLayer.isReusable(geohashOptions)) { this._recreateGeohashLayer(this._chartData); diff --git a/src/server/config/schema.js b/src/server/config/schema.js index c8077f221540..453808d60178 100644 --- a/src/server/config/schema.js +++ b/src/server/config/schema.js @@ -188,6 +188,7 @@ export default () => Joi.object({ }).default() }).default(), regionmap: Joi.object({ + includeElasticMapsService: Joi.boolean().default(true), layers: Joi.array().items(Joi.object({ url: Joi.string(), type: Joi.string(),