[Maps] move grid resolution to source (#29294) (#29429)

This commit is contained in:
Thomas Neirynck 2019-01-28 11:26:19 -05:00 committed by GitHub
parent 7a209d217d
commit 5b5b8e5e9a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 118 additions and 100 deletions

View file

@ -319,7 +319,6 @@ export function onDataLoadError(layerId, dataId, requestToken, errorMessage) {
}
export function updateSourceProp(layerId, propName, value) {
return (dispatch) => {
dispatch({
type: UPDATE_SOURCE_PROP,
@ -488,16 +487,12 @@ export function triggerRefreshTimer() {
}
export function updateLayerStyleForSelectedLayer(style, temporary = true) {
return async (dispatch, getState) => {
await dispatch({
type: UPDATE_LAYER_STYLE_FOR_SELECTED_LAYER,
style: {
...style,
temporary
},
});
const layer = getSelectedLayer(getState());
dispatch(syncDataForLayer(layer.getId()));
return {
type: UPDATE_LAYER_STYLE_FOR_SELECTED_LAYER,
style: {
...style,
temporary
},
};
}

View file

@ -23,8 +23,7 @@ function mapStateToProps(state = {}) {
layerId: selectedLayer.getId(),
maxZoom: selectedLayer.getMaxZoom(),
minZoom: selectedLayer.getMinZoom(),
renderSourceDetails: selectedLayer.renderSourceDetails,
renderSourceSettingsEditor: selectedLayer.renderSourceSettingsEditor
layer: selectedLayer
};
}

View file

@ -134,7 +134,7 @@ export class SettingsPanel extends Component {
return (
<Fragment>
{this.props.renderSourceDetails()}
{this.props.layer.renderSourceDetails()}
<EuiSpacer margin="m"/>
</Fragment>
);
@ -166,7 +166,7 @@ export class SettingsPanel extends Component {
{this.renderAlphaSlider()}
{this.props.renderSourceSettingsEditor({ onChange: this.onSourceChange })}
{this.props.layer.renderSourceSettingsEditor({ onChange: this.onSourceChange })}
</EuiPanel>
);

View file

@ -33,6 +33,10 @@ export function StyleTabs({ layer, reset, updateStyle }) {
resetStyle: () => reset()
});
if (!styleEditor) {
return null;
}
return (
<EuiPanel key={index}>
<EuiTitle size="xs"><h5>{Style.getDisplayName()}</h5></EuiTitle>

View file

@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
export const GRID_RESOLUTION = {
'COARSE': 'COARSE',
'FINE': 'FINE',
'MOST_FINE': 'MOST_FINE'
};

View file

@ -93,6 +93,7 @@ export class HeatmapLayer extends AbstractLayer {
layerId: heatmapLayerId,
propertyName: SCALED_PROPERTY_NAME,
alpha: this.getAlpha(),
resolution: this._source.getGridResolution()
});
mbMap.setLayerZoomRange(heatmapLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
}
@ -114,7 +115,7 @@ export class HeatmapLayer extends AbstractLayer {
const dataMeta = sourceDataRequest ? sourceDataRequest.getMeta() : {};
const targetPrecisionUnadjusted = getGeohashPrecisionForZoom(dataFilters.zoom);
const targetPrecision = targetPrecisionUnadjusted + this._style.getPrecisionRefinementDelta();
const targetPrecision = targetPrecisionUnadjusted + this._source.getGeohashPrecisionResolutionDelta();
const isSamePrecision = dataMeta.precision === targetPrecision;
const isSameTime = _.isEqual(dataMeta.timeFilters, dataFilters.timeFilters);
@ -135,7 +136,8 @@ export class HeatmapLayer extends AbstractLayer {
&& !updateDueToExtent
&& !updateDueToRefreshTimer
&& !updateDueToQuery
&& !updateDueToMetricChange) {
&& !updateDueToMetricChange
) {
return;
}

View file

@ -21,6 +21,7 @@ import { VectorStyle } from '../../styles/vector_style';
import { RENDER_AS } from './render_as';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
import { GRID_RESOLUTION } from '../../grid_resolution';
const COUNT_PROP_LABEL = 'Count';
const COUNT_PROP_NAME = 'doc_count';
@ -53,13 +54,14 @@ export class ESGeohashGridSource extends AbstractESSource {
static title = 'Elasticsearch geohash aggregation';
static description = 'Group geospatial data in grids with metrics for each gridded cell';
static createDescriptor({ indexPatternId, geoField, requestType }) {
static createDescriptor({ indexPatternId, geoField, requestType, resolution }) {
return {
type: ESGeohashGridSource.type,
id: uuid(),
indexPatternId: indexPatternId,
geoField: geoField,
requestType: requestType
requestType: requestType,
resolution: resolution ? resolution : GRID_RESOLUTION.COARSE
};
}
@ -80,6 +82,7 @@ export class ESGeohashGridSource extends AbstractESSource {
onChange={onChange}
metrics={this._descriptor.metrics}
renderAs={this._descriptor.requestType}
resolution={this._descriptor.resolution}
/>
);
}
@ -105,6 +108,24 @@ export class ESGeohashGridSource extends AbstractESSource {
return true;
}
getGridResolution() {
return this._descriptor.resolution;
}
getGeohashPrecisionResolutionDelta() {
let refinementFactor;
if (this._descriptor.resolution === GRID_RESOLUTION.COARSE) {
refinementFactor = 0;
} else if (this._descriptor.resolution === GRID_RESOLUTION.FINE) {
refinementFactor = 1;
} else if (this._descriptor.resolution === GRID_RESOLUTION.MOST_FINE) {
refinementFactor = 2;
} else {
throw new Error(`Resolution param not recognized: ${this._descriptor.resolution}`);
}
return refinementFactor;
}
async getGeoJsonWithMeta({ layerName }, searchFilters) {
const featureCollection = await this.getGeoJsonPoints({ layerName }, {

View file

@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import React, { Fragment } from 'react';
import { GRID_RESOLUTION } from '../../grid_resolution';
import {
EuiSuperSelect,
EuiFlexGroup,
EuiFlexItem,
EuiFormLabel
} from '@elastic/eui';
const OPTIONS = [
{ value: GRID_RESOLUTION.COARSE, inputDisplay: 'coarse' },
{ value: GRID_RESOLUTION.FINE, inputDisplay: 'fine' },
{ value: GRID_RESOLUTION.MOST_FINE, inputDisplay: 'finest' }
];
export function ResolutionEditor({ resolution, onChange }) {
return (
<Fragment>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={true}>
<EuiFormLabel style={{ marginBottom: 0 }}>
Grid resolution
</EuiFormLabel>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup alignItems="center">
<EuiFlexItem grow={true}>
<EuiSuperSelect options={OPTIONS} valueOfSelected={resolution} onChange={onChange} />
</EuiFlexItem>
</EuiFlexGroup>
</Fragment>
);
}

View file

@ -9,6 +9,7 @@ import React, { Fragment, Component } from 'react';
import { RENDER_AS } from './render_as';
import { MetricsEditor } from '../../../components/metrics_editor';
import { indexPatternService } from '../../../../kibana_services';
import { ResolutionEditor } from './resolution_editor';
export class UpdateSourceEditor extends Component {
@ -49,14 +50,17 @@ export class UpdateSourceEditor extends Component {
this.props.onChange({ propName: 'metrics', value: metrics });
};
_onResolutionChange = (e) => {
this.props.onChange({ propName: 'resolution', value: e });
};
_renderMetricsEditor() {
const metricsFilter = (this.props.renderAs === RENDER_AS.HEATMAP) ? ((metric) => {
//these are countable metrics, where blending heatmap color blobs make sense
return ['count', 'sum'].includes(metric.value);
}) : null;
const allowMultipleMetrics = (this.props.renderAs === RENDER_AS.HEATMAP) ? false : true;
const allowMultipleMetrics = this.props.renderAs !== RENDER_AS.HEATMAP;
return (
<MetricsEditor
allowMultipleMetrics={allowMultipleMetrics}
@ -71,6 +75,7 @@ export class UpdateSourceEditor extends Component {
render() {
return (
<Fragment>
<ResolutionEditor resolution={this.props.resolution} onChange={this._onResolutionChange}/>
{this._renderMetricsEditor()}
</Fragment>
);

View file

@ -4,11 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/
import React from 'react';
import {
EuiSuperSelect,
} from '@elastic/eui';
import { GRID_RESOLUTION } from '../grid_resolution';
export class HeatmapStyle {
@ -39,24 +35,17 @@ export class HeatmapStyle {
return 'Heatmap style';
}
static renderEditor({ style, handleStyleChange }) {
const onChange = (refinement) => {
const styleDescriptor = HeatmapStyle.createDescriptor(refinement);
handleStyleChange(styleDescriptor);
};
return (<HeatmapEditor seedRefinement={style.getRefinement()} onRefinementChange={onChange} />);
static renderEditor() {
return null;
}
setMBPaintProperties({ alpha, mbMap, layerId, propertyName }) {
setMBPaintProperties({ alpha, mbMap, layerId, propertyName, resolution }) {
let radius;
if (this._descriptor.refinement === 'coarse') {
if (resolution === GRID_RESOLUTION.COARSE) {
radius = 64;
} else if (this._descriptor.refinement === 'fine') {
} else if (resolution === GRID_RESOLUTION.FINE) {
radius = 32;
} else if (this._descriptor.refinement === 'most_fine') {
} else if (resolution === GRID_RESOLUTION.MOST_FINE) {
radius = 16;
} else {
throw new Error(`Refinement param not recognized: ${this._descriptor.refinement}`);
@ -69,57 +58,5 @@ export class HeatmapStyle {
mbMap.setPaintProperty(layerId, 'heatmap-opacity', alpha);
}
getRefinement() {
return this._descriptor.refinement;
}
getPrecisionRefinementDelta() {
let refinementFactor;
if (this._descriptor.refinement === 'coarse') {
refinementFactor = 0;
} else if (this._descriptor.refinement === 'fine') {
refinementFactor = 1;
} else if (this._descriptor.refinement === 'most_fine') {
refinementFactor = 2;
} else {
throw new Error(`Refinement param not recognized: ${this._descriptor.refinement}`);
}
return refinementFactor;
}
}
class HeatmapEditor extends React.Component {
constructor() {
super();
this.state = {
refinement: null
};
}
render() {
const options = [
{ value: 'coarse', inputDisplay: 'coarse' },
{ value: 'fine', inputDisplay: 'fine' },
{ value: 'most_fine', inputDisplay: 'finest' }
];
const onChange = (value) => {
this.setState({
refinement: value
});
this.props.onRefinementChange(value);
};
const refinement = this.state.refinement === null ? this.props.seedRefinement : this.state.refinement;
return (
<div>
<EuiSuperSelect options={options} valueOfSelected={refinement} onChange={onChange} />
</div>
);
}
}

View file

@ -96,11 +96,6 @@ export class VectorLayer extends AbstractLayer {
return 'vector';
}
getColorRamp() {
// TODO: Determine if can be data-driven first
return this._style.getColorRamp();
}
getTOCDetails() {
return this._style.getTOCDetails();
}
@ -236,6 +231,10 @@ export class VectorLayer extends AbstractLayer {
&& !updateDueToPrecisionChange;
}
_getTargetGeohashPrecision(precision) {
return this._source.getGeohashPrecisionResolutionDelta() + precision;
}
async _syncJoin(join, { startLoading, stopLoading, onLoadError, dataFilters }) {
const joinSource = join.getJoinSource();
@ -289,7 +288,11 @@ export class VectorLayer extends AbstractLayer {
})
];
const targetPrecision = getGeohashPrecisionForZoom(dataFilters.zoom);
let targetPrecision = getGeohashPrecisionForZoom(dataFilters.zoom);
if (this._source.isGeohashPrecisionAware()) {
targetPrecision = this._getTargetGeohashPrecision(targetPrecision);
}
return {
...dataFilters,
fieldNames: _.uniq(fieldNames).sort(),

View file

@ -9,7 +9,7 @@
"title" : "[Logs] Web Traffic",
"description" : "",
"mapStateJSON" : "{\"zoom\":3.92,\"center\":{\"lon\":-83.95443,\"lat\":38.02463},\"timeFilters\":{\"from\":\"now-7d\",\"to\":\"now\"}}",
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"alpha\":1,\"minZoom\":0,\"maxZoom\":24},{\"id\":\"ajk2l\",\"label\":\"logs(heatmap)\",\"alpha\":1,\"minZoom\":0,\"maxZoom\":9,\"sourceDescriptor\":{\"type\":\"ES_GEOHASH_GRID\",\"id\":\"60c5dffb-7fca-431c-b1f0-9cc2e6697e8c\",\"indexPatternId\":\"90943e30-9a47-11e8-b64d-95841ca0b247\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{\"alphaValue\":0.75},\"previousStyle\":null},\"type\":\"HEATMAP\"},{\"id\":\"6hgh2\",\"label\":\"logs(documents)\",\"alpha\":1,\"minZoom\":7,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"541f2ca1-6a0f-4937-8846-a589222b7f28\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"90943e30-9a47-11e8-b64d-95841ca0b247\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[\"timestamp\",\"clientip\",\"url\"]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":0.75},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"alpha\":1,\"minZoom\":0,\"maxZoom\":24},{\"id\":\"ajk2l\",\"label\":\"logs(heatmap)\",\"alpha\":1,\"minZoom\":0,\"maxZoom\":9,\"sourceDescriptor\":{\"resolution\": \"COARSE\", \"type\":\"ES_GEOHASH_GRID\",\"id\":\"60c5dffb-7fca-431c-b1f0-9cc2e6697e8c\",\"indexPatternId\":\"90943e30-9a47-11e8-b64d-95841ca0b247\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{\"alphaValue\":0.75},\"previousStyle\":null},\"type\":\"HEATMAP\"},{\"id\":\"6hgh2\",\"label\":\"logs(documents)\",\"alpha\":1,\"minZoom\":7,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"541f2ca1-6a0f-4937-8846-a589222b7f28\",\"type\":\"ES_SEARCH\",\"indexPatternId\":\"90943e30-9a47-11e8-b64d-95841ca0b247\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[\"timestamp\",\"clientip\",\"url\"]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"alphaValue\":0.75},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
"uiStateJSON" : "{\"isDarkMode\":false}",
"bounds" : {
"type" : "envelope",

View file

@ -202,7 +202,7 @@
"gis-map" : {
"title" : "geohashgrid heatmap example",
"mapStateJSON" : "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"3xlvm\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"type\":\"ES_GEOHASH_GRID\",\"id\":\"427aa49d-a552-4e7d-a629-67c47db27128\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{\"alphaValue\":1},\"previousStyle\":null},\"type\":\"HEATMAP\"}]",
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"3xlvm\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEOHASH_GRID\",\"id\":\"427aa49d-a552-4e7d-a629-67c47db27128\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"heatmap\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"HEATMAP\",\"refinement\":\"coarse\",\"properties\":{\"alphaValue\":1},\"previousStyle\":null},\"type\":\"HEATMAP\"}]",
"uiStateJSON" : "{\"isDarkMode\":false}",
"bounds" : {
"type" : "envelope",
@ -234,7 +234,7 @@
"title" : "geohashgrid vector grid example",
"description" : "",
"mapStateJSON" : "{\"zoom\":3.59,\"center\":{\"lon\":-98.05765,\"lat\":38.32288},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-20T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000}}",
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"type\":\"ES_GEOHASH_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\"}]",
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{\"alphaValue\":1}},\"type\":\"TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"g1xkv\",\"label\":null,\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"resolution\": \"COARSE\",\"type\":\"ES_GEOHASH_GRID\",\"id\":\"9305f6ea-4518-4c06-95b9-33321aa38d6a\",\"indexPatternId\":\"c698b940-e149-11e8-a35a-370a8516603a\",\"geoField\":\"geo.coordinates\",\"requestType\":\"grid\",\"metrics\":[{\"type\":\"count\"},{\"type\":\"max\",\"field\":\"bytes\"}]},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"max of bytes\",\"name\":\"max_of_bytes\",\"origin\":\"source\"},\"color\":\"Blues\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#cccccc\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"DYNAMIC\",\"options\":{\"field\":{\"label\":\"Count\",\"name\":\"doc_count\",\"origin\":\"source\"},\"minSize\":4,\"maxSize\":32}},\"alphaValue\":1},\"temporary\":true,\"previousStyle\":null},\"type\":\"VECTOR\"}]",
"uiStateJSON" : "{\"isDarkMode\":false}",
"bounds" : {
"type" : "envelope",