Skip to content

Commit

Permalink
[Maps] Update default map client (#323)
Browse files Browse the repository at this point in the history
* [Build] Update default maps client

Update to not use EMS so it works out of the box.
Related to: #221

Fails linter and should problem write more unit tests but working with smoke tests.

Signed-off-by: Kawika Avilla <[email protected]>

* [Build] fix linter for map messages

Signed-off-by: Kawika Avilla <[email protected]>

* [Build] enable and update map func tests

Passing on the CI. Needed to update the casing of the expected response
but that was all that was needed.

Signed-off-by: Kawika Avilla <[email protected]>

* [Rename] rename to osd_version

Signed-off-by: Kawika Avilla <[email protected]>
  • Loading branch information
kavilla committed May 21, 2021
1 parent a0594e7 commit f4da95a
Show file tree
Hide file tree
Showing 15 changed files with 237 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ opensearch_dashboards_vars=(
logging.silent
logging.useUTC
logging.verbose
map.includeElasticMapsService
map.proxyElasticMapsServiceInMaps
map.includeOpenSearchMapsService
map.proxyOpenSearchMapsServiceInMaps
map.regionmap
map.tilemap.options.attribution
map.tilemap.options.maxZoom
Expand Down
70 changes: 69 additions & 1 deletion src/legacy/server/config/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,75 @@ export default () =>
path: HANDLED_IN_NEW_PLATFORM,
stats: HANDLED_IN_NEW_PLATFORM,
status: HANDLED_IN_NEW_PLATFORM,
map: HANDLED_IN_NEW_PLATFORM,

map: Joi.object({
includeOpenSearchMapsService: Joi.boolean().default(true),
proxyOpenSearchMapsServiceInMaps: Joi.boolean().default(false),
tilemap: Joi.object({
url: Joi.string(),
options: Joi.object({
attribution: Joi.string(),
minZoom: Joi.number().min(0, 'Must be 0 or higher').default(0),
maxZoom: Joi.number().default(10),
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: Joi.boolean(),
}).default({
default: true,
}),
}).default(),
regionmap: Joi.object({
includeOpenSearchMapsService: Joi.boolean().default(true),
layers: Joi.array()
.items(
Joi.object({
url: Joi.string(),
format: Joi.object({
type: Joi.string().default('geojson'),
}).default({
type: 'geojson',
}),
meta: Joi.object({
feature_collection_path: Joi.string().default('data'),
}).default({
feature_collection_path: 'data',
}),
attribution: Joi.string(),
name: Joi.string(),
fields: Joi.array().items(
Joi.object({
name: Joi.string(),
description: Joi.string(),
})
),
})
)
.default([]),
}).default(),
manifestServiceUrl: Joi.string().default('').allow(''),
opensearchManifestServiceUrl: Joi.string().default(
'https://maps.search-services.aws.a2z.com/v4/ap-southeast-1/manifest'
),
emsFileApiUrl: Joi.string().default('https://vector.maps.elastic.co'),
emsTileApiUrl: Joi.string().default('https://tiles.maps.elastic.co'),
emsLandingPageUrl: Joi.string().default('https://maps.elastic.co/v7.9'),
emsFontLibraryUrl: Joi.string().default(
'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf'
),
emsTileLayerId: Joi.object({
bright: Joi.string().default('road_map'),
desaturated: Joi.string().default('road_map_desaturated'),
dark: Joi.string().default('dark_map'),
}).default({
bright: 'road_map',
desaturated: 'road_map_desaturated',
dark: 'dark_map',
}),
}).default(),

i18n: Joi.object({
locale: Joi.string().default('en'),
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/maps_legacy/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ export const configSchema = schema.object({
tilemap: tilemapSchema,
regionmap: regionmapSchema,
manifestServiceUrl: schema.string({ defaultValue: '' }),
opensearchManifestServiceUrl: schema.string({
defaultValue: 'https://maps.search-services.aws.a2z.com/v4/us-east-1/manifest',
}),
emsFileApiUrl: schema.string({ defaultValue: 'https://vector.maps.opensearch.org' }),
emsTileApiUrl: schema.string({ defaultValue: 'https://tiles.maps.opensearch.org' }),
emsLandingPageUrl: schema.string({ defaultValue: 'https://maps.opensearch.org/v7.10' }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"type": "id",
"id": "iso2",
"label": {
"en": "ISO 3166-1 alpha-2 code",
"en": "ISO 3166-1 alpha-2 Code",
"af": "landkode (ISO 3166-1 alpha-2)",
"ar": "أيزو 3166-1 حرفي-2",
"be": "код краіны (ISO 3166-1 alpha-2)",
Expand Down Expand Up @@ -115,7 +115,7 @@
"type": "id",
"id": "iso3",
"label": {
"en": "ISO 3166-1 alpha-3 code",
"en": "ISO 3166-1 alpha-3 Code",
"af": "landkode (ISO 3166-1 alpha-3)",
"ar": "أيزو 3166-1 حرفي-3",
"be": "код краіны (ISO 3166-1 alpha-3)",
Expand Down Expand Up @@ -195,7 +195,7 @@
"type": "property",
"id": "name",
"label": {
"en": "name",
"en": "Name",
"am": "ስም",
"ar": "الاسم",
"ast": "alcuñu",
Expand Down Expand Up @@ -439,7 +439,7 @@
"type": "id",
"id": "iso2",
"label": {
"en": "ISO 3166-1 alpha-2 code"
"en": "ISO 3166-1 alpha-2 Code"
}
}
],
Expand Down
35 changes: 35 additions & 0 deletions src/plugins/maps_legacy/public/common/opensearch_maps_client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

import { EMSClient } from '@elastic/ems-client';

export class OpenSearchMapsClient extends EMSClient {
constructor({ osdVersion, manifestServiceUrl, language, landingPageUrl, fetchFunction }) {
super({ osdVersion, manifestServiceUrl, language, landingPageUrl, fetchFunction });
this._queryParams = {
osd_version: osdVersion,
opensearch_tos_agree: true,
};
this._manifestServiceUrl = manifestServiceUrl;
}

async isEnabled() {
let result;
try {
result = await this._fetchWithTimeout(this._manifestServiceUrl);
} catch (e) {
// silently ignoring the exception and returning false.
return false;
}
if (result.ok) {
const resultJson = await result.json();
return resultJson.enabled;
}
return false;
}
}
61 changes: 59 additions & 2 deletions src/plugins/maps_legacy/public/map/map_messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,67 @@
* GitHub history for details.
*/

import React from 'react';
/* eslint-disable react/no-multi-comp */
import React, { Fragment } from 'react';
import ReactDOM from 'react-dom';
import { FormattedMessage } from '@osd/i18n/react';
import { EuiSpacer, EuiButtonEmpty } from '@elastic/eui';
import { EuiSpacer, EuiButtonEmpty, EuiEmptyPrompt } from '@elastic/eui';
import { toMountPoint } from '../../../opensearch_dashboards_react/public';

export const createRegionBlockedWarning = (function () {
/* eslint-disable react/prefer-stateless-function */
class RegionBlockedWarningOverlay extends React.Component {
constructor(props) {
super(props);
}

render() {
return (
<EuiEmptyPrompt
iconType="gisApp"
iconColor={null}
title={<h2>The default Web Map Service is currently not available in your region.</h2>}
titleSize="xs"
body={
<Fragment>
<p>
You can configure OpenSearch Dash to use a different map server for coordinate maps
by modifying the default WMS properties.
</p>
</Fragment>
}
/>
);
}
}
return () => {
let messageBlock = document.getElementById('blocker-div');
if (!messageBlock) {
messageBlock = document.createElement('div');
messageBlock.id = 'blocker-div';
messageBlock.setAttribute('class', 'visError leaflet-popup-pane');
Array.prototype.forEach.call(
document.getElementsByClassName('leaflet-container'),
(leafletDom) => {
ReactDOM.render(
new RegionBlockedWarningOverlay().render(),
leafletDom.appendChild(messageBlock)
);
}
);
}
};
})();

export const removeRegionBlockedWarning = (function () {
return () => {
const childEle = document.getElementById('blocker-div');
if (childEle) {
childEle.parentNode.removeChild(childEle);
}
};
})();

export const createZoomWarningMsg = (function () {
let disableZoomMsg = false;
const setZoomMsg = (boolDisableMsg) => (disableZoomMsg = boolDisableMsg);
Expand All @@ -59,6 +115,7 @@ export const createZoomWarningMsg = (function () {
access to additional zoom levels for free through the {ems}.
Or, you can configure your own map server. Please go to
{ wms } or { configSettings} for more information."
// TODO: [RENAMEME] Need valid URLs
values={{
defaultDistribution: (
<a target="_blank" href="https://www.opensearch.org/downloads/kibana">
Expand Down
12 changes: 11 additions & 1 deletion src/plugins/maps_legacy/public/map/opensearch_dashboards_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@
*/

import { EventEmitter } from 'events';
import { createZoomWarningMsg } from './map_messages';
import {
createZoomWarningMsg,
createRegionBlockedWarning,
removeRegionBlockedWarning,
} from './map_messages';
import $ from 'jquery';
import { get, isEqual, escape } from 'lodash';
import { zoomToPrecision } from './zoom_to_precision';
Expand Down Expand Up @@ -606,6 +610,11 @@ export class OpenSearchDashboardsMap extends EventEmitter {
baseLayer.on('loading', () => {
this.emit('baseLayer:loading');
});
baseLayer.on('tileerror', () => {
if (baseLayer._url.includes('search-services.aws.a2z.com')) {
createRegionBlockedWarning();
}
});

this._leafletBaseLayer = baseLayer;
if (settings.options.showZoomMessage) {
Expand Down Expand Up @@ -684,6 +693,7 @@ export class OpenSearchDashboardsMap extends EventEmitter {
}

_updateDesaturation() {
removeRegionBlockedWarning();
const tiles = $('img.leaflet-tile-loaded');
// Don't apply client-side styling to EMS basemaps
if (get(this._baseLayerSettings, 'options.origin') === ORIGIN.EMS) {
Expand Down
40 changes: 38 additions & 2 deletions src/plugins/maps_legacy/public/map/service_settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import _ from 'lodash';
import MarkdownIt from 'markdown-it';
import { EMSClient } from '@elastic/ems-client';
import { OpenSearchMapsClient } from '../common/opensearch_maps_client.js';
import { i18n } from '@osd/i18n';
import { getOpenSearchDashboardsVersion } from '../opensearch_dashboards_services';
import { ORIGIN } from '../common/constants/origin';
Expand All @@ -46,13 +47,15 @@ export class ServiceSettings {
this._hasTmsConfigured = typeof tilemapsConfig.url === 'string' && tilemapsConfig.url !== '';

this._showZoomMessage = true;
this._emsClient = new EMSClient({
this._emsClient = null;
this._opensearchMapsClient = new OpenSearchMapsClient({
language: i18n.getLocale(),
appVersion: getOpenSearchDashboardsVersion(),
appName: 'opensearch-dashboards',
fileApiUrl: this._mapConfig.emsFileApiUrl,
tileApiUrl: this._mapConfig.emsTileApiUrl,
landingPageUrl: this._mapConfig.emsLandingPageUrl,
landingPageUrl: '',
manifestServiceUrl: this._mapConfig.opensearchManifestServiceUrl,
// Wrap to avoid errors passing window fetch
fetchFunction: function (...args) {
return fetch(...args);
Expand Down Expand Up @@ -87,6 +90,7 @@ export class ServiceSettings {
}

__debugStubManifestCalls(manifestRetrieval) {
this._emsClient = this._opensearchMapsClient;
const oldGetManifest = this._emsClient.getManifest;
this._emsClient.getManifest = manifestRetrieval;
return {
Expand Down Expand Up @@ -118,11 +122,39 @@ export class ServiceSettings {
};
};

// anyone using this._emsClient should call this method before, to set the right client
async _setMapServices() {
// if client is not null, return immediately.
// Effectively, client creation will be called only once.
if (this._emsClient) {
return;
}
const useOpenSearchMaps = await this._opensearchMapsClient.isEnabled();
if (useOpenSearchMaps) {
// using OpenSearch Maps.
this._emsClient = this._opensearchMapsClient;
} else {
// not using OpenSearch Maps, fallback to default maps.
this._emsClient = new EMSClient({
language: i18n.getLocale(),
appVersion: getOpenSearchDashboardsVersion(),
appName: 'opensearch-dashboards',
fileApiUrl: this._mapConfig.emsFileApiUrl,
tileApiUrl: this._mapConfig.emsTileApiUrl,
landingPageUrl: this._mapConfig.emsLandingPageUrl,
fetchFunction: function (...args) {
return fetch(...args);
},
});
}
}

async getFileLayers() {
if (!this._mapConfig.includeOpenSearchMapsService) {
return [];
}

await this._setMapServices();
const fileLayers = await this._emsClient.getFileLayers();
return fileLayers.map(this._backfillSettings);
}
Expand All @@ -141,6 +173,7 @@ export class ServiceSettings {
allServices.push(tmsService);
}

await this._setMapServices();
if (this._mapConfig.includeOpenSearchMapsService) {
const servicesFromManifest = await this._emsClient.getTMSServices();
const strippedServiceFromManifest = await Promise.all(
Expand Down Expand Up @@ -183,6 +216,7 @@ export class ServiceSettings {
}

async getEMSHotLink(fileLayerConfig) {
await this._setMapServices();
const layer = await this.getFileLayerFromConfig(fileLayerConfig);
return layer ? layer.getEMSHotLink() : null;
}
Expand All @@ -193,6 +227,7 @@ export class ServiceSettings {
}

async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) {
await this._setMapServices();
const tmsServices = await this._emsClient.getTMSServices();
const emsTileLayerId = this._mapConfig.emsTileLayerId;
let serviceId;
Expand Down Expand Up @@ -236,6 +271,7 @@ export class ServiceSettings {
}

async _getFileUrlFromEMS(fileLayerConfig) {
await this._setMapServices();
const fileLayers = await this._emsClient.getFileLayers();
const layer = fileLayers.find((fileLayer) => {
const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy
Expand Down
6 changes: 3 additions & 3 deletions src/plugins/maps_legacy/public/map/service_settings.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,9 @@ describe('service_settings (FKA tile_map test)', function () {
'<a rel="noreferrer noopener" href="http://www.naturalearthdata.com/about/terms-of-use">Made with NaturalEarth</a> | <a rel="noreferrer noopener" href="https://www.opensearch.org/elastic-maps-service">OpenSearch Maps Service</a>',
format: 'geojson',
fields: [
{ type: 'id', name: 'iso2', description: 'ISO 3166-1 alpha-2 code' },
{ type: 'id', name: 'iso3', description: 'ISO 3166-1 alpha-3 code' },
{ type: 'property', name: 'name', description: 'name' },
{ type: 'id', name: 'iso2', description: 'ISO 3166-1 alpha-2 Code' },
{ type: 'id', name: 'iso3', description: 'ISO 3166-1 alpha-3 Code' },
{ type: 'property', name: 'name', description: 'Name' },
],
created_at: '2017-04-26T17:12:15.978370', //not present in 6.6
name: 'World Countries',
Expand Down
Loading

0 comments on commit f4da95a

Please sign in to comment.