From 64d439b1feaebf53d8a0f72cde07b9eaffa0dc96 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 2 Sep 2020 11:28:22 -0400 Subject: [PATCH 01/46] boilerplate --- x-pack/plugins/maps/common/constants.ts | 1 + .../maps/public/classes/layers/layer.tsx | 2 +- .../es_geo_grid_source/es_geo_grid_source.js | 14 ++++++++-- .../es_geo_grid_source.test.ts | 16 +++++++++++ .../es_geo_grid_source/resolution_editor.js | 17 +++++++++--- .../update_source_editor.js | 27 ++++++++++++++++--- .../classes/styles/heatmap/heatmap_style.tsx | 2 ++ 7 files changed, 70 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index a4f20caedfc9bd..8a26421b5a79e8 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -164,6 +164,7 @@ export enum GRID_RESOLUTION { COARSE = 'COARSE', FINE = 'FINE', MOST_FINE = 'MOST_FINE', + SUPER_FINE = 'SUPER_FINE', } export const TOP_TERM_PERCENTAGE_SUFFIX = '__percentage'; diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 8026f48fe6093b..cd720063c67031 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -423,7 +423,7 @@ export class AbstractLayer implements ILayer { renderSourceSettingsEditor({ onChange }: SourceEditorArgs) { const source = this.getSourceForEditing(); - return source.renderSourceSettingsEditor({ onChange }); + return source.renderSourceSettingsEditor({ onChange, currentLayerType: this._descriptor.type }); } getPrevRequestToken(dataId: string): symbol | undefined { diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index a6322ff3ba784b..38cdafdb60d89b 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -48,9 +48,10 @@ export class ESGeoGridSource extends AbstractESAggSource { }; } - renderSourceSettingsEditor({ onChange }) { + renderSourceSettingsEditor({ onChange, currentLayerType }) { return ( { it('should use heuristic to derive precision', () => { expect(geogridSource.getGeoGridPrecision(10)).toBe(12); }); + + it('Should not return valid precision for super-fine resolution', () => { + const superFineSource = new ESGeoGridSource( + { + id: 'foobar', + indexPatternId: 'fooIp', + geoField: geoFieldName, + metrics: [], + resolution: GRID_RESOLUTION.SUPER_FINE, + type: SOURCE_TYPES.ES_GEO_GRID, + requestType: RENDER_AS.HEATMAP, + }, + {} + ); + expect(superFineSource.getGeoGridPrecision(10)).toBe(NaN); + }); }); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js index 28c24f58a0efcf..71133cb25280c7 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js @@ -9,7 +9,7 @@ import { GRID_RESOLUTION } from '../../../../common/constants'; import { EuiSelect, EuiFormRow } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -const OPTIONS = [ +const BASE_OPTIONS = [ { value: GRID_RESOLUTION.COARSE, text: i18n.translate('xpack.maps.source.esGrid.coarseDropdownOption', { @@ -30,7 +30,18 @@ const OPTIONS = [ }, ]; -export function ResolutionEditor({ resolution, onChange }) { +export function ResolutionEditor({ resolution, onChange, includeSuperFine }) { + const options = [...BASE_OPTIONS]; + + if (includeSuperFine) { + options.push({ + value: GRID_RESOLUTION.SUPER_FINE, + text: i18n.translate('xpack.maps.source.esGrid.superFineDropDownOption', { + defaultMessage: 'super fine (beta)', + }), + }); + } + return ( onChange(e.target.value)} compressed diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js index ac7d809c40f61b..e2de17fe31d5ba 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js @@ -6,7 +6,7 @@ import React, { Fragment, Component } from 'react'; -import { RENDER_AS } from '../../../../common/constants'; +import { GRID_RESOLUTION, LAYER_TYPE, RENDER_AS } from '../../../../common/constants'; import { MetricsEditor } from '../../../components/metrics_editor'; import { getIndexPatternService } from '../../../kibana_services'; import { ResolutionEditor } from './resolution_editor'; @@ -62,8 +62,28 @@ export class UpdateSourceEditor extends Component { this.props.onChange({ propName: 'metrics', value: metrics }); }; - _onResolutionChange = (e) => { - this.props.onChange({ propName: 'resolution', value: e }); + _onResolutionChange = (resolution) => { + let newLayerType; + if ( + this.props.currentLayerType === LAYER_TYPE.VECTOR || + this.props.currentLayerType === LAYER_TYPE.TILED_VECTOR + ) { + if (resolution === GRID_RESOLUTION.SUPER_FINE) { + newLayerType = LAYER_TYPE.TILED_VECTOR; + } else { + newLayerType = LAYER_TYPE.VECTOR; + } + } else if (this.props.currentLayerType === LAYER_TYPE.HEATMAP) { + if (resolution === GRID_RESOLUTION.SUPER_FINE) { + throw new Error('NOT SUPPORTED!!'); + } else { + newLayerType = LAYER_TYPE.HEATMAP; + } + } else { + throw new Error('Unexpected layer-type'); + } + + this.props.onChange({ propName: 'resolution', value: resolution, newLayerType }); }; _onRequestTypeSelect = (requestType) => { @@ -115,6 +135,7 @@ export class UpdateSourceEditor extends Component { diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx index a3002251785269..915e9a8a9b57d4 100644 --- a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx @@ -85,6 +85,8 @@ export class HeatmapStyle implements IStyle { radius = 64; } else if (resolution === GRID_RESOLUTION.MOST_FINE) { radius = 32; + } else if (resolution === GRID_RESOLUTION.SUPER_FINE) { + radius = 8; } else { const errorMessage = i18n.translate('xpack.maps.style.heatmap.resolutionStyleErrorMessage', { defaultMessage: `Resolution param not recognized: {resolution}`, From c21d5650cc7e18f975a494c2ca5c73a871c44a23 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 2 Sep 2020 12:18:20 -0400 Subject: [PATCH 02/46] more boilerplate --- x-pack/plugins/maps/common/constants.ts | 1 + .../es_geo_grid_source.d.ts | 20 ++++- .../es_geo_grid_source/es_geo_grid_source.js | 82 ++++++++++++++++--- 3 files changed, 92 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 8a26421b5a79e8..e96f2c2bf78f2c 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -36,6 +36,7 @@ export const FONTS_API_PATH = `${GIS_API_PATH}/fonts`; export const API_ROOT_PATH = `/${GIS_API_PATH}`; export const MVT_GETTILE_API_PATH = 'mvt/getTile'; +export const MVT_GETGRIDTILE_API_PATH = 'mvt/getGridTile'; export const MVT_SOURCE_LAYER_NAME = 'source_layer'; export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__'; export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 51ee15e7ea5af0..0c85cdadf552e0 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -7,8 +7,9 @@ import { AbstractESAggSource } from '../es_agg_source'; import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; import { GRID_RESOLUTION } from '../../../../common/constants'; +import { ITiledSingleLayerVectorSource } from '../vector_source'; -export class ESGeoGridSource extends AbstractESAggSource { +export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingleLayerVectorSource { static createDescriptor({ indexPatternId, geoField, @@ -21,4 +22,21 @@ export class ESGeoGridSource extends AbstractESAggSource { getFieldNames(): string[]; getGridResolution(): GRID_RESOLUTION; getGeoGridPrecision(zoom: number): number; + + getLayerName(): string; + + getUrlTemplateWithMeta( + searchFilters: MapFilters & { + applyGlobalQuery: boolean; + fieldNames: string[]; + geogridPrecision?: number; + sourceQuery: MapQuery; + sourceMeta: VectorSourceSyncMeta; + } + ): Promise<{ + layerName: string; + urlTemplate: string; + minSourceZoom: number; + maxSourceZoom: number; + }>; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 38cdafdb60d89b..1d6324b33ba8bb 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -15,6 +15,9 @@ import { RENDER_AS, GRID_RESOLUTION, VECTOR_SHAPE_TYPE, + MVT_SOURCE_LAYER_NAME, + GIS_API_PATH, + MVT_GETGRIDTILE_API_PATH, } from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; @@ -22,6 +25,8 @@ import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { DataRequestAbortError } from '../../util/data_request'; import { registerSource } from '../source_registry'; import { makeESBbox } from '../../../../common/elasticsearch_geo_utils'; +import rison from 'rison-node'; +import { getHttp } from '../../../kibana_services'; export const MAX_GEOTILE_LEVEL = 29; @@ -239,16 +244,10 @@ export class ESGeoGridSource extends AbstractESAggSource { return features; } - // Do not use composite aggregation when there are no terms sub-aggregations - // see https://github.com/elastic/kibana/pull/57875#issuecomment-590515482 for explanation on using separate code paths - async _nonCompositeAggRequest({ + _addNonCompositeAggregationsToSearchSource( searchSource, - indexPattern, - precision, - layerName, - registerCancelCallback, - bufferedExtent, - }) { + { indexPattern, precision, bufferedExtent } + ) { searchSource.setField('aggs', { gridSplit: { geotile_grid: { @@ -268,6 +267,23 @@ export class ESGeoGridSource extends AbstractESAggSource { }, }, }); + } + + // Do not use composite aggregation when there are no terms sub-aggregations + // see https://github.com/elastic/kibana/pull/57875#issuecomment-590515482 for explanation on using separate code paths + async _nonCompositeAggRequest({ + searchSource, + indexPattern, + precision, + layerName, + registerCancelCallback, + bufferedExtent, + }) { + this._addNonCompositeAggregationsToSearchSource(searchSource, { + indexPattern, + precision, + bufferedExtent, + }); const esResponse = await this._runEsQuery({ requestId: this.getId(), @@ -323,8 +339,54 @@ export class ESGeoGridSource extends AbstractESAggSource { }; } + getLayerName() { + return MVT_SOURCE_LAYER_NAME; + } + + async getUrlTemplateWithMeta(searchFilters) { + console.log('url template', searchFilters); + + const indexPattern = await this.getIndexPattern(); + const searchSource = await this.makeSearchSource(searchFilters, 0); + + this._addNonCompositeAggregationsToSearchSource(searchSource, { + indexPattern, + precision: searchFilters.geogridPrecision, + bufferedExtent: searchFilters.buffer, + }); + + //todo! + console.warn('THIS IS WONKY!'); + + const dsl = await searchSource.getSearchRequestBody(); + + console.log(JSON.stringify(dsl, null, '\t')); + + const risonDsl = rison.encode(dsl); + + const mvtUrlServicePath = getHttp().basePath.prepend( + `/${GIS_API_PATH}/${MVT_GETGRIDTILE_API_PATH}` + ); + + console.log('mv', mvtUrlServicePath); + + const urlTemplate = `${mvtUrlServicePath}?x={x}&y={y}&z={z}&geometryFieldName=${this._descriptor.geoField}&index=${indexPattern.title}&requestBody=${risonDsl}`; + return { + layerName: this.getLayerName(), + minSourceZoom: this.getMinZoom(), + maxSourceZoom: this.getMaxZoom(), + urlTemplate: urlTemplate, + }; + } + isFilterByMapBounds() { - return true; + if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) { + //MVT gridded data. Should exclude bounds-filter from ES-DSL + return false; + } else { + //Should include bounds-filter from ES-DSL + return true; + } } canFormatFeatureProperties() { From abf23ca65087283df7893dec58dfbdf991a56cf5 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 2 Sep 2020 12:28:32 -0400 Subject: [PATCH 03/46] even more boilerplate --- x-pack/plugins/maps/server/mvt/get_tile.ts | 23 +++++++ x-pack/plugins/maps/server/mvt/mvt_routes.ts | 65 +++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 9621f7f174a306..594bcda0468674 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -31,6 +31,29 @@ interface ESBounds { }; } +export async function getGridTile({ + logger, + callElasticsearch, + index, + geometryFieldName, + x, + y, + z, + requestBody = {}, +}: { + x: number; + y: number; + z: number; + geometryFieldName: string; + index: string; + callElasticsearch: (type: string, ...args: any[]) => Promise; + logger: Logger; + requestBody: any; +}): Promise { + logger.warn('getGridTile not implemented'); + return null; +} + export async function getTile({ logger, callElasticsearch, diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 32c14a355ba2a1..a99930333ec775 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -8,8 +8,12 @@ import rison from 'rison-node'; import { schema } from '@kbn/config-schema'; import { Logger } from 'src/core/server'; import { IRouter } from 'src/core/server'; -import { MVT_GETTILE_API_PATH, API_ROOT_PATH } from '../../common/constants'; -import { getTile } from './get_tile'; +import { + MVT_GETTILE_API_PATH, + API_ROOT_PATH, + MVT_GETGRIDTILE_API_PATH, +} from '../../common/constants'; +import { getGridTile, getTile } from './get_tile'; const CACHE_TIMEOUT = 0; // Todo. determine good value. Unsure about full-implications (e.g. wrt. time-based data). @@ -70,4 +74,61 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou } } ); + + router.get( + { + path: `${API_ROOT_PATH}/${MVT_GETGRIDTILE_API_PATH}`, + validate: { + query: schema.object({ + x: schema.number(), + y: schema.number(), + z: schema.number(), + geometryFieldName: schema.string(), + requestBody: schema.string(), + index: schema.string(), + }), + }, + }, + async (context, request, response) => { + const { query } = request; + + const callElasticsearch = async (type: string, ...args: any[]): Promise => { + return await context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); + }; + + const requestBodyDSL = rison.decode(query.requestBody); + + const tile = await getGridTile({ + logger, + callElasticsearch, + geometryFieldName: query.geometryFieldName, + x: query.x, + y: query.y, + z: query.z, + index: query.index, + requestBody: requestBodyDSL, + }); + + if (tile) { + // return response.ok({ + // body: tile, + // headers: { + // 'content-disposition': 'inline', + // 'content-length': `${tile.length}`, + // 'Content-Type': 'application/x-protobuf', + // 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, + // }, + // }); + } else { + return response.ok({ + headers: { + 'content-disposition': 'inline', + 'content-length': '0', + 'Content-Type': 'application/x-protobuf', + 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, + }, + }); + } + } + ); } From d5e882d3651d153c13506e52d3cb55b3ffd9b77b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 2 Sep 2020 16:33:34 -0400 Subject: [PATCH 04/46] add round-trip boilerplate --- x-pack/plugins/maps/common/constants.ts | 4 + .../tiled_vector_layer/tiled_vector_layer.tsx | 4 + .../es_geo_grid_source/convert_to_geojson.js | 14 +- .../es_geo_grid_source/es_geo_grid_source.js | 29 +++-- x-pack/plugins/maps/server/mvt/get_tile.ts | 120 +++++++++++++++++- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 18 +-- 6 files changed, 165 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index e96f2c2bf78f2c..b611f41a285507 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -168,6 +168,10 @@ export enum GRID_RESOLUTION { SUPER_FINE = 'SUPER_FINE', } +export const SUPER_FINE_ZOOM_DELTA = 7; // (2 ^ SUPER_FINE_ZOOM_DELTA) ^ 2 = number of cells in a given tile +export const GEOTILE_GRID_AGG_NAME = 'gridSplit'; +export const GEOCENTROID_AGG_NAME = 'gridCentroid'; + export const TOP_TERM_PERCENTAGE_SUFFIX = '__percentage'; export const COUNT_PROP_LABEL = i18n.translate('xpack.maps.aggs.defaultCountLabel', { diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index 70bf8ea3883b72..36f4571c17fb63 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -66,7 +66,10 @@ export class TiledVectorLayer extends VectorLayer { const templateWithMeta = await this._source.getUrlTemplateWithMeta(searchFilters); if (prevDataRequest) { const data: MVTSingleLayerVectorSourceConfig = prevDataRequest.getData() as MVTSingleLayerVectorSourceConfig; + if (data) { + // console.log('urlT', { existing: data.urlTemplate, new: templateWithMeta.urlTemplate }); + const canSkipBecauseNoChanges = data.layerName === this._source.getLayerName() && data.minSourceZoom === this._source.getMinZoom() && @@ -74,6 +77,7 @@ export class TiledVectorLayer extends VectorLayer { data.urlTemplate === templateWithMeta.urlTemplate; if (canSkipBecauseNoChanges) { + // console.loog('CAN SKIP!!~!'); return null; } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js index 35dbebdfd3c8a4..1759935d94285f 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js @@ -5,12 +5,16 @@ */ import _ from 'lodash'; -import { RENDER_AS } from '../../../../common/constants'; +import { + RENDER_AS, + GEOTILE_GRID_AGG_NAME, + GEOCENTROID_AGG_NAME, +} from '../../../../common/constants'; import { getTileBoundingBox } from './geo_tile_utils'; import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; import { clamp } from '../../../../common/elasticsearch_geo_utils'; -const GRID_BUCKET_KEYS_TO_IGNORE = ['key', 'gridCentroid']; +const GRID_BUCKET_KEYS_TO_IGNORE = ['key', GEOCENTROID_AGG_NAME]; export function convertCompositeRespToGeoJson(esResponse, renderAs) { return convertToGeoJson( @@ -20,7 +24,7 @@ export function convertCompositeRespToGeoJson(esResponse, renderAs) { return _.get(esResponse, 'aggregations.compositeSplit.buckets', []); }, (gridBucket) => { - return gridBucket.key.gridSplit; + return gridBucket.key[GEOTILE_GRID_AGG_NAME]; } ); } @@ -30,7 +34,7 @@ export function convertRegularRespToGeoJson(esResponse, renderAs) { esResponse, renderAs, (esResponse) => { - return _.get(esResponse, 'aggregations.gridSplit.buckets', []); + return _.get(esResponse, `aggregations.${GEOTILE_GRID_AGG_NAME}.buckets`, []); }, (gridBucket) => { return gridBucket.key; @@ -49,7 +53,7 @@ function convertToGeoJson(esResponse, renderAs, pluckGridBuckets, pluckGridKey) type: 'Feature', geometry: rowToGeometry({ gridKey, - gridCentroid: gridBucket.gridCentroid, + [GEOCENTROID_AGG_NAME]: gridBucket[GEOCENTROID_AGG_NAME], renderAs, }), id: gridKey, diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 1d6324b33ba8bb..8004e6e7655f23 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -18,6 +18,8 @@ import { MVT_SOURCE_LAYER_NAME, GIS_API_PATH, MVT_GETGRIDTILE_API_PATH, + GEOTILE_GRID_AGG_NAME, + GEOCENTROID_AGG_NAME, } from '../../../../common/constants'; import { i18n } from '@kbn/i18n'; import { getDataSourceLabel } from '../../../../common/i18n_getters'; @@ -106,7 +108,16 @@ export class ESGeoGridSource extends AbstractESAggSource { } isGeoGridPrecisionAware() { - return true; + console.log('is precisoin aware?', this._descriptor.resolution); + if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) { + // MVT gridded data should not bootstrap each time the precision changes + // MBtiles needs to handle this + console.log('NOT AWARE'); + return false; + } else { + // Should requery each time grid-precision changes + return true; + } } showJoinEditor() { @@ -171,7 +182,7 @@ export class ESGeoGridSource extends AbstractESAggSource { size: gridsPerRequest, sources: [ { - gridSplit: { + [GEOTILE_GRID_AGG_NAME]: { geotile_grid: { bounds: makeESBbox(bufferedExtent), field: this._descriptor.geoField, @@ -182,7 +193,7 @@ export class ESGeoGridSource extends AbstractESAggSource { ], }, aggs: { - gridCentroid: { + [GEOCENTROID_AGG_NAME]: { geo_centroid: { field: this._descriptor.geoField, }, @@ -249,16 +260,16 @@ export class ESGeoGridSource extends AbstractESAggSource { { indexPattern, precision, bufferedExtent } ) { searchSource.setField('aggs', { - gridSplit: { + [GEOTILE_GRID_AGG_NAME]: { geotile_grid: { - bounds: makeESBbox(bufferedExtent), + bounds: bufferedExtent ? makeESBbox(bufferedExtent) : null, field: this._descriptor.geoField, precision, size: DEFAULT_MAX_BUCKETS_LIMIT, shard_size: DEFAULT_MAX_BUCKETS_LIMIT, }, aggs: { - gridCentroid: { + [GEOCENTROID_AGG_NAME]: { geo_centroid: { field: this._descriptor.geoField, }, @@ -351,8 +362,8 @@ export class ESGeoGridSource extends AbstractESAggSource { this._addNonCompositeAggregationsToSearchSource(searchSource, { indexPattern, - precision: searchFilters.geogridPrecision, - bufferedExtent: searchFilters.buffer, + precision: -1, // This needs to be set server-side + bufferedExtent: null, //this needs to be stripped server-side }); //todo! @@ -360,7 +371,7 @@ export class ESGeoGridSource extends AbstractESAggSource { const dsl = await searchSource.getSearchRequestBody(); - console.log(JSON.stringify(dsl, null, '\t')); + // console.log(JSON.stringify(dsl, null, '\t')); const risonDsl = rison.encode(dsl); diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 594bcda0468674..8fc76515c727aa 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -13,8 +13,12 @@ import { Feature, FeatureCollection, Polygon } from 'geojson'; import { ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, + GEOCENTROID_AGG_NAME, + GEOTILE_GRID_AGG_NAME, KBN_TOO_MANY_FEATURES_PROPERTY, + MAX_ZOOM, MVT_SOURCE_LAYER_NAME, + SUPER_FINE_ZOOM_DELTA, } from '../../common/constants'; import { hitsToGeoJson } from '../../common/elasticsearch_geo_utils'; @@ -51,7 +55,109 @@ export async function getGridTile({ requestBody: any; }): Promise { logger.warn('getGridTile not implemented'); - return null; + + const esBbox = tileToESBbox(x, y, z); + const geojsonPolyhon = tileToGeoJsonPolygon(x, y, z); + + try { + let result; + try { + // todo: needs to be different from geo_point and geo_shape + const geoBoundingBox = { + geo_bounding_box: { + [geometryFieldName]: esBbox, + }, + }; + requestBody.query.bool.filter.push(geoBoundingBox); + + const targetPrecision = Math.min(z + SUPER_FINE_ZOOM_DELTA, MAX_ZOOM); + logger.warn(`z ${z} -> targetPrecision ${targetPrecision}`); + + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = targetPrecision; + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; + + const esGeotileGridQuery = { + index, + body: requestBody, + }; + + logger.warn(JSON.stringify(esGeotileGridQuery)); + + const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); + + // logger.warn(JSON.stringify(gridAggResult, null, '\t')); + + // todo: pass iun aggnames + const aggNames = ['doc_count']; + const ffeats = []; + gridAggResult.aggregations[GEOTILE_GRID_AGG_NAME].buckets.forEach((bucket) => { + const feature = { + type: 'Feature', + properties: {}, + geometry: null, + }; + + for (let i = 0; i < aggNames.length; i++) { + const aggName = aggNames[i]; + if (aggName === 'doc_count') { + feature.properties[aggName] = bucket[aggName]; + feature.properties.count = bucket[aggName]; + } else if (aggName === GEOCENTROID_AGG_NAME) { + // do nothing + } else { + feature.properties[aggName] = bucket[aggName].value; + } + } + + feature.properties[KBN_TOO_MANY_FEATURES_PROPERTY] = false; + + // Todo: needs to differentiate output between clusters and grids + const centroid = { + type: 'Point', + coordinates: [ + parseFloat(bucket[GEOCENTROID_AGG_NAME].location.lon), + parseFloat(bucket[GEOCENTROID_AGG_NAME].location.lat), + ], + }; + + feature.geometry = centroid; + + ffeats.push(feature); + }); + + const featureCollection = { + features: ffeats, + type: 'FeatureCollection', + }; + + const tileIndex = geojsonvt(featureCollection, { + maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 + tolerance: 3, // simplification tolerance (higher means simpler) + extent: 4096, // tile extent (both width and height) + buffer: 64, // tile buffer on each side + debug: 0, // logging level (0 to disable, 1 or 2) + lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features + promoteId: null, // name of a feature property to promote to feature.id. Cannot be used with `generateId` + generateId: false, // whether to generate feature ids. Cannot be used with `promoteId` + indexMaxZoom: 5, // max zoom in the initial tile index + indexMaxPoints: 100000, // max number of points per tile in the index + }); + const tile = tileIndex.getTile(z, x, y); + + if (tile) { + const pbf = vtpbf.fromGeojsonVt({ [MVT_SOURCE_LAYER_NAME]: tile }, { version: 2 }); + return Buffer.from(pbf); + } else { + return null; + } + } catch (e) { + logger.warn(e.message); + throw e; + } + } catch (e) { + logger.warn(`Cannot generate grid-tile for ${z}/${x}/${y}: ${e.message}`); + return null; + } } export async function getTile({ @@ -227,6 +333,18 @@ function tile2lat(y: number, z: number): number { return (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); } +function tileToESBbox(x, y, z) { + const wLon = tile2long(x, z); + const sLat = tile2lat(y + 1, z); + const eLon = tile2long(x + 1, z); + const nLat = tile2lat(y, z); + + return { + top_left: [wLon, nLat], + bottom_right: [eLon, sLat], + }; +} + function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { let minLon = esBounds.top_left.lon; const maxLon = esBounds.bottom_right.lon; diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index a99930333ec775..c269ddc9900e25 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -110,15 +110,15 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }); if (tile) { - // return response.ok({ - // body: tile, - // headers: { - // 'content-disposition': 'inline', - // 'content-length': `${tile.length}`, - // 'Content-Type': 'application/x-protobuf', - // 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - // }, - // }); + return response.ok({ + body: tile, + headers: { + 'content-disposition': 'inline', + 'content-length': `${tile.length}`, + 'Content-Type': 'application/x-protobuf', + 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, + }, + }); } else { return response.ok({ headers: { From 6b0415654d95d82c7752e8afe19db8554814e233 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 7 Sep 2020 20:29:46 -0400 Subject: [PATCH 05/46] move to common --- .../es_geo_grid_source => common}/geo_tile_utils.js | 4 ++-- .../geo_tile_utils.test.js | 0 .../sources/es_geo_grid_source/convert_to_geojson.js | 2 +- .../sources/es_geo_grid_source/es_geo_grid_source.js | 11 ----------- .../es_geo_grid_source/update_source_editor.js | 2 +- .../public/classes/sources/es_source/es_source.js | 2 +- .../plugins/maps/public/classes/util/es_agg_utils.ts | 2 +- 7 files changed, 6 insertions(+), 17 deletions(-) rename x-pack/plugins/maps/{public/classes/sources/es_geo_grid_source => common}/geo_tile_utils.js (95%) rename x-pack/plugins/maps/{public/classes/sources/es_geo_grid_source => common}/geo_tile_utils.test.js (100%) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js b/x-pack/plugins/maps/common/geo_tile_utils.js similarity index 95% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js rename to x-pack/plugins/maps/common/geo_tile_utils.js index 89b24522e42755..798c170f5152fa 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.js @@ -5,8 +5,8 @@ */ import _ from 'lodash'; -import { DECIMAL_DEGREES_PRECISION } from '../../../../common/constants'; -import { clampToLatBounds } from '../../../../common/elasticsearch_geo_utils'; +import { DECIMAL_DEGREES_PRECISION } from './constants'; +import { clampToLatBounds } from './elasticsearch_geo_utils'; const ZOOM_TILE_KEY_INDEX = 0; const X_TILE_KEY_INDEX = 1; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.test.js b/x-pack/plugins/maps/common/geo_tile_utils.test.js similarity index 100% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/geo_tile_utils.test.js rename to x-pack/plugins/maps/common/geo_tile_utils.test.js diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js index 1759935d94285f..8ac2a79942c6e5 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js @@ -10,7 +10,7 @@ import { GEOTILE_GRID_AGG_NAME, GEOCENTROID_AGG_NAME, } from '../../../../common/constants'; -import { getTileBoundingBox } from './geo_tile_utils'; +import { getTileBoundingBox } from '../../../../common/geo_tile_utils'; import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; import { clamp } from '../../../../common/elasticsearch_geo_utils'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 8004e6e7655f23..4451ec20e6a4af 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -108,11 +108,9 @@ export class ESGeoGridSource extends AbstractESAggSource { } isGeoGridPrecisionAware() { - console.log('is precisoin aware?', this._descriptor.resolution); if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) { // MVT gridded data should not bootstrap each time the precision changes // MBtiles needs to handle this - console.log('NOT AWARE'); return false; } else { // Should requery each time grid-precision changes @@ -355,8 +353,6 @@ export class ESGeoGridSource extends AbstractESAggSource { } async getUrlTemplateWithMeta(searchFilters) { - console.log('url template', searchFilters); - const indexPattern = await this.getIndexPattern(); const searchSource = await this.makeSearchSource(searchFilters, 0); @@ -366,21 +362,14 @@ export class ESGeoGridSource extends AbstractESAggSource { bufferedExtent: null, //this needs to be stripped server-side }); - //todo! - console.warn('THIS IS WONKY!'); - const dsl = await searchSource.getSearchRequestBody(); - // console.log(JSON.stringify(dsl, null, '\t')); - const risonDsl = rison.encode(dsl); const mvtUrlServicePath = getHttp().basePath.prepend( `/${GIS_API_PATH}/${MVT_GETGRIDTILE_API_PATH}` ); - console.log('mv', mvtUrlServicePath); - const urlTemplate = `${mvtUrlServicePath}?x={x}&y={y}&z={z}&geometryFieldName=${this._descriptor.geoField}&index=${indexPattern.title}&requestBody=${risonDsl}`; return { layerName: this.getLayerName(), diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js index e2de17fe31d5ba..9a3b747906c5b2 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js @@ -75,7 +75,7 @@ export class UpdateSourceEditor extends Component { } } else if (this.props.currentLayerType === LAYER_TYPE.HEATMAP) { if (resolution === GRID_RESOLUTION.SUPER_FINE) { - throw new Error('NOT SUPPORTED!!'); + throw new Error('Heatmap does not support SUPER_FINE resolution'); } else { newLayerType = LAYER_TYPE.HEATMAP; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js index d51ca46fd98fff..264c5c8f8405b5 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js @@ -18,7 +18,7 @@ import uuid from 'uuid/v4'; import { copyPersistentState } from '../../../reducers/util'; import { DataRequestAbortError } from '../../util/data_request'; -import { expandToTileBoundaries } from '../es_geo_grid_source/geo_tile_utils'; +import { expandToTileBoundaries } from '../../../../common/geo_tile_utils'; import { search } from '../../../../../../../src/plugins/data/public'; export class AbstractESSource extends AbstractVectorSource { diff --git a/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts b/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts index 329a2a6fc64fb1..b064db578740d1 100644 --- a/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts +++ b/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; -import { IndexPattern, IFieldType } from '../../../../../../src/plugins/data/public'; +import { IndexPattern, IFieldType } from '../../../../../../src/plugins/data/common'; import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; export function getField(indexPattern: IndexPattern, fieldName: string) { From 3f42ffe8e505204c9f16b0f3e70dd527974a1e55 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 7 Sep 2020 23:24:30 -0400 Subject: [PATCH 06/46] move more files --- .../{public/classes/util => common}/es_agg_utils.test.ts | 0 .../maps/{public/classes/util => common}/es_agg_utils.ts | 0 x-pack/plugins/maps/public/classes/fields/es_agg_field.ts | 2 +- .../sources/es_geo_grid_source/convert_to_geojson.js | 2 +- .../classes/sources/es_pew_pew_source/convert_to_lines.js | 2 +- .../classes/sources/es_search_source/es_search_source.js | 2 +- .../public/classes/sources/es_term_source/es_term_source.js | 6 +++++- 7 files changed, 9 insertions(+), 5 deletions(-) rename x-pack/plugins/maps/{public/classes/util => common}/es_agg_utils.test.ts (100%) rename x-pack/plugins/maps/{public/classes/util => common}/es_agg_utils.ts (100%) diff --git a/x-pack/plugins/maps/public/classes/util/es_agg_utils.test.ts b/x-pack/plugins/maps/common/es_agg_utils.test.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/util/es_agg_utils.test.ts rename to x-pack/plugins/maps/common/es_agg_utils.test.ts diff --git a/x-pack/plugins/maps/public/classes/util/es_agg_utils.ts b/x-pack/plugins/maps/common/es_agg_utils.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/util/es_agg_utils.ts rename to x-pack/plugins/maps/common/es_agg_utils.ts diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 7b184819b839b4..8e47c8e5a9e1dd 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -12,7 +12,7 @@ import { IVectorSource } from '../sources/vector_source'; import { ESDocField } from './es_doc_field'; import { AGG_TYPE, FIELD_ORIGIN } from '../../../common/constants'; import { isMetricCountable } from '../util/is_metric_countable'; -import { getField, addFieldToDSL } from '../util/es_agg_utils'; +import { getField, addFieldToDSL } from '../../../common/es_agg_utils'; import { TopTermPercentageField } from './top_term_percentage_field'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { ESAggTooltipProperty } from '../tooltips/es_agg_tooltip_property'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js index 8ac2a79942c6e5..97e08445eb742a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js @@ -11,7 +11,7 @@ import { GEOCENTROID_AGG_NAME, } from '../../../../common/constants'; import { getTileBoundingBox } from '../../../../common/geo_tile_utils'; -import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; +import { extractPropertiesFromBucket } from '../../../../common/es_agg_utils'; import { clamp } from '../../../../common/elasticsearch_geo_utils'; const GRID_BUCKET_KEYS_TO_IGNORE = ['key', GEOCENTROID_AGG_NAME]; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js index 96a7f50cdf523a..b9081db3964744 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import { extractPropertiesFromBucket } from '../../util/es_agg_utils'; +import { extractPropertiesFromBucket } from '../../../../common/es_agg_utils'; const LAT_INDEX = 0; const LON_INDEX = 1; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js index 7ac2738eaeb51f..e6ed56790f4bb8 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js @@ -31,7 +31,7 @@ import uuid from 'uuid/v4'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { ESDocField } from '../../fields/es_doc_field'; -import { getField, addFieldToDSL } from '../../util/es_agg_utils'; +import { getField, addFieldToDSL } from '../../../../common/es_agg_utils'; import { registerSource } from '../source_registry'; export const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', { diff --git a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js index 8cc8dd5c4a0809..6b18ae4d4ab349 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js @@ -16,7 +16,11 @@ import { import { getJoinAggKey } from '../../../../common/get_agg_key'; import { ESDocField } from '../../fields/es_doc_field'; import { AbstractESAggSource } from '../es_agg_source'; -import { getField, addFieldToDSL, extractPropertiesFromBucket } from '../../util/es_agg_utils'; +import { + getField, + addFieldToDSL, + extractPropertiesFromBucket, +} from '../../../../common/es_agg_utils'; const TERMS_AGG_NAME = 'join'; From 46e162a096e97fe9aa6851daf1a41ba7b32052a9 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 7 Sep 2020 23:32:17 -0400 Subject: [PATCH 07/46] move more utils --- .../convert_to_geojson.js | 12 ++++-------- .../convert_to_geojson.test.ts | 0 x-pack/plugins/maps/common/es_agg_utils.ts | 2 +- .../sources/es_geo_grid_source/es_geo_grid_source.js | 5 ++++- 4 files changed, 9 insertions(+), 10 deletions(-) rename x-pack/plugins/maps/{public/classes/sources/es_geo_grid_source => common}/convert_to_geojson.js (87%) rename x-pack/plugins/maps/{public/classes/sources/es_geo_grid_source => common}/convert_to_geojson.test.ts (100%) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js b/x-pack/plugins/maps/common/convert_to_geojson.js similarity index 87% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js rename to x-pack/plugins/maps/common/convert_to_geojson.js index 97e08445eb742a..86b51d4f2925f9 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.js +++ b/x-pack/plugins/maps/common/convert_to_geojson.js @@ -5,14 +5,10 @@ */ import _ from 'lodash'; -import { - RENDER_AS, - GEOTILE_GRID_AGG_NAME, - GEOCENTROID_AGG_NAME, -} from '../../../../common/constants'; -import { getTileBoundingBox } from '../../../../common/geo_tile_utils'; -import { extractPropertiesFromBucket } from '../../../../common/es_agg_utils'; -import { clamp } from '../../../../common/elasticsearch_geo_utils'; +import { RENDER_AS, GEOTILE_GRID_AGG_NAME, GEOCENTROID_AGG_NAME } from './constants'; +import { getTileBoundingBox } from './geo_tile_utils'; +import { extractPropertiesFromBucket } from './es_agg_utils'; +import { clamp } from './elasticsearch_geo_utils'; const GRID_BUCKET_KEYS_TO_IGNORE = ['key', GEOCENTROID_AGG_NAME]; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.test.ts b/x-pack/plugins/maps/common/convert_to_geojson.test.ts similarity index 100% rename from x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/convert_to_geojson.test.ts rename to x-pack/plugins/maps/common/convert_to_geojson.test.ts diff --git a/x-pack/plugins/maps/common/es_agg_utils.ts b/x-pack/plugins/maps/common/es_agg_utils.ts index b064db578740d1..fbf9f8fd64339b 100644 --- a/x-pack/plugins/maps/common/es_agg_utils.ts +++ b/x-pack/plugins/maps/common/es_agg_utils.ts @@ -6,7 +6,7 @@ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; import { IndexPattern, IFieldType } from '../../../../../../src/plugins/data/common'; -import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; +import { TOP_TERM_PERCENTAGE_SUFFIX } from './constants'; export function getField(indexPattern: IndexPattern, fieldName: string) { const field = indexPattern.fields.getByName(fieldName); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 4451ec20e6a4af..a20dff8427ee89 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -7,7 +7,10 @@ import React from 'react'; import uuid from 'uuid/v4'; -import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; +import { + convertCompositeRespToGeoJson, + convertRegularRespToGeoJson, +} from '../../../../common/convert_to_geojson'; import { UpdateSourceEditor } from './update_source_editor'; import { SOURCE_TYPES, From 3a679829f5f4e23c3f259179f1e07710df5e84e5 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 7 Sep 2020 23:46:03 -0400 Subject: [PATCH 08/46] reuse existing implementation --- x-pack/plugins/maps/server/mvt/get_tile.ts | 47 +++------------------- 1 file changed, 6 insertions(+), 41 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 8fc76515c727aa..bc99fa7f023388 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -18,12 +18,16 @@ import { KBN_TOO_MANY_FEATURES_PROPERTY, MAX_ZOOM, MVT_SOURCE_LAYER_NAME, + RENDER_AS, SUPER_FINE_ZOOM_DELTA, } from '../../common/constants'; import { hitsToGeoJson } from '../../common/elasticsearch_geo_utils'; import { flattenHit } from './util'; +// @ts-expect-error +import { convertRegularRespToGeoJson } from '../../common/convert_to_geojson'; + interface ESBounds { top_left: { lon: number; @@ -85,48 +89,9 @@ export async function getGridTile({ const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); - // logger.warn(JSON.stringify(gridAggResult, null, '\t')); - - // todo: pass iun aggnames - const aggNames = ['doc_count']; - const ffeats = []; - gridAggResult.aggregations[GEOTILE_GRID_AGG_NAME].buckets.forEach((bucket) => { - const feature = { - type: 'Feature', - properties: {}, - geometry: null, - }; - - for (let i = 0; i < aggNames.length; i++) { - const aggName = aggNames[i]; - if (aggName === 'doc_count') { - feature.properties[aggName] = bucket[aggName]; - feature.properties.count = bucket[aggName]; - } else if (aggName === GEOCENTROID_AGG_NAME) { - // do nothing - } else { - feature.properties[aggName] = bucket[aggName].value; - } - } - - feature.properties[KBN_TOO_MANY_FEATURES_PROPERTY] = false; - - // Todo: needs to differentiate output between clusters and grids - const centroid = { - type: 'Point', - coordinates: [ - parseFloat(bucket[GEOCENTROID_AGG_NAME].location.lon), - parseFloat(bucket[GEOCENTROID_AGG_NAME].location.lat), - ], - }; - - feature.geometry = centroid; - - ffeats.push(feature); - }); - + const features = convertRegularRespToGeoJson(gridAggResult, RENDER_AS.POINT); const featureCollection = { - features: ffeats, + features, type: 'FeatureCollection', }; From 0df9b29ea295cf899e6855d47307c0bcf3ebc1d8 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 00:17:24 -0400 Subject: [PATCH 09/46] fix autodomain --- .../maps/public/classes/fields/es_agg_field.ts | 11 ++++++++--- .../tiled_vector_layer/tiled_vector_layer.tsx | 3 --- .../sources/es_agg_source/es_agg_source.d.ts | 10 +++++++--- .../classes/sources/es_agg_source/es_agg_source.js | 13 +++++++++---- .../es_geo_grid_source/es_geo_grid_source.d.ts | 8 +++++++- .../es_geo_grid_source/es_geo_grid_source.js | 8 ++++++++ x-pack/plugins/maps/server/mvt/get_tile.ts | 4 ++-- 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 8e47c8e5a9e1dd..f08be35e790099 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -30,6 +30,7 @@ export class ESAggField implements IESAggField { private readonly _label?: string; private readonly _aggType: AGG_TYPE; private readonly _esDocField?: IField | undefined; + private readonly _canReadFromGeoJson: boolean; constructor({ label, @@ -37,6 +38,7 @@ export class ESAggField implements IESAggField { aggType, esDocField, origin, + canReadFromGeoJson = true, }: { label?: string; source: IESAggSource; @@ -49,6 +51,7 @@ export class ESAggField implements IESAggField { this._label = label; this._aggType = aggType; this._esDocField = esDocField; + this._canReadFromGeoJson = canReadFromGeoJson; } getSource(): IVectorSource { @@ -132,18 +135,19 @@ export class ESAggField implements IESAggField { } supportsAutoDomain(): boolean { - return true; + return this._canReadFromGeoJson ? true : this.supportsFieldMeta(); } canReadFromGeoJson(): boolean { - return true; + return this._canReadFromGeoJson; } } export function esAggFieldsFactory( aggDescriptor: AggDescriptor, source: IESAggSource, - origin: FIELD_ORIGIN + origin: FIELD_ORIGIN, + canReadFromGeoJson?: boolean = true ): IESAggField[] { const aggField = new ESAggField({ label: aggDescriptor.label, @@ -153,6 +157,7 @@ export function esAggFieldsFactory( aggType: aggDescriptor.type, source, origin, + canReadFromGeoJson, }); const aggFields: IESAggField[] = [aggField]; diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index 36f4571c17fb63..47184d13359ddc 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -68,8 +68,6 @@ export class TiledVectorLayer extends VectorLayer { const data: MVTSingleLayerVectorSourceConfig = prevDataRequest.getData() as MVTSingleLayerVectorSourceConfig; if (data) { - // console.log('urlT', { existing: data.urlTemplate, new: templateWithMeta.urlTemplate }); - const canSkipBecauseNoChanges = data.layerName === this._source.getLayerName() && data.minSourceZoom === this._source.getMinZoom() && @@ -77,7 +75,6 @@ export class TiledVectorLayer extends VectorLayer { data.urlTemplate === templateWithMeta.urlTemplate; if (canSkipBecauseNoChanges) { - // console.loog('CAN SKIP!!~!'); return null; } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts index eb50cd7528c8b2..1f9685f7eaa255 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts @@ -13,17 +13,21 @@ import { AbstractESAggSourceDescriptor } from '../../../../common/descriptor_typ export interface IESAggSource extends IESSource { getAggKey(aggType: AGG_TYPE, fieldName: string): string; getAggLabel(aggType: AGG_TYPE, fieldName: string): string; - getMetricFields(): IESAggField[]; + getMetricFields(canReadFromGeoJson?: boolean): IESAggField[]; hasMatchingMetricField(fieldName: string): boolean; getMetricFieldForName(fieldName: string): IESAggField | null; } export class AbstractESAggSource extends AbstractESSource implements IESAggSource { - constructor(sourceDescriptor: AbstractESAggSourceDescriptor, inspectorAdapters: object); + constructor( + sourceDescriptor: AbstractESAggSourceDescriptor, + inspectorAdapters: object, + canReadFromGeoJson? + ); getAggKey(aggType: AGG_TYPE, fieldName: string): string; getAggLabel(aggType: AGG_TYPE, fieldName: string): string; - getMetricFields(): IESAggField[]; + getMetricFields(canReadFromGeoJson?: boolean): IESAggField[]; hasMatchingMetricField(fieldName: string): boolean; getMetricFieldForName(fieldName: string): IESAggField | null; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.js b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.js index e20c509ccd4a29..7563a0fa1ec1c8 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.js @@ -13,13 +13,13 @@ import { getSourceAggKey } from '../../../../common/get_agg_key'; export const DEFAULT_METRIC = { type: AGG_TYPE.COUNT }; export class AbstractESAggSource extends AbstractESSource { - constructor(descriptor, inspectorAdapters) { + constructor(descriptor, inspectorAdapters, canReadFromGeoJson = true) { super(descriptor, inspectorAdapters); this._metricFields = []; if (this._descriptor.metrics) { this._descriptor.metrics.forEach((aggDescriptor) => { this._metricFields.push( - ...esAggFieldsFactory(aggDescriptor, this, this.getOriginForField()) + ...esAggFieldsFactory(aggDescriptor, this, this.getOriginForField(), canReadFromGeoJson) ); }); } @@ -48,11 +48,16 @@ export class AbstractESAggSource extends AbstractESSource { return FIELD_ORIGIN.SOURCE; } - getMetricFields() { + getMetricFields(canReadFromGeoJson = true) { const metrics = this._metricFields.filter((esAggField) => esAggField.isValid()); // Handle case where metrics is empty because older saved object state is empty array or there are no valid aggs. return metrics.length === 0 - ? esAggFieldsFactory({ type: AGG_TYPE.COUNT }, this, this.getOriginForField()) + ? esAggFieldsFactory( + { type: AGG_TYPE.COUNT }, + this, + this.getOriginForField(), + canReadFromGeoJson + ) : metrics; } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 0c85cdadf552e0..89ba27a8644a48 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -5,7 +5,11 @@ */ import { AbstractESAggSource } from '../es_agg_source'; -import { ESGeoGridSourceDescriptor } from '../../../../common/descriptor_types'; +import { + ESGeoGridSourceDescriptor, + MapFilters, + MapQuery, +} from '../../../../common/descriptor_types'; import { GRID_RESOLUTION } from '../../../../common/constants'; import { ITiledSingleLayerVectorSource } from '../vector_source'; @@ -19,6 +23,8 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); + private readonly _descriptor: ESGeoGridSourceDescriptor; + getFieldNames(): string[]; getGridResolution(): GRID_RESOLUTION; getGeoGridPrecision(zoom: number): number; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index a20dff8427ee89..409b0385086999 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -58,6 +58,10 @@ export class ESGeoGridSource extends AbstractESAggSource { }; } + constructor(descriptor, inspectorAdapters) { + super(descriptor, inspectorAdapters, descriptor.resolution !== GRID_RESOLUTION.SUPER_FINE); + } + renderSourceSettingsEditor({ onChange, currentLayerType }) { return ( esAggMetricField.getName()); } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index bc99fa7f023388..693341279a33ba 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -13,7 +13,6 @@ import { Feature, FeatureCollection, Polygon } from 'geojson'; import { ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, - GEOCENTROID_AGG_NAME, GEOTILE_GRID_AGG_NAME, KBN_TOO_MANY_FEATURES_PROPERTY, MAX_ZOOM, @@ -61,7 +60,6 @@ export async function getGridTile({ logger.warn('getGridTile not implemented'); const esBbox = tileToESBbox(x, y, z); - const geojsonPolyhon = tileToGeoJsonPolygon(x, y, z); try { let result; @@ -95,6 +93,8 @@ export async function getGridTile({ type: 'FeatureCollection', }; + logger.warn(`first featyreL ${JSON.stringify(featureCollection.features[0], null, '\t')}`); + const tileIndex = geojsonvt(featureCollection, { maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 tolerance: 3, // simplification tolerance (higher means simpler) From b1aa69226cb2ee2d7dc7b3019fa0e956a3721494 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 00:35:24 -0400 Subject: [PATCH 10/46] minor fixes --- x-pack/plugins/maps/public/classes/fields/es_agg_field.ts | 4 ++-- .../public/classes/fields/top_term_percentage_field.ts | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index f08be35e790099..d2ee9fea5cf134 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -135,7 +135,7 @@ export class ESAggField implements IESAggField { } supportsAutoDomain(): boolean { - return this._canReadFromGeoJson ? true : this.supportsFieldMeta(); + return this._canReadFromGeoJson; } canReadFromGeoJson(): boolean { @@ -163,7 +163,7 @@ export function esAggFieldsFactory( const aggFields: IESAggField[] = [aggField]; if (aggDescriptor.field && aggDescriptor.type === AGG_TYPE.TERMS) { - aggFields.push(new TopTermPercentageField(aggField)); + aggFields.push(new TopTermPercentageField(aggField, canReadFromGeoJson)); } return aggFields; diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index fc931b13619ef3..0aa6613927afb3 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -13,9 +13,11 @@ import { FIELD_ORIGIN } from '../../../common/constants'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; + private readonly _canReadFromGeoJson: boolean; - constructor(topTermAggField: IESAggField) { + constructor(topTermAggField: IESAggField, canReadFromGeoJson?: boolean = true) { this._topTermAggField = topTermAggField; + this._canReadFromGeoJson = canReadFromGeoJson; } getSource(): IVectorSource { @@ -61,7 +63,7 @@ export class TopTermPercentageField implements IESAggField { } supportsAutoDomain(): boolean { - return true; + return this._canReadFromGeoJson; } supportsFieldMeta(): boolean { @@ -81,6 +83,6 @@ export class TopTermPercentageField implements IESAggField { } canReadFromGeoJson(): boolean { - return true; + return this._canReadFromGeoJson; } } From 2d84c57bb22db819b099d66f299e0a32989d843c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 00:38:31 -0400 Subject: [PATCH 11/46] undo typo --- x-pack/plugins/maps/public/classes/fields/es_agg_field.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index d2ee9fea5cf134..c1d3982165f428 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -135,7 +135,7 @@ export class ESAggField implements IESAggField { } supportsAutoDomain(): boolean { - return this._canReadFromGeoJson; + return this._canReadFromGeoJson ? true : this.supportsFieldMeta(); } canReadFromGeoJson(): boolean { From 9bb547f7a635409508214603568a8ab474dbd0fa Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 00:43:44 -0400 Subject: [PATCH 12/46] enable grids --- .../classes/sources/es_geo_grid_source/es_geo_grid_source.js | 2 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 4 +++- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 2 ++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 409b0385086999..e36306eabb471a 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -381,7 +381,7 @@ export class ESGeoGridSource extends AbstractESAggSource { `/${GIS_API_PATH}/${MVT_GETGRIDTILE_API_PATH}` ); - const urlTemplate = `${mvtUrlServicePath}?x={x}&y={y}&z={z}&geometryFieldName=${this._descriptor.geoField}&index=${indexPattern.title}&requestBody=${risonDsl}`; + const urlTemplate = `${mvtUrlServicePath}?x={x}&y={y}&z={z}&geometryFieldName=${this._descriptor.geoField}&index=${indexPattern.title}&requestBody=${risonDsl}&requestType=${this._descriptor.requestType}`; return { layerName: this.getLayerName(), minSourceZoom: this.getMinZoom(), diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 693341279a33ba..b8e051351fb028 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -47,6 +47,7 @@ export async function getGridTile({ y, z, requestBody = {}, + requestType = RENDER_AS.POINT, }: { x: number; y: number; @@ -56,6 +57,7 @@ export async function getGridTile({ callElasticsearch: (type: string, ...args: any[]) => Promise; logger: Logger; requestBody: any; + requestType: RENDER_AS; }): Promise { logger.warn('getGridTile not implemented'); @@ -87,7 +89,7 @@ export async function getGridTile({ const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); - const features = convertRegularRespToGeoJson(gridAggResult, RENDER_AS.POINT); + const features = convertRegularRespToGeoJson(gridAggResult, requestType); const featureCollection = { features, type: 'FeatureCollection', diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index c269ddc9900e25..4639bca05c0724 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -86,6 +86,7 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou geometryFieldName: schema.string(), requestBody: schema.string(), index: schema.string(), + requestType: schema.string(), }), }, }, @@ -107,6 +108,7 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou z: query.z, index: query.index, requestBody: requestBodyDSL, + requestType: query.requestType, }); if (tile) { From a63d8a74d3378ca460fb9affcfd1ede720f99284 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 09:44:12 -0400 Subject: [PATCH 13/46] add shape support --- .../es_geo_grid_source/es_geo_grid_source.js | 3 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 37 ++++++++++++------- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 2 + 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index e36306eabb471a..42a0a3a260f38b 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -381,7 +381,8 @@ export class ESGeoGridSource extends AbstractESAggSource { `/${GIS_API_PATH}/${MVT_GETGRIDTILE_API_PATH}` ); - const urlTemplate = `${mvtUrlServicePath}?x={x}&y={y}&z={z}&geometryFieldName=${this._descriptor.geoField}&index=${indexPattern.title}&requestBody=${risonDsl}&requestType=${this._descriptor.requestType}`; + const geoField = await this._getGeoField(); + const urlTemplate = `${mvtUrlServicePath}?x={x}&y={y}&z={z}&geometryFieldName=${this._descriptor.geoField}&index=${indexPattern.title}&requestBody=${risonDsl}&requestType=${this._descriptor.requestType}&geoFieldType=${geoField.type}`; return { layerName: this.getLayerName(), minSourceZoom: this.getMinZoom(), diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index b8e051351fb028..95f4be0a86427a 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -23,7 +23,6 @@ import { import { hitsToGeoJson } from '../../common/elasticsearch_geo_utils'; import { flattenHit } from './util'; - // @ts-expect-error import { convertRegularRespToGeoJson } from '../../common/convert_to_geojson'; @@ -48,6 +47,7 @@ export async function getGridTile({ z, requestBody = {}, requestType = RENDER_AS.POINT, + geoFieldType = ES_GEO_FIELD_TYPE.GEO_POINT, }: { x: number; y: number; @@ -58,24 +58,37 @@ export async function getGridTile({ logger: Logger; requestBody: any; requestType: RENDER_AS; + geoFieldType: ES_GEO_FIELD_TYPE; }): Promise { logger.warn('getGridTile not implemented'); const esBbox = tileToESBbox(x, y, z); - try { - let result; try { // todo: needs to be different from geo_point and geo_shape - const geoBoundingBox = { - geo_bounding_box: { - [geometryFieldName]: esBbox, - }, - }; - requestBody.query.bool.filter.push(geoBoundingBox); + let bboxFilter; + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { + bboxFilter = { + geo_bounding_box: { + [geometryFieldName]: esBbox, + }, + }; + } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { + const geojsonPolygon = tileToGeoJsonPolygon(x, y, z); + bboxFilter = { + geo_shape: { + [geometryFieldName]: { + shape: geojsonPolygon, + relation: 'INTERSECTS', + }, + }, + }; + } else { + throw new Error(`${geoFieldType} is not valid geo field-type`); + } + requestBody.query.bool.filter.push(bboxFilter); const targetPrecision = Math.min(z + SUPER_FINE_ZOOM_DELTA, MAX_ZOOM); - logger.warn(`z ${z} -> targetPrecision ${targetPrecision}`); requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = targetPrecision; requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; @@ -85,8 +98,6 @@ export async function getGridTile({ body: requestBody, }; - logger.warn(JSON.stringify(esGeotileGridQuery)); - const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); const features = convertRegularRespToGeoJson(gridAggResult, requestType); @@ -95,8 +106,6 @@ export async function getGridTile({ type: 'FeatureCollection', }; - logger.warn(`first featyreL ${JSON.stringify(featureCollection.features[0], null, '\t')}`); - const tileIndex = geojsonvt(featureCollection, { maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 tolerance: 3, // simplification tolerance (higher means simpler) diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 4639bca05c0724..8a9745d5b3697f 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -87,6 +87,7 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou requestBody: schema.string(), index: schema.string(), requestType: schema.string(), + geoFieldType: schema.string(), }), }, }, @@ -109,6 +110,7 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou index: query.index, requestBody: requestBodyDSL, requestType: query.requestType, + geoFieldType: query.geoFieldType, }); if (tile) { From 2342a3569cc6d3ac22f2606ed0cb7a08aa3b3cdc Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 16:05:04 -0400 Subject: [PATCH 14/46] create util folder --- .../{ => elasticsearch_util}/convert_to_geojson.js | 4 ++-- .../{ => elasticsearch_util}/convert_to_geojson.test.ts | 4 +--- .../elasticsearch_geo_utils.d.ts | 4 ++-- .../{ => elasticsearch_util}/elasticsearch_geo_utils.js | 6 +++--- .../elasticsearch_geo_utils.test.js | 0 .../common/{ => elasticsearch_util}/es_agg_utils.test.ts | 0 .../maps/common/{ => elasticsearch_util}/es_agg_utils.ts | 4 ++-- x-pack/plugins/maps/common/elasticsearch_util/index.ts | 9 +++++++++ x-pack/plugins/maps/common/geo_tile_utils.js | 2 +- .../plugins/maps/public/actions/data_request_actions.ts | 2 +- x-pack/plugins/maps/public/actions/map_actions.ts | 2 +- .../plugins/maps/public/classes/fields/es_agg_field.ts | 2 +- .../sources/es_geo_grid_source/es_geo_grid_source.js | 5 +++-- .../sources/es_pew_pew_source/convert_to_lines.js | 2 +- .../sources/es_pew_pew_source/es_pew_pew_source.js | 2 +- .../classes/sources/es_search_source/es_search_source.js | 4 ++-- .../maps/public/classes/sources/es_source/es_source.js | 2 +- .../classes/sources/es_term_source/es_term_source.js | 2 +- .../map/features_tooltip/feature_geometry_filter_form.js | 2 +- .../map/mb/draw_control/draw_control.js | 2 +- .../maps/public/connected_components/map/mb/view.js | 2 +- x-pack/plugins/maps/public/selectors/map_selectors.ts | 2 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 4 ++-- 23 files changed, 38 insertions(+), 30 deletions(-) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/convert_to_geojson.js (96%) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/convert_to_geojson.test.ts (97%) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/elasticsearch_geo_utils.d.ts (89%) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/elasticsearch_geo_utils.js (98%) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/elasticsearch_geo_utils.test.js (100%) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/es_agg_utils.test.ts (100%) rename x-pack/plugins/maps/common/{ => elasticsearch_util}/es_agg_utils.ts (93%) create mode 100644 x-pack/plugins/maps/common/elasticsearch_util/index.ts diff --git a/x-pack/plugins/maps/common/convert_to_geojson.js b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.js similarity index 96% rename from x-pack/plugins/maps/common/convert_to_geojson.js rename to x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.js index 86b51d4f2925f9..a8f32bb4e7f5da 100644 --- a/x-pack/plugins/maps/common/convert_to_geojson.js +++ b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.js @@ -5,8 +5,8 @@ */ import _ from 'lodash'; -import { RENDER_AS, GEOTILE_GRID_AGG_NAME, GEOCENTROID_AGG_NAME } from './constants'; -import { getTileBoundingBox } from './geo_tile_utils'; +import { RENDER_AS, GEOTILE_GRID_AGG_NAME, GEOCENTROID_AGG_NAME } from '../constants'; +import { getTileBoundingBox } from '../geo_tile_utils'; import { extractPropertiesFromBucket } from './es_agg_utils'; import { clamp } from './elasticsearch_geo_utils'; diff --git a/x-pack/plugins/maps/common/convert_to_geojson.test.ts b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.test.ts similarity index 97% rename from x-pack/plugins/maps/common/convert_to_geojson.test.ts rename to x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.test.ts index 523cc869150108..ee40a1f2fc7513 100644 --- a/x-pack/plugins/maps/common/convert_to_geojson.test.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.test.ts @@ -4,11 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../kibana_services', () => {}); - // @ts-ignore import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; -import { RENDER_AS } from '../../../../common/constants'; +import { RENDER_AS } from '../constants'; describe('convertCompositeRespToGeoJson', () => { const esResponse = { diff --git a/x-pack/plugins/maps/common/elasticsearch_geo_utils.d.ts b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts similarity index 89% rename from x-pack/plugins/maps/common/elasticsearch_geo_utils.d.ts rename to x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts index e57efca94d95e7..cff8ba119e1de2 100644 --- a/x-pack/plugins/maps/common/elasticsearch_geo_utils.d.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.d.ts @@ -5,8 +5,8 @@ */ import { FeatureCollection, GeoJsonProperties } from 'geojson'; -import { MapExtent } from './descriptor_types'; -import { ES_GEO_FIELD_TYPE } from './constants'; +import { MapExtent } from '../descriptor_types'; +import { ES_GEO_FIELD_TYPE } from '../constants'; export function scaleBounds(bounds: MapExtent, scaleFactor: number): MapExtent; diff --git a/x-pack/plugins/maps/common/elasticsearch_geo_utils.js b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js similarity index 98% rename from x-pack/plugins/maps/common/elasticsearch_geo_utils.js rename to x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js index f2bf83ae18bb0d..be214e3b01e67b 100644 --- a/x-pack/plugins/maps/common/elasticsearch_geo_utils.js +++ b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.js @@ -15,9 +15,9 @@ import { POLYGON_COORDINATES_EXTERIOR_INDEX, LON_INDEX, LAT_INDEX, -} from '../common/constants'; -import { getEsSpatialRelationLabel } from './i18n_getters'; -import { FILTERS } from '../../../../src/plugins/data/common'; +} from '../constants'; +import { getEsSpatialRelationLabel } from '../i18n_getters'; +import { FILTERS } from '../../../../../src/plugins/data/common'; import turfCircle from '@turf/circle'; const SPATIAL_FILTER_TYPE = FILTERS.SPATIAL_FILTER; diff --git a/x-pack/plugins/maps/common/elasticsearch_geo_utils.test.js b/x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js similarity index 100% rename from x-pack/plugins/maps/common/elasticsearch_geo_utils.test.js rename to x-pack/plugins/maps/common/elasticsearch_util/elasticsearch_geo_utils.test.js diff --git a/x-pack/plugins/maps/common/es_agg_utils.test.ts b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.test.ts similarity index 100% rename from x-pack/plugins/maps/common/es_agg_utils.test.ts rename to x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.test.ts diff --git a/x-pack/plugins/maps/common/es_agg_utils.ts b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts similarity index 93% rename from x-pack/plugins/maps/common/es_agg_utils.ts rename to x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts index fbf9f8fd64339b..7828c3cc6410b5 100644 --- a/x-pack/plugins/maps/common/es_agg_utils.ts +++ b/x-pack/plugins/maps/common/elasticsearch_util/es_agg_utils.ts @@ -5,8 +5,8 @@ */ import { i18n } from '@kbn/i18n'; import _ from 'lodash'; -import { IndexPattern, IFieldType } from '../../../../../../src/plugins/data/common'; -import { TOP_TERM_PERCENTAGE_SUFFIX } from './constants'; +import { IndexPattern, IFieldType } from '../../../../../src/plugins/data/common'; +import { TOP_TERM_PERCENTAGE_SUFFIX } from '../constants'; export function getField(indexPattern: IndexPattern, fieldName: string) { const field = indexPattern.fields.getByName(fieldName); diff --git a/x-pack/plugins/maps/common/elasticsearch_util/index.ts b/x-pack/plugins/maps/common/elasticsearch_util/index.ts new file mode 100644 index 00000000000000..ffb4a542374fa2 --- /dev/null +++ b/x-pack/plugins/maps/common/elasticsearch_util/index.ts @@ -0,0 +1,9 @@ +/* + * 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 * from './es_agg_utils'; +export * from './convert_to_geojson'; +export * from './elasticsearch_geo_utils'; diff --git a/x-pack/plugins/maps/common/geo_tile_utils.js b/x-pack/plugins/maps/common/geo_tile_utils.js index 798c170f5152fa..7136c709524c72 100644 --- a/x-pack/plugins/maps/common/geo_tile_utils.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.js @@ -6,7 +6,7 @@ import _ from 'lodash'; import { DECIMAL_DEGREES_PRECISION } from './constants'; -import { clampToLatBounds } from './elasticsearch_geo_utils'; +import { clampToLatBounds } from './elasticsearch_util'; const ZOOM_TILE_KEY_INDEX = 0; const X_TILE_KEY_INDEX = 1; diff --git a/x-pack/plugins/maps/public/actions/data_request_actions.ts b/x-pack/plugins/maps/public/actions/data_request_actions.ts index 2876f3d668a69e..14d81969005068 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -40,7 +40,7 @@ import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer/vector_layer'; import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; -import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_geo_utils'; +import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util'; import { IVectorStyle } from '../classes/styles/vector/vector_style'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; diff --git a/x-pack/plugins/maps/public/actions/map_actions.ts b/x-pack/plugins/maps/public/actions/map_actions.ts index b00594cb7fb23f..09491e5c3a7b3e 100644 --- a/x-pack/plugins/maps/public/actions/map_actions.ts +++ b/x-pack/plugins/maps/public/actions/map_actions.ts @@ -54,7 +54,7 @@ import { MapRefreshConfig, } from '../../common/descriptor_types'; import { INITIAL_LOCATION } from '../../common/constants'; -import { scaleBounds } from '../../common/elasticsearch_geo_utils'; +import { scaleBounds } from '../../common/elasticsearch_util'; export function setMapInitError(errorMessage: string) { return { diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index c1d3982165f428..492906096cd1cb 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -12,7 +12,7 @@ import { IVectorSource } from '../sources/vector_source'; import { ESDocField } from './es_doc_field'; import { AGG_TYPE, FIELD_ORIGIN } from '../../../common/constants'; import { isMetricCountable } from '../util/is_metric_countable'; -import { getField, addFieldToDSL } from '../../../common/es_agg_utils'; +import { getField, addFieldToDSL } from '../../../common/elasticsearch_util'; import { TopTermPercentageField } from './top_term_percentage_field'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { ESAggTooltipProperty } from '../tooltips/es_agg_tooltip_property'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 42a0a3a260f38b..4880df0c3ae238 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -10,7 +10,8 @@ import uuid from 'uuid/v4'; import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson, -} from '../../../../common/convert_to_geojson'; + makeESBbox, +} from '../../../../common/elasticsearch_util'; import { UpdateSourceEditor } from './update_source_editor'; import { SOURCE_TYPES, @@ -29,7 +30,7 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { DataRequestAbortError } from '../../util/data_request'; import { registerSource } from '../source_registry'; -import { makeESBbox } from '../../../../common/elasticsearch_geo_utils'; + import rison from 'rison-node'; import { getHttp } from '../../../kibana_services'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js index b9081db3964744..24ac6d31bc6456 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/convert_to_lines.js @@ -5,7 +5,7 @@ */ import _ from 'lodash'; -import { extractPropertiesFromBucket } from '../../../../common/es_agg_utils'; +import { extractPropertiesFromBucket } from '../../../../common/elasticsearch_util'; const LAT_INDEX = 0; const LON_INDEX = 1; diff --git a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js index 92b0c717f67246..d0b773bcca4d6c 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_pew_pew_source/es_pew_pew_source.js @@ -16,7 +16,7 @@ import { getDataSourceLabel } from '../../../../common/i18n_getters'; import { convertToLines } from './convert_to_lines'; import { AbstractESAggSource, DEFAULT_METRIC } from '../es_agg_source'; import { registerSource } from '../source_registry'; -import { turfBboxToBounds } from '../../../../common/elasticsearch_geo_utils'; +import { turfBboxToBounds } from '../../../../common/elasticsearch_util'; import { DataRequestAbortError } from '../../util/data_request'; const MAX_GEOTILE_LEVEL = 29; diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js index e6ed56790f4bb8..699b14455247b5 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.js @@ -10,7 +10,7 @@ import rison from 'rison-node'; import { AbstractESSource } from '../es_source'; import { getSearchService, getHttp } from '../../../kibana_services'; -import { hitsToGeoJson } from '../../../../common/elasticsearch_geo_utils'; +import { hitsToGeoJson, getField, addFieldToDSL } from '../../../../common/elasticsearch_util'; import { UpdateSourceEditor } from './update_source_editor'; import { SOURCE_TYPES, @@ -31,7 +31,7 @@ import uuid from 'uuid/v4'; import { DEFAULT_FILTER_BY_MAP_BOUNDS } from './constants'; import { ESDocField } from '../../fields/es_doc_field'; -import { getField, addFieldToDSL } from '../../../../common/es_agg_utils'; + import { registerSource } from '../source_registry'; export const sourceTitle = i18n.translate('xpack.maps.source.esSearchTitle', { diff --git a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js index 264c5c8f8405b5..ab56ceeab4e771 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_source/es_source.js @@ -11,7 +11,7 @@ import { getTimeFilter, getSearchService, } from '../../../kibana_services'; -import { createExtentFilter } from '../../../../common/elasticsearch_geo_utils'; +import { createExtentFilter } from '../../../../common/elasticsearch_util'; import _ from 'lodash'; import { i18n } from '@kbn/i18n'; import uuid from 'uuid/v4'; diff --git a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js index 6b18ae4d4ab349..d051f20dde9b7b 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_term_source/es_term_source.js @@ -20,7 +20,7 @@ import { getField, addFieldToDSL, extractPropertiesFromBucket, -} from '../../../../common/es_agg_utils'; +} from '../../../../common/elasticsearch_util'; const TERMS_AGG_NAME = 'join'; diff --git a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js index 98267965fd30fb..33a0f1c5bf0884 100644 --- a/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js +++ b/x-pack/plugins/maps/public/connected_components/map/features_tooltip/feature_geometry_filter_form.js @@ -8,7 +8,7 @@ import React, { Component } from 'react'; import { i18n } from '@kbn/i18n'; import { URL_MAX_LENGTH } from '../../../../../../../src/core/public'; -import { createSpatialFilterWithGeometry } from '../../../../common/elasticsearch_geo_utils'; +import { createSpatialFilterWithGeometry } from '../../../../common/elasticsearch_util'; import { GEO_JSON_TYPE } from '../../../../common/constants'; import { GeometryFilterForm } from '../../../components/geometry_filter_form'; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js index 49675ac6a39243..0356a8267c18af 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/draw_control/draw_control.js @@ -15,7 +15,7 @@ import { createSpatialFilterWithGeometry, getBoundingBoxGeometry, roundCoordinates, -} from '../../../../../common/elasticsearch_geo_utils'; +} from '../../../../../common/elasticsearch_util'; import { DrawTooltip } from './draw_tooltip'; const DRAW_RECTANGLE = 'draw_rectangle'; diff --git a/x-pack/plugins/maps/public/connected_components/map/mb/view.js b/x-pack/plugins/maps/public/connected_components/map/mb/view.js index eede1edf40cc4f..ddc48cfc9c329b 100644 --- a/x-pack/plugins/maps/public/connected_components/map/mb/view.js +++ b/x-pack/plugins/maps/public/connected_components/map/mb/view.js @@ -23,7 +23,7 @@ import sprites1 from '@elastic/maki/dist/sprite@1.png'; import sprites2 from '@elastic/maki/dist/sprite@2.png'; import { DrawControl } from './draw_control'; import { TooltipControl } from './tooltip_control'; -import { clampToLatBounds, clampToLonBounds } from '../../../../common/elasticsearch_geo_utils'; +import { clampToLatBounds, clampToLonBounds } from '../../../../common/elasticsearch_util'; import { getInitialView } from './get_initial_view'; import { getPreserveDrawingBuffer } from '../../../kibana_services'; diff --git a/x-pack/plugins/maps/public/selectors/map_selectors.ts b/x-pack/plugins/maps/public/selectors/map_selectors.ts index 03e0f753812c9f..db4371e9cd590f 100644 --- a/x-pack/plugins/maps/public/selectors/map_selectors.ts +++ b/x-pack/plugins/maps/public/selectors/map_selectors.ts @@ -31,7 +31,7 @@ import { SPATIAL_FILTERS_LAYER_ID, } from '../../common/constants'; // @ts-ignore -import { extractFeaturesFromFilters } from '../../common/elasticsearch_geo_utils'; +import { extractFeaturesFromFilters } from '../../common/elasticsearch_util'; import { MapStoreState } from '../reducers/store'; import { DataRequestDescriptor, diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 95f4be0a86427a..47252a0c0ff87d 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -21,10 +21,10 @@ import { SUPER_FINE_ZOOM_DELTA, } from '../../common/constants'; -import { hitsToGeoJson } from '../../common/elasticsearch_geo_utils'; +import { hitsToGeoJson } from '../../common/elasticsearch_util'; import { flattenHit } from './util'; // @ts-expect-error -import { convertRegularRespToGeoJson } from '../../common/convert_to_geojson'; +import { convertRegularRespToGeoJson } from '../../common/elasticsearch_util'; interface ESBounds { top_left: { From b986964276a385111ea9c608db158e4b61012932 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 16:24:39 -0400 Subject: [PATCH 15/46] remove some dupe --- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 82 +++++++------------- 1 file changed, 30 insertions(+), 52 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 8a9745d5b3697f..5928d49076b4ab 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -34,16 +34,11 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }, async (context, request, response) => { const { query } = request; - - const callElasticsearch = async (type: string, ...args: any[]): Promise => { - return await context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); - }; - const requestBodyDSL = rison.decode(query.requestBody); const tile = await getTile({ logger, - callElasticsearch, + callElasticsearch: makeCallElasticsearch(context), geometryFieldName: query.geometryFieldName, x: query.x, y: query.y, @@ -52,26 +47,7 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou requestBody: requestBodyDSL, }); - if (tile) { - return response.ok({ - body: tile, - headers: { - 'content-disposition': 'inline', - 'content-length': `${tile.length}`, - 'Content-Type': 'application/x-protobuf', - 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - }, - }); - } else { - return response.ok({ - headers: { - 'content-disposition': 'inline', - 'content-length': '0', - 'Content-Type': 'application/x-protobuf', - 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - }, - }); - } + return sendResponse(response, tile); } ); @@ -93,16 +69,11 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }, async (context, request, response) => { const { query } = request; - - const callElasticsearch = async (type: string, ...args: any[]): Promise => { - return await context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); - }; - const requestBodyDSL = rison.decode(query.requestBody); const tile = await getGridTile({ logger, - callElasticsearch, + callElasticsearch: makeCallElasticsearch(context), geometryFieldName: query.geometryFieldName, x: query.x, y: query.y, @@ -113,26 +84,33 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou geoFieldType: query.geoFieldType, }); - if (tile) { - return response.ok({ - body: tile, - headers: { - 'content-disposition': 'inline', - 'content-length': `${tile.length}`, - 'Content-Type': 'application/x-protobuf', - 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - }, - }); - } else { - return response.ok({ - headers: { - 'content-disposition': 'inline', - 'content-length': '0', - 'Content-Type': 'application/x-protobuf', - 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, - }, - }); - } + return sendResponse(response, tile); } ); } + +function sendResponse(response, tile) { + const headers = { + 'content-disposition': 'inline', + 'content-length': tile ? `${tile.length}` : 0, + 'Content-Type': 'application/x-protobuf', + 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, + }; + + if (tile) { + return response.ok({ + body: tile, + headers, + }); + } else { + return response.ok({ + headers, + }); + } +} + +function makeCallElasticsearch(context) { + return async (type: string, ...args: any[]): Promise => { + return await context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); + }; +} From 86105f4ff317b5ba0a4863257c8266c884e686b0 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 16:49:59 -0400 Subject: [PATCH 16/46] not done --- x-pack/plugins/maps/server/mvt/get_tile.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 47252a0c0ff87d..4560a7fe311dcc 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -60,8 +60,6 @@ export async function getGridTile({ requestType: RENDER_AS; geoFieldType: ES_GEO_FIELD_TYPE; }): Promise { - logger.warn('getGridTile not implemented'); - const esBbox = tileToESBbox(x, y, z); try { try { From 96930420eb4e4c764cbcbfd26f140129188996c9 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 8 Sep 2020 18:25:30 -0400 Subject: [PATCH 17/46] add new api extension --- .../public/classes/fields/es_agg_field.ts | 13 ++++++++++++ .../maps/public/classes/fields/field.ts | 21 +++++++++++++++++++ .../fields/top_term_percentage_field.ts | 13 ++++++++++++ .../dynamic_orientation_property.ts | 5 +---- .../properties/dynamic_text_property.ts | 4 +--- 5 files changed, 49 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 492906096cd1cb..c534cc3a02f75d 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -16,6 +16,7 @@ import { getField, addFieldToDSL } from '../../../common/elasticsearch_util'; import { TopTermPercentageField } from './top_term_percentage_field'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { ESAggTooltipProperty } from '../tooltips/es_agg_tooltip_property'; +import { getComputedFieldName } from '../styles/vector/style_util'; const TERMS_AGG_SHARD_SIZE = 5; @@ -141,6 +142,18 @@ export class ESAggField implements IESAggField { canReadFromGeoJson(): boolean { return this._canReadFromGeoJson; } + + getMbPropertyNameField(styleName): string { + let targetName; + if (this.canReadFromGeoJson()) { + targetName = this.supportsAutoDomain() + ? getComputedFieldName(styleName, this.getName()) + : this.getName(); + } else { + targetName = this.getName(); + } + return targetName; + } } export function esAggFieldsFactory( diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 2c190d54f02651..c4a85168d1d93b 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -7,6 +7,7 @@ import { FIELD_ORIGIN } from '../../../common/constants'; import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; +import { getComputedFieldName } from '../styles/vector/style_util'; export interface IField { getName(): string; @@ -32,6 +33,14 @@ export interface IField { supportsFieldMeta(): boolean; canReadFromGeoJson(): boolean; + + // Returns the name that should be used for accessing the data from the mb-style rule + // Depending on + // - whether the field is used for labeling, icon-orientation, or other properties (color, size, ...), `feature-state` and or `get` is used + // - whether the field was run through a field-formatter, a new dynamic field is created with the formatted-value + // The combination of both will inform what field-name (e.g. the "raw" field name from the properties, the "computed field-name" for an on-the-fly created property (e.g. for feature-state or field-formatting). + // todo: There is an existing limitation to .mvt backed sources, where the field-formatters are not applied. Here, the raw-data needs to be accessed. + getMbPropertyNameField(styleName: string): string; } export class AbstractField implements IField { @@ -99,4 +108,16 @@ export class AbstractField implements IField { canReadFromGeoJson(): boolean { return true; } + + getMbPropertyNameField(styleName): string { + let targetName; + if (this.canReadFromGeoJson()) { + targetName = this.supportsAutoDomain() + ? getComputedFieldName(styleName, this.getName()) + : this.getName(); + } else { + targetName = this.getName(); + } + return targetName; + } } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index 0aa6613927afb3..4008b3f39fac64 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -10,6 +10,7 @@ import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; +import { getComputedFieldName } from '../styles/vector/style_util'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; @@ -85,4 +86,16 @@ export class TopTermPercentageField implements IESAggField { canReadFromGeoJson(): boolean { return this._canReadFromGeoJson; } + + getMbPropertyNameField(styleName): string { + let targetName; + if (this.canReadFromGeoJson()) { + targetName = this.supportsAutoDomain() + ? getComputedFieldName(styleName, this._field.getName()) + : this.getName(); + } else { + targetName = this._field.getName(); + } + return targetName; + } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts index dd976027a50f2f..d43dc39e3d0cfe 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts @@ -13,10 +13,7 @@ import { OrientationDynamicOptions } from '../../../../../common/descriptor_type export class DynamicOrientationProperty extends DynamicStyleProperty { syncIconRotationWithMb(symbolLayerId: string, mbMap: MbMap) { if (this._field && this._field.isValid()) { - const targetName = this._field.supportsAutoDomain() - ? getComputedFieldName(VECTOR_STYLES.ICON_ORIENTATION, this.getFieldName()) - : this._field.getName(); - // Using property state instead of feature-state because layout properties do not support feature-state + const targetName = this._field.getMbPropertyNameField(); mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', ['coalesce', ['get', targetName], 0]); } else { mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', 0); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts index d55a6e1cfb4441..582b3708092520 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts @@ -14,9 +14,7 @@ export class DynamicTextProperty extends DynamicStyleProperty Date: Wed, 9 Sep 2020 11:46:51 -0400 Subject: [PATCH 18/46] reuse implementation --- .../public/classes/fields/es_agg_field.ts | 15 +++-------- .../maps/public/classes/fields/field.ts | 26 +++++++++++-------- .../fields/top_term_percentage_field.ts | 15 +++-------- .../dynamic_orientation_property.ts | 2 +- .../properties/dynamic_text_property.ts | 2 +- 5 files changed, 23 insertions(+), 37 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index c534cc3a02f75d..2bc9939e9c4e76 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -5,7 +5,7 @@ */ import { IndexPattern } from 'src/plugins/data/public'; -import { IField } from './field'; +import { AbstractField, IField } from './field'; import { AggDescriptor } from '../../../common/descriptor_types'; import { IESAggSource } from '../sources/es_agg_source'; import { IVectorSource } from '../sources/vector_source'; @@ -16,7 +16,6 @@ import { getField, addFieldToDSL } from '../../../common/elasticsearch_util'; import { TopTermPercentageField } from './top_term_percentage_field'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { ESAggTooltipProperty } from '../tooltips/es_agg_tooltip_property'; -import { getComputedFieldName } from '../styles/vector/style_util'; const TERMS_AGG_SHARD_SIZE = 5; @@ -143,16 +142,8 @@ export class ESAggField implements IESAggField { return this._canReadFromGeoJson; } - getMbPropertyNameField(styleName): string { - let targetName; - if (this.canReadFromGeoJson()) { - targetName = this.supportsAutoDomain() - ? getComputedFieldName(styleName, this.getName()) - : this.getName(); - } else { - targetName = this.getName(); - } - return targetName; + getMbPropertyName(styleName): string { + return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index c4a85168d1d93b..0135ccb089cd3e 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -40,10 +40,22 @@ export interface IField { // - whether the field was run through a field-formatter, a new dynamic field is created with the formatted-value // The combination of both will inform what field-name (e.g. the "raw" field name from the properties, the "computed field-name" for an on-the-fly created property (e.g. for feature-state or field-formatting). // todo: There is an existing limitation to .mvt backed sources, where the field-formatters are not applied. Here, the raw-data needs to be accessed. - getMbPropertyNameField(styleName: string): string; + getMbPropertyName(styleName: string): string; } export class AbstractField implements IField { + static getMbPropertyName(field: IField, styleName: string) { + let targetName; + if (field.canReadFromGeoJson()) { + targetName = field.supportsAutoDomain() + ? getComputedFieldName(styleName, field.getName()) + : field.getName(); + } else { + targetName = field.getName(); + } + return targetName; + } + private readonly _fieldName: string; private readonly _origin: FIELD_ORIGIN; @@ -109,15 +121,7 @@ export class AbstractField implements IField { return true; } - getMbPropertyNameField(styleName): string { - let targetName; - if (this.canReadFromGeoJson()) { - targetName = this.supportsAutoDomain() - ? getComputedFieldName(styleName, this.getName()) - : this.getName(); - } else { - targetName = this.getName(); - } - return targetName; + getMbPropertyName(styleName): string { + return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index 4008b3f39fac64..2224d3c6642fa3 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -4,13 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IESAggField } from './es_agg_field'; +import { IESAggField, AbstractField } from './es_agg_field'; import { IVectorSource } from '../sources/vector_source'; // @ts-ignore import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; -import { getComputedFieldName } from '../styles/vector/style_util'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; @@ -87,15 +86,7 @@ export class TopTermPercentageField implements IESAggField { return this._canReadFromGeoJson; } - getMbPropertyNameField(styleName): string { - let targetName; - if (this.canReadFromGeoJson()) { - targetName = this.supportsAutoDomain() - ? getComputedFieldName(styleName, this._field.getName()) - : this.getName(); - } else { - targetName = this._field.getName(); - } - return targetName; + getMbPropertyName(styleName: string): string { + return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts index d43dc39e3d0cfe..2e4e9db0489b5e 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts @@ -13,7 +13,7 @@ import { OrientationDynamicOptions } from '../../../../../common/descriptor_type export class DynamicOrientationProperty extends DynamicStyleProperty { syncIconRotationWithMb(symbolLayerId: string, mbMap: MbMap) { if (this._field && this._field.isValid()) { - const targetName = this._field.getMbPropertyNameField(); + const targetName = this._field.getMbPropertyName(); mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', ['coalesce', ['get', targetName], 0]); } else { mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', 0); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts index 582b3708092520..0a1644bd59778e 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts @@ -14,7 +14,7 @@ export class DynamicTextProperty extends DynamicStyleProperty Date: Wed, 9 Sep 2020 12:11:56 -0400 Subject: [PATCH 19/46] ts fixes --- .../convert_to_geojson.d.ts | 11 +++++++++ .../public/classes/fields/es_agg_field.ts | 5 ++-- .../maps/public/classes/fields/field.ts | 2 +- .../fields/top_term_percentage_field.ts | 5 ++-- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 23 +++++++++++++++---- 5 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts diff --git a/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts new file mode 100644 index 00000000000000..b1c1b181d81300 --- /dev/null +++ b/x-pack/plugins/maps/common/elasticsearch_util/convert_to_geojson.d.ts @@ -0,0 +1,11 @@ +/* + * 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 { Feature } from 'geojson'; +import { RENDER_AS } from '../constants'; + +export function convertCompositeRespToGeoJson(esResponse: any, renderAs: RENDER_AS): Feature[]; +export function convertRegularRespToGeoJson(esResponse: any, renderAs: RENDER_AS): Feature[]; diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 2bc9939e9c4e76..021fdf7c8caabb 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -45,6 +45,7 @@ export class ESAggField implements IESAggField { aggType: AGG_TYPE; esDocField?: IField; origin: FIELD_ORIGIN; + canReadFromGeoJson: boolean; }) { this._source = source; this._origin = origin; @@ -142,7 +143,7 @@ export class ESAggField implements IESAggField { return this._canReadFromGeoJson; } - getMbPropertyName(styleName): string { + getMbPropertyName(styleName: string): string { return AbstractField.getMbPropertyName(this, styleName); } } @@ -151,7 +152,7 @@ export function esAggFieldsFactory( aggDescriptor: AggDescriptor, source: IESAggSource, origin: FIELD_ORIGIN, - canReadFromGeoJson?: boolean = true + canReadFromGeoJson: boolean = true ): IESAggField[] { const aggField = new ESAggField({ label: aggDescriptor.label, diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 0135ccb089cd3e..71442ca7cfdeff 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -121,7 +121,7 @@ export class AbstractField implements IField { return true; } - getMbPropertyName(styleName): string { + getMbPropertyName(styleName: string): string { return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index 2224d3c6642fa3..db3461f7adcd73 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -4,18 +4,19 @@ * you may not use this file except in compliance with the Elastic License. */ -import { IESAggField, AbstractField } from './es_agg_field'; +import { IESAggField } from './es_agg_field'; import { IVectorSource } from '../sources/vector_source'; // @ts-ignore import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; +import { AbstractField } from './field'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; private readonly _canReadFromGeoJson: boolean; - constructor(topTermAggField: IESAggField, canReadFromGeoJson?: boolean = true) { + constructor(topTermAggField: IESAggField, canReadFromGeoJson: boolean = true) { this._topTermAggField = topTermAggField; this._canReadFromGeoJson = canReadFromGeoJson; } diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index 5928d49076b4ab..86436ad7716567 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -6,7 +6,12 @@ import rison from 'rison-node'; import { schema } from '@kbn/config-schema'; -import { Logger } from 'src/core/server'; +import { + KibanaRequest, + KibanaResponseFactory, + Logger, + RequestHandlerContext, +} from 'src/core/server'; import { IRouter } from 'src/core/server'; import { MVT_GETTILE_API_PATH, @@ -17,6 +22,10 @@ import { getGridTile, getTile } from './get_tile'; const CACHE_TIMEOUT = 0; // Todo. determine good value. Unsure about full-implications (e.g. wrt. time-based data). +// context: RequestHandlerContext, +// request: KibanaRequest, +// response: ResponseFactory + export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRouter }) { router.get( { @@ -32,7 +41,11 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }), }, }, - async (context, request, response) => { + async ( + context: RequestHandlerContext, + request: KibanaRequest, + response: KibanaResponseFactory + ) => { const { query } = request; const requestBodyDSL = rison.decode(query.requestBody); @@ -89,7 +102,7 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou ); } -function sendResponse(response, tile) { +function sendResponse(response: KibanaResponseFactory, tile: unknown) { const headers = { 'content-disposition': 'inline', 'content-length': tile ? `${tile.length}` : 0, @@ -109,8 +122,8 @@ function sendResponse(response, tile) { } } -function makeCallElasticsearch(context) { +function makeCallElasticsearch(context: RequestHandlerContext) { return async (type: string, ...args: any[]): Promise => { - return await context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); + return context.core.elasticsearch.legacy.client.callAsCurrentUser(type, ...args); }; } From 9aa20384cd29c5a5bcd1d5b3bd9f4a44489a346d Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 13:33:24 -0400 Subject: [PATCH 20/46] type fixes --- x-pack/plugins/maps/common/constants.ts | 2 - .../maps/public/classes/fields/field.ts | 4 +- .../es_geo_grid_source/resolution_editor.js | 1 + .../dynamic_orientation_property.ts | 4 +- .../properties/dynamic_text_property.ts | 3 +- .../classes/styles/vector/style_util.ts | 6 +-- x-pack/plugins/maps/server/mvt/get_tile.ts | 3 +- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 50 ++++++++++--------- 8 files changed, 35 insertions(+), 38 deletions(-) diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index b611f41a285507..3c6ff5c8433224 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -235,8 +235,6 @@ export enum SCALING_TYPES { MVT = 'MVT', } -export const RGBA_0000 = 'rgba(0,0,0,0)'; - export enum MVT_FIELD_TYPE { STRING = 'String', NUMBER = 'Number', diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 71442ca7cfdeff..b7a52123fb5718 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FIELD_ORIGIN } from '../../../common/constants'; +import {FIELD_ORIGIN, VECTOR_STYLES} from '../../../common/constants'; import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { getComputedFieldName } from '../styles/vector/style_util'; @@ -44,7 +44,7 @@ export interface IField { } export class AbstractField implements IField { - static getMbPropertyName(field: IField, styleName: string) { + static getMbPropertyName(field: IField, styleName: VECTOR_STYLES) { let targetName; if (field.canReadFromGeoJson()) { targetName = field.supportsAutoDomain() diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js index 71133cb25280c7..0b26fb95d10aff 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js @@ -31,6 +31,7 @@ const BASE_OPTIONS = [ ]; export function ResolutionEditor({ resolution, onChange, includeSuperFine }) { + console.log('resoliution editor', resolution, onChange, includeSuperFine); const options = [...BASE_OPTIONS]; if (includeSuperFine) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts index 2e4e9db0489b5e..f6ebab4fdb63fa 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_orientation_property.ts @@ -6,14 +6,12 @@ import { Map as MbMap } from 'mapbox-gl'; import { DynamicStyleProperty } from './dynamic_style_property'; -import { getComputedFieldName } from '../style_util'; -import { VECTOR_STYLES } from '../../../../../common/constants'; import { OrientationDynamicOptions } from '../../../../../common/descriptor_types'; export class DynamicOrientationProperty extends DynamicStyleProperty { syncIconRotationWithMb(symbolLayerId: string, mbMap: MbMap) { if (this._field && this._field.isValid()) { - const targetName = this._field.getMbPropertyName(); + const targetName = this._field.getMbPropertyName(this.getStyleName()); mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', ['coalesce', ['get', targetName], 0]); } else { mbMap.setLayoutProperty(symbolLayerId, 'icon-rotate', 0); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts index 0a1644bd59778e..aa94eeb7424fa6 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_text_property.ts @@ -6,7 +6,6 @@ import { Map as MbMap } from 'mapbox-gl'; import { DynamicStyleProperty } from './dynamic_style_property'; -import { getComputedFieldName } from '../style_util'; import { LabelDynamicOptions } from '../../../../../common/descriptor_types'; export class DynamicTextProperty extends DynamicStyleProperty { @@ -14,7 +13,7 @@ export class DynamicTextProperty extends DynamicStyleProperty, -// response: ResponseFactory - export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRouter }) { router.get( { @@ -43,21 +41,21 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }, async ( context: RequestHandlerContext, - request: KibanaRequest, + request: KibanaRequest, unknown>, response: KibanaResponseFactory ) => { const { query } = request; - const requestBodyDSL = rison.decode(query.requestBody); + const requestBodyDSL = rison.decode(query.requestBody as string); const tile = await getTile({ logger, callElasticsearch: makeCallElasticsearch(context), - geometryFieldName: query.geometryFieldName, - x: query.x, - y: query.y, - z: query.z, - index: query.index, - requestBody: requestBodyDSL, + geometryFieldName: query.geometryFieldName as string, + x: query.x as number, + y: query.y as number, + z: query.z as number, + index: query.index as string, + requestBody: requestBodyDSL as any, }); return sendResponse(response, tile); @@ -80,21 +78,25 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou }), }, }, - async (context, request, response) => { + async ( + context: RequestHandlerContext, + request: KibanaRequest, unknown>, + response: KibanaResponseFactory + ) => { const { query } = request; - const requestBodyDSL = rison.decode(query.requestBody); + const requestBodyDSL = rison.decode(query.requestBody as string); const tile = await getGridTile({ logger, callElasticsearch: makeCallElasticsearch(context), - geometryFieldName: query.geometryFieldName, - x: query.x, - y: query.y, - z: query.z, - index: query.index, - requestBody: requestBodyDSL, - requestType: query.requestType, - geoFieldType: query.geoFieldType, + geometryFieldName: query.geometryFieldName as string, + x: query.x as number, + y: query.y as number, + z: query.z as number, + index: query.index as string, + requestBody: requestBodyDSL as any, + requestType: query.requestType as RENDER_AS, + geoFieldType: query.geoFieldType as ES_GEO_FIELD_TYPE, }); return sendResponse(response, tile); @@ -102,10 +104,10 @@ export function initMVTRoutes({ router, logger }: { logger: Logger; router: IRou ); } -function sendResponse(response: KibanaResponseFactory, tile: unknown) { +function sendResponse(response: KibanaResponseFactory, tile: any) { const headers = { 'content-disposition': 'inline', - 'content-length': tile ? `${tile.length}` : 0, + 'content-length': tile ? `${tile.length}` : `0`, 'Content-Type': 'application/x-protobuf', 'Cache-Control': `max-age=${CACHE_TIMEOUT}`, }; From 9428aa14af2e17c5178c68920a25952d4d5a1f68 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 13:43:36 -0400 Subject: [PATCH 21/46] more type fixes --- x-pack/plugins/maps/public/classes/fields/es_agg_field.ts | 2 +- x-pack/plugins/maps/public/classes/fields/field.ts | 6 +++--- .../public/classes/sources/es_agg_source/es_agg_source.d.ts | 2 +- .../sources/es_geo_grid_source/es_geo_grid_source.d.ts | 1 + x-pack/plugins/maps/public/classes/sources/source.ts | 1 + .../plugins/maps/public/classes/styles/vector/style_util.ts | 2 +- 6 files changed, 8 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 021fdf7c8caabb..d4930fe7a61c55 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -45,7 +45,7 @@ export class ESAggField implements IESAggField { aggType: AGG_TYPE; esDocField?: IField; origin: FIELD_ORIGIN; - canReadFromGeoJson: boolean; + canReadFromGeoJson?: boolean; }) { this._source = source; this._origin = origin; diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index b7a52123fb5718..3b3e22d33976a5 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import {FIELD_ORIGIN, VECTOR_STYLES} from '../../../common/constants'; +import { FIELD_ORIGIN, VECTOR_STYLES } from '../../../common/constants'; import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { getComputedFieldName } from '../styles/vector/style_util'; @@ -40,7 +40,7 @@ export interface IField { // - whether the field was run through a field-formatter, a new dynamic field is created with the formatted-value // The combination of both will inform what field-name (e.g. the "raw" field name from the properties, the "computed field-name" for an on-the-fly created property (e.g. for feature-state or field-formatting). // todo: There is an existing limitation to .mvt backed sources, where the field-formatters are not applied. Here, the raw-data needs to be accessed. - getMbPropertyName(styleName: string): string; + getMbPropertyName(styleName: VECTOR_STYLES): string; } export class AbstractField implements IField { @@ -121,7 +121,7 @@ export class AbstractField implements IField { return true; } - getMbPropertyName(styleName: string): string { + getMbPropertyName(styleName: VECTOR_STYLES): string { return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts index 1f9685f7eaa255..885ecc6bff3274 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.d.ts @@ -22,7 +22,7 @@ export class AbstractESAggSource extends AbstractESSource implements IESAggSourc constructor( sourceDescriptor: AbstractESAggSourceDescriptor, inspectorAdapters: object, - canReadFromGeoJson? + canReadFromGeoJson?: boolean ); getAggKey(aggType: AGG_TYPE, fieldName: string): string; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts index 89ba27a8644a48..f47379d8c5eed9 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -9,6 +9,7 @@ import { ESGeoGridSourceDescriptor, MapFilters, MapQuery, + VectorSourceSyncMeta, } from '../../../../common/descriptor_types'; import { GRID_RESOLUTION } from '../../../../common/constants'; import { ITiledSingleLayerVectorSource } from '../vector_source'; diff --git a/x-pack/plugins/maps/public/classes/sources/source.ts b/x-pack/plugins/maps/public/classes/sources/source.ts index 4a050cc3d7d198..8bf25fe4f298e1 100644 --- a/x-pack/plugins/maps/public/classes/sources/source.ts +++ b/x-pack/plugins/maps/public/classes/sources/source.ts @@ -18,6 +18,7 @@ import { OnSourceChangeArgs } from '../../connected_components/layer_panel/view' export type SourceEditorArgs = { onChange: (...args: OnSourceChangeArgs[]) => void; + currentLayerType?: string; }; export type ImmutableSourceProperty = { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts index 12aeefe260f7e0..49d6ccdeb9316d 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/style_util.ts @@ -5,7 +5,7 @@ */ import { i18n } from '@kbn/i18n'; -import {MB_LOOKUP_FUNCTION, VECTOR_SHAPE_TYPE, VECTOR_STYLES} from '../../../../common/constants'; +import { MB_LOOKUP_FUNCTION, VECTOR_SHAPE_TYPE, VECTOR_STYLES } from '../../../../common/constants'; import { Category } from '../../../../common/descriptor_types'; export function getOtherCategoryLabel() { From 16f26d2297b05f1e2cf439664d61d650b7932cd4 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 13:46:01 -0400 Subject: [PATCH 22/46] more type fixes --- x-pack/plugins/maps/public/classes/fields/es_agg_field.ts | 4 ++-- .../maps/public/classes/fields/top_term_percentage_field.ts | 5 ++--- .../sources/es_geo_grid_source/es_geo_grid_source.d.ts | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index d4930fe7a61c55..7527cb8ef8c6e3 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -10,7 +10,7 @@ import { AggDescriptor } from '../../../common/descriptor_types'; import { IESAggSource } from '../sources/es_agg_source'; import { IVectorSource } from '../sources/vector_source'; import { ESDocField } from './es_doc_field'; -import { AGG_TYPE, FIELD_ORIGIN } from '../../../common/constants'; +import { AGG_TYPE, FIELD_ORIGIN, VECTOR_STYLES } from '../../../common/constants'; import { isMetricCountable } from '../util/is_metric_countable'; import { getField, addFieldToDSL } from '../../../common/elasticsearch_util'; import { TopTermPercentageField } from './top_term_percentage_field'; @@ -143,7 +143,7 @@ export class ESAggField implements IESAggField { return this._canReadFromGeoJson; } - getMbPropertyName(styleName: string): string { + getMbPropertyName(styleName: VECTOR_STYLES): string { return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index db3461f7adcd73..7ee3ad2258075c 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -6,9 +6,8 @@ import { IESAggField } from './es_agg_field'; import { IVectorSource } from '../sources/vector_source'; -// @ts-ignore import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; -import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; +import { TOP_TERM_PERCENTAGE_SUFFIX, VECTOR_STYLES } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; import { AbstractField } from './field'; @@ -87,7 +86,7 @@ export class TopTermPercentageField implements IESAggField { return this._canReadFromGeoJson; } - getMbPropertyName(styleName: string): string { + getMbPropertyName(styleName: VECTOR_STYLES): string { return AbstractField.getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts index f47379d8c5eed9..33655af3420e28 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.d.ts @@ -24,7 +24,7 @@ export class ESGeoGridSource extends AbstractESAggSource implements ITiledSingle constructor(sourceDescriptor: ESGeoGridSourceDescriptor, inspectorAdapters: unknown); - private readonly _descriptor: ESGeoGridSourceDescriptor; + readonly _descriptor: ESGeoGridSourceDescriptor; getFieldNames(): string[]; getGridResolution(): GRID_RESOLUTION; From b3bd0f1599e571f6a0f384eb72651b08c8a452bc Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 13:51:41 -0400 Subject: [PATCH 23/46] remove cruft --- x-pack/plugins/maps/common/geo_tile_utils.test.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/x-pack/plugins/maps/common/geo_tile_utils.test.js b/x-pack/plugins/maps/common/geo_tile_utils.test.js index 88a6ce048a1788..ae2623e1687663 100644 --- a/x-pack/plugins/maps/common/geo_tile_utils.test.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.test.js @@ -4,8 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -jest.mock('../../../kibana_services', () => {}); - import { parseTileKey, getTileBoundingBox, expandToTileBoundaries } from './geo_tile_utils'; it('Should parse tile key', () => { From a148f5cfce8630343b491f27535a0dcc3427ead9 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 13:55:52 -0400 Subject: [PATCH 24/46] remove log --- .../classes/sources/es_geo_grid_source/resolution_editor.js | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js index 0b26fb95d10aff..71133cb25280c7 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.js @@ -31,7 +31,6 @@ const BASE_OPTIONS = [ ]; export function ResolutionEditor({ resolution, onChange, includeSuperFine }) { - console.log('resoliution editor', resolution, onChange, includeSuperFine); const options = [...BASE_OPTIONS]; if (includeSuperFine) { From db23dc56418618fb0e0502515977e7876dd148d1 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 14:01:16 -0400 Subject: [PATCH 25/46] remove dupes --- x-pack/plugins/maps/server/mvt/get_tile.ts | 72 +++++++++------------- 1 file changed, 29 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index c61dc2dd497e72..897cb0b1cc50a1 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -85,9 +85,10 @@ export async function getGridTile({ } requestBody.query.bool.filter.push(bboxFilter); - const targetPrecision = Math.min(z + SUPER_FINE_ZOOM_DELTA, MAX_ZOOM); - - requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = targetPrecision; + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = Math.min( + z + SUPER_FINE_ZOOM_DELTA, + MAX_ZOOM + ); requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; const esGeotileGridQuery = { @@ -103,26 +104,7 @@ export async function getGridTile({ type: 'FeatureCollection', }; - const tileIndex = geojsonvt(featureCollection, { - maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 - tolerance: 3, // simplification tolerance (higher means simpler) - extent: 4096, // tile extent (both width and height) - buffer: 64, // tile buffer on each side - debug: 0, // logging level (0 to disable, 1 or 2) - lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features - promoteId: null, // name of a feature property to promote to feature.id. Cannot be used with `generateId` - generateId: false, // whether to generate feature ids. Cannot be used with `promoteId` - indexMaxZoom: 5, // max zoom in the initial tile index - indexMaxPoints: 100000, // max number of points per tile in the index - }); - const tile = tileIndex.getTile(z, x, y); - - if (tile) { - const pbf = vtpbf.fromGeojsonVt({ [MVT_SOURCE_LAYER_NAME]: tile }, { version: 2 }); - return Buffer.from(pbf); - } else { - return null; - } + return createMvtTile(featureCollection); } catch (e) { logger.warn(e.message); throw e; @@ -251,26 +233,7 @@ export async function getTile({ type: 'FeatureCollection', }; - const tileIndex = geojsonvt(featureCollection, { - maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 - tolerance: 3, // simplification tolerance (higher means simpler) - extent: 4096, // tile extent (both width and height) - buffer: 64, // tile buffer on each side - debug: 0, // logging level (0 to disable, 1 or 2) - lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features - promoteId: null, // name of a feature property to promote to feature.id. Cannot be used with `generateId` - generateId: false, // whether to generate feature ids. Cannot be used with `promoteId` - indexMaxZoom: 5, // max zoom in the initial tile index - indexMaxPoints: 100000, // max number of points per tile in the index - }); - const tile = tileIndex.getTile(z, x, y); - - if (tile) { - const pbf = vtpbf.fromGeojsonVt({ [MVT_SOURCE_LAYER_NAME]: tile }, { version: 2 }); - return Buffer.from(pbf); - } else { - return null; - } + return createMvtTile(featureCollection); } catch (e) { logger.warn(`Cannot generate tile for ${z}/${x}/${y}: ${e.message}`); return null; @@ -338,3 +301,26 @@ function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { ], }; } + +function createMvtTile(featureCollection: FeatureCollection): Buffer | null { + const tileIndex = geojsonvt(featureCollection, { + maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 + tolerance: 3, // simplification tolerance (higher means simpler) + extent: 4096, // tile extent (both width and height) + buffer: 64, // tile buffer on each side + debug: 0, // logging level (0 to disable, 1 or 2) + lineMetrics: false, // whether to enable line metrics tracking for LineString/MultiLineString features + promoteId: null, // name of a feature property to promote to feature.id. Cannot be used with `generateId` + generateId: false, // whether to generate feature ids. Cannot be used with `promoteId` + indexMaxZoom: 5, // max zoom in the initial tile index + indexMaxPoints: 100000, // max number of points per tile in the index + }); + const tile = tileIndex.getTile(z, x, y); + + if (tile) { + const pbf = vtpbf.fromGeojsonVt({ [MVT_SOURCE_LAYER_NAME]: tile }, { version: 2 }); + return Buffer.from(pbf); + } else { + return null; + } +} From 1ed2b67553f4768e8539bc798fb871780892d50a Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 14:31:05 -0400 Subject: [PATCH 26/46] simplification --- x-pack/plugins/maps/common/geo_tile_utils.js | 4 ++-- .../tiled_vector_layer/tiled_vector_layer.tsx | 1 - x-pack/plugins/maps/server/mvt/get_tile.ts | 15 ++++++++++----- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/maps/common/geo_tile_utils.js b/x-pack/plugins/maps/common/geo_tile_utils.js index 7136c709524c72..526e5b9893d330 100644 --- a/x-pack/plugins/maps/common/geo_tile_utils.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.js @@ -61,13 +61,13 @@ function precisionRounding(v, minPrecision, binSize) { return _.round(v, precision); } -function tileToLatitude(y, tileCount) { +export function tileToLatitude(y, tileCount) { const radians = Math.atan(sinh(Math.PI - (2 * Math.PI * y) / tileCount)); const lat = (180 / Math.PI) * radians; return precisionRounding(lat, DECIMAL_DEGREES_PRECISION, 180 / tileCount); } -function tileToLongitude(x, tileCount) { +export function tileToLongitude(x, tileCount) { const lon = (x / tileCount) * 360 - 180; return precisionRounding(lon, DECIMAL_DEGREES_PRECISION, 360 / tileCount); } diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index 47184d13359ddc..70bf8ea3883b72 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -66,7 +66,6 @@ export class TiledVectorLayer extends VectorLayer { const templateWithMeta = await this._source.getUrlTemplateWithMeta(searchFilters); if (prevDataRequest) { const data: MVTSingleLayerVectorSourceConfig = prevDataRequest.getData() as MVTSingleLayerVectorSourceConfig; - if (data) { const canSkipBecauseNoChanges = data.layerName === this._source.getLayerName() && diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 897cb0b1cc50a1..e67680989578f3 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -98,13 +98,13 @@ export async function getGridTile({ const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); - const features = convertRegularRespToGeoJson(gridAggResult, requestType); - const featureCollection = { + const features: Feature[] = convertRegularRespToGeoJson(gridAggResult, requestType); + const featureCollection: FeatureCollection = { features, type: 'FeatureCollection', }; - return createMvtTile(featureCollection); + return createMvtTile(featureCollection, z, x, y); } catch (e) { logger.warn(e.message); throw e; @@ -233,7 +233,7 @@ export async function getTile({ type: 'FeatureCollection', }; - return createMvtTile(featureCollection); + return createMvtTile(featureCollection, z, x, y); } catch (e) { logger.warn(`Cannot generate tile for ${z}/${x}/${y}: ${e.message}`); return null; @@ -302,7 +302,12 @@ function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { }; } -function createMvtTile(featureCollection: FeatureCollection): Buffer | null { +function createMvtTile( + featureCollection: FeatureCollection, + z: number, + x: number, + y: number +): Buffer | null { const tileIndex = geojsonvt(featureCollection, { maxZoom: 24, // max zoom to preserve detail on; can't be higher than 24 tolerance: 3, // simplification tolerance (higher means simpler) From 270f82c2883c927c0126aeaa2aaf84c8ee6e6396 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 9 Sep 2020 14:59:54 -0400 Subject: [PATCH 27/46] reuse existing tile parsing --- .../{geo_tile_utils.js => geo_tile_utils.ts} | 64 +++++++++++++++---- x-pack/plugins/maps/server/mvt/get_tile.ts | 35 +--------- 2 files changed, 55 insertions(+), 44 deletions(-) rename x-pack/plugins/maps/common/{geo_tile_utils.js => geo_tile_utils.ts} (68%) diff --git a/x-pack/plugins/maps/common/geo_tile_utils.js b/x-pack/plugins/maps/common/geo_tile_utils.ts similarity index 68% rename from x-pack/plugins/maps/common/geo_tile_utils.js rename to x-pack/plugins/maps/common/geo_tile_utils.ts index 526e5b9893d330..c6e35224458c52 100644 --- a/x-pack/plugins/maps/common/geo_tile_utils.js +++ b/x-pack/plugins/maps/common/geo_tile_utils.ts @@ -7,16 +7,30 @@ import _ from 'lodash'; import { DECIMAL_DEGREES_PRECISION } from './constants'; import { clampToLatBounds } from './elasticsearch_util'; +import { MapExtent } from './descriptor_types'; const ZOOM_TILE_KEY_INDEX = 0; const X_TILE_KEY_INDEX = 1; const Y_TILE_KEY_INDEX = 2; -function getTileCount(zoom) { +function getTileCount(zoom: number): number { return Math.pow(2, zoom); } -export function parseTileKey(tileKey) { +export interface ESBounds { + top_left: { + lon: number; + lat: number; + }; + bottom_right: { + lon: number; + lat: number; + }; +} + +export function parseTileKey( + tileKey: string +): { x: number; y: number; zoom: number; tileCount: number } { const tileKeyParts = tileKey.split('/'); if (tileKeyParts.length !== 3) { @@ -42,7 +56,7 @@ export function parseTileKey(tileKey) { return { x, y, zoom, tileCount }; } -function sinh(x) { +function sinh(x: number): number { return (Math.exp(x) - Math.exp(-x)) / 2; } @@ -55,24 +69,52 @@ function sinh(x) { // We add one extra decimal level of precision because, at high zoom // levels rounding exactly can cause the boxes to render as uneven sizes // (some will be slightly larger and some slightly smaller) -function precisionRounding(v, minPrecision, binSize) { +function precisionRounding(v: number, minPrecision: number, binSize: number): number { let precision = Math.ceil(Math.abs(Math.log10(binSize))) + 1; precision = Math.max(precision, minPrecision); return _.round(v, precision); } -export function tileToLatitude(y, tileCount) { +export function tile2long(x: number, z: number): number { + const tileCount = getTileCount(z); + return tileToLongitude(x, tileCount); +} + +export function tile2lat(y: number, z: number): number { + const tileCount = getTileCount(z); + return tileToLatitude(y, tileCount); +} + +export function tileToESBbox(x: number, y: number, z: number): ESBounds { + const wLon = tile2long(x, z); + const sLat = tile2lat(y + 1, z); + const eLon = tile2long(x + 1, z); + const nLat = tile2lat(y, z); + + return { + top_left: { + lon: wLon, + lat: nLat, + }, + bottom_right: { + lon: eLon, + lat: sLat, + }, + }; +} + +export function tileToLatitude(y: number, tileCount: number) { const radians = Math.atan(sinh(Math.PI - (2 * Math.PI * y) / tileCount)); const lat = (180 / Math.PI) * radians; return precisionRounding(lat, DECIMAL_DEGREES_PRECISION, 180 / tileCount); } -export function tileToLongitude(x, tileCount) { +export function tileToLongitude(x: number, tileCount: number) { const lon = (x / tileCount) * 360 - 180; return precisionRounding(lon, DECIMAL_DEGREES_PRECISION, 360 / tileCount); } -export function getTileBoundingBox(tileKey) { +export function getTileBoundingBox(tileKey: string) { const { x, y, tileCount } = parseTileKey(tileKey); return { @@ -83,22 +125,22 @@ export function getTileBoundingBox(tileKey) { }; } -function sec(value) { +function sec(value: number): number { return 1 / Math.cos(value); } -function latitudeToTile(lat, tileCount) { +function latitudeToTile(lat: number, tileCount: number) { const radians = (clampToLatBounds(lat) * Math.PI) / 180; const y = ((1 - Math.log(Math.tan(radians) + sec(radians)) / Math.PI) / 2) * tileCount; return Math.floor(y); } -function longitudeToTile(lon, tileCount) { +function longitudeToTile(lon: number, tileCount: number) { const x = ((lon + 180) / 360) * tileCount; return Math.floor(x); } -export function expandToTileBoundaries(extent, zoom) { +export function expandToTileBoundaries(extent: MapExtent, zoom: number): MapExtent { const tileCount = getTileCount(zoom); const upperLeftX = longitudeToTile(extent.minLon, tileCount); diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index e67680989578f3..82d6b7fed52776 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -24,17 +24,7 @@ import { import { hitsToGeoJson } from '../../common/elasticsearch_util'; import { flattenHit } from './util'; import { convertRegularRespToGeoJson } from '../../common/elasticsearch_util'; - -interface ESBounds { - top_left: { - lon: number; - lat: number; - }; - bottom_right: { - lon: number; - lat: number; - }; -} +import { ESBounds, tile2lat, tile2long, tileToESBbox } from '../../common/geo_tile_utils'; export async function getGridTile({ logger, @@ -59,7 +49,7 @@ export async function getGridTile({ requestType: RENDER_AS; geoFieldType: ES_GEO_FIELD_TYPE; }): Promise { - const esBbox = tileToESBbox(x, y, z); + const esBbox: ESBounds = tileToESBbox(x, y, z); try { try { // todo: needs to be different from geo_point and geo_shape @@ -260,27 +250,6 @@ function tileToGeoJsonPolygon(x: number, y: number, z: number): Polygon { }; } -function tile2long(x: number, z: number): number { - return (x / Math.pow(2, z)) * 360 - 180; -} - -function tile2lat(y: number, z: number): number { - const n = Math.PI - (2 * Math.PI * y) / Math.pow(2, z); - return (180 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))); -} - -function tileToESBbox(x: number, y: number, z: number) { - const wLon = tile2long(x, z); - const sLat = tile2lat(y + 1, z); - const eLon = tile2long(x + 1, z); - const nLat = tile2lat(y, z); - - return { - top_left: [wLon, nLat], - bottom_right: [eLon, sLat], - }; -} - function esBboxToGeoJsonPolygon(esBounds: ESBounds): Polygon { let minLon = esBounds.top_left.lon; const maxLon = esBounds.bottom_right.lon; From 4e71f483271685d84bc7a3f1b992246df34b2cd0 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 10 Sep 2020 18:33:34 -0400 Subject: [PATCH 28/46] review feedback --- .../public/classes/fields/es_agg_field.ts | 4 +-- .../maps/public/classes/fields/field.ts | 26 +++++++++---------- .../fields/top_term_percentage_field.ts | 4 +-- .../sources/es_agg_source/es_agg_source.ts | 13 +++++++--- .../maps/public/classes/sources/source.ts | 4 +-- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 7527cb8ef8c6e3..02ea2af94baddb 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -5,7 +5,7 @@ */ import { IndexPattern } from 'src/plugins/data/public'; -import { AbstractField, IField } from './field'; +import { getMbPropertyName, IField } from './field'; import { AggDescriptor } from '../../../common/descriptor_types'; import { IESAggSource } from '../sources/es_agg_source'; import { IVectorSource } from '../sources/vector_source'; @@ -144,7 +144,7 @@ export class ESAggField implements IESAggField { } getMbPropertyName(styleName: VECTOR_STYLES): string { - return AbstractField.getMbPropertyName(this, styleName); + return getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index 3b3e22d33976a5..ada4b7deeaf07f 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -44,18 +44,6 @@ export interface IField { } export class AbstractField implements IField { - static getMbPropertyName(field: IField, styleName: VECTOR_STYLES) { - let targetName; - if (field.canReadFromGeoJson()) { - targetName = field.supportsAutoDomain() - ? getComputedFieldName(styleName, field.getName()) - : field.getName(); - } else { - targetName = field.getName(); - } - return targetName; - } - private readonly _fieldName: string; private readonly _origin: FIELD_ORIGIN; @@ -122,6 +110,18 @@ export class AbstractField implements IField { } getMbPropertyName(styleName: VECTOR_STYLES): string { - return AbstractField.getMbPropertyName(this, styleName); + return getMbPropertyName(this, styleName); + } +} + +export function getMbPropertyName(field: IField, styleName: VECTOR_STYLES) { + let targetName; + if (field.canReadFromGeoJson()) { + targetName = field.supportsAutoDomain() + ? getComputedFieldName(styleName, field.getName()) + : field.getName(); + } else { + targetName = field.getName(); } + return targetName; } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index 7ee3ad2258075c..d5fec8ea104291 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -9,7 +9,7 @@ import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; import { TOP_TERM_PERCENTAGE_SUFFIX, VECTOR_STYLES } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; -import { AbstractField } from './field'; +import { getMbPropertyName } from './field'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; @@ -87,6 +87,6 @@ export class TopTermPercentageField implements IESAggField { } getMbPropertyName(styleName: VECTOR_STYLES): string { - return AbstractField.getMbPropertyName(this, styleName); + return getMbPropertyName(this, styleName); } } diff --git a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts index fba4f004d5243b..be947d79f4e395 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_agg_source/es_agg_source.ts @@ -31,6 +31,7 @@ export interface IESAggSource extends IESSource { export class AbstractESAggSource extends AbstractESSource { private readonly _metricFields: IESAggField[]; + private readonly _canReadFromGeoJson: boolean; constructor( descriptor: AbstractESAggSourceDescriptor, @@ -39,10 +40,16 @@ export class AbstractESAggSource extends AbstractESSource { ) { super(descriptor, inspectorAdapters); this._metricFields = []; + this._canReadFromGeoJson = canReadFromGeoJson; if (descriptor.metrics) { descriptor.metrics.forEach((aggDescriptor: AggDescriptor) => { this._metricFields.push( - ...esAggFieldsFactory(aggDescriptor, this, this.getOriginForField(), canReadFromGeoJson) + ...esAggFieldsFactory( + aggDescriptor, + this, + this.getOriginForField(), + this._canReadFromGeoJson + ) ); }); } @@ -72,7 +79,7 @@ export class AbstractESAggSource extends AbstractESSource { return FIELD_ORIGIN.SOURCE; } - getMetricFields(canReadFromGeoJson = true): IESAggField[] { + getMetricFields(): IESAggField[] { const metrics = this._metricFields.filter((esAggField) => esAggField.isValid()); // Handle case where metrics is empty because older saved object state is empty array or there are no valid aggs. return metrics.length === 0 @@ -80,7 +87,7 @@ export class AbstractESAggSource extends AbstractESSource { { type: AGG_TYPE.COUNT }, this, this.getOriginForField(), - canReadFromGeoJson + this._canReadFromGeoJson ) : metrics; } diff --git a/x-pack/plugins/maps/public/classes/sources/source.ts b/x-pack/plugins/maps/public/classes/sources/source.ts index 8bf25fe4f298e1..1c53ff1499ead6 100644 --- a/x-pack/plugins/maps/public/classes/sources/source.ts +++ b/x-pack/plugins/maps/public/classes/sources/source.ts @@ -53,7 +53,7 @@ export interface ISource { getImmutableProperties(): Promise; getAttributions(): Promise; isESSource(): boolean; - renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null; + renderSourceSettingsEditor(sourceEditorArgs: SourceEditorArgs): ReactElement | null; supportsFitToBounds(): Promise; showJoinEditor(): boolean; getJoinsDisabledReason(): string | null; @@ -129,7 +129,7 @@ export class AbstractSource implements ISource { return []; } - renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null { + renderSourceSettingsEditor(sourceEditorArgs: SourceEditorArgs): ReactElement | null { return null; } From 348a7ab75f8179c0674928262ef92522586364dd Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 10 Sep 2020 18:35:48 -0400 Subject: [PATCH 29/46] remove param --- .../classes/sources/es_geo_grid_source/es_geo_grid_source.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 54ad4cb2b33a17..ee9656433342a6 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -112,7 +112,7 @@ export class ESGeoGridSource extends AbstractESAggSource { } getMetricFields() { - return super.getMetricFields(this._descriptor.resolution !== GRID_RESOLUTION.SUPER_FINE); + return super.getMetricFields(); } getFieldNames() { From 0d5d0b6cbf4327a52d44064e7e4fdfb4597aba1d Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 10 Sep 2020 18:39:14 -0400 Subject: [PATCH 30/46] remove fluffy try-catch --- .../es_geo_grid_source/es_geo_grid_source.js | 2 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 78 +++++++++---------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index ee9656433342a6..2152b2dd16c4eb 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -122,7 +122,7 @@ export class ESGeoGridSource extends AbstractESAggSource { isGeoGridPrecisionAware() { if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) { // MVT gridded data should not bootstrap each time the precision changes - // MBtiles needs to handle this + // mapbox-gl needs to handle this return false; } else { // Should requery each time grid-precision changes diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 82d6b7fed52776..e044d9da8bb0b1 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -51,54 +51,48 @@ export async function getGridTile({ }): Promise { const esBbox: ESBounds = tileToESBbox(x, y, z); try { - try { - // todo: needs to be different from geo_point and geo_shape - let bboxFilter; - if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { - bboxFilter = { - geo_bounding_box: { - [geometryFieldName]: esBbox, - }, - }; - } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { - const geojsonPolygon = tileToGeoJsonPolygon(x, y, z); - bboxFilter = { - geo_shape: { - [geometryFieldName]: { - shape: geojsonPolygon, - relation: 'INTERSECTS', - }, + let bboxFilter; + if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_POINT) { + bboxFilter = { + geo_bounding_box: { + [geometryFieldName]: esBbox, + }, + }; + } else if (geoFieldType === ES_GEO_FIELD_TYPE.GEO_SHAPE) { + const geojsonPolygon = tileToGeoJsonPolygon(x, y, z); + bboxFilter = { + geo_shape: { + [geometryFieldName]: { + shape: geojsonPolygon, + relation: 'INTERSECTS', }, - }; - } else { - throw new Error(`${geoFieldType} is not valid geo field-type`); - } - requestBody.query.bool.filter.push(bboxFilter); + }, + }; + } else { + throw new Error(`${geoFieldType} is not valid geo field-type`); + } + requestBody.query.bool.filter.push(bboxFilter); - requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = Math.min( - z + SUPER_FINE_ZOOM_DELTA, - MAX_ZOOM - ); - requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.precision = Math.min( + z + SUPER_FINE_ZOOM_DELTA, + MAX_ZOOM + ); + requestBody.aggs[GEOTILE_GRID_AGG_NAME].geotile_grid.bounds = esBbox; - const esGeotileGridQuery = { - index, - body: requestBody, - }; + const esGeotileGridQuery = { + index, + body: requestBody, + }; - const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); + const gridAggResult = await callElasticsearch('search', esGeotileGridQuery); - const features: Feature[] = convertRegularRespToGeoJson(gridAggResult, requestType); - const featureCollection: FeatureCollection = { - features, - type: 'FeatureCollection', - }; + const features: Feature[] = convertRegularRespToGeoJson(gridAggResult, requestType); + const featureCollection: FeatureCollection = { + features, + type: 'FeatureCollection', + }; - return createMvtTile(featureCollection, z, x, y); - } catch (e) { - logger.warn(e.message); - throw e; - } + return createMvtTile(featureCollection, z, x, y); } catch (e) { logger.warn(`Cannot generate grid-tile for ${z}/${x}/${y}: ${e.message}`); return null; From a3946de2a81a0f066376e756bb01e13ed0210b04 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Mon, 14 Sep 2020 15:33:42 -0600 Subject: [PATCH 31/46] Add deprecation message to coordinate map and region map --- src/plugins/tile_map/public/tile_map_type.js | 8 +++++ .../public/vis_types/base_vis_type.ts | 7 ++++ .../components/deprecated_vis_info.tsx | 32 +++++++++++++++++++ .../components/visualize_editor_common.tsx | 4 +++ 4 files changed, 51 insertions(+) create mode 100644 src/plugins/visualize/public/application/components/deprecated_vis_info.tsx diff --git a/src/plugins/tile_map/public/tile_map_type.js b/src/plugins/tile_map/public/tile_map_type.js index f76da26022a778..31e5154ef3ce8e 100644 --- a/src/plugins/tile_map/public/tile_map_type.js +++ b/src/plugins/tile_map/public/tile_map_type.js @@ -32,6 +32,14 @@ export function createTileMapTypeDefinition(dependencies) { return { name: 'tile_map', + isDeprecated: true, + getDeprecationMessage: (vis) => { + console.log(vis); + return i18n.translate('tileMap.vis.deprecationMessage', { + defaultMessage: + 'In 8.0, Coordinate maps will be migrating to Maps. With Maps, you can add multiple layers and indices, plot individual documents, symbolize features from data values, and more.', + }); + }, title: i18n.translate('tileMap.vis.mapTitle', { defaultMessage: 'Coordinate Map', }), diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index fa0bbfc5e250a6..d072f9bba1a825 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -18,6 +18,7 @@ */ import _ from 'lodash'; +import { ReactElement } from 'react'; import { VisToExpressionAst, VisualizationControllerConstructor } from '../types'; import { TriggerContextMapping } from '../../../ui_actions/public'; import { Adapters } from '../../../inspector/public'; @@ -43,6 +44,8 @@ export interface BaseVisTypeOptions { useCustomNoDataScreen?: boolean; inspectorAdapters?: Adapters | (() => Adapters); toExpressionAst?: VisToExpressionAst; + isDeprecated?: boolean; + getDeprecationMessage?: (vis: Vis) => ReactElement | string; } export class BaseVisType { @@ -68,6 +71,8 @@ export class BaseVisType { useCustomNoDataScreen: boolean; inspectorAdapters?: Adapters | (() => Adapters); toExpressionAst?: VisToExpressionAst; + isDeprecated: boolean; + getDeprecationMessage?: (vis: Vis) => ReactElement | string; constructor(opts: BaseVisTypeOptions) { if (!opts.icon && !opts.image) { @@ -105,6 +110,8 @@ export class BaseVisType { this.useCustomNoDataScreen = opts.useCustomNoDataScreen || false; this.inspectorAdapters = opts.inspectorAdapters; this.toExpressionAst = opts.toExpressionAst; + this.isDeprecated = opts.isDeprecated || false; + this.getDeprecationMessage = opts.getDeprecationMessage; } public get schemas() { diff --git a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx new file mode 100644 index 00000000000000..ea6764cfcbb636 --- /dev/null +++ b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx @@ -0,0 +1,32 @@ +/* + * 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 React, { ReactElement } from 'react'; +import { EuiCallOut } from '@elastic/eui'; + +export const DeprecatedVisInfo = ({ message }: ReactElement | string) => { + return ( + + ); +}; diff --git a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx index b811936c63b140..868b8737e67f96 100644 --- a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx +++ b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx @@ -22,6 +22,7 @@ import { FormattedMessage } from '@kbn/i18n/react'; import { EuiScreenReaderOnly } from '@elastic/eui'; import { VisualizeTopNav } from './visualize_top_nav'; import { ExperimentalVisInfo } from './experimental_vis_info'; +import { DeprecatedVisInfo } from './deprecated_vis_info'; import { SavedVisInstance, VisualizeAppState, @@ -79,6 +80,9 @@ export const VisualizeEditorCommon = ({ /> )} {visInstance?.vis?.type?.isExperimental && } + {visInstance?.vis?.type?.isDeprecated && visInstance?.vis?.type?.getDeprecationMessage && ( + + )} {visInstance && (

From bbf755fd3f1d4b29d7a8e22769803618a52be542 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 15 Sep 2020 09:44:57 -0600 Subject: [PATCH 32/46] clean up text --- src/plugins/tile_map/public/tile_map_type.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/tile_map/public/tile_map_type.js b/src/plugins/tile_map/public/tile_map_type.js index 31e5154ef3ce8e..d3b47a0c771251 100644 --- a/src/plugins/tile_map/public/tile_map_type.js +++ b/src/plugins/tile_map/public/tile_map_type.js @@ -37,7 +37,7 @@ export function createTileMapTypeDefinition(dependencies) { console.log(vis); return i18n.translate('tileMap.vis.deprecationMessage', { defaultMessage: - 'In 8.0, Coordinate maps will be migrating to Maps. With Maps, you can add multiple layers and indices, plot individual documents, symbolize features from data values, and more.', + 'Coordinate maps will migrate to Maps in 8.0. With Maps, you can add multiple layers and indices, plot individual documents, symbolize features from data values, and more.', }); }, title: i18n.translate('tileMap.vis.mapTitle', { From b773bb3d0e5b4aef3db4d7adb5367e9fff16a6d2 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 16 Sep 2020 09:24:32 -0400 Subject: [PATCH 33/46] remove interfaces --- .../public/classes/fields/es_agg_field.ts | 4 --- .../maps/public/classes/fields/field.ts | 28 ++----------------- .../fields/top_term_percentage_field.ts | 4 --- 3 files changed, 2 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index 02ea2af94baddb..ee8c02b4dc2ff9 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -142,10 +142,6 @@ export class ESAggField implements IESAggField { canReadFromGeoJson(): boolean { return this._canReadFromGeoJson; } - - getMbPropertyName(styleName: VECTOR_STYLES): string { - return getMbPropertyName(this, styleName); - } } export function esAggFieldsFactory( diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index ada4b7deeaf07f..bc9ac1118d229b 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -22,25 +22,17 @@ export interface IField { getOrdinalFieldMetaRequest(): Promise; getCategoricalFieldMetaRequest(size: number): Promise; - // Determines whether Maps-app can automatically determine the domain of the field-values + // Whether Maps-app can automatically determine the domain of the field-values // if this is not the case (e.g. for .mvt tiled data), // then styling properties that require the domain to be known cannot use this property. supportsAutoDomain(): boolean; - // Determinse wheter Maps-app can automatically deterime the domain of the field-values + // Whether Maps-app can automatically determine the domain of the field-values // _without_ having to retrieve the data as GeoJson // e.g. for ES-sources, this would use the extended_stats API supportsFieldMeta(): boolean; canReadFromGeoJson(): boolean; - - // Returns the name that should be used for accessing the data from the mb-style rule - // Depending on - // - whether the field is used for labeling, icon-orientation, or other properties (color, size, ...), `feature-state` and or `get` is used - // - whether the field was run through a field-formatter, a new dynamic field is created with the formatted-value - // The combination of both will inform what field-name (e.g. the "raw" field name from the properties, the "computed field-name" for an on-the-fly created property (e.g. for feature-state or field-formatting). - // todo: There is an existing limitation to .mvt backed sources, where the field-formatters are not applied. Here, the raw-data needs to be accessed. - getMbPropertyName(styleName: VECTOR_STYLES): string; } export class AbstractField implements IField { @@ -108,20 +100,4 @@ export class AbstractField implements IField { canReadFromGeoJson(): boolean { return true; } - - getMbPropertyName(styleName: VECTOR_STYLES): string { - return getMbPropertyName(this, styleName); - } -} - -export function getMbPropertyName(field: IField, styleName: VECTOR_STYLES) { - let targetName; - if (field.canReadFromGeoJson()) { - targetName = field.supportsAutoDomain() - ? getComputedFieldName(styleName, field.getName()) - : field.getName(); - } else { - targetName = field.getName(); - } - return targetName; } diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index d5fec8ea104291..e4d76448f6eb3e 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -85,8 +85,4 @@ export class TopTermPercentageField implements IESAggField { canReadFromGeoJson(): boolean { return this._canReadFromGeoJson; } - - getMbPropertyName(styleName: VECTOR_STYLES): string { - return getMbPropertyName(this, styleName); - } } From 1b5a90074eaf3f4d98a298bbb39254dfa76f2b1e Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 16 Sep 2020 12:12:58 -0600 Subject: [PATCH 34/46] add default distro link and view in maps link --- src/plugins/tile_map/kibana.json | 3 +- .../public/get_deprecation_message.tsx | 80 +++++++++++++++++++ src/plugins/tile_map/public/plugin.ts | 20 +++-- src/plugins/tile_map/public/services.ts | 6 ++ src/plugins/tile_map/public/tile_map_type.js | 9 +-- .../public/vis_types/base_vis_type.ts | 4 +- .../components/deprecated_vis_info.tsx | 57 ++++++++++--- .../components/visualize_editor_common.tsx | 5 +- 8 files changed, 157 insertions(+), 27 deletions(-) create mode 100644 src/plugins/tile_map/public/get_deprecation_message.tsx diff --git a/src/plugins/tile_map/kibana.json b/src/plugins/tile_map/kibana.json index 9881a2dd72308b..747b4cc83fa0e8 100644 --- a/src/plugins/tile_map/kibana.json +++ b/src/plugins/tile_map/kibana.json @@ -10,7 +10,8 @@ "expressions", "mapsLegacy", "kibanaLegacy", - "data" + "data", + "share" ], "requiredBundles": [ "kibanaUtils", diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx new file mode 100644 index 00000000000000..e35d8895040e6b --- /dev/null +++ b/src/plugins/tile_map/public/get_deprecation_message.tsx @@ -0,0 +1,80 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiButton, EuiLink } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { getCoreService, getQueryService, getShareService } from './services'; + +export async function getDeprecationMessage(vis: Vis) { + const mapsUrlGenerator = getShareService().urlGenerators.getUrlGenerator( + 'MAPS_APP_URL_GENERATOR' + ); + + let action; + if (!mapsUrlGenerator) { + action = ( + + default distribution + + ), + }} + /> + ); + } else { + const query = getQueryService(); + const url = await mapsUrlGenerator.createUrl({ + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }); + action = ( +
+ { + e.preventDefault(); + getCoreService().application.navigateToUrl(url); + }} + size="s" + > + + +
+ ); + } + + return ( + + ); +} diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts index 9a164f8a303f84..b4baac248ffc7a 100644 --- a/src/plugins/tile_map/public/plugin.ts +++ b/src/plugins/tile_map/public/plugin.ts @@ -34,8 +34,15 @@ import { createTileMapFn } from './tile_map_fn'; import { createTileMapTypeDefinition } from './tile_map_type'; import { IServiceSettings, MapsLegacyPluginSetup } from '../../maps_legacy/public'; import { DataPublicPluginStart } from '../../data/public'; -import { setFormatService, setQueryService, setKibanaLegacy } from './services'; +import { + setCoreService, + setFormatService, + setQueryService, + setKibanaLegacy, + setShareService, +} from './services'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; +import { SharePluginSetup, SharePluginStart } from '../../share/public'; export interface TileMapConfigType { tilemap: any; @@ -61,6 +68,7 @@ export interface TileMapPluginSetupDependencies { export interface TileMapPluginStartDependencies { data: DataPublicPluginStart; kibanaLegacy: KibanaLegacyStart; + share: SharePluginStart; } export interface TileMapPluginSetup { @@ -100,10 +108,12 @@ export class TileMapPlugin implements Plugin('Core'); export const [getFormatService, setFormatService] = createGetterSetter< DataPublicPluginStart['fieldFormats'] @@ -29,6 +33,8 @@ export const [getQueryService, setQueryService] = createGetterSetter< DataPublicPluginStart['query'] >('Query'); +export const [getShareService, setShareService] = createGetterSetter('Share'); + export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( 'KibanaLegacy' ); diff --git a/src/plugins/tile_map/public/tile_map_type.js b/src/plugins/tile_map/public/tile_map_type.js index d3b47a0c771251..e11a5e703c5bc5 100644 --- a/src/plugins/tile_map/public/tile_map_type.js +++ b/src/plugins/tile_map/public/tile_map_type.js @@ -25,6 +25,7 @@ import { createTileMapVisualization } from './tile_map_visualization'; import { TileMapOptions } from './components/tile_map_options'; import { supportsCssFilters } from './css_filters'; import { truncatedColorSchemas } from '../../charts/public'; +import { getDeprecationMessage } from './get_deprecation_message'; export function createTileMapTypeDefinition(dependencies) { const CoordinateMapsVisualization = createTileMapVisualization(dependencies); @@ -33,13 +34,7 @@ export function createTileMapTypeDefinition(dependencies) { return { name: 'tile_map', isDeprecated: true, - getDeprecationMessage: (vis) => { - console.log(vis); - return i18n.translate('tileMap.vis.deprecationMessage', { - defaultMessage: - 'Coordinate maps will migrate to Maps in 8.0. With Maps, you can add multiple layers and indices, plot individual documents, symbolize features from data values, and more.', - }); - }, + getDeprecationMessage, title: i18n.translate('tileMap.vis.mapTitle', { defaultMessage: 'Coordinate Map', }), diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index d072f9bba1a825..e62c86acd2287d 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -45,7 +45,7 @@ export interface BaseVisTypeOptions { inspectorAdapters?: Adapters | (() => Adapters); toExpressionAst?: VisToExpressionAst; isDeprecated?: boolean; - getDeprecationMessage?: (vis: Vis) => ReactElement | string; + getDeprecationMessage?: (vis: Vis) => Promise>; } export class BaseVisType { @@ -72,7 +72,7 @@ export class BaseVisType { inspectorAdapters?: Adapters | (() => Adapters); toExpressionAst?: VisToExpressionAst; isDeprecated: boolean; - getDeprecationMessage?: (vis: Vis) => ReactElement | string; + getDeprecationMessage?: (vis: Vis) => Promise>; constructor(opts: BaseVisTypeOptions) { if (!opts.icon && !opts.image) { diff --git a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx index ea6764cfcbb636..101657a895065e 100644 --- a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx +++ b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx @@ -17,16 +17,51 @@ * under the License. */ -import React, { ReactElement } from 'react'; +import React, { Component, ReactElement } from 'react'; import { EuiCallOut } from '@elastic/eui'; -export const DeprecatedVisInfo = ({ message }: ReactElement | string) => { - return ( - - ); -}; +interface Props { + getDeprecationMessage: (vis: Vis) => ReactElement; + vis: Vis; +} + +interface State { + message?: ReactElement; +} + +export class DeprecatedVisInfo extends Component { + private _isMounted: boolean = false; + + state: State = {}; + + componentDidMount() { + this._isMounted = true; + this.loadMessage(); + } + + componentWillUnmount() { + this._isMounted = false; + } + + async loadMessage() { + const message = await this.props.getDeprecationMessage(this.props.vis); + if (this._isMounted) { + this.setState({ message }); + } + } + + render() { + if (!this.state.message) { + return null; + } + + return ( + + ); + } +} diff --git a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx index 868b8737e67f96..8b9a1e0ba42fbd 100644 --- a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx +++ b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx @@ -81,7 +81,10 @@ export const VisualizeEditorCommon = ({ )} {visInstance?.vis?.type?.isExperimental && } {visInstance?.vis?.type?.isDeprecated && visInstance?.vis?.type?.getDeprecationMessage && ( - + )} {visInstance && ( From 7571e3d103d974b44885fdeb724bfdfb70764710 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 16 Sep 2020 12:39:48 -0600 Subject: [PATCH 35/46] move url generation into onClick handler --- .../public/get_deprecation_message.tsx | 17 +++--- .../public/vis_types/base_vis_type.ts | 4 +- .../components/deprecated_vis_info.tsx | 55 ++++--------------- .../components/visualize_editor_common.tsx | 5 +- 4 files changed, 22 insertions(+), 59 deletions(-) diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx index e35d8895040e6b..82fce0dcd76926 100644 --- a/src/plugins/tile_map/public/get_deprecation_message.tsx +++ b/src/plugins/tile_map/public/get_deprecation_message.tsx @@ -23,7 +23,7 @@ import { EuiButton, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { getCoreService, getQueryService, getShareService } from './services'; -export async function getDeprecationMessage(vis: Vis) { +export function getDeprecationMessage(vis: Vis) { const mapsUrlGenerator = getShareService().urlGenerators.getUrlGenerator( 'MAPS_APP_URL_GENERATOR' ); @@ -49,17 +49,18 @@ export async function getDeprecationMessage(vis: Vis) { /> ); } else { - const query = getQueryService(); - const url = await mapsUrlGenerator.createUrl({ - filters: query.filterManager.getFilters(), - query: query.queryString.getQuery(), - timeRange: query.timefilter.timefilter.getTime(), - }); action = (
{ + onClick={async (e) => { e.preventDefault(); + console.log('vis', vis); + const query = getQueryService(); + const url = await mapsUrlGenerator.createUrl({ + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }); getCoreService().application.navigateToUrl(url); }} size="s" diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index e62c86acd2287d..9a2ab70d5f09ec 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -45,7 +45,7 @@ export interface BaseVisTypeOptions { inspectorAdapters?: Adapters | (() => Adapters); toExpressionAst?: VisToExpressionAst; isDeprecated?: boolean; - getDeprecationMessage?: (vis: Vis) => Promise>; + getDeprecationMessage?: (vis: Vis) => ReactElement; } export class BaseVisType { @@ -72,7 +72,7 @@ export class BaseVisType { inspectorAdapters?: Adapters | (() => Adapters); toExpressionAst?: VisToExpressionAst; isDeprecated: boolean; - getDeprecationMessage?: (vis: Vis) => Promise>; + getDeprecationMessage?: (vis: Vis) => ReactElement; constructor(opts: BaseVisTypeOptions) { if (!opts.icon && !opts.image) { diff --git a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx index 101657a895065e..9b4ed5cb4dfa1b 100644 --- a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx +++ b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx @@ -17,51 +17,16 @@ * under the License. */ -import React, { Component, ReactElement } from 'react'; +import React, { ReactElement } from 'react'; import { EuiCallOut } from '@elastic/eui'; -interface Props { - getDeprecationMessage: (vis: Vis) => ReactElement; - vis: Vis; -} - -interface State { - message?: ReactElement; -} - -export class DeprecatedVisInfo extends Component { - private _isMounted: boolean = false; - - state: State = {}; - - componentDidMount() { - this._isMounted = true; - this.loadMessage(); - } - - componentWillUnmount() { - this._isMounted = false; - } - - async loadMessage() { - const message = await this.props.getDeprecationMessage(this.props.vis); - if (this._isMounted) { - this.setState({ message }); - } - } - - render() { - if (!this.state.message) { - return null; - } - - return ( - - ); - } +export function DeprecatedVisInfo({ message }: ReactElement) { + return ( + + ); } diff --git a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx index 8b9a1e0ba42fbd..868b8737e67f96 100644 --- a/src/plugins/visualize/public/application/components/visualize_editor_common.tsx +++ b/src/plugins/visualize/public/application/components/visualize_editor_common.tsx @@ -81,10 +81,7 @@ export const VisualizeEditorCommon = ({ )} {visInstance?.vis?.type?.isExperimental && } {visInstance?.vis?.type?.isDeprecated && visInstance?.vis?.type?.getDeprecationMessage && ( - + )} {visInstance && ( From 7ab105ba208781b79dccfbb4f163fb13f46bbbe2 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Wed, 16 Sep 2020 15:44:49 -0600 Subject: [PATCH 36/46] create tile map layer descritor --- .../public/get_deprecation_message.tsx | 43 +++++- .../create_tile_map_layer_descriptor.ts | 133 ++++++++++++++++++ x-pack/plugins/maps/public/plugin.ts | 22 +-- x-pack/plugins/maps/public/url_generator.ts | 133 +++++++++++++----- 4 files changed, 280 insertions(+), 51 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx index 82fce0dcd76926..b68b842c00839d 100644 --- a/src/plugins/tile_map/public/get_deprecation_message.tsx +++ b/src/plugins/tile_map/public/get_deprecation_message.tsx @@ -22,14 +22,15 @@ import { i18n } from '@kbn/i18n'; import { EuiButton, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { getCoreService, getQueryService, getShareService } from './services'; +import { indexPatterns } from '../../data/public'; export function getDeprecationMessage(vis: Vis) { - const mapsUrlGenerator = getShareService().urlGenerators.getUrlGenerator( - 'MAPS_APP_URL_GENERATOR' + const mapsTileMapUrlGenerator = getShareService().urlGenerators.getUrlGenerator( + 'MAPS_APP_TILE_MAP_URL_GENERATOR' ); let action; - if (!mapsUrlGenerator) { + if (!mapsTileMapUrlGenerator) { action = ( { e.preventDefault(); - console.log('vis', vis); + + let geoFieldName: string; + const bucketAggs = vis.data?.aggs.byType('buckets'); + if (bucketAggs.length && bucketAggs[0].type.dslName === 'geohash_grid') { + geoFieldName = bucketAggs[0].getField()?.name; + } else { + // attempt to default to first geo point field when geohash is not configured yet + const geoField = vis.data.indexPattern.fields.find((field) => { + return ( + !indexPatterns.isNestedField(field) && + field.aggregatable && + field.type === 'geo_point' + ); + }); + if (geoField) { + geoFieldName = geoField.name; + } + } + + let metricAgg: string = 'count'; + let metricFieldName: string; + const metricAggs = vis.data?.aggs.byType('metrics'); + if (metricAggs.length) { + metricAgg = metricAggs[0].type.dslName; + metricFieldName = metricAggs[0].getField()?.name; + } + const query = getQueryService(); - const url = await mapsUrlGenerator.createUrl({ + const url = await mapsTileMapUrlGenerator.createUrl({ + title: vis.title, + mapType: vis.params.mapType, + indexPatternId: vis.data.indexPattern.id, + geoFieldName, + metricAgg, + metricFieldName, filters: query.filterManager.getFilters(), query: query.queryString.getQuery(), timeRange: query.timefilter.timefilter.getTime(), diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts new file mode 100644 index 00000000000000..1a815c14bafd25 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts @@ -0,0 +1,133 @@ +/* + * 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 uuid from 'uuid/v4'; +import { i18n } from '@kbn/i18n'; +import { + AggDescriptor, + ColorDynamicOptions, + LayerDescriptor, + SizeDynamicOptions, + StylePropertyField, + VectorStylePropertiesDescriptor, +} from '../../../common/descriptor_types'; +import { + AGG_TYPE, + COLOR_MAP_TYPE, + FIELD_ORIGIN, + GRID_RESOLUTION, + RENDER_AS, + SOURCE_TYPES, + STYLE_TYPE, + VECTOR_STYLES, +} from '../../../common/constants'; +import { VectorStyle } from '../styles/vector/vector_style'; +// @ts-ignore +import { ESGeoGridSource } from '../sources/es_geo_grid_source'; +import { VectorLayer } from './vector_layer/vector_layer'; +// @ts-ignore +import { HeatmapLayer } from './heatmap_layer/heatmap_layer'; +import { getDefaultDynamicProperties } from '../styles/vector/vector_style_defaults'; +import { getSourceAggKey } from '../../../common/get_agg_key'; + +const defaultDynamicProperties = getDefaultDynamicProperties(); + +function getGeoGridRequestType(mapType: string): RENDER_AS { + if (mapType === 'Heatmap') { + return RENDER_AS.HEATMAP; + } + + if (mapType === 'Shaded Geohash Grid') { + return RENDER_AS.GRID; + } + + return RENDER_AS.POINT; +} + +function createAggDescriptor(metricAgg: string, metricFieldName?: string): AggDescriptor { + return { type: AGG_TYPE.COUNT }; +} + +export function createTileMapLayerDescriptor({ + title, + mapType, + indexPatternId, + geoFieldName, + metricAgg, + metricFieldName, +}: { + title?: string; + mapType: string; + indexPatternId: string; + geoFieldName?: string; + metricAgg: string; + metricFieldName?: string; +}): LayerDescriptor | null { + if (!geoFieldName) { + return null; + } + + const label = title ? title : 'Coordinate map'; + const metricsDescriptor = createAggDescriptor(metricAgg, metricFieldName); + const geoGridSourceDescriptor = ESGeoGridSource.createDescriptor({ + indexPatternId, + geoField: geoFieldName, + metrics: [metricsDescriptor], + requestType: getGeoGridRequestType(mapType), + resolution: GRID_RESOLUTION.MOST_FINE, + }); + + if (mapType === 'Heatmap') { + return HeatmapLayer.createDescriptor({ + label, + sourceDescriptor: geoGridSourceDescriptor, + }); + } + + const metricSourceKey = getSourceAggKey({ + aggType: metricsDescriptor.type, + aggFieldName: metricsDescriptor.field, + }); + const metricStyleField = { + name: metricSourceKey, + origin: FIELD_ORIGIN.SOURCE, + }; + + const styleProperties: VectorStylePropertiesDescriptor = { + [VECTOR_STYLES.FILL_COLOR]: { + type: STYLE_TYPE.DYNAMIC, + options: { + ...(defaultDynamicProperties[VECTOR_STYLES.FILL_COLOR]!.options as ColorDynamicOptions), + field: metricStyleField, + color: 'Yellow to Red', + type: COLOR_MAP_TYPE.ORDINAL, + }, + }, + [VECTOR_STYLES.LINE_COLOR]: { + type: STYLE_TYPE.STATIC, + options: { + color: '#3d3d3d', + }, + }, + }; + + /* + [VECTOR_STYLES.ICON_SIZE]: { + type: STYLE_TYPE.DYNAMIC, + options: { + ...(defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE]!.options as SizeDynamicOptions), + field: metricStyleField, + }, + } +} +*/ + + return VectorLayer.createDescriptor({ + label, + sourceDescriptor: geoGridSourceDescriptor, + style: VectorStyle.createDescriptor(styleProperties), + }); +} diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 8f49598cf2a8d4..8f8d88ab8a4d14 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -32,7 +32,7 @@ import { HomePublicPluginSetup } from '../../../../src/plugins/home/public'; import { VisualizationsSetup } from '../../../../src/plugins/visualizations/public'; import { APP_ICON_SOLUTION, APP_ID, MAP_SAVED_OBJECT_TYPE } from '../common/constants'; import { VISUALIZE_GEO_FIELD_TRIGGER } from '../../../../src/plugins/ui_actions/public'; -import { createMapsUrlGenerator } from './url_generator'; +import { createMapsUrlGenerator, createTileMapUrlGenerator } from './url_generator'; import { visualizeGeoFieldAction } from './trigger_actions/visualize_geo_field_action'; import { MapEmbeddableFactory } from './embeddable/map_embeddable_factory'; import { EmbeddableSetup } from '../../../../src/plugins/embeddable/public'; @@ -97,15 +97,17 @@ export class MapsPlugin setKibanaCommonConfig(plugins.mapsLegacy.config); setMapAppConfig(config); setKibanaVersion(this._initializerContext.env.packageInfo.version); - plugins.share.urlGenerators.registerUrlGenerator( - createMapsUrlGenerator(async () => { - const [coreStart] = await core.getStartServices(); - return { - appBasePath: coreStart.application.getUrlForApp('maps'), - useHashedUrl: coreStart.uiSettings.get('state:storeInSessionStorage'), - }; - }) - ); + + // register url generators + const getStartServices = async () => { + const [coreStart] = await core.getStartServices(); + return { + appBasePath: coreStart.application.getUrlForApp('maps'), + useHashedUrl: coreStart.uiSettings.get('state:storeInSessionStorage'), + }; + }; + plugins.share.urlGenerators.registerUrlGenerator(createMapsUrlGenerator(getStartServices)); + plugins.share.urlGenerators.registerUrlGenerator(createTileMapUrlGenerator(getStartServices)); plugins.inspector.registerView(MapView); if (plugins.home) { diff --git a/x-pack/plugins/maps/public/url_generator.ts b/x-pack/plugins/maps/public/url_generator.ts index 3fbb361342c7ae..c8cf8174f9fb1b 100644 --- a/x-pack/plugins/maps/public/url_generator.ts +++ b/x-pack/plugins/maps/public/url_generator.ts @@ -16,11 +16,13 @@ import { setStateToKbnUrl } from '../../../../src/plugins/kibana_utils/public'; import { UrlGeneratorsDefinition } from '../../../../src/plugins/share/public'; import { LayerDescriptor } from '../common/descriptor_types'; import { INITIAL_LAYERS_KEY } from '../common/constants'; +import { createTileMapLayerDescriptor } from './classes/layers/create_tile_map_layer_descriptor'; const STATE_STORAGE_KEY = '_a'; const GLOBAL_STATE_STORAGE_KEY = '_g'; export const MAPS_APP_URL_GENERATOR = 'MAPS_APP_URL_GENERATOR'; +export const MAPS_APP_TILE_MAP_URL_GENERATOR = 'MAPS_APP_TILE_MAP_URL_GENERATOR'; export interface MapsUrlGeneratorState { /** @@ -59,51 +61,110 @@ export interface MapsUrlGeneratorState { hash?: boolean; } +type GetStartServices = () => Promise<{ + appBasePath: string; + useHashedUrl: boolean; +}>; + +async function createMapUrl({ + getStartServices, + mapId, + filters, + query, + refreshInterval, + timeRange, + initialLayers, + hash, +}: MapsUrlGeneratorState & { getStartServices: GetStartServices }): Promise { + const startServices = await getStartServices(); + const useHash = hash ?? startServices.useHashedUrl; + const appBasePath = startServices.appBasePath; + + const appState: { + query?: Query; + filters?: Filter[]; + vis?: unknown; + } = {}; + const queryState: QueryState = {}; + + if (query) appState.query = query; + if (filters && filters.length) + appState.filters = filters?.filter((f) => !esFilters.isFilterPinned(f)); + + if (timeRange) queryState.time = timeRange; + if (filters && filters.length) + queryState.filters = filters?.filter((f) => esFilters.isFilterPinned(f)); + if (refreshInterval) queryState.refreshInterval = refreshInterval; + + let url = `${appBasePath}/map#/${mapId || ''}`; + url = setStateToKbnUrl(GLOBAL_STATE_STORAGE_KEY, queryState, { useHash }, url); + url = setStateToKbnUrl(STATE_STORAGE_KEY, appState, { useHash }, url); + + if (initialLayers && initialLayers.length) { + // @ts-ignore + const risonEncodedInitialLayers = rison.encode_array(initialLayers); + url = `${url}&${INITIAL_LAYERS_KEY}=${encodeURIComponent(risonEncodedInitialLayers)}`; + } + + return url; +} + export const createMapsUrlGenerator = ( - getStartServices: () => Promise<{ - appBasePath: string; - useHashedUrl: boolean; - }> + getStartServices: GetStartServices ): UrlGeneratorsDefinition => ({ id: MAPS_APP_URL_GENERATOR, + createUrl: async (mapsUrlGeneratorState: MapsUrlGeneratorState): Promise => { + return createMapUrl({ ...mapsUrlGeneratorState, getStartServices }); + }, +}); + +export const createTileMapUrlGenerator = ( + getStartServices: GetStartServices +): UrlGeneratorsDefinition => ({ + id: MAPS_APP_TILE_MAP_URL_GENERATOR, createUrl: async ({ - mapId, + title, + mapType, + indexPatternId, + geoFieldName, + metricAgg, + metricFieldName, filters, query, - refreshInterval, timeRange, - initialLayers, hash, - }: MapsUrlGeneratorState): Promise => { - const startServices = await getStartServices(); - const useHash = hash ?? startServices.useHashedUrl; - const appBasePath = startServices.appBasePath; - - const appState: { - query?: Query; - filters?: Filter[]; - vis?: unknown; - } = {}; - const queryState: QueryState = {}; - - if (query) appState.query = query; - if (filters && filters.length) - appState.filters = filters?.filter((f) => !esFilters.isFilterPinned(f)); - - if (timeRange) queryState.time = timeRange; - if (filters && filters.length) - queryState.filters = filters?.filter((f) => esFilters.isFilterPinned(f)); - if (refreshInterval) queryState.refreshInterval = refreshInterval; - - let url = `${appBasePath}/map#/${mapId || ''}`; - url = setStateToKbnUrl(GLOBAL_STATE_STORAGE_KEY, queryState, { useHash }, url); - url = setStateToKbnUrl(STATE_STORAGE_KEY, appState, { useHash }, url); - - if (initialLayers && initialLayers.length) { - // @ts-ignore - url = `${url}&${INITIAL_LAYERS_KEY}=${rison.encode_array(initialLayers)}`; + }: { + title?: string; + mapType: string; + indexPatternId: string; + geoFieldName?: string; + metricAgg: string; + metricFieldName?: string; + timeRange?: TimeRange; + filters?: Filter[]; + query?: Query; + hash?: boolean; + }): Promise => { + const initialLayers = []; + const tileMapLayerDescriptor = createTileMapLayerDescriptor({ + title, + mapType, + indexPatternId, + geoFieldName, + metricAgg, + metricFieldName, + }); + if (tileMapLayerDescriptor) { + initialLayers.push(tileMapLayerDescriptor); } - return url; + return createMapUrl({ + initialLayers, + filters, + query, + timeRange, + hash: true, + getStartServices, + }); }, }); From a18083ccf7af3b7830e4a240ff4b70776faccdc6 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 17 Sep 2020 09:20:03 -0600 Subject: [PATCH 37/46] set metrics and color and scaling --- .../public/get_deprecation_message.tsx | 1 + .../create_tile_map_layer_descriptor.test.ts | 43 +++++++++++++++++ .../create_tile_map_layer_descriptor.ts | 47 ++++++++++++++----- x-pack/plugins/maps/public/url_generator.ts | 3 ++ 4 files changed, 81 insertions(+), 13 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.test.ts diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx index b68b842c00839d..ad7e5b83e49b69 100644 --- a/src/plugins/tile_map/public/get_deprecation_message.tsx +++ b/src/plugins/tile_map/public/get_deprecation_message.tsx @@ -86,6 +86,7 @@ export function getDeprecationMessage(vis: Vis) { const url = await mapsTileMapUrlGenerator.createUrl({ title: vis.title, mapType: vis.params.mapType, + colorSchema: vis.params.colorSchema, indexPatternId: vis.data.indexPattern.id, geoFieldName, metricAgg, diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.test.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.test.ts new file mode 100644 index 00000000000000..18e5f462bb3106 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.test.ts @@ -0,0 +1,43 @@ +/* + * 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 { createAggDescriptor } from './create_tile_map_layer_descriptor'; + +describe('createAggDescriptor', () => { + test('Should allow supported metric aggs', () => { + expect(createAggDescriptor('Scaled Circle Markers', 'sum', 'bytes')).toEqual({ + type: 'sum', + field: 'bytes', + }); + }); + + test('Should fallback to count when field not provided', () => { + expect(createAggDescriptor('Scaled Circle Markers', 'sum', undefined)).toEqual({ + type: 'count', + }); + }); + + test('Should fallback to count when metric agg is not supported in maps', () => { + expect(createAggDescriptor('Scaled Circle Markers', 'top_hits', 'bytes')).toEqual({ + type: 'count', + }); + }); + + describe('heatmap', () => { + test('Should allow countable metric aggs', () => { + expect(createAggDescriptor('Heatmap', 'sum', 'bytes')).toEqual({ + type: 'sum', + field: 'bytes', + }); + }); + + test('Should fallback to count for non-countable metric aggs', () => { + expect(createAggDescriptor('Heatmap', 'avg', 'bytes')).toEqual({ + type: 'count', + }); + }); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts index 1a815c14bafd25..a29b22cbf0477c 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts @@ -31,29 +31,47 @@ import { VectorLayer } from './vector_layer/vector_layer'; // @ts-ignore import { HeatmapLayer } from './heatmap_layer/heatmap_layer'; import { getDefaultDynamicProperties } from '../styles/vector/vector_style_defaults'; +import { NUMERICAL_COLOR_PALETTES } from '../styles/color_palettes'; import { getSourceAggKey } from '../../../common/get_agg_key'; +import { isMetricCountable } from '../util/is_metric_countable'; const defaultDynamicProperties = getDefaultDynamicProperties(); +function isHeatmap(mapType: string): boolean { + return mapType.toLowerCase() === 'heatmap'; +} + function getGeoGridRequestType(mapType: string): RENDER_AS { - if (mapType === 'Heatmap') { + if (isHeatmap(mapType)) { return RENDER_AS.HEATMAP; } - if (mapType === 'Shaded Geohash Grid') { + if (mapType.toLowerCase() === 'shaded geohash grid') { return RENDER_AS.GRID; } return RENDER_AS.POINT; } -function createAggDescriptor(metricAgg: string, metricFieldName?: string): AggDescriptor { - return { type: AGG_TYPE.COUNT }; +export function createAggDescriptor( + mapType: string, + metricAgg: string, + metricFieldName?: string +): AggDescriptor { + const aggTypeKey = Object.keys(AGG_TYPE).find((key) => { + return AGG_TYPE[key] === metricAgg; + }); + const aggType = aggTypeKey ? AGG_TYPE[aggTypeKey] : undefined; + + return aggType && metricFieldName && (!isHeatmap(mapType) || isMetricCountable(aggType)) + ? { type: aggType, field: metricFieldName } + : { type: AGG_TYPE.COUNT }; } export function createTileMapLayerDescriptor({ title, mapType, + colorSchema, indexPatternId, geoFieldName, metricAgg, @@ -61,6 +79,7 @@ export function createTileMapLayerDescriptor({ }: { title?: string; mapType: string; + colorSchema: string; indexPatternId: string; geoFieldName?: string; metricAgg: string; @@ -71,7 +90,7 @@ export function createTileMapLayerDescriptor({ } const label = title ? title : 'Coordinate map'; - const metricsDescriptor = createAggDescriptor(metricAgg, metricFieldName); + const metricsDescriptor = createAggDescriptor(mapType, metricAgg, metricFieldName); const geoGridSourceDescriptor = ESGeoGridSource.createDescriptor({ indexPatternId, geoField: geoFieldName, @@ -80,7 +99,7 @@ export function createTileMapLayerDescriptor({ resolution: GRID_RESOLUTION.MOST_FINE, }); - if (mapType === 'Heatmap') { + if (isHeatmap(mapType)) { return HeatmapLayer.createDescriptor({ label, sourceDescriptor: geoGridSourceDescriptor, @@ -96,13 +115,16 @@ export function createTileMapLayerDescriptor({ origin: FIELD_ORIGIN.SOURCE, }; + const colorPallette = NUMERICAL_COLOR_PALETTES.find((pallette) => { + return pallette.value.toLowerCase() === colorSchema.toLowerCase(); + }); const styleProperties: VectorStylePropertiesDescriptor = { [VECTOR_STYLES.FILL_COLOR]: { type: STYLE_TYPE.DYNAMIC, options: { ...(defaultDynamicProperties[VECTOR_STYLES.FILL_COLOR]!.options as ColorDynamicOptions), field: metricStyleField, - color: 'Yellow to Red', + color: colorPallette ? colorPallette.value : 'Yellow to Red', type: COLOR_MAP_TYPE.ORDINAL, }, }, @@ -113,17 +135,16 @@ export function createTileMapLayerDescriptor({ }, }, }; - - /* - [VECTOR_STYLES.ICON_SIZE]: { + if (mapType.toLowerCase() === 'scaled circle markers') { + styleProperties[VECTOR_STYLES.ICON_SIZE] = { type: STYLE_TYPE.DYNAMIC, options: { ...(defaultDynamicProperties[VECTOR_STYLES.ICON_SIZE]!.options as SizeDynamicOptions), + maxSize: 18, field: metricStyleField, }, - } -} -*/ + }; + } return VectorLayer.createDescriptor({ label, diff --git a/x-pack/plugins/maps/public/url_generator.ts b/x-pack/plugins/maps/public/url_generator.ts index c8cf8174f9fb1b..e9de05d8dd067f 100644 --- a/x-pack/plugins/maps/public/url_generator.ts +++ b/x-pack/plugins/maps/public/url_generator.ts @@ -125,6 +125,7 @@ export const createTileMapUrlGenerator = ( createUrl: async ({ title, mapType, + colorSchema, indexPatternId, geoFieldName, metricAgg, @@ -136,6 +137,7 @@ export const createTileMapUrlGenerator = ( }: { title?: string; mapType: string; + colorSchema: string; indexPatternId: string; geoFieldName?: string; metricAgg: string; @@ -149,6 +151,7 @@ export const createTileMapUrlGenerator = ( const tileMapLayerDescriptor = createTileMapLayerDescriptor({ title, mapType, + colorSchema, indexPatternId, geoFieldName, metricAgg, From 820acb303ce48db06a1a54c3a8227b0a9168a9c8 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 17 Sep 2020 09:27:15 -0600 Subject: [PATCH 38/46] lazy load createTileMapLayerDescriptor --- .../maps/public/lazy_load_bundle/index.ts | 19 +++++++++++++++++++ .../public/lazy_load_bundle/lazy/index.ts | 1 + x-pack/plugins/maps/public/url_generator.ts | 5 +++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/lazy_load_bundle/index.ts b/x-pack/plugins/maps/public/lazy_load_bundle/index.ts index 03752a1c3e11e8..8041e75020a498 100644 --- a/x-pack/plugins/maps/public/lazy_load_bundle/index.ts +++ b/x-pack/plugins/maps/public/lazy_load_bundle/index.ts @@ -48,6 +48,23 @@ interface LazyLoadedMapModules { registerLayerWizard: (layerWizard: LayerWizard) => void; registerSource(entry: SourceRegistryEntry): void; getIndexPatternsFromIds: (indexPatternIds: string[]) => Promise; + createTileMapLayerDescriptor: ({ + title, + mapType, + colorSchema, + indexPatternId, + geoFieldName, + metricAgg, + metricFieldName, + }: { + title?: string; + mapType: string; + colorSchema: string; + indexPatternId: string; + geoFieldName?: string; + metricAgg: string; + metricFieldName?: string; + }) => LayerDescriptor | null; } export async function lazyLoadMapModules(): Promise { @@ -72,6 +89,7 @@ export async function lazyLoadMapModules(): Promise { registerLayerWizard, registerSource, getIndexPatternsFromIds, + createTileMapLayerDescriptor, } = await import('./lazy'); resolve({ @@ -90,6 +108,7 @@ export async function lazyLoadMapModules(): Promise { registerLayerWizard, registerSource, getIndexPatternsFromIds, + createTileMapLayerDescriptor, }); }); return loadModulesPromise; diff --git a/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts b/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts index 28f5acdc17656a..d20af9eb40ff34 100644 --- a/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts +++ b/x-pack/plugins/maps/public/lazy_load_bundle/lazy/index.ts @@ -20,3 +20,4 @@ export * from '../../classes/layers/solution_layers/security'; export { registerLayerWizard } from '../../classes/layers/layer_wizard_registry'; export { registerSource } from '../../classes/sources/source_registry'; export { getIndexPatternsFromIds } from '../../index_pattern_util'; +export { createTileMapLayerDescriptor } from '../../classes/layers/create_tile_map_layer_descriptor'; diff --git a/x-pack/plugins/maps/public/url_generator.ts b/x-pack/plugins/maps/public/url_generator.ts index e9de05d8dd067f..5f20817531b9aa 100644 --- a/x-pack/plugins/maps/public/url_generator.ts +++ b/x-pack/plugins/maps/public/url_generator.ts @@ -16,7 +16,7 @@ import { setStateToKbnUrl } from '../../../../src/plugins/kibana_utils/public'; import { UrlGeneratorsDefinition } from '../../../../src/plugins/share/public'; import { LayerDescriptor } from '../common/descriptor_types'; import { INITIAL_LAYERS_KEY } from '../common/constants'; -import { createTileMapLayerDescriptor } from './classes/layers/create_tile_map_layer_descriptor'; +import { lazyLoadMapModules } from './lazy_load_bundle'; const STATE_STORAGE_KEY = '_a'; const GLOBAL_STATE_STORAGE_KEY = '_g'; @@ -147,8 +147,9 @@ export const createTileMapUrlGenerator = ( query?: Query; hash?: boolean; }): Promise => { + const mapModules = await lazyLoadMapModules(); const initialLayers = []; - const tileMapLayerDescriptor = createTileMapLayerDescriptor({ + const tileMapLayerDescriptor = mapModules.createTileMapLayerDescriptor({ title, mapType, colorSchema, From c9fa756f677617e7164dcdf741fa8f768c20c75b Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 17 Sep 2020 12:55:55 -0600 Subject: [PATCH 39/46] tslint fixes --- .../public/get_deprecation_message.tsx | 2 +- .../public/vis_types/base_vis_type.ts | 1 + .../components/deprecated_vis_info.tsx | 2 +- .../components/visualize_editor_common.tsx | 41 ++++++++++--------- .../create_tile_map_layer_descriptor.ts | 13 +++--- 5 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx index ad7e5b83e49b69..c92f6374bcd1c8 100644 --- a/src/plugins/tile_map/public/get_deprecation_message.tsx +++ b/src/plugins/tile_map/public/get_deprecation_message.tsx @@ -18,11 +18,11 @@ */ import React from 'react'; -import { i18n } from '@kbn/i18n'; import { EuiButton, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { getCoreService, getQueryService, getShareService } from './services'; import { indexPatterns } from '../../data/public'; +import { Vis } from '../../visualizations/public'; export function getDeprecationMessage(vis: Vis) { const mapsTileMapUrlGenerator = getShareService().urlGenerators.getUrlGenerator( diff --git a/src/plugins/visualizations/public/vis_types/base_vis_type.ts b/src/plugins/visualizations/public/vis_types/base_vis_type.ts index 9a2ab70d5f09ec..cf7a8b8def26e1 100644 --- a/src/plugins/visualizations/public/vis_types/base_vis_type.ts +++ b/src/plugins/visualizations/public/vis_types/base_vis_type.ts @@ -22,6 +22,7 @@ import { ReactElement } from 'react'; import { VisToExpressionAst, VisualizationControllerConstructor } from '../types'; import { TriggerContextMapping } from '../../../ui_actions/public'; import { Adapters } from '../../../inspector/public'; +import { Vis } from '../vis'; export interface BaseVisTypeOptions { name: string; diff --git a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx index 9b4ed5cb4dfa1b..5e7728480f167f 100644 --- a/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx +++ b/src/plugins/visualize/public/application/components/deprecated_vis_info.tsx @@ -20,7 +20,7 @@ import React, { ReactElement } from 'react'; import { EuiCallOut } from '@elastic/eui'; -export function DeprecatedVisInfo({ message }: ReactElement) { +export function DeprecatedVisInfo({ message }: { message: ReactElement }) { return (

- {'savedVis' in visInstance && visInstance.savedVis.id ? ( - - ) : ( - - )} + { + // @ts-expect-error + 'savedVis' in visInstance && visInstance.savedVis.id ? ( + + ) : ( + + ) + }

)} diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts index a29b22cbf0477c..9a1e5f65ce7bc8 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts @@ -4,14 +4,12 @@ * you may not use this file except in compliance with the Elastic License. */ -import uuid from 'uuid/v4'; import { i18n } from '@kbn/i18n'; import { AggDescriptor, ColorDynamicOptions, LayerDescriptor, SizeDynamicOptions, - StylePropertyField, VectorStylePropertiesDescriptor, } from '../../../common/descriptor_types'; import { @@ -20,7 +18,6 @@ import { FIELD_ORIGIN, GRID_RESOLUTION, RENDER_AS, - SOURCE_TYPES, STYLE_TYPE, VECTOR_STYLES, } from '../../../common/constants'; @@ -59,9 +56,9 @@ export function createAggDescriptor( metricFieldName?: string ): AggDescriptor { const aggTypeKey = Object.keys(AGG_TYPE).find((key) => { - return AGG_TYPE[key] === metricAgg; + return AGG_TYPE[key as keyof typeof AGG_TYPE] === metricAgg; }); - const aggType = aggTypeKey ? AGG_TYPE[aggTypeKey] : undefined; + const aggType = aggTypeKey ? AGG_TYPE[aggTypeKey as keyof typeof AGG_TYPE] : undefined; return aggType && metricFieldName && (!isHeatmap(mapType) || isMetricCountable(aggType)) ? { type: aggType, field: metricFieldName } @@ -89,7 +86,11 @@ export function createTileMapLayerDescriptor({ return null; } - const label = title ? title : 'Coordinate map'; + const label = title + ? title + : i18n.translate('xpack.maps.createTileMapDescriptor.layerLabel', { + defaultMessage: 'Coordinate map', + }); const metricsDescriptor = createAggDescriptor(mapType, metricAgg, metricFieldName); const geoGridSourceDescriptor = ESGeoGridSource.createDescriptor({ indexPatternId, From 99ca7d82d6d9c127ef962ba8d20e5fd51a1b3d19 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 18 Sep 2020 09:27:15 -0400 Subject: [PATCH 40/46] remove things --- x-pack/plugins/maps/public/classes/fields/es_agg_field.ts | 4 ++-- x-pack/plugins/maps/public/classes/fields/field.ts | 3 +-- .../maps/public/classes/fields/top_term_percentage_field.ts | 3 +-- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts index ee8c02b4dc2ff9..8cff98205186fc 100644 --- a/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/es_agg_field.ts @@ -5,12 +5,12 @@ */ import { IndexPattern } from 'src/plugins/data/public'; -import { getMbPropertyName, IField } from './field'; +import { IField } from './field'; import { AggDescriptor } from '../../../common/descriptor_types'; import { IESAggSource } from '../sources/es_agg_source'; import { IVectorSource } from '../sources/vector_source'; import { ESDocField } from './es_doc_field'; -import { AGG_TYPE, FIELD_ORIGIN, VECTOR_STYLES } from '../../../common/constants'; +import { AGG_TYPE, FIELD_ORIGIN } from '../../../common/constants'; import { isMetricCountable } from '../util/is_metric_countable'; import { getField, addFieldToDSL } from '../../../common/elasticsearch_util'; import { TopTermPercentageField } from './top_term_percentage_field'; diff --git a/x-pack/plugins/maps/public/classes/fields/field.ts b/x-pack/plugins/maps/public/classes/fields/field.ts index bc9ac1118d229b..658c2bba878479 100644 --- a/x-pack/plugins/maps/public/classes/fields/field.ts +++ b/x-pack/plugins/maps/public/classes/fields/field.ts @@ -4,10 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { FIELD_ORIGIN, VECTOR_STYLES } from '../../../common/constants'; +import { FIELD_ORIGIN } from '../../../common/constants'; import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; -import { getComputedFieldName } from '../styles/vector/style_util'; export interface IField { getName(): string; diff --git a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts index e4d76448f6eb3e..50db04d08b2aab 100644 --- a/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/top_term_percentage_field.ts @@ -7,9 +7,8 @@ import { IESAggField } from './es_agg_field'; import { IVectorSource } from '../sources/vector_source'; import { ITooltipProperty, TooltipProperty } from '../tooltips/tooltip_property'; -import { TOP_TERM_PERCENTAGE_SUFFIX, VECTOR_STYLES } from '../../../common/constants'; +import { TOP_TERM_PERCENTAGE_SUFFIX } from '../../../common/constants'; import { FIELD_ORIGIN } from '../../../common/constants'; -import { getMbPropertyName } from './field'; export class TopTermPercentageField implements IESAggField { private readonly _topTermAggField: IESAggField; From cfc4d21d78eb08c7194547e69f87c4d852ba6701 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 18 Sep 2020 10:49:18 -0400 Subject: [PATCH 41/46] add unit tests --- .../es_geo_grid_source.test.ts | 128 ++++++++++++------ 1 file changed, 83 insertions(+), 45 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts index 28001391433b98..0359b8cf5fbb39 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.test.ts @@ -7,7 +7,7 @@ import { MapExtent, VectorSourceRequestMeta } from '../../../../common/descripto jest.mock('../../../kibana_services'); -import { getIndexPatternService, getSearchService } from '../../../kibana_services'; +import { getIndexPatternService, getSearchService, getHttp } from '../../../kibana_services'; import { ESGeoGridSource } from './es_geo_grid_source'; import { ES_GEO_FIELD_TYPE, @@ -20,6 +20,9 @@ import { SearchSource } from '../../../../../../../src/plugins/data/public/searc export class MockSearchSource { setField = jest.fn(); setParent() {} + getSearchRequestBody() { + return { foobar: 'ES_DSL_PLACEHOLDER', params: this.setField.mock.calls }; + } } describe('ESGeoGridSource', () => { @@ -96,59 +99,67 @@ describe('ESGeoGridSource', () => { }; }; - describe('getGeoJsonWithMeta', () => { - let mockSearchSource: unknown; - beforeEach(async () => { - mockSearchSource = new MockSearchSource(); - const mockSearchService = { - searchSource: { - async create() { - return mockSearchSource as SearchSource; - }, - createEmpty() { - return mockSearchSource as SearchSource; - }, + let mockSearchSource: unknown; + beforeEach(async () => { + mockSearchSource = new MockSearchSource(); + const mockSearchService = { + searchSource: { + async create() { + return mockSearchSource as SearchSource; }, - }; + createEmpty() { + return mockSearchSource as SearchSource; + }, + }, + }; - // @ts-expect-error - getIndexPatternService.mockReturnValue(mockIndexPatternService); - // @ts-expect-error - getSearchService.mockReturnValue(mockSearchService); + // @ts-expect-error + getIndexPatternService.mockReturnValue(mockIndexPatternService); + // @ts-expect-error + getSearchService.mockReturnValue(mockSearchService); + // @ts-expect-error + getHttp.mockReturnValue({ + basePath: { + prepend(path: string) { + return `rootdir${path};`; + }, + }, }); + }); - const extent: MapExtent = { - minLon: -160, - minLat: -80, - maxLon: 160, - maxLat: 80, - }; + const extent: MapExtent = { + minLon: -160, + minLat: -80, + maxLon: 160, + maxLat: 80, + }; - const mapFilters: VectorSourceRequestMeta = { - geogridPrecision: 4, - filters: [], - timeFilters: { - from: 'now', - to: '15m', - mode: 'relative', - }, - extent, - applyGlobalQuery: true, - fieldNames: [], - buffer: extent, - sourceQuery: { - query: '', - language: 'KQL', - queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', - }, - sourceMeta: null, - zoom: 0, - }; + const vectorSourceRequestMeta: VectorSourceRequestMeta = { + geogridPrecision: 4, + filters: [], + timeFilters: { + from: 'now', + to: '15m', + mode: 'relative', + }, + extent, + applyGlobalQuery: true, + fieldNames: [], + buffer: extent, + sourceQuery: { + query: '', + language: 'KQL', + queryLastTriggeredAt: '2019-04-25T20:53:22.331Z', + }, + sourceMeta: null, + zoom: 0, + }; + describe('getGeoJsonWithMeta', () => { it('Should configure the SearchSource correctly', async () => { const { data, meta } = await geogridSource.getGeoJsonWithMeta( 'foobarLayer', - mapFilters, + vectorSourceRequestMeta, () => {} ); @@ -232,4 +243,31 @@ describe('ESGeoGridSource', () => { expect(superFineSource.getGeoGridPrecision(10)).toBe(NaN); }); }); + + describe('ITiledSingleLayerVectorSource', () => { + it('getLayerName', () => { + expect(geogridSource.getLayerName()).toBe('source_layer'); + }); + + it('getMinZoom', () => { + expect(geogridSource.getMinZoom()).toBe(0); + }); + + it('getMaxZoom', () => { + expect(geogridSource.getMaxZoom()).toBe(24); + }); + + it('getUrlTemplateWithMeta', async () => { + const urlTemplateWithMeta = await geogridSource.getUrlTemplateWithMeta( + vectorSourceRequestMeta + ); + + expect(urlTemplateWithMeta.layerName).toBe('source_layer'); + expect(urlTemplateWithMeta.minSourceZoom).toBe(0); + expect(urlTemplateWithMeta.maxSourceZoom).toBe(24); + expect(urlTemplateWithMeta.urlTemplate).toBe( + "rootdir/api/maps/mvt/getGridTile;?x={x}&y={y}&z={z}&geometryFieldName=bar&index=undefined&requestBody=(foobar:ES_DSL_PLACEHOLDER,params:('0':('0':index,'1':(fields:())),'1':('0':size,'1':0),'2':('0':filter,'1':!((geo_bounding_box:(bar:(bottom_right:!(180,-82.67628),top_left:!(-180,82.67628)))))),'3':('0':query),'4':('0':index,'1':(fields:())),'5':('0':query,'1':(language:KQL,query:'',queryLastTriggeredAt:'2019-04-25T20:53:22.331Z')),'6':('0':aggs,'1':(gridSplit:(aggs:(gridCentroid:(geo_centroid:(field:bar))),geotile_grid:(bounds:!n,field:bar,precision:-1,shard_size:65535,size:65535))))))&requestType=heatmap&geoFieldType=geo_point" + ); + }); + }); }); From bb478aa99fe69bd7c0ef8dd71e84f372b39f5c54 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 18 Sep 2020 11:22:03 -0400 Subject: [PATCH 42/46] add unit tests --- .../update_source_editor.test.tsx.snap | 181 ++++++++++++++++++ .../resolution_editor.test.tsx | 29 +++ .../update_source_editor.test.tsx | 45 +++++ 3 files changed, 255 insertions(+) create mode 100644 x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap create mode 100644 x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx create mode 100644 x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap new file mode 100644 index 00000000000000..97d51e77fb87cf --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap @@ -0,0 +1,181 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`source editor geo_grid_source default vector layer config should allow super-fine option 1`] = ` + + + +
+ +
+
+ + +
+ + + +
+ +
+
+ + + +
+ +
+`; + +exports[`source editor geo_grid_source should put limitations based on heatmap-rendering selection should disable multiple metrics 1`] = ` + + + +
+ +
+
+ + +
+ + + +
+ +
+
+ + + +
+ +
+`; + +exports[`source editor geo_grid_source should put limitations based on heatmap-rendering selection should not allow super-fine option for heatmaps 1`] = ` + + + +
+ +
+
+ + +
+ + + +
+ +
+
+ + + +
+ +
+`; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx new file mode 100644 index 00000000000000..909dd210593ff6 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx @@ -0,0 +1,29 @@ +/* + * 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 from 'react'; +import { shallow } from 'enzyme'; + +// @ts-expect-error +import { ResolutionEditor } from './resolution_editor'; +import { GRID_RESOLUTION } from '../../../../common/constants'; + +const defaultProps = { + resolution: GRID_RESOLUTION.COARSE, + onChange: () => {}, + includeSuperFine: false, +}; + +describe('resolution editor', () => { + test('should omit super-fine option', async () => { + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + test('should add super-fine option', async () => { + const component = shallow(); + expect(component).toMatchSnapshot(); + }); +}); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx new file mode 100644 index 00000000000000..2d9dce6c82f882 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx @@ -0,0 +1,45 @@ +/* + * 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 from 'react'; +import { shallow } from 'enzyme'; + +// @ts-expect-error +import { UpdateSourceEditor } from './update_source_editor'; +import { GRID_RESOLUTION, LAYER_TYPE, RENDER_AS } from '../../../../common/constants'; + +const defaultProps = { + currentLayerType: LAYER_TYPE.VECTOR, + indexPatternId: 'foobar', + onChange: () => {}, + metrics: [], + renderAs: RENDER_AS.POINT, + resolution: GRID_RESOLUTION.COARSE, +}; + +describe('source editor geo_grid_source', () => { + describe('default vector layer config', () => { + test('should allow super-fine option', async () => { + const component = shallow(); + expect(component).toMatchSnapshot(); + }); + }); + + describe('should put limitations based on heatmap-rendering selection', () => { + test('should not allow super-fine option for heatmaps', async () => { + const component = shallow( + + ); + expect(component).toMatchSnapshot(); + }); + test('should disable multiple metrics', async () => { + const component = shallow( + + ); + expect(component).toMatchSnapshot(); + }); + }); +}); From 45d587b3cffdfa74f9d61b8c9c2dc077fa9ceb9d Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Fri, 18 Sep 2020 09:27:23 -0600 Subject: [PATCH 43/46] tslint cleanup for OSS code --- .../public/get_deprecation_message.tsx | 49 +++++++++---------- src/plugins/tile_map/public/plugin.ts | 2 +- src/plugins/tile_map/public/services.ts | 4 +- .../create_tile_map_layer_descriptor.ts | 4 +- x-pack/plugins/maps/public/url_generator.ts | 2 +- 5 files changed, 29 insertions(+), 32 deletions(-) diff --git a/src/plugins/tile_map/public/get_deprecation_message.tsx b/src/plugins/tile_map/public/get_deprecation_message.tsx index c92f6374bcd1c8..b322fc7bf3f16c 100644 --- a/src/plugins/tile_map/public/get_deprecation_message.tsx +++ b/src/plugins/tile_map/public/get_deprecation_message.tsx @@ -53,14 +53,25 @@ export function getDeprecationMessage(vis: Vis) { action = (
{ + onClick={async (e: React.MouseEvent) => { e.preventDefault(); - let geoFieldName: string; - const bucketAggs = vis.data?.aggs.byType('buckets'); - if (bucketAggs.length && bucketAggs[0].type.dslName === 'geohash_grid') { - geoFieldName = bucketAggs[0].getField()?.name; - } else { + const query = getQueryService(); + const createUrlParams = { + title: vis.title, + mapType: vis.params.mapType, + colorSchema: vis.params.colorSchema, + indexPatternId: vis.data.indexPattern?.id, + metricAgg: 'count', + filters: query.filterManager.getFilters(), + query: query.queryString.getQuery(), + timeRange: query.timefilter.timefilter.getTime(), + }; + + const bucketAggs = vis.data?.aggs?.byType('buckets'); + if (bucketAggs?.length && bucketAggs[0].type.dslName === 'geohash_grid') { + createUrlParams.geoFieldName = bucketAggs[0].getField()?.name; + } else if (vis.data.indexPattern) { // attempt to default to first geo point field when geohash is not configured yet const geoField = vis.data.indexPattern.fields.find((field) => { return ( @@ -70,31 +81,17 @@ export function getDeprecationMessage(vis: Vis) { ); }); if (geoField) { - geoFieldName = geoField.name; + createUrlParams.geoFieldName = geoField.name; } } - let metricAgg: string = 'count'; - let metricFieldName: string; - const metricAggs = vis.data?.aggs.byType('metrics'); - if (metricAggs.length) { - metricAgg = metricAggs[0].type.dslName; - metricFieldName = metricAggs[0].getField()?.name; + const metricAggs = vis.data?.aggs?.byType('metrics'); + if (metricAggs?.length) { + createUrlParams.metricAgg = metricAggs[0].type.dslName; + createUrlParams.metricFieldName = metricAggs[0].getField()?.name; } - const query = getQueryService(); - const url = await mapsTileMapUrlGenerator.createUrl({ - title: vis.title, - mapType: vis.params.mapType, - colorSchema: vis.params.colorSchema, - indexPatternId: vis.data.indexPattern.id, - geoFieldName, - metricAgg, - metricFieldName, - filters: query.filterManager.getFilters(), - query: query.queryString.getQuery(), - timeRange: query.timefilter.timefilter.getTime(), - }); + const url = await mapsTileMapUrlGenerator.createUrl(createUrlParams); getCoreService().application.navigateToUrl(url); }} size="s" diff --git a/src/plugins/tile_map/public/plugin.ts b/src/plugins/tile_map/public/plugin.ts index b4baac248ffc7a..49c4a8f1228791 100644 --- a/src/plugins/tile_map/public/plugin.ts +++ b/src/plugins/tile_map/public/plugin.ts @@ -42,7 +42,7 @@ import { setShareService, } from './services'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; -import { SharePluginSetup, SharePluginStart } from '../../share/public'; +import { SharePluginStart } from '../../share/public'; export interface TileMapConfigType { tilemap: any; diff --git a/src/plugins/tile_map/public/services.ts b/src/plugins/tile_map/public/services.ts index 8ddb9daeff7a99..a0435d9ba4dc0d 100644 --- a/src/plugins/tile_map/public/services.ts +++ b/src/plugins/tile_map/public/services.ts @@ -21,7 +21,7 @@ import { CoreStart } from 'kibana/public'; import { createGetterSetter } from '../../kibana_utils/public'; import { DataPublicPluginStart } from '../../data/public'; import { KibanaLegacyStart } from '../../kibana_legacy/public'; -import { SharePluginSetup, SharePluginStart } from '../../share/public'; +import { SharePluginStart } from '../../share/public'; export const [getCoreService, setCoreService] = createGetterSetter('Core'); @@ -33,7 +33,7 @@ export const [getQueryService, setQueryService] = createGetterSetter< DataPublicPluginStart['query'] >('Query'); -export const [getShareService, setShareService] = createGetterSetter('Share'); +export const [getShareService, setShareService] = createGetterSetter('Share'); export const [getKibanaLegacy, setKibanaLegacy] = createGetterSetter( 'KibanaLegacy' diff --git a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts index 9a1e5f65ce7bc8..7bb501f69c1c0b 100644 --- a/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts +++ b/x-pack/plugins/maps/public/classes/layers/create_tile_map_layer_descriptor.ts @@ -77,12 +77,12 @@ export function createTileMapLayerDescriptor({ title?: string; mapType: string; colorSchema: string; - indexPatternId: string; + indexPatternId?: string; geoFieldName?: string; metricAgg: string; metricFieldName?: string; }): LayerDescriptor | null { - if (!geoFieldName) { + if (!indexPatternId || !geoFieldName) { return null; } diff --git a/x-pack/plugins/maps/public/url_generator.ts b/x-pack/plugins/maps/public/url_generator.ts index 5f20817531b9aa..8b8308ad678828 100644 --- a/x-pack/plugins/maps/public/url_generator.ts +++ b/x-pack/plugins/maps/public/url_generator.ts @@ -138,7 +138,7 @@ export const createTileMapUrlGenerator = ( title?: string; mapType: string; colorSchema: string; - indexPatternId: string; + indexPatternId?: string; geoFieldName?: string; metricAgg: string; metricFieldName?: string; From 9fce05d08bdc3878dccbc09981d155a865676474 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Fri, 18 Sep 2020 11:27:31 -0400 Subject: [PATCH 44/46] add snapshot --- .../resolution_editor.test.tsx.snap | 73 +++++++++++++++++++ .../resolution_editor.test.tsx | 4 +- 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap new file mode 100644 index 00000000000000..ca9775594a9d73 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/resolution_editor.test.tsx.snap @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`resolution editor should add super-fine option 1`] = ` + + + +`; + +exports[`resolution editor should omit super-fine option 1`] = ` + + + +`; diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx index 909dd210593ff6..fe4b215912955b 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx @@ -19,11 +19,11 @@ const defaultProps = { describe('resolution editor', () => { test('should omit super-fine option', async () => { - const component = shallow(); + const component = shallow(); expect(component).toMatchSnapshot(); }); test('should add super-fine option', async () => { - const component = shallow(); + const component = shallow(); expect(component).toMatchSnapshot(); }); }); From debec1eb27f5e680e4f8f5eade13b5eef463fec2 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 22 Sep 2020 10:22:14 -0400 Subject: [PATCH 45/46] feedback --- .../es_geo_grid_source/es_geo_grid_source.js | 36 +++++++++---------- .../resolution_editor.test.tsx | 4 +-- .../update_source_editor.js | 7 ++-- .../classes/styles/heatmap/heatmap_style.tsx | 3 +- 4 files changed, 21 insertions(+), 29 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js index 2152b2dd16c4eb..16694d0d4fc3ae 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.js @@ -111,10 +111,6 @@ export class ESGeoGridSource extends AbstractESAggSource { ]; } - getMetricFields() { - return super.getMetricFields(); - } - getFieldNames() { return this.getMetricFields().map((esAggMetricField) => esAggMetricField.getName()); } @@ -139,11 +135,12 @@ export class ESGeoGridSource extends AbstractESAggSource { } getGeoGridPrecision(zoom) { - const delta = this._getGeoGridPrecisionResolutionDelta(); - if (delta === null) { + if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) { + // The target-precision needs to be determined server side. return NaN; } - const targetGeotileLevel = Math.ceil(zoom) + delta; + + const targetGeotileLevel = Math.ceil(zoom) + this._getGeoGridPrecisionResolutionDelta(); return Math.min(targetGeotileLevel, MAX_GEOTILE_LEVEL); } @@ -160,11 +157,6 @@ export class ESGeoGridSource extends AbstractESAggSource { return 4; } - if (this._descriptor.resolution === GRID_RESOLUTION.SUPER_FINE) { - // The target-precision needs to be determined server side. - return null; - } - throw new Error( i18n.translate('xpack.maps.source.esGrid.resolutionParamErrorMessage', { defaultMessage: `Grid resolution param not recognized: {resolution}`, @@ -267,7 +259,9 @@ export class ESGeoGridSource extends AbstractESAggSource { _addNonCompositeAggregationsToSearchSource( searchSource, - { indexPattern, precision, bufferedExtent } + indexPattern, + precision, + bufferedExtent ) { searchSource.setField('aggs', { [GEOTILE_GRID_AGG_NAME]: { @@ -300,11 +294,12 @@ export class ESGeoGridSource extends AbstractESAggSource { registerCancelCallback, bufferedExtent, }) { - this._addNonCompositeAggregationsToSearchSource(searchSource, { + this._addNonCompositeAggregationsToSearchSource( + searchSource, indexPattern, precision, - bufferedExtent, - }); + bufferedExtent + ); const esResponse = await this._runEsQuery({ requestId: this.getId(), @@ -368,11 +363,12 @@ export class ESGeoGridSource extends AbstractESAggSource { const indexPattern = await this.getIndexPattern(); const searchSource = await this.makeSearchSource(searchFilters, 0); - this._addNonCompositeAggregationsToSearchSource(searchSource, { + this._addNonCompositeAggregationsToSearchSource( + searchSource, indexPattern, - precision: -1, // This needs to be set server-side - bufferedExtent: null, //this needs to be stripped server-side - }); + null, // needs to be set server-side + null // needs to be stripped server-side + ); const dsl = await searchSource.getSearchRequestBody(); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx index fe4b215912955b..369203dbe16c0f 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/resolution_editor.test.tsx @@ -18,11 +18,11 @@ const defaultProps = { }; describe('resolution editor', () => { - test('should omit super-fine option', async () => { + test('should omit super-fine option', () => { const component = shallow(); expect(component).toMatchSnapshot(); }); - test('should add super-fine option', async () => { + test('should add super-fine option', () => { const component = shallow(); expect(component).toMatchSnapshot(); }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js index 9a3b747906c5b2..daf19d2a6f0bd4 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.js @@ -68,11 +68,8 @@ export class UpdateSourceEditor extends Component { this.props.currentLayerType === LAYER_TYPE.VECTOR || this.props.currentLayerType === LAYER_TYPE.TILED_VECTOR ) { - if (resolution === GRID_RESOLUTION.SUPER_FINE) { - newLayerType = LAYER_TYPE.TILED_VECTOR; - } else { - newLayerType = LAYER_TYPE.VECTOR; - } + newLayerType = + resolution === GRID_RESOLUTION.SUPER_FINE ? LAYER_TYPE.TILED_VECTOR : LAYER_TYPE.VECTOR; } else if (this.props.currentLayerType === LAYER_TYPE.HEATMAP) { if (resolution === GRID_RESOLUTION.SUPER_FINE) { throw new Error('Heatmap does not support SUPER_FINE resolution'); diff --git a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx index 915e9a8a9b57d4..c75698805225f1 100644 --- a/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/heatmap/heatmap_style.tsx @@ -85,9 +85,8 @@ export class HeatmapStyle implements IStyle { radius = 64; } else if (resolution === GRID_RESOLUTION.MOST_FINE) { radius = 32; - } else if (resolution === GRID_RESOLUTION.SUPER_FINE) { - radius = 8; } else { + // SUPER_FINE or any other is not supported. const errorMessage = i18n.translate('xpack.maps.style.heatmap.resolutionStyleErrorMessage', { defaultMessage: `Resolution param not recognized: {resolution}`, values: { resolution }, From 0b9fe763faeb4e6c421071937432fbdaf7a0bf5e Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 22 Sep 2020 10:28:37 -0400 Subject: [PATCH 46/46] make use of currentLayerType consistent --- .../update_source_editor.test.tsx.snap | 62 +------------------ .../update_source_editor.js | 6 +- .../update_source_editor.test.tsx | 8 +-- 3 files changed, 5 insertions(+), 71 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap index 97d51e77fb87cf..dfce6b36396a75 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/__snapshots__/update_source_editor.test.tsx.snap @@ -60,7 +60,7 @@ exports[`source editor geo_grid_source default vector layer config should allow `; -exports[`source editor geo_grid_source should put limitations based on heatmap-rendering selection should disable multiple metrics 1`] = ` +exports[`source editor geo_grid_source should put limitations based on heatmap-rendering selection should not allow super-fine option for heatmaps and should not allow multiple metrics 1`] = ` - - -
- -
-
- - - -
- -
-`; - -exports[`source editor geo_grid_source should put limitations based on heatmap-rendering selection should not allow super-fine option for heatmaps 1`] = ` - - - -
- -
-
- - -
- { //these are countable metrics, where blending heatmap color blobs make sense return isMetricCountable(metric.value); } : null; - const allowMultipleMetrics = this.props.renderAs !== RENDER_AS.HEATMAP; + const allowMultipleMetrics = this.props.currentLayerType !== LAYER_TYPE.HEATMAP; return ( diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx index 2d9dce6c82f882..ceb79230bc8320 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/update_source_editor.test.tsx @@ -29,17 +29,11 @@ describe('source editor geo_grid_source', () => { }); describe('should put limitations based on heatmap-rendering selection', () => { - test('should not allow super-fine option for heatmaps', async () => { + test('should not allow super-fine option for heatmaps and should not allow multiple metrics', async () => { const component = shallow( ); expect(component).toMatchSnapshot(); }); - test('should disable multiple metrics', async () => { - const component = shallow( - - ); - expect(component).toMatchSnapshot(); - }); }); });