mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
* [Maps] remove duplicated logic between heatmap layer and vector layer * removed unused getGeoJsonPoints function from geo_grid_source * cleanup i18n translations * review feedback * fix jest test
This commit is contained in:
parent
5e3281f8d3
commit
d96e33bc72
10 changed files with 44 additions and 157 deletions
|
@ -51,3 +51,8 @@ export const GEO_JSON_TYPE = {
|
|||
MULTI_POLYGON: 'MultiPolygon',
|
||||
GEOMETRY_COLLECTION: 'GeometryCollection',
|
||||
};
|
||||
|
||||
export const EMPTY_FEATURE_COLLECTION = {
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
};
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
jest.mock('../shared/layers/vector_layer', () => {});
|
||||
jest.mock('../shared/layers/heatmap_layer', () => {});
|
||||
jest.mock('../shared/layers/sources/all_sources', () => {});
|
||||
jest.mock('../reducers/non_serializable_instances', () => ({
|
||||
getInspectorAdapters: () => {
|
||||
|
|
|
@ -5,17 +5,14 @@
|
|||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { AbstractLayer } from './layer';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
import { VectorLayer } from './vector_layer';
|
||||
import { HeatmapStyle } from './styles/heatmap_style';
|
||||
import { SOURCE_DATA_ID_ORIGIN } from '../../../common/constants';
|
||||
import { isRefreshOnlyQuery } from './util/is_refresh_only_query';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EMPTY_FEATURE_COLLECTION } from '../../../common/constants';
|
||||
|
||||
const SCALED_PROPERTY_NAME = '__kbn_heatmap_weight__';//unique name to store scaled value for weighting
|
||||
|
||||
export class HeatmapLayer extends AbstractLayer {
|
||||
export class HeatmapLayer extends VectorLayer {
|
||||
|
||||
static type = 'HEATMAP';
|
||||
|
||||
|
@ -34,36 +31,26 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
}
|
||||
}
|
||||
|
||||
getIndexPatternIds() {
|
||||
return this._source.getIndexPatternIds();
|
||||
}
|
||||
|
||||
_getPropKeyOfSelectedMetric() {
|
||||
const metricfields = this._source.getMetricFields();
|
||||
return metricfields[0].propertyKey;
|
||||
}
|
||||
|
||||
_getMbLayerId() {
|
||||
_getHeatmapLayerId() {
|
||||
return this.getId() + '_heatmap';
|
||||
}
|
||||
|
||||
getMbLayerIds() {
|
||||
return [this._getMbLayerId()];
|
||||
return [this._getHeatmapLayerId()];
|
||||
}
|
||||
|
||||
syncLayerWithMB(mbMap) {
|
||||
super._syncSourceBindingWithMb(mbMap);
|
||||
|
||||
const mbSource = mbMap.getSource(this.getId());
|
||||
const mbLayerId = this._getMbLayerId();
|
||||
|
||||
if (!mbSource) {
|
||||
mbMap.addSource(this.getId(), {
|
||||
type: 'geojson',
|
||||
data: { 'type': 'FeatureCollection', 'features': [] }
|
||||
});
|
||||
|
||||
const heatmapLayerId = this._getHeatmapLayerId();
|
||||
if (!mbMap.getLayer(heatmapLayerId)) {
|
||||
mbMap.addLayer({
|
||||
id: mbLayerId,
|
||||
id: heatmapLayerId,
|
||||
type: 'heatmap',
|
||||
source: this.getId(),
|
||||
paint: {}
|
||||
|
@ -74,7 +61,7 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
const sourceDataRequest = this.getSourceDataRequest();
|
||||
const featureCollection = sourceDataRequest ? sourceDataRequest.getData() : null;
|
||||
if (!featureCollection) {
|
||||
mbSourceAfter.setData({ 'type': 'FeatureCollection', 'features': [] });
|
||||
mbSourceAfter.setData(EMPTY_FEATURE_COLLECTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,124 +78,21 @@ export class HeatmapLayer extends AbstractLayer {
|
|||
mbSourceAfter.setData(featureCollection);
|
||||
}
|
||||
|
||||
mbMap.setLayoutProperty(mbLayerId, 'visibility', this.isVisible() ? 'visible' : 'none');
|
||||
mbMap.setLayoutProperty(heatmapLayerId, 'visibility', this.isVisible() ? 'visible' : 'none');
|
||||
this._style.setMBPaintProperties({
|
||||
mbMap,
|
||||
layerId: mbLayerId,
|
||||
layerId: heatmapLayerId,
|
||||
propertyName: SCALED_PROPERTY_NAME,
|
||||
resolution: this._source.getGridResolution()
|
||||
});
|
||||
mbMap.setPaintProperty(mbLayerId, 'heatmap-opacity', this.getAlpha());
|
||||
mbMap.setLayerZoomRange(mbLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
|
||||
}
|
||||
|
||||
async getBounds(dataFilters) {
|
||||
const searchFilters = this._getSearchFilters(dataFilters);
|
||||
return await this._source.getBoundsForFilters(searchFilters);
|
||||
}
|
||||
|
||||
async syncData({ startLoading, stopLoading, onLoadError, dataFilters }) {
|
||||
if (!this.isVisible() || !this.showAtZoomLevel(dataFilters.zoom)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dataFilters.buffer) {
|
||||
return;
|
||||
}
|
||||
|
||||
const searchFilters = this._getSearchFilters(dataFilters);
|
||||
|
||||
const sourceDataRequest = this.getSourceDataRequest();
|
||||
const meta = sourceDataRequest ? sourceDataRequest.getMeta() : {};
|
||||
|
||||
const isSamePrecision = meta.geogridPrecision === searchFilters.geogridPrecision;
|
||||
|
||||
const isSameTime = _.isEqual(meta.timeFilters, searchFilters.timeFilters);
|
||||
|
||||
const updateDueToRefreshTimer = searchFilters.refreshTimerLastTriggeredAt
|
||||
&& !_.isEqual(meta.refreshTimerLastTriggeredAt, searchFilters.refreshTimerLastTriggeredAt);
|
||||
|
||||
const updateDueToExtent = this.updateDueToExtent(this._source, meta, searchFilters);
|
||||
|
||||
let updateDueToQuery = false;
|
||||
let updateDueToFilters = false;
|
||||
if (searchFilters.applyGlobalQuery) {
|
||||
updateDueToQuery = !_.isEqual(meta.query, searchFilters.query);
|
||||
updateDueToFilters = !_.isEqual(meta.filters, searchFilters.filters);
|
||||
} else {
|
||||
// Global filters and query are not applied to layer search request so no re-fetch required.
|
||||
// Exception is "Refresh" query.
|
||||
updateDueToQuery = isRefreshOnlyQuery(meta.query, searchFilters.query);
|
||||
}
|
||||
const updateDueToSourceQuery = searchFilters.sourceQuery
|
||||
&& !_.isEqual(meta.sourceQuery, searchFilters.sourceQuery);
|
||||
const updateDueToApplyGlobalQuery = meta.applyGlobalQuery !== searchFilters.applyGlobalQuery;
|
||||
|
||||
const updateDueToMetricChange = !_.isEqual(meta.metric, searchFilters.metric);
|
||||
|
||||
if (isSamePrecision
|
||||
&& isSameTime
|
||||
&& !updateDueToExtent
|
||||
&& !updateDueToRefreshTimer
|
||||
&& !updateDueToQuery
|
||||
&& !updateDueToSourceQuery
|
||||
&& !updateDueToApplyGlobalQuery
|
||||
&& !updateDueToFilters
|
||||
&& !updateDueToMetricChange
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._fetchNewData({ startLoading, stopLoading, onLoadError, searchFilters });
|
||||
}
|
||||
|
||||
_getSearchFilters(dataFilters) {
|
||||
return {
|
||||
...dataFilters,
|
||||
sourceQuery: this.getQuery(),
|
||||
applyGlobalQuery: this.getApplyGlobalQuery(),
|
||||
geogridPrecision: this._source.getGeoGridPrecision(dataFilters.zoom),
|
||||
metric: this._getPropKeyOfSelectedMetric()
|
||||
};
|
||||
}
|
||||
|
||||
async _fetchNewData({ startLoading, stopLoading, onLoadError, searchFilters }) {
|
||||
const requestToken = Symbol(`layer-source-refresh: this.getId()`);
|
||||
startLoading(SOURCE_DATA_ID_ORIGIN, requestToken, searchFilters);
|
||||
try {
|
||||
const layerName = await this.getDisplayName();
|
||||
const data = await this._source.getGeoJsonPoints(layerName, searchFilters);
|
||||
stopLoading(SOURCE_DATA_ID_ORIGIN, requestToken, data);
|
||||
} catch (error) {
|
||||
onLoadError(SOURCE_DATA_ID_ORIGIN, requestToken, error.message);
|
||||
}
|
||||
mbMap.setPaintProperty(heatmapLayerId, 'heatmap-opacity', this.getAlpha());
|
||||
mbMap.setLayerZoomRange(heatmapLayerId, this._descriptor.minZoom, this._descriptor.maxZoom);
|
||||
}
|
||||
|
||||
getLayerTypeIconName() {
|
||||
return 'heatmap';
|
||||
}
|
||||
|
||||
getCustomIconAndTooltipContent() {
|
||||
const sourceDataRequest = this.getSourceDataRequest();
|
||||
const featureCollection = sourceDataRequest ? sourceDataRequest.getData() : null;
|
||||
if (!featureCollection || featureCollection.features.length === 0) {
|
||||
return {
|
||||
icon: (
|
||||
<EuiIcon
|
||||
size="m"
|
||||
color="subdued"
|
||||
type="minusInCircle"
|
||||
/>
|
||||
),
|
||||
tooltipContent: i18n.translate('xpack.maps.heatmapLayer.noResultsFoundTooltip', {
|
||||
defaultMessage: `No results found.`
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
return super.getCustomIconAndTooltipContent();
|
||||
}
|
||||
|
||||
hasLegendDetails() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,7 @@
|
|||
|
||||
import { RENDER_AS } from './render_as';
|
||||
import { getTileBoundingBox } from './geo_tile_utils';
|
||||
|
||||
const EMPTY_FEATURE_COLLECTION = {
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
};
|
||||
import { EMPTY_FEATURE_COLLECTION } from '../../../../../common/constants';
|
||||
|
||||
export function convertToGeoJson({ table, renderAs }) {
|
||||
|
||||
|
|
|
@ -176,23 +176,13 @@ export class ESGeoGridSource extends AbstractESSource {
|
|||
}));
|
||||
}
|
||||
|
||||
async getGeoJsonWithMeta(layerName, searchFilters) {
|
||||
const featureCollection = await this.getGeoJsonPoints(layerName, searchFilters);
|
||||
return {
|
||||
data: featureCollection,
|
||||
meta: {
|
||||
areResultsTrimmed: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async getNumberFields() {
|
||||
return this.getMetricFields().map(({ propertyKey: name, propertyLabel: label }) => {
|
||||
return { label, name };
|
||||
});
|
||||
}
|
||||
|
||||
async getGeoJsonPoints(layerName, searchFilters) {
|
||||
async getGeoJsonWithMeta(layerName, searchFilters) {
|
||||
const indexPattern = await this._getIndexPattern();
|
||||
const searchSource = await this._makeSearchSource(searchFilters, 0);
|
||||
const aggConfigs = new AggConfigs(indexPattern, this._makeAggConfigs(searchFilters.geogridPrecision), aggSchemas.all);
|
||||
|
@ -207,14 +197,18 @@ export class ESGeoGridSource extends AbstractESSource {
|
|||
renderAs: this._descriptor.requestType,
|
||||
});
|
||||
|
||||
return featureCollection;
|
||||
return {
|
||||
data: featureCollection,
|
||||
meta: {
|
||||
areResultsTrimmed: false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
isFilterByMapBounds() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
_formatMetricKey(metric) {
|
||||
return metric.type !== 'count' ? `${metric.type}_of_${metric.field}` : COUNT_PROP_NAME;
|
||||
}
|
||||
|
|
|
@ -23,4 +23,8 @@ export class AbstractStyle {
|
|||
renderEditor(/* { layer, onStyleDescriptorChange } */) {
|
||||
return null;
|
||||
}
|
||||
|
||||
getSourceFieldNames() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { HeatmapLegend } from './components/heatmap/legend/heatmap_legend';
|
|||
import { DEFAULT_HEATMAP_COLOR_RAMP_NAME } from './components/heatmap/heatmap_constants';
|
||||
import { getColorRampStops } from './color_utils';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiIcon } from '@elastic/eui';
|
||||
|
||||
export class HeatmapStyle extends AbstractStyle {
|
||||
|
||||
|
@ -58,6 +59,15 @@ export class HeatmapStyle extends AbstractStyle {
|
|||
);
|
||||
}
|
||||
|
||||
getIcon() {
|
||||
return (
|
||||
<EuiIcon
|
||||
size="m"
|
||||
type="heatmap"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
setMBPaintProperties({ mbMap, layerId, propertyName, resolution }) {
|
||||
let radius;
|
||||
if (resolution === GRID_RESOLUTION.COARSE) {
|
||||
|
|
|
@ -13,7 +13,8 @@ import {
|
|||
GEO_JSON_TYPE,
|
||||
FEATURE_ID_PROPERTY_NAME,
|
||||
SOURCE_DATA_ID_ORIGIN,
|
||||
FEATURE_VISIBLE_PROPERTY_NAME
|
||||
FEATURE_VISIBLE_PROPERTY_NAME,
|
||||
EMPTY_FEATURE_COLLECTION
|
||||
} from '../../../common/constants';
|
||||
import _ from 'lodash';
|
||||
import { JoinTooltipProperty } from './tooltips/join_tooltip_property';
|
||||
|
@ -21,11 +22,6 @@ import { isRefreshOnlyQuery } from './util/is_refresh_only_query';
|
|||
import { EuiIcon } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
const EMPTY_FEATURE_COLLECTION = {
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
};
|
||||
|
||||
const VISIBILITY_FILTER_CLAUSE = ['all',
|
||||
[
|
||||
'==',
|
||||
|
@ -137,7 +133,6 @@ export class VectorLayer extends AbstractLayer {
|
|||
const sourceDataRequest = this.getSourceDataRequest();
|
||||
const featureCollection = sourceDataRequest ? sourceDataRequest.getData() : null;
|
||||
|
||||
|
||||
const noResultsIcon = (
|
||||
<EuiIcon
|
||||
size="m"
|
||||
|
|
|
@ -5585,7 +5585,6 @@
|
|||
"xpack.maps.featureRegistry.mapsFeatureName": "Maps",
|
||||
"xpack.maps.geoGrid.resolutionLabel": "グリッド解像度",
|
||||
"xpack.maps.heatmap.colorRampLabel": "色の範囲",
|
||||
"xpack.maps.heatmapLayer.noResultsFoundTooltip": "結果が見つかりませんでした。",
|
||||
"xpack.maps.heatmapLegend.coldLabel": "コールド",
|
||||
"xpack.maps.heatmapLegend.hotLabel": "ホット",
|
||||
"xpack.maps.helpMenu.docLabel": "Maps ドキュメンテーション",
|
||||
|
|
|
@ -5586,7 +5586,6 @@
|
|||
"xpack.maps.featureRegistry.mapsFeatureName": "Maps",
|
||||
"xpack.maps.geoGrid.resolutionLabel": "网格分辨率",
|
||||
"xpack.maps.heatmap.colorRampLabel": "颜色范围",
|
||||
"xpack.maps.heatmapLayer.noResultsFoundTooltip": "找不到结果",
|
||||
"xpack.maps.heatmapLegend.coldLabel": "冷",
|
||||
"xpack.maps.heatmapLegend.hotLabel": "热",
|
||||
"xpack.maps.helpMenu.docLabel": "地图文档",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue