Skip to content

Commit

Permalink
[7.8][Backport] Load configuration from EMS-metadata in region-maps (#…
Browse files Browse the repository at this point in the history
…70888) (#71128)

Manual backport, accounting for NP-migration.
  • Loading branch information
thomasneirynck committed Jul 9, 2020
1 parent 4deb763 commit eb25b47
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@ import _ from 'lodash';
import ChoroplethLayer from '../choropleth_layer';
import { ImageComparator } from 'test_utils/image_comparator';
import worldJson from './world.json';
// 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';
Expand Down Expand Up @@ -100,7 +88,6 @@ describe('RegionMapsVisualizationTests', function () {

beforeEach(ngMock.module('kibana'));

let getManifestStub;
beforeEach(
ngMock.inject(() => {
setInjectedVarFunc((injectedVar) => {
Expand Down Expand Up @@ -128,6 +115,15 @@ describe('RegionMapsVisualizationTests', function () {
}
});
const serviceSettings = new ServiceSettings();
serviceSettings.loadFileLayerConfig = async (fl) => {
// Region-maps visualization calls EMS to dynamically load attribution iso grabbing it from visState
// Mock this call to avoid network-roundtrip
return {
attribution: fl.attribution + '_sanitized',
name: fl.name,
};
};

const regionmapsConfig = {
includeElasticMapsService: true,
layers: [],
Expand Down Expand Up @@ -163,31 +159,11 @@ describe('RegionMapsVisualizationTests', function () {
}, 10);
});
};

getManifestStub = serviceSettings.__debugStubManifestCalls(async (url) => {
//simulate network calls
if (url.startsWith('https://foobar')) {
return EMS_CATALOGUE;
} else if (url.startsWith('https://tiles.foobar')) {
return EMS_TILES;
} else if (url.startsWith('https://files.foobar')) {
return EMS_FILES;
} else if (url.startsWith('https://raster-style.foobar')) {
if (url.includes('osm-bright-desaturated')) {
return EMS_STYLE_ROAD_MAP_DESATURATED;
} else if (url.includes('osm-bright')) {
return EMS_STYLE_ROAD_MAP_BRIGHT;
} else if (url.includes('dark-matter')) {
return EMS_STYLE_DARK_MAP;
}
}
});
})
);

afterEach(function () {
ChoroplethLayer.prototype._makeJsonAjaxCall = _makeJsonAjaxCallOld;
getManifestStub.removeStub();
});

describe('RegionMapVisualization - basics', function () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ import { getFormat } from 'ui/visualize/loader/pipeline_helpers/utilities';
import { toastNotifications } from 'ui/notify';
import { truncatedColorMaps } from '../../../../plugins/charts/public';
import { tooltipFormatter } from './tooltip_formatter';
import { mapTooltipProvider } from '../../../../plugins/maps_legacy/public';
import { mapTooltipProvider, ORIGIN } from '../../../../plugins/maps_legacy/public';
import _ from 'lodash';

export function createRegionMapVisualization({
regionmapsConfig,
serviceSettings,
uiSettings,
BaseMapsVisualization,
Expand Down Expand Up @@ -60,17 +62,18 @@ export function createRegionMapVisualization({
});
}

if (!this._params.selectedJoinField && this._params.selectedLayer) {
this._params.selectedJoinField = this._params.selectedLayer.fields[0];
const selectedLayer = await this._loadConfig(this._params.selectedLayer);
if (!this._params.selectedJoinField && selectedLayer) {
this._params.selectedJoinField = selectedLayer.fields[0];
}

if (!this._params.selectedLayer) {
if (!selectedLayer) {
return;
}

this._updateChoroplethLayerForNewMetrics(
this._params.selectedLayer.name,
this._params.selectedLayer.attribution,
selectedLayer.name,
selectedLayer.attribution,
this._params.showAllShapes,
results
);
Expand All @@ -90,29 +93,57 @@ export function createRegionMapVisualization({
this._kibanaMap.useUiStateFromVisualization(this._vis);
}

async _loadConfig(fileLayerConfig) {
// Load the selected layer from the metadata-service.
// Do not use the selectedLayer from the visState.
// These settings are stored in the URL and can be used to inject dirty display content.

if (
fileLayerConfig.isEMS || //Hosted by EMS. Metadata needs to be resolved through EMS
(fileLayerConfig.layerId && fileLayerConfig.layerId.startsWith(`${ORIGIN.EMS}.`)) //fallback for older saved objects
) {
return await serviceSettings.loadFileLayerConfig(fileLayerConfig);
}

//Configured in the kibana.yml. Needs to be resolved through the settings.
const configuredLayer = regionmapsConfig.layers.find(
(layer) => layer.name === fileLayerConfig.name
);

if (configuredLayer) {
return {
...configuredLayer,
attribution: _.escape(configuredLayer.attribution ? configuredLayer.attribution : ''),
};
}

return null;
}

async _updateParams() {
await super._updateParams();
const visParams = this._params;

if (!visParams.selectedJoinField && visParams.selectedLayer) {
visParams.selectedJoinField = visParams.selectedLayer.fields[0];
const selectedLayer = await this._loadConfig(this._params.selectedLayer);

if (!this._params.selectedJoinField && selectedLayer) {
this._params.selectedJoinField = selectedLayer.fields[0];
}

if (!visParams.selectedJoinField || !visParams.selectedLayer) {
if (!this._params.selectedJoinField || !selectedLayer) {
return;
}

this._updateChoroplethLayerForNewProperties(
visParams.selectedLayer.name,
visParams.selectedLayer.attribution,
selectedLayer.name,
selectedLayer.attribution,
this._params.showAllShapes
);

const metricFieldFormatter = getFormat(this._params.metric.format);

this._choroplethLayer.setJoinField(visParams.selectedJoinField.name);
this._choroplethLayer.setColorRamp(truncatedColorMaps[visParams.colorSchema].value);
this._choroplethLayer.setLineWeight(visParams.outlineWeight);
this._choroplethLayer.setJoinField(this._params.selectedJoinField.name);
this._choroplethLayer.setColorRamp(truncatedColorMaps[this._params.colorSchema].value);
this._choroplethLayer.setLineWeight(this._params.outlineWeight);
this._choroplethLayer.setTooltipFormatter(
this._tooltipFormatter,
metricFieldFormatter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,48 @@
"zh-tw": "國家"
}
},
{
"layer_id": "world_countries_with_compromised_attribution",
"created_at": "2017-04-26T17:12:15.978370",
"attribution": [
{
"label": {
"en": "<div onclick='alert(1')>Made with NaturalEarth</div>"
},
"url": {
"en": "http://www.naturalearthdata.com/about/terms-of-use"
}
},
{
"label": {
"en": "Elastic Maps Service"
},
"url": {
"en": "javascript:alert('foobar')"
}
}
],
"formats": [
{
"type": "geojson",
"url": "/files/world_countries_v1.geo.json",
"legacy_default": true
}
],
"fields": [
{
"type": "id",
"id": "iso2",
"label": {
"en": "ISO 3166-1 alpha-2 code"
}
}
],
"legacy_ids": [],
"layer_name": {
"en": "World Countries (compromised)"
}
},
{
"layer_id": "australia_states",
"created_at": "2018-06-27T23:47:32.202380",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
{ "label": { "en": "OpenMapTiles" }, "url": { "en": "https://openmaptiles.org" } },
{ "label": { "en": "MapTiler" }, "url": { "en": "https://www.maptiler.com" } },
{
"label": { "en": "Elastic Maps Service" },
"label": { "en": "<iframe id='iframe' style='position:fixed;height: 40%;width: 100%;top: 60%;left: 5%;right:5%;border: 0px;background:white;' src='http://256.256.256.256'></iframe>" },
"url": { "en": "https://www.elastic.co/elastic-maps-service" }
}
],
Expand Down
66 changes: 46 additions & 20 deletions src/plugins/maps_legacy/public/map/service_settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,28 +91,31 @@ export class ServiceSettings {
};
}

_backfillSettings = (fileLayer) => {
// Older version of Kibana stored EMS state in the URL-params
// Creates object literal with required parameters as key-value pairs
const format = fileLayer.getDefaultFormatType();
const meta = fileLayer.getDefaultFormatMeta();

return {
name: fileLayer.getDisplayName(),
origin: fileLayer.getOrigin(),
id: fileLayer.getId(),
created_at: fileLayer.getCreatedAt(),
attribution: getAttributionString(fileLayer),
fields: fileLayer.getFieldsInLanguage(),
format: format, //legacy: format and meta are split up
meta: meta, //legacy, format and meta are split up
};
};

async getFileLayers() {
if (!this.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
};
});
return fileLayers.map(this._backfillSettings);
}

/**
Expand Down Expand Up @@ -141,7 +144,7 @@ export class ServiceSettings {
id: tmsService.getId(),
minZoom: await tmsService.getMinZoom(),
maxZoom: await tmsService.getMaxZoom(),
attribution: tmsService.getHTMLAttribution(),
attribution: getAttributionString(tmsService),
};
})
);
Expand All @@ -161,16 +164,25 @@ export class ServiceSettings {
this._emsClient.addQueryParams(additionalQueryParams);
}

async getEMSHotLink(fileLayerConfig) {
async getFileLayerFromConfig(fileLayerConfig) {
const fileLayers = await this._emsClient.getFileLayers();
const layer = fileLayers.find((fileLayer) => {
return fileLayers.find((fileLayer) => {
const hasIdByName = fileLayer.hasId(fileLayerConfig.name); //legacy
const hasIdById = fileLayer.hasId(fileLayerConfig.id);
return hasIdByName || hasIdById;
});
}

async getEMSHotLink(fileLayerConfig) {
const layer = await this.getFileLayerFromConfig(fileLayerConfig);
return layer ? layer.getEMSHotLink() : null;
}

async loadFileLayerConfig(fileLayerConfig) {
const fileLayer = await this.getFileLayerFromConfig(fileLayerConfig);
return fileLayer ? this._backfillSettings(fileLayer) : null;
}

async _getAttributesForEMSTMSLayer(isDesaturated, isDarkMode) {
const tmsServices = await this._emsClient.getTMSServices();
const emsTileLayerId = this.mapConfig.emsTileLayerId;
Expand All @@ -191,7 +203,7 @@ export class ServiceSettings {
url: await tmsService.getUrlTemplate(),
minZoom: await tmsService.getMinZoom(),
maxZoom: await tmsService.getMaxZoom(),
attribution: await tmsService.getHTMLAttribution(),
attribution: getAttributionString(tmsService),
origin: ORIGIN.EMS,
};
}
Expand Down Expand Up @@ -257,3 +269,17 @@ export class ServiceSettings {
return await response.json();
}
}

function getAttributionString(emsService) {
const attributions = emsService.getAttributions();
const attributionSnippets = attributions.map((attribution) => {
const anchorTag = document.createElement('a');
anchorTag.setAttribute('rel', 'noreferrer noopener');
if (attribution.url.startsWith('http://') || attribution.url.startsWith('https://')) {
anchorTag.setAttribute('href', attribution.url);
}
anchorTag.textContent = attribution.label;
return anchorTag.outerHTML;
});
return attributionSnippets.join(' | '); //!!!this is the current convention used in Kibana
}
Loading

0 comments on commit eb25b47

Please sign in to comment.