diff --git a/src/cli/serve/read_yaml_config.js b/src/cli/serve/read_yaml_config.js index 3387b20c2aa80..adfe4027d1036 100644 --- a/src/cli/serve/read_yaml_config.js +++ b/src/cli/serve/read_yaml_config.js @@ -32,6 +32,11 @@ let legacySettingMap = { request_timeout: 'elasticsearch.requestTimeout', shard_timeout: 'elasticsearch.shardTimeout', startup_timeout: 'elasticsearch.startupTimeout', + tilemap_url: 'tilemap.url', + tilemap_min_zoom: 'tilemap.options.minZoom', + tilemap_max_zoom: 'tilemap.options.maxZoom', + tilemap_attribution: 'tilemap.options.attribution', + tilemap_subdomains: 'tilemap.options.subdomains', verify_ssl: 'elasticsearch.ssl.verify', }; diff --git a/src/plugins/kibana/index.js b/src/plugins/kibana/index.js index 358c04c9b5f3f..4f89aec013366 100644 --- a/src/plugins/kibana/index.js +++ b/src/plugins/kibana/index.js @@ -38,7 +38,8 @@ module.exports = function (kibana) { let config = server.config(); return { - kbnDefaultAppId: config.get('kibana.defaultAppId') + kbnDefaultAppId: config.get('kibana.defaultAppId'), + tilemap: config.get('tilemap') }; } }, diff --git a/src/plugins/testsBundle/testsEntryTemplate.js b/src/plugins/testsBundle/testsEntryTemplate.js index 61127f4bfc48f..002bb15d433a0 100644 --- a/src/plugins/testsBundle/testsEntryTemplate.js +++ b/src/plugins/testsBundle/testsEntryTemplate.js @@ -27,7 +27,15 @@ window.__KBN__ = { kbnIndex: '.kibana', esShardTimeout: 1500, esApiVersion: '2.0', - esRequestTimeout: '300000' + esRequestTimeout: '300000', + tilemap: { + url: 'https://tiles.elastic.co/v1/default/{z}/{x}/{y}.png?my_app_name=kibana&my_app_version=1.2.3&elastic_tile_service_tos=agree', + options: { + minZoom: 1, + maxZoom: 7, + attribution: '© [Elastic Tile Service](https://www.elastic.co/elastic_tile_service)' + } + } } }; diff --git a/src/server/config/schema.js b/src/server/config/schema.js index daaa8a1da2853..5741b6e0a0fbb 100644 --- a/src/server/config/schema.js +++ b/src/server/config/schema.js @@ -8,6 +8,8 @@ let fromRoot = utils('fromRoot'); const randomBytes = require('crypto').randomBytes; const getData = require('../path').getData; +import pkg from '../../../src/utils/packageJson'; + module.exports = () => Joi.object({ pkg: Joi.object({ version: Joi.string().default(Joi.ref('$version')), @@ -119,6 +121,21 @@ module.exports = () => Joi.object({ status: Joi.object({ allowAnonymous: Joi.boolean().default(false) + }).default(), + + tilemap: Joi.object({ + url: Joi.string().default(`https://tiles.elastic.co/v1/default/{z}/{x}/{y}.png?my_app_name=kibana&my_app_version=${pkg.version}&elastic_tile_service_tos=agree`), + options: Joi.object({ + attribution: Joi.string().default('© [Elastic Tile Service](https://www.elastic.co/elastic-tile-service)'), + minZoom: Joi.number().min(1, 'Must not be less than 1').default(1), + maxZoom: Joi.number().default(7), + tileSize: Joi.number(), + subdomains: Joi.array().items(Joi.string()).single(), + errorTileUrl: Joi.string().uri(), + tms: Joi.boolean(), + reuseTiles: Joi.boolean(), + bounds: Joi.array().items(Joi.array().items(Joi.number()).min(2).required()).min(2) + }).default() }).default() }).default(); diff --git a/src/ui/public/vislib/styles/_tilemap.less b/src/ui/public/vislib/styles/_tilemap.less index 2fd7d98e709a9..6d4d513660a54 100644 --- a/src/ui/public/vislib/styles/_tilemap.less +++ b/src/ui/public/vislib/styles/_tilemap.less @@ -158,6 +158,10 @@ .leaflet-control-attribution { background-color: @tilemap-leaflet-footer-bg !important; color: @tilemap-leaflet-footer-color !important; + + p { + display: inline; + } } .leaflet-left { diff --git a/src/ui/public/vislib/visualizations/_map.js b/src/ui/public/vislib/visualizations/_map.js index 5fa0b78ad05f0..30f6d92496f21 100644 --- a/src/ui/public/vislib/visualizations/_map.js +++ b/src/ui/public/vislib/visualizations/_map.js @@ -1,21 +1,24 @@ define(function (require) { - return function MapFactory(Private) { + return function MapFactory(Private, tilemap) { let _ = require('lodash'); let $ = require('jquery'); let L = require('leaflet'); + let marked = require('marked'); + marked.setOptions({ + gfm: true, // Github-flavored markdown + sanitize: true // Sanitize HTML tags + }); let defaultMapZoom = 2; let defaultMapCenter = [15, 5]; let defaultMarkerType = 'Scaled Circle Markers'; + let tilemapOptions = tilemap.options; + let attribution = marked(tilemapOptions.attribution); + let mapTiles = { - url: 'https://otile{s}-s.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.jpeg', - options: { - attribution: 'Tiles by MapQuest — ' + - 'Map data © OpenStreetMap contributors, ' + - 'CC-BY-SA', - subdomains: '1234' - } + url: tilemap.url, + options: _.assign({}, tilemapOptions, { attribution }) }; let markerTypes = { @@ -47,8 +50,8 @@ define(function (require) { this._attr = params.attr || {}; let mapOptions = { - minZoom: 1, - maxZoom: 18, + minZoom: tilemapOptions.minZoom, + maxZoom: tilemapOptions.maxZoom, noWrap: true, maxBounds: L.latLngBounds([-90, -220], [90, 220]), scrollWheelZoom: false, @@ -261,9 +264,18 @@ define(function (require) { TileMapMap.prototype._createMap = function (mapOptions) { if (this.map) this.destroy(); + if (this._attr.wms && this._attr.wms.enabled) { + _.assign(mapOptions, { + minZoom: 1, + maxZoom: 18 + }); + } + + const savedZoom = _.get(this._geoJson, 'properties.zoom'); + // get center and zoom from mapdata, or use defaults this._mapCenter = _.get(this._geoJson, 'properties.center') || defaultMapCenter; - this._mapZoom = _.get(this._geoJson, 'properties.zoom') || defaultMapZoom; + this._mapZoom = Math.max(Math.min(savedZoom || defaultMapZoom, mapOptions.maxZoom), mapOptions.minZoom); // add map tiles layer, using the mapTiles object settings if (this._attr.wms && this._attr.wms.enabled) {