Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.5] Backport. Display regionmap attribution (#12647) #12849

Merged
merged 1 commit into from
Jul 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion docs/setup/settings.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ The file must use the WGS84 coordinate reference system and only include polygon
If the file is hosted on a separate domain from Kibana, the server needs to be CORS-enabled so Kibana can download the file.
The url field also serves as a unique identifier for the file.
Each layer can contain multiple fields to indicate what properties from the geojson features you want to expose.
The field.description is the human readable text that is shown in the Region Map visualization's field menu.
The field.description is the human readable text that is shown in the Region Map visualization's field menu.
An optional attribution value can be added as well.
The following example shows a valid regionmap configuration.

regionmap:
layers:
- name: "Departments of France"
url: "http://my.cors.enabled.server.org/france_departements.geojson"
attribution: "INRAP"
fields:
- name: "department"
description: "Full department name"
Expand Down
6 changes: 2 additions & 4 deletions src/core_plugins/region_map/public/choropleth_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ import { truncatedColorMaps } from 'ui/vislib/components/color/truncated_colorma

export default class ChoroplethLayer extends KibanaMapLayer {

constructor(geojsonUrl) {
constructor(geojsonUrl, attribution) {
super();


this._metrics = null;
this._joinField = null;
this._colorRamp = truncatedColorMaps[Object.keys(truncatedColorMaps)[0]];
this._tooltipFormatter = () => '';
this._attribution = attribution;

this._geojsonUrl = geojsonUrl;
this._leafletLayer = L.geoJson(null, {
Expand Down Expand Up @@ -162,9 +162,7 @@ export default class ChoroplethLayer extends KibanaMapLayer {

jqueryDiv.append(label);
});

}

}


Expand Down
8 changes: 4 additions & 4 deletions src/core_plugins/region_map/public/region_map_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private,
return;
}

updateChoroplethLayer($scope.vis.params.selectedLayer.url);
updateChoroplethLayer($scope.vis.params.selectedLayer.url, $scope.vis.params.selectedLayer.attribution);
choroplethLayer.setMetrics(results, metricsAgg);
setTooltipFormatter();

Expand All @@ -74,7 +74,7 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private,
return;
}

updateChoroplethLayer(visParams.selectedLayer.url);
updateChoroplethLayer(visParams.selectedLayer.url, visParams.selectedLayer.attribution);
choroplethLayer.setJoinField(visParams.selectedJoinField.name);
choroplethLayer.setColorRamp(truncatedColorMaps[visParams.colorSchema]);
setTooltipFormatter();
Expand Down Expand Up @@ -109,7 +109,7 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private,
}
}

