diff --git a/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.html b/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.html
index c4a97803d2db..37321e173737 100644
--- a/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.html
+++ b/src/core_plugins/spy_modes/public/req_resp_stats_spy_mode.html
@@ -14,7 +14,7 @@
-
diff --git a/src/core_plugins/tile_map/public/kibana_map.js b/src/core_plugins/tile_map/public/kibana_map.js
index 958b16e0ca5b..a9959daee390 100644
--- a/src/core_plugins/tile_map/public/kibana_map.js
+++ b/src/core_plugins/tile_map/public/kibana_map.js
@@ -663,7 +663,7 @@ export class KibanaMap extends EventEmitter {
if (!centerFromUIState || centerFromMap.lon !== centerFromUIState[1] || centerFromMap.lat !== centerFromUIState[0]) {
visualization.uiStateVal('mapCenter', [centerFromMap.lat, centerFromMap.lon]);
}
- uiState.set('mapBounds', this.getUntrimmedBounds());
+ visualization.sessionState.mapBounds = this.getUntrimmedBounds();
}
this.on('dragend', persistMapStateInUiState);
diff --git a/src/core_plugins/tile_map/public/maps_visualization.js b/src/core_plugins/tile_map/public/maps_visualization.js
index 53a1b7746c06..4694afb1ad06 100644
--- a/src/core_plugins/tile_map/public/maps_visualization.js
+++ b/src/core_plugins/tile_map/public/maps_visualization.js
@@ -20,13 +20,11 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState
class MapsVisualization {
constructor(element, vis) {
-
this.vis = vis;
this.$el = $(element);
this._$container = this.$el;
this._geohashLayer = null;
this._kibanaMap = null;
- this._kibanaMapReady = this._makeKibanaMap();
this._baseLayerDirty = true;
this._currentParams = null;
}
@@ -37,6 +35,11 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState
}
}
+ init() {
+ this._kibanaMapReady = this._makeKibanaMap();
+ return this._kibanaMapReady;
+ }
+
async render(esResponse, status) {
return new Promise(async(resolve) => {
@@ -66,7 +69,6 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState
//**********************************************************************************************************
async _makeKibanaMap() {
-
try {
this._tmsService = await serviceSettings.getTMSService();
this._tmsError = null;
@@ -88,8 +90,8 @@ export function MapsVisualizationProvider(serviceSettings, Notifier, getAppState
options.center = centerFromUIState ? centerFromUIState : this.vis.type.visConfig.defaults.mapCenter;
this._kibanaMap = new KibanaMap(containerElement, options);
- uiState.set('mapZoom', this._kibanaMap.getZoomLevel());
- uiState.set('mapBounds', this._kibanaMap.getUntrimmedBounds());
+ this.vis.sessionState.mapBounds = this._kibanaMap.getUntrimmedBounds();
+
this._kibanaMap.addDrawControl();
this._kibanaMap.addFitControl();
this._kibanaMap.addLegendControl();
@@ -170,7 +172,6 @@ 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;
diff --git a/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js b/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js
index 4f5928689356..f4e89091c143 100644
--- a/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js
+++ b/src/ui/public/agg_types/__tests__/buckets/_geo_hash.js
@@ -1,17 +1,48 @@
import expect from 'expect.js';
import { AggTypesBucketsGeoHashProvider } from 'ui/agg_types/buckets/geo_hash';
-describe('Geohash Agg', function () {
+describe('Geohash Agg', () => {
- // Mock BucketAggType that does not create an AggType, but instead returns the AggType parameters
+ const intialZoom = 10;
+ const initialMapBounds = {
+ top_left: { lat: 1.0, lon: -1.0 },
+ bottom_right: { lat: -1.0, lon: 1.0 }
+ };
+ const aggMock = {
+ getField: () => {
+ return {
+ name: 'location'
+ };
+ },
+ params: {
+ isFilteredByCollar: true,
+ useGeocentroid: true
+ },
+ vis: {
+ hasUiState: () => {
+ return false;
+ },
+ params: {
+ mapZoom: intialZoom
+ },
+ sessionState: {}
+ },
+ type: 'geohash_grid',
+ };
const BucketAggTypeMock = (aggOptions) => {
- return aggOptions.params;
+ return aggOptions;
+ };
+ const AggConfigMock = (vis, aggOptions) => {
+ return aggOptions;
};
const PrivateMock = (provider) => {
switch (provider.name) {
case 'AggTypesBucketsBucketAggTypeProvider':
return BucketAggTypeMock;
break;
+ case 'VisAggConfigProvider':
+ return AggConfigMock;
+ break;
default:
return () => {};
}
@@ -21,18 +52,54 @@ describe('Geohash Agg', function () {
return 7;//"visualization:tileMap:maxPrecision"
}
};
- const params = AggTypesBucketsGeoHashProvider(PrivateMock, configMock); // eslint-disable-line new-cap
- describe('precision parameter', function () {
+ function initVisSessionState() {
+ aggMock.vis.sessionState = {
+ mapBounds: initialMapBounds
+ };
+ }
+
+ function initAggParams() {
+ aggMock.params.isFilteredByCollar = true;
+ aggMock.params.useGeocentroid = true;
+ }
+
+ function zoomMap(zoomChange) {
+ aggMock.vis.params.mapZoom += zoomChange;
+ }
+
+ function moveMap(newBounds) {
+ aggMock.vis.sessionState.mapBounds = newBounds;
+ }
+
+ function resetMap() {
+ aggMock.vis.params.mapZoom = intialZoom;
+ aggMock.vis.sessionState.mapBounds = initialMapBounds;
+ aggMock.vis.sessionState.mapCollar = {
+ top_left: { lat: 1.5, lon: -1.5 },
+ bottom_right: { lat: -1.5, lon: 1.5 },
+ zoom: intialZoom
+ };
+ }
+
+ let geohashAgg;
+ beforeEach(() => {
+ geohashAgg = AggTypesBucketsGeoHashProvider(PrivateMock, configMock); // eslint-disable-line new-cap
+ });
+
+ describe('precision parameter', () => {
const PRECISION_PARAM_INDEX = 6;
- const precisionParam = params[PRECISION_PARAM_INDEX];
+ let precisionParam;
+ beforeEach(() => {
+ precisionParam = geohashAgg.params[PRECISION_PARAM_INDEX];
+ });
it('should select precision parameter', () => {
expect(precisionParam.name).to.equal('precision');
});
- describe('precision parameter write', function () {
+ describe('precision parameter write', () => {
const zoomToGeoHashPrecision = {
0: 1,
@@ -77,4 +144,115 @@ describe('Geohash Agg', function () {
});
});
+
+ describe('getRequestAggs', () => {
+
+ describe('initial aggregation creation', () => {
+ let requestAggs;
+ beforeEach(() => {
+ initVisSessionState();
+ initAggParams();
+ requestAggs = geohashAgg.getRequestAggs(aggMock);
+ });
+
+ it('should create filter, geohash_grid, and geo_centroid aggregations', () => {
+ expect(requestAggs.length).to.equal(3);
+ expect(requestAggs[0].type).to.equal('filter');
+ expect(requestAggs[1].type).to.equal('geohash_grid');
+ expect(requestAggs[2].type).to.equal('geo_centroid');
+ });
+
+ it('should set mapCollar in vis session state', () => {
+ expect(aggMock.vis.sessionState).to.have.property('mapCollar');
+ expect(aggMock.vis.sessionState.mapCollar).to.have.property('top_left');
+ expect(aggMock.vis.sessionState.mapCollar).to.have.property('bottom_right');
+ expect(aggMock.vis.sessionState.mapCollar).to.have.property('zoom');
+ });
+
+ // there was a bug because of an "&& mapZoom" check which excluded 0 as a valid mapZoom, but it is.
+ it('should create filter, geohash_grid, and geo_centroid aggregations when zoom level 0', () => {
+ aggMock.vis.params.mapZoom = 0;
+ requestAggs = geohashAgg.getRequestAggs(aggMock);
+ expect(requestAggs.length).to.equal(3);
+ expect(requestAggs[0].type).to.equal('filter');
+ expect(requestAggs[1].type).to.equal('geohash_grid');
+ expect(requestAggs[2].type).to.equal('geo_centroid');
+ });
+ });
+
+ describe('aggregation options', () => {
+
+ beforeEach(() => {
+ initVisSessionState();
+ initAggParams();
+ });
+
+ it('should only create geohash_grid and geo_centroid aggregations when isFilteredByCollar is false', () => {
+ aggMock.params.isFilteredByCollar = false;
+ const requestAggs = geohashAgg.getRequestAggs(aggMock);
+ expect(requestAggs.length).to.equal(2);
+ expect(requestAggs[0].type).to.equal('geohash_grid');
+ expect(requestAggs[1].type).to.equal('geo_centroid');
+ });
+
+ it('should only create filter and geohash_grid aggregations when useGeocentroid is false', () => {
+ aggMock.params.useGeocentroid = false;
+ const requestAggs = geohashAgg.getRequestAggs(aggMock);
+ expect(requestAggs.length).to.equal(2);
+ expect(requestAggs[0].type).to.equal('filter');
+ expect(requestAggs[1].type).to.equal('geohash_grid');
+
+ });
+ });
+
+ describe('aggregation creation after map interaction', () => {
+
+ let origRequestAggs;
+ let origMapCollar;
+ beforeEach(() => {
+ resetMap();
+ initAggParams();
+ origRequestAggs = geohashAgg.getRequestAggs(aggMock);
+ origMapCollar = aggMock.vis.sessionState.mapCollar;
+ });
+
+ it('should not change geo_bounding_box filter aggregation and vis session state when map movement is within map collar', () => {
+ moveMap({
+ top_left: { lat: 1.1, lon: -1.1 },
+ bottom_right: { lat: -0.9, lon: 0.9 }
+ });
+
+ const newRequestAggs = geohashAgg.getRequestAggs(aggMock);
+ expect(JSON.stringify(origRequestAggs[0].params, null, '')).to.equal(JSON.stringify(newRequestAggs[0].params, null, ''));
+
+ const newMapCollar = aggMock.vis.sessionState.mapCollar;
+ expect(JSON.stringify(origMapCollar, null, '')).to.equal(JSON.stringify(newMapCollar, null, ''));
+ });
+
+ it('should change geo_bounding_box filter aggregation and vis session state when map movement is outside map collar', () => {
+ moveMap({
+ top_left: { lat: 10.0, lon: -10.0 },
+ bottom_right: { lat: 9.0, lon: -9.0 }
+ });
+
+ const newRequestAggs = geohashAgg.getRequestAggs(aggMock);
+ expect(JSON.stringify(origRequestAggs[0].params, null, '')).not.to.equal(JSON.stringify(newRequestAggs[0].params, null, ''));
+
+ const newMapCollar = aggMock.vis.sessionState.mapCollar;
+ expect(JSON.stringify(origMapCollar, null, '')).not.to.equal(JSON.stringify(newMapCollar, null, ''));
+ });
+
+ it('should change geo_bounding_box filter aggregation and vis session state when map zoom level changes', () => {
+ zoomMap(-1);
+
+ const newRequestAggs = geohashAgg.getRequestAggs(aggMock);
+ expect(JSON.stringify(origRequestAggs[0].params, null, '')).not.to.equal(JSON.stringify(newRequestAggs[0].params, null, ''));
+
+ const newMapCollar = aggMock.vis.sessionState.mapCollar;
+ expect(JSON.stringify(origMapCollar, null, '')).not.to.equal(JSON.stringify(newMapCollar, null, ''));
+ });
+
+ });
+
+ });
});
diff --git a/src/ui/public/agg_types/buckets/geo_hash.js b/src/ui/public/agg_types/buckets/geo_hash.js
index 231f1c472ef5..cfdda6cd002e 100644
--- a/src/ui/public/agg_types/buckets/geo_hash.js
+++ b/src/ui/public/agg_types/buckets/geo_hash.js
@@ -45,6 +45,14 @@ export function AggTypesBucketsGeoHashProvider(Private, config) {
return precision;
}
+ function getMapZoom(vis) {
+ if (vis.hasUiState() && parseInt(vis.uiStateVal('mapZoom')) >= 0) {
+ return parseInt(vis.uiStateVal('mapZoom'));
+ }
+
+ return vis.params.mapZoom;
+ }
+
function isOutsideCollar(bounds, collar) {
return bounds && collar && !geoContains(collar, bounds);
}
@@ -89,11 +97,8 @@ export function AggTypesBucketsGeoHashProvider(Private, config) {
},
write: function (aggConfig, output) {
const vis = aggConfig.vis;
- let currZoom;
- if (vis.hasUiState()) {
- currZoom = parseInt(vis.uiStateVal('mapZoom'), 10);
- }
- const autoPrecisionVal = zoomPrecision[currZoom >= 0 ? currZoom : parseInt(vis.params.mapZoom)];
+ const currZoom = getMapZoom(vis);
+ const autoPrecisionVal = zoomPrecision[currZoom];
output.params.precision = aggConfig.params.autoPrecision ? autoPrecisionVal : getPrecision(aggConfig.params.precision);
}
}
@@ -103,25 +108,23 @@ export function AggTypesBucketsGeoHashProvider(Private, config) {
if (agg.params.isFilteredByCollar && agg.getField()) {
const vis = agg.vis;
- let mapBounds;
- let mapZoom;
- if (vis.hasUiState()) {
- mapBounds = vis.uiStateVal('mapBounds');
- mapZoom = vis.uiStateVal('mapZoom');
- }
- if (mapBounds && mapZoom) {
- const lastMapCollar = vis.uiStateVal('mapCollar');
+ const mapBounds = vis.sessionState.mapBounds;
+ const mapZoom = getMapZoom(vis);
+ if (mapBounds) {
+ const lastMapCollar = vis.sessionState.mapCollar;
let mapCollar;
if (!lastMapCollar || lastMapCollar.zoom !== mapZoom || isOutsideCollar(mapBounds, lastMapCollar)) {
mapCollar = scaleBounds(mapBounds);
mapCollar.zoom = mapZoom;
- vis.getUiState().set('mapCollar', mapCollar);
+ vis.sessionState.mapCollar = mapCollar;
} else {
mapCollar = lastMapCollar;
}
const boundingBox = {};
- delete mapCollar.zoom; // zoom is not part of bounding box filter
- boundingBox[agg.getField().name] = mapCollar;
+ boundingBox[agg.getField().name] = {
+ top_left: mapCollar.top_left,
+ bottom_right: mapCollar.bottom_right
+ };
aggs.push(new AggConfig(agg.vis, {
type: 'filter',
id: 'filter_agg',
diff --git a/src/ui/public/agg_types/controls/precision.html b/src/ui/public/agg_types/controls/precision.html
index 5a83f224aa51..c567f3d56593 100644
--- a/src/ui/public/agg_types/controls/precision.html
+++ b/src/ui/public/agg_types/controls/precision.html
@@ -40,6 +40,7 @@