Skip to content

Commit

Permalink
[6.7] Share global filters & queries with coordinate maps vis. (#30595)…
Browse files Browse the repository at this point in the history
… (#31273)
  • Loading branch information
lukeelmers authored Feb 15, 2019
1 parent 206f825 commit 14e4da8
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,9 @@
*/

import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import { GeohashLayer } from './geohash_layer';
import { BaseMapsVisualizationProvider } from './base_maps_visualization';
import { TileMapTooltipFormatterProvider } from './editors/_tooltip_formatter';
import { toastNotifications } from 'ui/notify';

export function CoordinateMapsVisualizationProvider(Notifier, Private) {
const BaseMapsVisualization = Private(BaseMapsVisualizationProvider);
Expand All @@ -37,7 +35,6 @@ export function CoordinateMapsVisualizationProvider(Notifier, Private) {
this._notify = new Notifier({ location: 'Coordinate Map' });
}


async _makeKibanaMap() {

await super._makeKibanaMap();
Expand Down Expand Up @@ -161,7 +158,6 @@ export function CoordinateMapsVisualizationProvider(Notifier, Private) {
}

_getGeohashOptions() {

const newParams = this._getMapsParams();
const metricAgg = this._getMetricAgg();
const boundTooltipFormatter = tooltipFormatter.bind(null, this.vis.getAggConfig(), metricAgg);
Expand All @@ -172,7 +168,7 @@ export function CoordinateMapsVisualizationProvider(Notifier, Private) {
tooltipFormatter: this._geoJsonFeatureCollectionAndMeta ? boundTooltipFormatter : null,
mapType: newParams.mapType,
isFilteredByCollar: this._isFilteredByCollar(),
fetchBounds: this.getGeohashBounds.bind(this),
fetchBounds: () => this.vis.API.getGeohashBounds(), // TODO: Remove this (elastic/kibana#30593)
colorRamp: newParams.colorSchema,
heatmap: {
heatClusterSize: newParams.heatClusterSize
Expand All @@ -196,47 +192,12 @@ export function CoordinateMapsVisualizationProvider(Notifier, Private) {
this.vis.updateState();
}

async getGeohashBounds() {
const agg = this._getGeoHashAgg();
if (agg) {
const searchSource = this.vis.searchSource.createChild();
searchSource.setField('size', 0);
searchSource.setField('aggs', () => {
const geoBoundsAgg = this.vis.getAggConfig().createAggConfig({
type: 'geo_bounds',
enabled: true,
params: {
field: agg.getField()
},
schema: 'metric',
}, { addToAggConfigs: false });
return {
'1': geoBoundsAgg.toDsl()
};
});
let esResp;
try {
esResp = await searchSource.fetch();
} catch(error) {
toastNotifications.addDanger({
title: i18n.translate('tileMap.coordinateMapsVisualization.unableToGetBoundErrorTitle', {
defaultMessage: 'Unable to get bounds',
}),
text: `${error.message}`,
});
return;
}
return _.get(esResp, 'aggregations.1.bounds');
}
}

_getGeoHashAgg() {
return this.vis.getAggConfig().find((agg) => {
return _.get(agg, 'type.dslName') === 'geohash_grid';
});
}


_getMetricAgg() {
return this.vis.getAggConfig().find((agg) => {
return agg.type.type === 'metrics';
Expand Down
11 changes: 11 additions & 0 deletions src/ui/public/visualize/loader/embedded_visualize_handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { VisualizeDataLoader } from './visualize_data_loader';
import { DataAdapter, RequestAdapter } from '../../inspector/adapters';

import { VisSavedObject, VisualizeLoaderParams, VisualizeUpdateParams } from './types';
import { queryGeohashBounds } from './utils';

interface EmbeddedVisualizeHandlerParams extends VisualizeLoaderParams {
Private: IPrivate;
Expand Down Expand Up @@ -142,6 +143,16 @@ export class EmbeddedVisualizeHandler {
timefilter.on('autoRefreshFetch', this.reload);
}

// This is a hack to give maps visualizations access to data in the
// globalState, since they can no longer access it via searchSource.
// TODO: Remove this as a part of elastic/kibana#30593
this.vis.API.getGeohashBounds = () => {
return queryGeohashBounds(this.vis, {
filters: this.dataLoaderParams.filters,
query: this.dataLoaderParams.query,
});
};

this.dataLoader = new VisualizeDataLoader(vis, Private);
this.renderCompleteHelper = new RenderCompleteHelper(element);
this.inspectorAdapters = this.getActiveInspectorAdapters();
Expand Down
20 changes: 20 additions & 0 deletions src/ui/public/visualize/loader/utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

export { queryGeohashBounds } from './query_geohash_bounds';
98 changes: 98 additions & 0 deletions src/ui/public/visualize/loader/utils/query_geohash_bounds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import { i18n } from '@kbn/i18n';
import { get } from 'lodash';
import { toastNotifications } from 'ui/notify';

import { AggConfig } from 'ui/vis';
import { Vis } from '../../../vis';
import { Filters, Query } from '../types';

interface QueryGeohashBoundsParams {
filters?: Filters;
query?: Query;
}

/**
* Coordinate map visualization needs to be able to query for the latest geohash
* bounds when a user clicks the "fit to data" map icon, which requires knowing
* about global filters & queries. This logic has been extracted here so we can
* keep `searchSource` out of the vis, but ultimately we need to design a
* long-term solution for situations like this.
*
* TODO: Remove this as a part of elastic/kibana#30593
*/
export async function queryGeohashBounds(vis: Vis, params: QueryGeohashBoundsParams) {
const agg = vis.getAggConfig().find((a: AggConfig) => {
return get(a, 'type.dslName') === 'geohash_grid';
});

if (agg) {
const searchSource = vis.searchSource.createChild();
searchSource.setField('size', 0);
searchSource.setField('aggs', () => {
const geoBoundsAgg = vis.getAggConfig().createAggConfig(
{
type: 'geo_bounds',
enabled: true,
params: {
field: agg.getField(),
},
schema: 'metric',
},
{
addToAggConfigs: false,
}
);
return {
'1': geoBoundsAgg.toDsl(),
};
});

const { filters, query } = params;
if (filters) {
searchSource.setField('filter', () => {
const activeFilters = [...filters];
const indexPattern = agg.getIndexPattern();
const useTimeFilter = !!indexPattern.timeFieldName;
if (useTimeFilter) {
activeFilters.push(vis.API.timeFilter.createFilter(indexPattern));
}
return activeFilters;
});
}
if (query) {
searchSource.setField('query', query);
}

try {
const esResp = await searchSource.fetch();
return get(esResp, 'aggregations.1.bounds');
} catch (error) {
toastNotifications.addDanger({
title: i18n.translate('common.ui.visualize.queryGeohashBounds.unableToGetBoundErrorTitle', {
defaultMessage: 'Unable to get bounds',
}),
text: `${error.message}`,
});
return;
}
}
}
23 changes: 22 additions & 1 deletion test/functional/apps/visualize/_tile_map.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export default function ({ getService, getPageObjects }) {
const retry = getService('retry');
const inspector = getService('inspector');
const find = getService('find');
const filterBar = getService('filterBar');
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const PageObjects = getPageObjects(['common', 'visualize', 'header', 'settings']);
const PageObjects = getPageObjects(['common', 'discover', 'visualize', 'header', 'settings']);


describe('tile map visualize app', function () {
Expand Down Expand Up @@ -167,6 +168,26 @@ export default function ({ getService, getPageObjects }) {
compareTableData(data, expectedPrecision2DataTable);
});

it('Fit data bounds works with pinned filter data', async () => {
const expectedPrecision2DataTable = [
['-', 'f05', '1', { lat: 45, lon: -85 }],
['-', 'dpr', '1', { lat: 40, lon: -79 }],
['-', '9qh', '1', { lat: 33, lon: -118 }],
];

await filterBar.addFilter('bytes', 'is between', '19980', '19990');
await filterBar.toggleFilterPinned('bytes');
await PageObjects.visualize.zoomAllTheWayOut();
await PageObjects.visualize.clickMapFitDataBounds();

await inspector.open();
const data = await inspector.getTableData();
await inspector.close();

await PageObjects.discover.removeAllFilters();
compareTableData(data, expectedPrecision2DataTable);
});

it('Newly saved visualization retains map bounds', async () => {
const vizName1 = 'Visualization TileMap';

Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/translations/translations/zh-CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2486,7 +2486,6 @@
"tagCloud.visParams.showLabelToggleLabel": "显示标签",
"tagCloud.visParams.textScaleLabel": "文本比例",
"tileMap.baseMapsVisualization.childShouldImplementMethodErrorMessage": "子函数应实现此方法以响应数据更新",
"tileMap.coordinateMapsVisualization.unableToGetBoundErrorTitle": "无法获取边界",
"tileMap.geohashLayer.mapTitle": "{mapType} 地图类型无法识别",
"tileMap.tooltipFormatter.latitudeLabel": "纬度",
"tileMap.tooltipFormatter.longitudeLabel": "经度",
Expand Down

0 comments on commit 14e4da8

Please sign in to comment.