function updateChoroplethLayer(url) {
function updateChoroplethLayer(url, attribution) {

if (choroplethLayer && choroplethLayer.equalsGeoJsonUrl(url)) {//no need to recreate the layer
return;
Expand All @@ -118,7 +118,7 @@ module.controller('KbnRegionMapController', function ($scope, $element, Private,

const previousMetrics = choroplethLayer ? choroplethLayer.getMetrics() : null;
const previousMetricsAgg = choroplethLayer ? choroplethLayer.getMetricsAgg() : null;
choroplethLayer = new ChoroplethLayer(url);
choroplethLayer = new ChoroplethLayer(url, attribution);
if (previousMetrics && previousMetricsAgg) {
choroplethLayer.setMetrics(previousMetrics, previousMetricsAgg);
}
Expand Down
1 change: 1 addition & 0 deletions src/server/config/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ module.exports = () => Joi.object({
layers: Joi.array().items(Joi.object({
url: Joi.string(),
type: Joi.string(),
attribution: Joi.string(),
name: Joi.string(),
fields: Joi.array().items(Joi.object({
name: Joi.string(),
Expand Down
49 changes: 47 additions & 2 deletions src/ui/public/vis_maps/__tests__/kibana_map.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import expect from 'expect.js';
import { KibanaMap } from 'ui/vis_maps/kibana_map';
import { KibanaMap } from '../kibana_map';
import { KibanaMapLayer } from '../kibana_map_layer';
import L from 'leaflet';

describe('kibana_map tests', function () {

Expand Down Expand Up @@ -66,10 +68,53 @@ describe('kibana_map tests', function () {
expect(bounds.top_left.lon).to.equal(-180);

});

});


describe('KibanaMap - attributions', function () {


beforeEach(async function () {
setupDOM();
kibanaMap = new KibanaMap(domNode, {
minZoom: 1,
maxZoom: 10,
center: [0, 0],
zoom: 0
});
});

afterEach(function () {
kibanaMap.destroy();
teardownDOM();
});

function makeMockLayer(attribution) {
const layer = new KibanaMapLayer();
layer._attribution = attribution;
layer._leafletLayer = L.geoJson(null);
return layer;
}

it('should update attributions correctly', function () {
kibanaMap.addLayer(makeMockLayer('foo|bar'));
expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal('foo, bar');

kibanaMap.addLayer(makeMockLayer('bar'));
expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal('foo, bar');

const layer = makeMockLayer('bar,stool');
kibanaMap.addLayer(layer);
expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal('foo, bar, stool');

kibanaMap.removeLayer(layer);
expect(domNode.querySelectorAll('.leaflet-control-attribution')[0].innerHTML).to.equal('foo, bar');


});

});

describe('KibanaMap - baseLayer', function () {

beforeEach(async function () {
Expand Down
86 changes: 67 additions & 19 deletions src/ui/public/vis_maps/kibana_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ export class KibanaMap extends EventEmitter {
};

this._leafletMap = L.map(containerNode, leafletOptions);
this._leafletMap.attributionControl.setPrefix('');
this._leafletMap.scrollWheelZoom.disable();
const worldBounds = L.latLngBounds(L.latLng(-90, -180), L.latLng(90, 180));
this._leafletMap.setMaxBounds(worldBounds);
Expand Down Expand Up @@ -236,19 +237,49 @@ export class KibanaMap extends EventEmitter {
this._layers.push(kibanaLayer);
kibanaLayer.addToLeafletMap(this._leafletMap);
this.emit('layers:update');

this._addAttributions(kibanaLayer.getAttributions());
}

removeLayer(layer) {
const index = this._layers.indexOf(layer);
removeLayer(kibanaLayer) {

if (!kibanaLayer) {
return;
}

this._removeAttributions(kibanaLayer.getAttributions());
const index = this._layers.indexOf(kibanaLayer);
if (index >= 0) {
this._layers.splice(index, 1);
layer.removeFromLeafletMap(this._leafletMap);
kibanaLayer.removeFromLeafletMap(this._leafletMap);
}
this._listeners.forEach(listener => {
if (listener.layer === layer) {
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() {
Expand Down Expand Up @@ -422,15 +453,18 @@ export class KibanaMap extends EventEmitter {
return;
}

this._baseLayerSettings = settings;

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;
Expand All @@ -443,15 +477,22 @@ export class KibanaMap extends EventEmitter {
baseLayer = this._getTMSBaseLayer((settings.options));
}

baseLayer.on('tileload', () => this._updateDesaturation());
baseLayer.on('load', () => { this.emit('baseLayer:loaded');});
baseLayer.on('loading', () => {this.emit('baseLayer:loading');});

this._leafletBaseLayer = baseLayer;
this._leafletBaseLayer.addTo(this._leafletMap);
this._leafletBaseLayer.bringToBack();
if (settings.options.minZoom > this._leafletMap.getZoom()) {
this._leafletMap.setZoom(settings.options.minZoom);
if (baseLayer) {
baseLayer.on('tileload', () => this._updateDesaturation());
baseLayer.on('load', () => {
this.emit('baseLayer:loaded');
});
baseLayer.on('loading', () => {
this.emit('baseLayer:loading');
});

this._leafletBaseLayer = 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();

Expand Down Expand Up @@ -487,16 +528,14 @@ export class KibanaMap extends EventEmitter {
return L.tileLayer(options.url, {
minZoom: options.minZoom,
maxZoom: options.maxZoom,
subdomains: options.subdomains || [],
attribution: options.attribution
subdomains: options.subdomains || []
});
}

_getWMSBaseLayer(options) {
return L.tileLayer.wms(options.url, {
attribution: options.attribution,
format: options.format,
layers: options.layers,
format: options.format || '',
layers: options.layers || '',
minZoom: options.minZoom,
maxZoom: options.maxZoom,
styles: options.styles,
Expand Down Expand Up @@ -550,3 +589,12 @@ export class KibanaMap extends EventEmitter {
}


function getAttributionArray(attribution) {
const attributionString = attribution || '';
let attributions = attributionString.split('|');
if (attributions.length === 1) {//temp work-around due to inconsistency in manifests of how attributions are delimited
attributions = attributions[0].split(',');
}
return attributions;
}

4 changes: 4 additions & 0 deletions src/ui/public/vis_maps/kibana_map_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export class KibanaMapLayer extends EventEmitter {

movePointer() {
}

getAttributions() {
return this._attribution;
}
}


Expand Down
1 change: 1 addition & 0 deletions src/ui/public/vis_maps/lib/service_settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ uiModules.get('kibana')
const layers = manifest.data.layers.filter(layer => layer.format === 'geojson');
layers.forEach((layer) => {
layer.url = this._extendUrlWithParams(layer.url);
layer.attribution = $sanitize(marked(layer.attribution));
});
return layers;
});
Expand Down