From d0c462b6bfaebd2db6f1217150eee98441294fd7 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 16 Mar 2021 15:31:25 -0400 Subject: [PATCH 01/68] init boilerplate --- .../public/actions/data_request_actions.ts | 41 +++++++++++++------ .../maps/public/actions/layer_actions.ts | 16 ++++++++ .../maps/public/classes/layers/layer.tsx | 4 ++ .../tiled_vector_layer/tiled_vector_layer.tsx | 28 +++++++++++++ .../properties/dynamic_color_property.tsx | 1 + .../properties/dynamic_style_property.tsx | 4 +- .../properties/test_helpers/test_util.ts | 6 +-- .../classes/styles/vector/style_meta.ts | 2 +- .../classes/styles/vector/vector_style.tsx | 22 +++++++--- .../connected_components/mb_map/index.ts | 8 +++- .../connected_components/mb_map/mb_map.tsx | 18 +++++++- .../mb_map/tile_status_tracker.ts | 2 +- 12 files changed, 123 insertions(+), 29 deletions(-) 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 6b57da132e895..a3d2f41a5a1e5 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -90,23 +90,40 @@ export function cancelAllInFlightRequests() { export function updateStyleMeta(layerId: string | null) { return async (dispatch: Dispatch, getState: () => MapStoreState) => { + console.log('update style meta!', layerId); const layer = getLayerById(layerId, getState()); if (!layer) { return; } - const sourceDataRequest = layer.getSourceDataRequest(); - const style = layer.getCurrentStyle(); - if (!style || !sourceDataRequest || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { - return; + + if ( + layer.getType() === LAYER_TYPE.VECTOR || + layer.getType() === LAYER_TYPE.HEATMAP || + layer.getType() === LAYER_TYPE.BLENDED_VECTOR + ) { + const sourceDataRequest = layer.getSourceDataRequest(); + console.log('sdr', sourceDataRequest); + const style = layer.getCurrentStyle(); + if (!style || !sourceDataRequest || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { + return; + } + const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromSourceDataRequest( + sourceDataRequest + ); + dispatch({ + type: SET_LAYER_STYLE_META, + layerId, + styleMeta, + }); + } else if (layer.getType() === LAYER_TYPE.TILED_VECTOR) { + console.log('do special tile thging here!!!'); + const styleMeta = { fieldMeta: {} }; + dispatch({ + type: SET_LAYER_STYLE_META, + layerId, + styleMeta, + }); } - const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromSourceDataRequest( - sourceDataRequest - ); - dispatch({ - type: SET_LAYER_STYLE_META, - layerId, - styleMeta, - }); }; } diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index fe62e9fe9da51..b3ea90badbf83 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -48,6 +48,7 @@ import { IVectorStyle } from '../classes/styles/vector/vector_style'; import { notifyLicensedFeatureUsage } from '../licensed_features'; import { IESAggField } from '../classes/fields/agg'; import { IField } from '../classes/fields/field'; +import { string } from '../../../security_solution/public/resolver/models/schema'; export function trackCurrentLayerState(layerId: string) { return { @@ -548,3 +549,18 @@ export function setAreTilesLoaded(layerId: string, areTilesLoaded: boolean) { newValue: areTilesLoaded, }; } + +export function updateCounts(layerId: string, foobar: any) { + return async ( + dispatch: ThunkDispatch, + getState: () => MapStoreState + ) => { + console.log('update counts', layerId); + const layer = getLayerById(layerId, getState()); + if (!layer) { + return; + } + + console.log('l', layer); + }; +} diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index a73449b0fa718..01c928c727f15 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -154,6 +154,10 @@ export class AbstractLayer implements ILayer { return mbStyle.sources[sourceId].data; } + queryForTileMeta(mbMap) { + return null; + } + async cloneDescriptor(): Promise { const clonedDescriptor = copyPersistentState(this._descriptor); // layer id is uuid used to track styles/layers in mapbox 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 f2fe916953801..81b0bb6e2649f 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 @@ -156,6 +156,34 @@ export class TiledVectorLayer extends VectorLayer { this._setMbCentroidProperties(mbMap, sourceMeta.layerName); } + queryForTileMeta(mbMap: MbMap) { + console.log('query for tile meta!', mbMap); + + // @ts-ignore + const mbSource = mbMap.getSource(this._getMbSourceId()); + if (!mbSource) { + return null; + } + + const sourceDataRequest = this.getSourceDataRequest(); + if (!sourceDataRequest) { + return; + } + const sourceMeta: MVTSingleLayerVectorSourceConfig = sourceDataRequest.getData() as MVTSingleLayerVectorSourceConfig; + if (sourceMeta.layerName === '') { + return; + } + + console.log('going to queyr', this._getMbSourceId(), sourceMeta.layerName); + const features = mbMap.querySourceFeatures(this._getMbSourceId(), { + sourceLayer: sourceMeta.layerName, + }); + + console.log('f', features); + + return null; + } + _requiresPrevSourceCleanup(mbMap: MbMap): boolean { const mbSource = mbMap.getSource(this._getMbSourceId()) as MbVectorSource | MbGeoJSONSource; if (!mbSource) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx index d654cdc6bff51..48fe1ecb4bf2d 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx @@ -201,6 +201,7 @@ export class DynamicColorProperty extends DynamicStyleProperty getRangeFieldMeta() { const style = this._layer.getStyle() as IVectorStyle; - const styleMeta = style.getStyleMeta(); + const styleMeta = style.getStyleMetaFromLocal(); const fieldName = this.getFieldName(); const rangeFieldMetaFromLocalFeatures = styleMeta.getRangeFieldMetaDescriptor(fieldName); @@ -152,7 +152,7 @@ export class DynamicStyleProperty getCategoryFieldMeta() { const style = this._layer.getStyle() as IVectorStyle; - const styleMeta = style.getStyleMeta(); + const styleMeta = style.getStyleMetaFromLocal(); const fieldName = this.getFieldName(); const categoryFieldMetaFromLocalFeatures = styleMeta.getCategoryFieldMetaDescriptor(fieldName); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts index ff2811f2b3df0..f6abe86a85865 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts @@ -7,7 +7,7 @@ // eslint-disable-next-line max-classes-per-file import { FIELD_ORIGIN, LAYER_STYLE_TYPE } from '../../../../../../common/constants'; -import { StyleMeta } from '../../style_meta'; +import { StyleMetaFromLocal } from '../../style_meta'; import { CategoryFieldMeta, GeometryTypes, @@ -76,7 +76,7 @@ export class MockStyle implements IStyle { return LAYER_STYLE_TYPE.VECTOR; } - getStyleMeta(): StyleMeta { + getStyleMeta(): StyleMetaFromLocal { const geomTypes: GeometryTypes = { isPointsOnly: false, isLinesOnly: false, @@ -110,7 +110,7 @@ export class MockStyle implements IStyle { }, }; - return new StyleMeta(styleMetaDescriptor); + return new StyleMetaFromLocal(styleMetaDescriptor); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts b/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts index 14fab5ca93748..88a1891df2b28 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts @@ -11,7 +11,7 @@ import { CategoryFieldMeta, } from '../../../../common/descriptor_types'; -export class StyleMeta { +export class StyleMetaFromLocal { private readonly _descriptor: StyleMetaDescriptor; constructor(styleMetaDescriptor: StyleMetaDescriptor | null | undefined) { this._descriptor = styleMetaDescriptor ? styleMetaDescriptor : { fieldMeta: {} }; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 692be08d07bc6..de7760649e81a 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -22,7 +22,7 @@ import { VECTOR_SHAPE_TYPE, VECTOR_STYLES, } from '../../../../common/constants'; -import { StyleMeta } from './style_meta'; +import { StyleMetaFromLocal } from './style_meta'; import { VectorIcon } from './components/legend/vector_icon'; import { VectorStyleLegend } from './components/legend/vector_style_legend'; import { isOnlySingleFeatureType } from './style_util'; @@ -83,7 +83,7 @@ export interface IVectorStyle extends IStyle { getAllStyleProperties(): Array>; getDynamicPropertiesArray(): Array>; getSourceFieldNames(): string[]; - getStyleMeta(): StyleMeta; + getStyleMetaFromLocal(): StyleMetaFromLocal; getDescriptorWithUpdatedStyleProps( nextFields: IField[], previousFields: IField[], @@ -145,7 +145,7 @@ export class VectorStyle implements IVectorStyle { private readonly _descriptor: VectorStyleDescriptor; private readonly _layer: IVectorLayer; private readonly _source: IVectorSource; - private readonly _styleMeta: StyleMeta; + private readonly _styleMeta: StyleMetaFromLocal; private readonly _symbolizeAsStyleProperty: SymbolizeAsProperty; private readonly _lineColorStyleProperty: StaticColorProperty | DynamicColorProperty; @@ -190,7 +190,7 @@ export class VectorStyle implements IVectorStyle { } : VectorStyle.createDescriptor(); - this._styleMeta = new StyleMeta(this._descriptor.__styleMeta); + this._styleMeta = new StyleMetaFromLocal(this._descriptor.__styleMeta); this._symbolizeAsStyleProperty = new SymbolizeAsProperty( this._descriptor.properties[VECTOR_STYLES.SYMBOLIZE_AS].options, @@ -488,9 +488,18 @@ export class VectorStyle implements IVectorStyle { ); } - async pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest) { + + + async pluckStyleMetaFromSourceDataRequest( + sourceDataRequest: DataRequest + ): Promise { + + console.log('pluck style meta', sourceDataRequest); + const features = _.get(sourceDataRequest.getData(), 'features', []); + console.log('f', features); + const supportedFeatures = await this._source.getSupportedShapeTypes(); const hasFeatureType = { [VECTOR_SHAPE_TYPE.POINT]: false, @@ -611,7 +620,8 @@ export class VectorStyle implements IVectorStyle { }); } - getStyleMeta() { + getStyleMetaFromLocal() { + console.log('gsm', this._styleMeta); return this._styleMeta; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts index 2c92f67bd7410..89197b40d70f0 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts @@ -8,7 +8,7 @@ import { AnyAction } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { connect } from 'react-redux'; -import { MBMap } from './mb_map'; +import { MbMap } from './mb_map'; import { mapExtentChanged, mapReady, @@ -19,6 +19,7 @@ import { setMapInitError, MapExtentState, setAreTilesLoaded, + updateCounts, } from '../../actions'; import { getLayerList, @@ -73,8 +74,11 @@ function mapDispatchToProps(dispatch: ThunkDispatch void; + updateCounts: (layerId: string, foobar: any) => void; } interface State { @@ -81,7 +82,7 @@ interface State { mbMap: MapboxMap | undefined; } -export class MBMap extends Component { +export class MbMap extends Component { private _checker?: ResizeChecker; private _isMounted: boolean = false; private _containerRef: HTMLDivElement | null = null; @@ -135,6 +136,14 @@ export class MBMap extends Component { this.props.onMapDestroyed(); } + _queryForMeta = _.debounce((layerId, layer) => { + console.log('query for da meta!!!', layerId, layer); + const meta = layer.queryForTileMeta(this.state.mbMap); + console.log(meta); + + // this.props.updateCounts(layerId, 'foobar'); + }, 512); + _debouncedSync = _.debounce(() => { if (this._isMounted && this.props.isMapReady && this.state.mbMap) { if (!this.state.hasSyncedLayerList) { @@ -207,7 +216,11 @@ export class MBMap extends Component { this._tileStatusTracker = new TileStatusTracker({ mbMap, getCurrentLayerList: () => this.props.layerList, - setAreTilesLoaded: this.props.setAreTilesLoaded, + setAreTilesLoaded: (layerId, areTilesLoaded, layer) => { + console.log('setAreTilesLaoded'); + this.props.setAreTilesLoaded(layerId, areTilesLoaded); + this._queryForMeta(layerId, layer); + }, }); const tooManyFeaturesImageSrc = @@ -268,6 +281,7 @@ export class MBMap extends Component { this.props.extentChanged(this._getMapState()); }, 100) ); + // Attach event only if view control is visible, which shows lat/lon if (!this.props.settings.hideViewControl) { const throttledSetMouseCoordinates = _.throttle((e: MapMouseEvent) => { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts index be946a12fe225..aad8397562ad0 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts @@ -108,7 +108,7 @@ export class TileStatusTracker { break; } } - this._setAreTilesLoaded(layer.getId(), !atLeastOnePendingTile); + this._setAreTilesLoaded(layer.getId(), !atLeastOnePendingTile, layer); } }, 100); From e68ecf042e81eec14f4a7e11670211bea13a4d16 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 16 Mar 2021 15:58:15 -0400 Subject: [PATCH 02/68] more boilerplate --- x-pack/plugins/maps/common/constants.ts | 1 + .../tiled_vector_layer/tiled_vector_layer.tsx | 9 +++++-- .../layers/vector_layer/vector_layer.tsx | 6 ++--- x-pack/plugins/maps/server/mvt/get_tile.ts | 24 +++++++++++++++++-- 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index f1e0ac25aa127..057fe47df8e30 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -48,6 +48,7 @@ export const MVT_SOURCE_LAYER_NAME = 'source_layer'; // Identifies vector tile "too many features" feature. // "too many features" feature is a box showing area that contains too many features for single ES search response export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__'; +export const KBN_IS_TILE_COMPLETE = '__kbn_is_tile_complete__'; export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__'; // Identifies centroid feature. // Centroids are a single point for representing lines, multiLines, polygons, and multiPolygons 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 81b0bb6e2649f..9ee684a7b7fda 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 @@ -14,7 +14,11 @@ import { import { EuiIcon } from '@elastic/eui'; import { Feature } from 'geojson'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; -import { SOURCE_DATA_REQUEST_ID, LAYER_TYPE } from '../../../../common/constants'; +import { + SOURCE_DATA_REQUEST_ID, + LAYER_TYPE, + KBN_TOO_MANY_FEATURES_PROPERTY, +} from '../../../../common/constants'; import { VectorLayer, VectorLayerArguments } from '../vector_layer'; import { ITiledSingleLayerVectorSource } from '../../sources/vector_source'; import { DataRequestContext } from '../../../actions'; @@ -177,9 +181,10 @@ export class TiledVectorLayer extends VectorLayer { console.log('going to queyr', this._getMbSourceId(), sourceMeta.layerName); const features = mbMap.querySourceFeatures(this._getMbSourceId(), { sourceLayer: sourceMeta.layerName, + filter: ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], }); - console.log('f', features); + console.log('metdata features', features); return null; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 104d0b56578d1..889809df33791 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -877,9 +877,9 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { } mbMap.addLayer(mbLayer); mbMap.setFilter(tooManyFeaturesLayerId, [ - '==', - ['get', KBN_TOO_MANY_FEATURES_PROPERTY], - true, + 'all', + ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], + ['==', ['get', 'isComplete'], false], ]); mbMap.setPaintProperty( tooManyFeaturesLayerId, diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 3274261cdba56..c8b8d4c2c6321 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -23,7 +23,7 @@ import { SUPER_FINE_ZOOM_DELTA, } from '../../common/constants'; -import { convertRegularRespToGeoJson, hitsToGeoJson } from '../../common/elasticsearch_util'; +import {convertRegularRespToGeoJson, formatEnvelopeAsPolygon, hitsToGeoJson} from '../../common/elasticsearch_util'; import { flattenHit } from './util'; import { ESBounds, tileToESBbox } from '../../common/geo_tile_utils'; import { getCentroidFeatures } from '../../common/get_centroid_features'; @@ -42,7 +42,6 @@ export async function getGridTile({ z, requestBody = {}, requestType = RENDER_AS.POINT, - geoFieldType = ES_GEO_FIELD_TYPE.GEO_POINT, searchSessionId, abortSignal, }: { @@ -83,6 +82,26 @@ export async function getGridTile({ ) .toPromise(); const features: Feature[] = convertRegularRespToGeoJson(response.rawResponse, requestType); + + + if (features.length) { + const bounds = formatEnvelopeAsPolygon({ + maxLat: tileBounds.top_left.lat, + minLat: tileBounds.bottom_right.lat, + maxLon: tileBounds.bottom_right.lon, + minLon: tileBounds.top_left.lon, + }); + const metaDataFeature = { + type: 'Feature', + properties: { + [KBN_TOO_MANY_FEATURES_PROPERTY]: true, + isComplete: true, + }, + geometry: bounds, + }; + features.push(metaDataFeature); + } + const featureCollection: FeatureCollection = { features, type: 'FeatureCollection', @@ -177,6 +196,7 @@ export async function getTile({ type: 'Feature', properties: { [KBN_TOO_MANY_FEATURES_PROPERTY]: true, + isComplete: false, }, geometry: esBboxToGeoJsonPolygon( bboxResponse.rawResponse.aggregations.data_bounds.bounds, From 54b8429c382508b1871af64a2337785d68c05acf Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 16 Mar 2021 18:33:37 -0400 Subject: [PATCH 03/68] boilerplate for doc_count --- .../layer_descriptor_types.ts | 1 + .../public/actions/data_request_actions.ts | 10 +++- .../maps/public/actions/layer_actions.ts | 17 +++++-- .../maps/public/classes/layers/layer.tsx | 5 ++ .../tiled_vector_layer/tiled_vector_layer.tsx | 9 ++-- .../classes/styles/vector/vector_style.tsx | 51 ++++++++++++++++++- .../connected_components/mb_map/mb_map.tsx | 6 +-- x-pack/plugins/maps/server/mvt/get_tile.ts | 24 ++++++++- 8 files changed, 108 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 7c4746fd2ccb3..3f3db967bc8fc 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -28,6 +28,7 @@ export type LayerDescriptor = { __errorMessage?: string; __trackedLayerDescriptor?: LayerDescriptor; __areTilesLoaded?: boolean; + __metaFromTiles?: any; alpha?: number; id: string; joins?: JoinDescriptor[]; 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 a3d2f41a5a1e5..42a722face9b6 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -117,7 +117,15 @@ export function updateStyleMeta(layerId: string | null) { }); } else if (layer.getType() === LAYER_TYPE.TILED_VECTOR) { console.log('do special tile thging here!!!'); - const styleMeta = { fieldMeta: {} }; + const style = layer.getCurrentStyle(); + if (!style || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { + return; + } + + const metaFromTiles = layer.getMetaFromTiles(); + console.log('got meta from tiles', metaFromTiles); + + const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromTileMeta(metaFromTiles); dispatch({ type: SET_LAYER_STYLE_META, layerId, diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index b3ea90badbf83..a143e893e5b16 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -48,7 +48,6 @@ import { IVectorStyle } from '../classes/styles/vector/vector_style'; import { notifyLicensedFeatureUsage } from '../licensed_features'; import { IESAggField } from '../classes/fields/agg'; import { IField } from '../classes/fields/field'; -import { string } from '../../../security_solution/public/resolver/models/schema'; export function trackCurrentLayerState(layerId: string) { return { @@ -550,17 +549,29 @@ export function setAreTilesLoaded(layerId: string, areTilesLoaded: boolean) { }; } -export function updateCounts(layerId: string, foobar: any) { +export function updateCounts(layerId: string, mbMetaFeatures: any) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState ) => { + + if (!mbMetaFeatures) { + return; + } + console.log('update counts', layerId); const layer = getLayerById(layerId, getState()); if (!layer) { return; } - console.log('l', layer); + await dispatch({ + type: UPDATE_LAYER_PROP, + id: layerId, + propName: '__metaFromTiles', + newValue: mbMetaFeatures, + }); + await dispatch(updateStyleMeta(layerId)); + }; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 01c928c727f15..2bd8adc57bd35 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -47,6 +47,7 @@ export interface ILayer { getDisplayName(source?: ISource): Promise; getId(): string; getSourceDataRequest(): DataRequest | undefined; + getMetaFromTiles(): any; getSource(): ISource; getSourceForEditing(): ISource; syncData(syncContext: DataRequestContext): void; @@ -158,6 +159,10 @@ export class AbstractLayer implements ILayer { return null; } + getMetaFromTiles(): any { + return this._descriptor.__metaFromTiles; + } + async cloneDescriptor(): Promise { const clonedDescriptor = copyPersistentState(this._descriptor); // layer id is uuid used to track styles/layers in mapbox 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 9ee684a7b7fda..6ebb682a87d85 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 @@ -160,7 +160,7 @@ export class TiledVectorLayer extends VectorLayer { this._setMbCentroidProperties(mbMap, sourceMeta.layerName); } - queryForTileMeta(mbMap: MbMap) { + queryForTileMeta(mbMap: MbMap) : any { console.log('query for tile meta!', mbMap); // @ts-ignore @@ -179,14 +179,15 @@ export class TiledVectorLayer extends VectorLayer { } console.log('going to queyr', this._getMbSourceId(), sourceMeta.layerName); - const features = mbMap.querySourceFeatures(this._getMbSourceId(), { + const mbFeatures = mbMap.querySourceFeatures(this._getMbSourceId(), { sourceLayer: sourceMeta.layerName, filter: ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], }); - console.log('metdata features', features); + console.log('f', mbFeatures); - return null; + + return mbFeatures; } _requiresPrevSourceCleanup(mbMap: MbMap): boolean { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index de7760649e81a..c6989ce2dc61d 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -89,6 +89,7 @@ export interface IVectorStyle extends IStyle { previousFields: IField[], mapColors: string[] ): Promise<{ hasChanges: boolean; nextStyleDescriptor?: VectorStyleDescriptor }>; + pluckStyleMetaFromTileMeta(foobar: any): Promise; pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): Promise; isTimeAware: () => boolean; getIcon: () => ReactElement; @@ -488,12 +489,59 @@ export class VectorStyle implements IVectorStyle { ); } + async pluckStyleMetaFromTileMeta(foobar: any): Promise { + console.log('get it from the tilemeta!', foobar); + const styleMeta = { + geometryTypes: { + isPointsOnly: false, + isLinesOnly: false, + isPolygonsOnly: false, + }, + fieldMeta: {}, + } as StyleMetaDescriptor; + + const dynamicProperties = this.getDynamicPropertiesArray(); + if (dynamicProperties.length === 0 || !foobar) { + // no additional meta data to pull from source data request. + return styleMeta; + } + + dynamicProperties.forEach((dynamicProperty) => { + const name = dynamicProperty.getFieldName(); + console.log('na', name); + if (!styleMeta.fieldMeta[name]) { + styleMeta.fieldMeta[name] = {}; + } + if (name === 'doc_count') { + styleMeta.fieldMeta[name] = {}; + + let min = Infinity; + let max = -Infinity; + for (let i = 0; i < foobar.length; i++) { + const metaFromTiles = JSON.parse(foobar[i].properties.doc_count); + console.log('must parse', foobar[i], metaFromTiles); + + min = Math.min(metaFromTiles.min, min); + max = Math.max(metaFromTiles.max, max); + } + + styleMeta.fieldMeta.doc_count = { + range: { + min, + max, + delta: max - min, + }, + }; + } + }); + console.log('form da tile', styleMeta); + return styleMeta; + } async pluckStyleMetaFromSourceDataRequest( sourceDataRequest: DataRequest ): Promise { - console.log('pluck style meta', sourceDataRequest); const features = _.get(sourceDataRequest.getData(), 'features', []); @@ -561,6 +609,7 @@ export class VectorStyle implements IVectorStyle { const categoricalStyleMeta = dynamicProperty.pluckCategoricalStyleMetaFromFeatures(features); const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromFeatures(features); const name = dynamicProperty.getFieldName(); + console.log('name', name); if (!styleMeta.fieldMeta[name]) { styleMeta.fieldMeta[name] = {}; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 9a7d26e426cb9..e27443391ab02 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -138,10 +138,8 @@ export class MbMap extends Component { _queryForMeta = _.debounce((layerId, layer) => { console.log('query for da meta!!!', layerId, layer); - const meta = layer.queryForTileMeta(this.state.mbMap); - console.log(meta); - - // this.props.updateCounts(layerId, 'foobar'); + const mbFeatures = layer.queryForTileMeta(this.state.mbMap); + this.props.updateCounts(layerId, mbFeatures); }, 512); _debouncedSync = _.debounce(() => { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index c8b8d4c2c6321..8a8ad44a00404 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -23,7 +23,11 @@ import { SUPER_FINE_ZOOM_DELTA, } from '../../common/constants'; -import {convertRegularRespToGeoJson, formatEnvelopeAsPolygon, hitsToGeoJson} from '../../common/elasticsearch_util'; +import { + convertRegularRespToGeoJson, + formatEnvelopeAsPolygon, + hitsToGeoJson, +} from '../../common/elasticsearch_util'; import { flattenHit } from './util'; import { ESBounds, tileToESBbox } from '../../common/geo_tile_utils'; import { getCentroidFeatures } from '../../common/get_centroid_features'; @@ -83,7 +87,6 @@ export async function getGridTile({ .toPromise(); const features: Feature[] = convertRegularRespToGeoJson(response.rawResponse, requestType); - if (features.length) { const bounds = formatEnvelopeAsPolygon({ maxLat: tileBounds.top_left.lat, @@ -91,11 +94,28 @@ export async function getGridTile({ maxLon: tileBounds.bottom_right.lon, minLon: tileBounds.top_left.lon, }); + + const rangeMeta = { + doc_count: { + min: Infinity, + max: -Infinity, + }, + }; + for (let i = 0; i < features.length; i++) { + const feature = features[i]; + const newValue = parseFloat(feature.properties ? feature.properties['doc_count'] : null); + if (!isNaN(newValue)) { + rangeMeta.doc_count.min = Math.min(rangeMeta.doc_count.min, newValue); + rangeMeta.doc_count.max = Math.max(rangeMeta.doc_count.max, newValue); + } + } + const metaDataFeature = { type: 'Feature', properties: { [KBN_TOO_MANY_FEATURES_PROPERTY]: true, isComplete: true, + ...rangeMeta, }, geometry: bounds, }; From 5f930ff29c2292c66e8ee5df2e328c025ea8828d Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 7 Apr 2021 19:09:25 -0400 Subject: [PATCH 04/68] cleanup --- .../maps/public/actions/data_request_actions.ts | 5 ----- .../plugins/maps/public/actions/layer_actions.ts | 3 --- .../public/classes/fields/agg/count_agg_field.ts | 2 +- .../tiled_vector_layer/tiled_vector_layer.tsx | 8 +------- .../vector/properties/dynamic_color_property.tsx | 1 - .../public/classes/styles/vector/vector_style.tsx | 14 ++------------ 6 files changed, 4 insertions(+), 29 deletions(-) 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 42a722face9b6..2166cb3895800 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -90,7 +90,6 @@ export function cancelAllInFlightRequests() { export function updateStyleMeta(layerId: string | null) { return async (dispatch: Dispatch, getState: () => MapStoreState) => { - console.log('update style meta!', layerId); const layer = getLayerById(layerId, getState()); if (!layer) { return; @@ -102,7 +101,6 @@ export function updateStyleMeta(layerId: string | null) { layer.getType() === LAYER_TYPE.BLENDED_VECTOR ) { const sourceDataRequest = layer.getSourceDataRequest(); - console.log('sdr', sourceDataRequest); const style = layer.getCurrentStyle(); if (!style || !sourceDataRequest || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { return; @@ -116,15 +114,12 @@ export function updateStyleMeta(layerId: string | null) { styleMeta, }); } else if (layer.getType() === LAYER_TYPE.TILED_VECTOR) { - console.log('do special tile thging here!!!'); const style = layer.getCurrentStyle(); if (!style || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { return; } const metaFromTiles = layer.getMetaFromTiles(); - console.log('got meta from tiles', metaFromTiles); - const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromTileMeta(metaFromTiles); dispatch({ type: SET_LAYER_STYLE_META, diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index a143e893e5b16..f23e2a4d6115b 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -554,12 +554,10 @@ export function updateCounts(layerId: string, mbMetaFeatures: any) { dispatch: ThunkDispatch, getState: () => MapStoreState ) => { - if (!mbMetaFeatures) { return; } - console.log('update counts', layerId); const layer = getLayerById(layerId, getState()); if (!layer) { return; @@ -572,6 +570,5 @@ export function updateCounts(layerId: string, mbMetaFeatures: any) { newValue: mbMetaFeatures, }); await dispatch(updateStyleMeta(layerId)); - }; } diff --git a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts index 56b966ae15851..efc761fd595d3 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts @@ -70,7 +70,7 @@ export class CountAggField implements IESAggField { } supportsFieldMeta(): boolean { - return false; + return true; } getBucketCount() { 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 6ebb682a87d85..11a0db5d52706 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 @@ -160,9 +160,7 @@ export class TiledVectorLayer extends VectorLayer { this._setMbCentroidProperties(mbMap, sourceMeta.layerName); } - queryForTileMeta(mbMap: MbMap) : any { - console.log('query for tile meta!', mbMap); - + queryForTileMeta(mbMap: MbMap): any { // @ts-ignore const mbSource = mbMap.getSource(this._getMbSourceId()); if (!mbSource) { @@ -178,15 +176,11 @@ export class TiledVectorLayer extends VectorLayer { return; } - console.log('going to queyr', this._getMbSourceId(), sourceMeta.layerName); const mbFeatures = mbMap.querySourceFeatures(this._getMbSourceId(), { sourceLayer: sourceMeta.layerName, filter: ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], }); - console.log('f', mbFeatures); - - return mbFeatures; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx index 48fe1ecb4bf2d..d654cdc6bff51 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.tsx @@ -201,7 +201,6 @@ export class DynamicColorProperty extends DynamicStyleProperty { - console.log('get it from the tilemeta!', foobar); const styleMeta = { geometryTypes: { isPointsOnly: false, @@ -508,10 +507,11 @@ export class VectorStyle implements IVectorStyle { dynamicProperties.forEach((dynamicProperty) => { const name = dynamicProperty.getFieldName(); - console.log('na', name); if (!styleMeta.fieldMeta[name]) { styleMeta.fieldMeta[name] = {}; } + + // todo - should support ALL countable metrics if (name === 'doc_count') { styleMeta.fieldMeta[name] = {}; @@ -519,8 +519,6 @@ export class VectorStyle implements IVectorStyle { let max = -Infinity; for (let i = 0; i < foobar.length; i++) { const metaFromTiles = JSON.parse(foobar[i].properties.doc_count); - console.log('must parse', foobar[i], metaFromTiles); - min = Math.min(metaFromTiles.min, min); max = Math.max(metaFromTiles.max, max); } @@ -535,19 +533,13 @@ export class VectorStyle implements IVectorStyle { } }); - console.log('form da tile', styleMeta); return styleMeta; } async pluckStyleMetaFromSourceDataRequest( sourceDataRequest: DataRequest ): Promise { - console.log('pluck style meta', sourceDataRequest); - const features = _.get(sourceDataRequest.getData(), 'features', []); - - console.log('f', features); - const supportedFeatures = await this._source.getSupportedShapeTypes(); const hasFeatureType = { [VECTOR_SHAPE_TYPE.POINT]: false, @@ -609,7 +601,6 @@ export class VectorStyle implements IVectorStyle { const categoricalStyleMeta = dynamicProperty.pluckCategoricalStyleMetaFromFeatures(features); const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromFeatures(features); const name = dynamicProperty.getFieldName(); - console.log('name', name); if (!styleMeta.fieldMeta[name]) { styleMeta.fieldMeta[name] = {}; } @@ -670,7 +661,6 @@ export class VectorStyle implements IVectorStyle { } getStyleMetaFromLocal() { - console.log('gsm', this._styleMeta); return this._styleMeta; } From ee10a58f665e1ec6f16c4cfb04a520fd07e3eba2 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 7 Apr 2021 20:31:31 -0400 Subject: [PATCH 05/68] more boiler --- .../public/classes/fields/agg/agg_field.ts | 8 ++-- .../classes/styles/vector/vector_style.tsx | 35 ++++++++------- .../connected_components/mb_map/mb_map.tsx | 6 +-- x-pack/plugins/maps/server/mvt/get_tile.ts | 44 ++++++++++++++----- 4 files changed, 61 insertions(+), 32 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts index 70d5cea6e4620..00b237dcd5561 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts @@ -34,10 +34,10 @@ export class AggField extends CountAggField { return !!this._esDocField; } - supportsFieldMeta(): boolean { - // count and sum aggregations are not within field bounds so they do not support field meta. - return !isMetricCountable(this._getAggType()); - } + // supportsFieldMeta(): boolean { + // // count and sum aggregations are not within field bounds so they do not support field meta. + // // return !isMetricCountable(this._getAggType()); + // } canValueBeFormatted(): boolean { return this._getAggType() !== AGG_TYPE.UNIQUE_COUNT; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 27bf23fb66e08..ce78367e71ab6 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -12,6 +12,7 @@ import { FeatureCollection } from 'geojson'; import { StyleProperties, VectorStyleEditor } from './components/vector_style_editor'; import { getDefaultStaticProperties, LINE_STYLES, POLYGON_STYLES } from './vector_style_defaults'; import { + COUNT_PROP_NAME, DEFAULT_ICON, FIELD_ORIGIN, GEO_JSON_TYPE, @@ -512,27 +513,31 @@ export class VectorStyle implements IVectorStyle { } // todo - should support ALL countable metrics - if (name === 'doc_count') { - styleMeta.fieldMeta[name] = {}; - - let min = Infinity; - let max = -Infinity; - for (let i = 0; i < foobar.length; i++) { - const metaFromTiles = JSON.parse(foobar[i].properties.doc_count); + console.log('pluck tile meta!', name, foobar); + // if (name === COUNT_PROP_NAME) { + styleMeta.fieldMeta[name] = {}; + + let min = Infinity; + let max = -Infinity; + for (let i = 0; i < foobar.length; i++) { + if (foobar[i].properties && foobar[i].properties[name]) { + const metaFromTiles = JSON.parse(foobar[i].properties[name]); min = Math.min(metaFromTiles.min, min); max = Math.max(metaFromTiles.max, max); } - - styleMeta.fieldMeta.doc_count = { - range: { - min, - max, - delta: max - min, - }, - }; } + + styleMeta.fieldMeta[name] = { + range: { + min, + max, + delta: max - min, + }, + }; + // } }); + console.log('sm', styleMeta); return styleMeta; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 13cf89eb16dc1..0e30f26b02ef1 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -139,7 +139,7 @@ export class MbMap extends Component { _queryForMeta = _.debounce((layerId, layer) => { const mbFeatures = layer.queryForTileMeta(this.state.mbMap); this.props.updateCounts(layerId, mbFeatures); - }, 512); + }, 1000); _debouncedSync = _.debounce(() => { if (this._isMounted && this.props.isMapReady && this.state.mbMap) { @@ -207,13 +207,13 @@ export class MbMap extends Component { options.bounds = [-170, -60, 170, 75]; } const mbMap = new mapboxgl.Map(options); - mbMap.dragRotate.disable(); + // mbMap.dragRotate.disable(); mbMap.touchZoomRotate.disableRotation(); this._tileStatusTracker = new TileStatusTracker({ mbMap, getCurrentLayerList: () => this.props.layerList, - setAreTilesLoaded: (layerId, areTilesLoaded, layer) => { + setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean, layer: ILayer) => { this.props.setAreTilesLoaded(layerId, areTilesLoaded); this._queryForMeta(layerId, layer); }, diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 067e0df06e916..c0dce7d436b5c 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -13,6 +13,7 @@ import { Logger } from 'src/core/server'; import type { DataRequestHandlerContext } from 'src/plugins/data/server'; import { Feature, FeatureCollection, Polygon } from 'geojson'; import { + COUNT_PROP_NAME, ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, GEOTILE_GRID_AGG_NAME, @@ -99,21 +100,42 @@ export async function getGridTile({ minLon: tileBounds.top_left.lon, }); - const rangeMeta = { - doc_count: { - min: Infinity, - max: -Infinity, - }, - }; + const rangeMeta: { [key: string]: { min: number; max: number } } = {}; for (let i = 0; i < features.length; i++) { const feature = features[i]; - const newValue = parseFloat(feature.properties ? feature.properties.doc_count : null); - if (!isNaN(newValue)) { - rangeMeta.doc_count.min = Math.min(rangeMeta.doc_count.min, newValue); - rangeMeta.doc_count.max = Math.max(rangeMeta.doc_count.max, newValue); + + if (feature.properties) { + for (const key in feature.properties) { + if (feature.properties.hasOwnProperty(key)) { + if (key !== 'key' && key !== 'gridCentroid') { + const rawValue = feature.properties[key]; + logger.warn(`${key} : ${JSON.stringify(rawValue)}`); + let numberValue: number; + if (key === COUNT_PROP_NAME) { + numberValue = parseFloat(rawValue); + } else { + numberValue = + typeof rawValue === 'number' ? rawValue : parseFloat(rawValue.value); + } + if (!isNaN(numberValue)) { + if (!rangeMeta[key]) { + rangeMeta[key] = { + min: Infinity, + max: -Infinity, + }; + } + + rangeMeta[key].min = Math.min(rangeMeta[key].min, numberValue); + rangeMeta[key].max = Math.max(rangeMeta[key].max, numberValue); + } + } + } + } } } + logger.warn(`tile ${z}/${x}/${y} ${JSON.stringify(rangeMeta)}`); + const metaDataFeature = { type: 'Feature', properties: { @@ -134,6 +156,8 @@ export async function getGridTile({ return createMvtTile(featureCollection, z, x, y); } catch (e) { if (!isAbortError(e)) { + // These are often circuit breaking exceptions + // Should return a tile with some error message logger.warn(`Cannot generate grid-tile for ${z}/${x}/${y}: ${e.message}`); } return null; From 410276efdf4ae92b25da176a37e456811aaf9f2d Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 8 Apr 2021 15:03:04 -0400 Subject: [PATCH 06/68] edits --- .../maps/public/classes/layers/layer.tsx | 3 +- .../connected_components/mb_map/mb_map.tsx | 35 ++++++++++++++++--- x-pack/plugins/maps/server/mvt/get_tile.ts | 3 -- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 2bd8adc57bd35..269239af4a921 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -98,6 +98,7 @@ export interface ILayer { isFittable(): Promise; getLicensedFeatures(): Promise; getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; + queryForTileMeta(mbMap: MbMap): any; } export type CustomIconAndTooltipContent = { @@ -155,7 +156,7 @@ export class AbstractLayer implements ILayer { return mbStyle.sources[sourceId].data; } - queryForTileMeta(mbMap) { + queryForTileMeta(mbMap: MbMap): any { return null; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 0e30f26b02ef1..1abe81b73f62c 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -136,10 +136,37 @@ export class MbMap extends Component { this.props.onMapDestroyed(); } - _queryForMeta = _.debounce((layerId, layer) => { - const mbFeatures = layer.queryForTileMeta(this.state.mbMap); - this.props.updateCounts(layerId, mbFeatures); - }, 1000); + // This keeps track of the latest update calls, per layerId + _queryForMeta = (() => { + const callMap = new Map(); + + let timerId: number | null = null; + + const updateAllLayers = () => { + callMap.forEach((layer: ILayer, layerId: string) => { + if (this.state.mbMap) { + if (layer.isVisible()) { + const mbFeatures = layer.queryForTileMeta(this.state.mbMap); + this.props.updateCounts(layerId, mbFeatures); + } + } + }); + callMap.clear(); + timerId = null; + }; + + return (layerId: string, layer: ILayer) => { + callMap.set(layerId, layer); + if (!timerId) { + timerId = setTimeout(updateAllLayers, 1200); + } + }; + })(); + + // _queryForMeta = _.debounce((layerId, layer) => { + // const mbFeatures = layer.queryForTileMeta(this.state.mbMap); + // this.props.updateCounts(layerId, mbFeatures); + // }, 1000); _debouncedSync = _.debounce(() => { if (this._isMounted && this.props.isMapReady && this.state.mbMap) { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index c0dce7d436b5c..97b1a068ccf81 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -109,7 +109,6 @@ export async function getGridTile({ if (feature.properties.hasOwnProperty(key)) { if (key !== 'key' && key !== 'gridCentroid') { const rawValue = feature.properties[key]; - logger.warn(`${key} : ${JSON.stringify(rawValue)}`); let numberValue: number; if (key === COUNT_PROP_NAME) { numberValue = parseFloat(rawValue); @@ -134,8 +133,6 @@ export async function getGridTile({ } } - logger.warn(`tile ${z}/${x}/${y} ${JSON.stringify(rangeMeta)}`); - const metaDataFeature = { type: 'Feature', properties: { From fe3bfbf9898480fa7e251b060d27cf72f80d13ec Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 14 Apr 2021 09:53:23 -0400 Subject: [PATCH 07/68] boiler for style --- x-pack/plugins/maps/common/constants.ts | 1 + .../maps/common/get_geometry_counts.ts | 45 +++++++++++++++++++ .../tiled_vector_layer/tiled_vector_layer.tsx | 5 ++- .../layers/vector_layer/vector_layer.tsx | 3 +- .../classes/styles/vector/vector_style.tsx | 5 --- x-pack/plugins/maps/server/mvt/get_tile.ts | 22 +++++++-- 6 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/maps/common/get_geometry_counts.ts diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 21ae4cb293179..c98c6fe06fe2e 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -50,6 +50,7 @@ export const MVT_SOURCE_LAYER_NAME = 'source_layer'; // "too many features" feature is a box showing area that contains too many features for single ES search response export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__'; export const KBN_IS_TILE_COMPLETE = '__kbn_is_tile_complete__'; +export const KBN_VECTOR_SHAPE_TYPE_COUNTS = '__kbn_vector_shape_type_counts__'; export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__'; // Identifies centroid feature. // Centroids are a single point for representing lines, multiLines, polygons, and multiPolygons diff --git a/x-pack/plugins/maps/common/get_geometry_counts.ts b/x-pack/plugins/maps/common/get_geometry_counts.ts new file mode 100644 index 0000000000000..cafed7d864b13 --- /dev/null +++ b/x-pack/plugins/maps/common/get_geometry_counts.ts @@ -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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Feature } from 'geojson'; +import { GEO_JSON_TYPE, VECTOR_SHAPE_TYPE } from './constants'; + +export interface IVectorShapeTypeCounts { + [VECTOR_SHAPE_TYPE.POINT]: number; + [VECTOR_SHAPE_TYPE.LINE]: number; + [VECTOR_SHAPE_TYPE.POLYGON]: number; +} + +export function countVectorShapeTypes(features: Feature[]): IVectorShapeTypeCounts { + const vectorShapeTypeCounts: IVectorShapeTypeCounts = { + [VECTOR_SHAPE_TYPE.POINT]: 0, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POLYGON]: 0, + }; + + for (let i = 0; i < features.length; i++) { + const feature: Feature = features[i]; + if ( + feature.geometry.type === GEO_JSON_TYPE.POINT || + feature.geometry.type === GEO_JSON_TYPE.MULTI_POINT + ) { + vectorShapeTypeCounts[VECTOR_SHAPE_TYPE.POINT] += 1; + } else if ( + feature.geometry.type === GEO_JSON_TYPE.LINE_STRING || + feature.geometry.type === GEO_JSON_TYPE.MULTI_LINE_STRING + ) { + vectorShapeTypeCounts[VECTOR_SHAPE_TYPE.LINE] += 1; + } else if ( + feature.geometry.type === GEO_JSON_TYPE.POLYGON || + feature.geometry.type === GEO_JSON_TYPE.MULTI_POLYGON + ) { + vectorShapeTypeCounts[VECTOR_SHAPE_TYPE.POLYGON] += 1; + } + } + + return vectorShapeTypeCounts; +} 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 11a0db5d52706..e5d182cd20ec6 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 @@ -11,7 +11,6 @@ import { GeoJSONSource as MbGeoJSONSource, VectorSource as MbVectorSource, } from 'mapbox-gl'; -import { EuiIcon } from '@elastic/eui'; import { Feature } from 'geojson'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { @@ -56,7 +55,9 @@ export class TiledVectorLayer extends VectorLayer { getCustomIconAndTooltipContent() { return { - icon: , + icon: this.getCurrentStyle().getIcon(), + tooltipContent: 'foobar', + areResultsTrimmed: false, }; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 889809df33791..c36e28bf3a172 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -24,6 +24,7 @@ import { FIELD_ORIGIN, KBN_TOO_MANY_FEATURES_IMAGE_ID, FieldFormatter, + KBN_IS_TILE_COMPLETE, } from '../../../../common/constants'; import { JoinTooltipProperty } from '../../tooltips/join_tooltip_property'; import { DataRequestAbortError } from '../../util/data_request'; @@ -879,7 +880,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { mbMap.setFilter(tooManyFeaturesLayerId, [ 'all', ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], - ['==', ['get', 'isComplete'], false], + ['==', ['get', KBN_IS_TILE_COMPLETE], false], ]); mbMap.setPaintProperty( tooManyFeaturesLayerId, diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index ce78367e71ab6..0724587bec2ff 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -512,9 +512,6 @@ export class VectorStyle implements IVectorStyle { styleMeta.fieldMeta[name] = {}; } - // todo - should support ALL countable metrics - console.log('pluck tile meta!', name, foobar); - // if (name === COUNT_PROP_NAME) { styleMeta.fieldMeta[name] = {}; let min = Infinity; @@ -534,10 +531,8 @@ export class VectorStyle implements IVectorStyle { delta: max - min, }, }; - // } }); - console.log('sm', styleMeta); return styleMeta; } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 97b1a068ccf81..6925b3994cf86 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -17,11 +17,14 @@ import { ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, GEOTILE_GRID_AGG_NAME, + KBN_IS_TILE_COMPLETE, KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_VECTOR_SHAPE_TYPE_COUNTS, MAX_ZOOM, MVT_SOURCE_LAYER_NAME, RENDER_AS, SUPER_FINE_ZOOM_DELTA, + VECTOR_SHAPE_TYPE, } from '../../common/constants'; import { @@ -60,7 +63,7 @@ export async function getGridTile({ context: DataRequestHandlerContext; logger: Logger; requestBody: any; - requestType: RENDER_AS; + requestType: RENDER_AS.GRID | RENDER_AS.POINT; geoFieldType: ES_GEO_FIELD_TYPE; searchSessionId?: string; abortSignal: AbortSignal; @@ -137,11 +140,24 @@ export async function getGridTile({ type: 'Feature', properties: { [KBN_TOO_MANY_FEATURES_PROPERTY]: true, - isComplete: true, + [KBN_IS_TILE_COMPLETE]: true, + [KBN_VECTOR_SHAPE_TYPE_COUNTS]: + requestType === RENDER_AS.GRID + ? { + [VECTOR_SHAPE_TYPE.POINT]: 0, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POLYGON]: features.length, + } + : { + [VECTOR_SHAPE_TYPE.POINT]: features.length, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POLYGON]: 0, + }, ...rangeMeta, }, geometry: bounds, }; + features.push(metaDataFeature); } @@ -249,7 +265,7 @@ export async function getTile({ type: 'Feature', properties: { [KBN_TOO_MANY_FEATURES_PROPERTY]: true, - isComplete: false, + [KBN_IS_TILE_COMPLETE]: false, }, geometry: esBboxToGeoJsonPolygon( // @ts-expect-error @elastic/elasticsearch no way to declare aggregations for search response From 40c0680d97611e730c6aa260a74c100ef34d9b81 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 14 Apr 2021 11:13:02 -0400 Subject: [PATCH 08/68] boiler for icon --- .../tiled_vector_layer/tiled_vector_layer.tsx | 52 +++++++++++++++++-- .../classes/styles/vector/vector_style.tsx | 14 +++-- x-pack/plugins/maps/server/mvt/get_tile.ts | 16 ++++++ 3 files changed, 74 insertions(+), 8 deletions(-) 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 e5d182cd20ec6..cd66a7879d511 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 @@ -7,16 +7,18 @@ import React from 'react'; import { - Map as MbMap, GeoJSONSource as MbGeoJSONSource, + Map as MbMap, VectorSource as MbVectorSource, } from 'mapbox-gl'; import { Feature } from 'geojson'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { - SOURCE_DATA_REQUEST_ID, - LAYER_TYPE, KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_VECTOR_SHAPE_TYPE_COUNTS, + LAYER_TYPE, + SOURCE_DATA_REQUEST_ID, + VECTOR_SHAPE_TYPE, } from '../../../../common/constants'; import { VectorLayer, VectorLayerArguments } from '../vector_layer'; import { ITiledSingleLayerVectorSource } from '../../sources/vector_source'; @@ -27,6 +29,7 @@ import { } from '../../../../common/descriptor_types'; import { MVTSingleLayerVectorSourceConfig } from '../../sources/mvt_single_layer_vector_source/types'; import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; +import { IVectorShapeTypeCounts } from '../../../../common/get_geometry_counts'; export class TiledVectorLayer extends VectorLayer { static type = LAYER_TYPE.TILED_VECTOR; @@ -54,8 +57,49 @@ export class TiledVectorLayer extends VectorLayer { } getCustomIconAndTooltipContent() { + const tileMetas = this.getMetaFromTiles(); + + if (!tileMetas) { + return { + icon: this.getCurrentStyle().getIcon(), + tooltipContent: 'foobar', + areResultsTrimmed: false, + }; + } + + const shapeTypeCountMeta: IVectorShapeTypeCounts = tileMetas.reduce( + (accumulator: IVectorShapeTypeCounts, tileMeta: any) => { + if ( + tileMeta.properties[KBN_TOO_MANY_FEATURES_PROPERTY] === true || + typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string' + ) { + return accumulator; + } + const counts = JSON.parse(tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS]); + + accumulator[VECTOR_SHAPE_TYPE.POINT] += counts[VECTOR_SHAPE_TYPE.POINT]; + accumulator[VECTOR_SHAPE_TYPE.LINE] += counts[VECTOR_SHAPE_TYPE.LINE]; + accumulator[VECTOR_SHAPE_TYPE.POLYGON] += counts[VECTOR_SHAPE_TYPE.POLYGON]; + + return accumulator; + }, + { + [VECTOR_SHAPE_TYPE.POLYGON]: 0, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POINT]: 0, + } + ); + + const isLinesOnly = + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] > 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] === 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; + const isPointsOnly = + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] === 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] > 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; return { - icon: this.getCurrentStyle().getIcon(), + icon: this.getCurrentStyle().getIconFromGeometryTypes(isLinesOnly, isPointsOnly), tooltipContent: 'foobar', areResultsTrimmed: false, }; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 0724587bec2ff..4663230fe06f8 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -94,6 +94,7 @@ export interface IVectorStyle extends IStyle { pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): Promise; isTimeAware: () => boolean; getIcon: () => ReactElement; + getIconFromGeometryTypes: (isLinesOnly: boolean, isPointsOnly: boolean) => ReactElement; hasLegendDetails: () => Promise; renderLegendDetails: () => ReactElement; clearFeatureState: (featureCollection: FeatureCollection, mbMap: MbMap, sourceId: string) => void; @@ -702,8 +703,7 @@ export class VectorStyle implements IVectorStyle { : (this._iconStyleProperty as StaticIconProperty).getOptions().value; } - getIcon = () => { - const isLinesOnly = this._getIsLinesOnly(); + getIconFromGeometryTypes(isLinesOnly: boolean, isPointsOnly: boolean) { let strokeColor; if (isLinesOnly) { strokeColor = extractColorFromStyleProperty( @@ -725,14 +725,20 @@ export class VectorStyle implements IVectorStyle { return ( ); - }; + } + + getIcon() { + const isLinesOnly = this._getIsLinesOnly(); + const isPointsOnly = this._getIsPointsOnly(); + return this.getIconFromGeometryTypes(isLinesOnly, isPointsOnly); + } _getLegendDetailStyleProperties = () => { return this.getDynamicPropertiesArray().filter((styleProperty) => { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 6925b3994cf86..639defb39b1c4 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -12,6 +12,7 @@ import vtpbf from 'vt-pbf'; import { Logger } from 'src/core/server'; import type { DataRequestHandlerContext } from 'src/plugins/data/server'; import { Feature, FeatureCollection, Polygon } from 'geojson'; +import { countVectorShapeTypes } from '../../common/get_geometry_counts'; import { COUNT_PROP_NAME, ES_GEO_FIELD_TYPE, @@ -313,6 +314,21 @@ export async function getTile({ } } + const counts = countVectorShapeTypes(features); + const metadataFeature = { + type: 'Feature', + properties: { + [KBN_TOO_MANY_FEATURES_PROPERTY]: true, + [KBN_IS_TILE_COMPLETE]: true, + [KBN_VECTOR_SHAPE_TYPE_COUNTS]: counts, + }, + // todo - constrain to actual features + geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), + }; + + // @ts-expect-error + features.push(metadataFeature); + const featureCollection: FeatureCollection = { features, type: 'FeatureCollection', From 405a9dfca5e1fbf9424e8756513db75b4fd744cd Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 14 Apr 2021 12:21:34 -0400 Subject: [PATCH 09/68] minor fixes --- x-pack/plugins/maps/public/actions/data_request_actions.ts | 1 + x-pack/plugins/maps/server/mvt/get_tile.ts | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) 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 2166cb3895800..cb05ab7c32810 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -261,6 +261,7 @@ function endDataLoad( dispatch(unregisterCancelCallback(requestToken)); const dataRequest = getDataRequestDescriptor(getState(), layerId, dataId); if (dataRequest && dataRequest.dataRequestToken !== requestToken) { + // todo - investigate - this may arise with failing style meta request and should not throw in that case throw new DataRequestAbortError(); } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 639defb39b1c4..772dc53960452 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -116,9 +116,12 @@ export async function getGridTile({ let numberValue: number; if (key === COUNT_PROP_NAME) { numberValue = parseFloat(rawValue); + } else if (typeof rawValue === 'number') { + numberValue = rawValue; + } else if (rawValue) { + numberValue = parseFloat(rawValue.value); } else { - numberValue = - typeof rawValue === 'number' ? rawValue : parseFloat(rawValue.value); + continue; } if (!isNaN(numberValue)) { if (!rangeMeta[key]) { From f506db2b1ae1ab528c08ca061ca6784be315fe94 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 26 May 2021 16:51:23 -0400 Subject: [PATCH 10/68] improve typing --- .../public/actions/data_request_actions.ts | 42 +++---------- .../maps/public/classes/layers/layer.tsx | 61 +++++++++++++++++++ .../tiled_vector_layer/tiled_vector_layer.tsx | 12 +++- .../layers/vector_layer/vector_layer.tsx | 23 ++++++- .../classes/styles/vector/vector_style.tsx | 2 - 5 files changed, 102 insertions(+), 38 deletions(-) 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 cb05ab7c32810..f2a2bb48c1e95 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -16,7 +16,6 @@ import { FeatureCollection } from 'geojson'; import { MapStoreState } from '../reducers/store'; import { KBN_IS_CENTROID_FEATURE, - LAYER_STYLE_TYPE, LAYER_TYPE, SOURCE_DATA_REQUEST_ID, } from '../../common/constants'; @@ -49,7 +48,6 @@ import { IVectorLayer } from '../classes/layers/vector_layer'; import { DataMeta, MapExtent, MapFilters } from '../../common/descriptor_types'; import { DataRequestAbortError } from '../classes/util/data_request'; import { scaleBounds, turfBboxToBounds } from '../../common/elasticsearch_util'; -import { IVectorStyle } from '../classes/styles/vector/vector_style'; const FIT_TO_BOUNDS_SCALE_FACTOR = 0.1; @@ -95,38 +93,16 @@ export function updateStyleMeta(layerId: string | null) { return; } - if ( - layer.getType() === LAYER_TYPE.VECTOR || - layer.getType() === LAYER_TYPE.HEATMAP || - layer.getType() === LAYER_TYPE.BLENDED_VECTOR - ) { - const sourceDataRequest = layer.getSourceDataRequest(); - const style = layer.getCurrentStyle(); - if (!style || !sourceDataRequest || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { - return; - } - const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromSourceDataRequest( - sourceDataRequest - ); - dispatch({ - type: SET_LAYER_STYLE_META, - layerId, - styleMeta, - }); - } else if (layer.getType() === LAYER_TYPE.TILED_VECTOR) { - const style = layer.getCurrentStyle(); - if (!style || style.getType() !== LAYER_STYLE_TYPE.VECTOR) { - return; - } - - const metaFromTiles = layer.getMetaFromTiles(); - const styleMeta = await (style as IVectorStyle).pluckStyleMetaFromTileMeta(metaFromTiles); - dispatch({ - type: SET_LAYER_STYLE_META, - layerId, - styleMeta, - }); + const styleMeta = await layer.getStyleMetaDescriptor(); + if (!styleMeta) { + return; } + + dispatch({ + type: SET_LAYER_STYLE_META, + layerId, + styleMeta, + }); }; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 01e3758e63161..c16f9b4fe7f02 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -36,6 +36,7 @@ import { LayerDescriptor, MapExtent, StyleDescriptor, + StyleMetaDescriptor, } from '../../../common/descriptor_types'; import { ImmutableSourceProperty, ISource, SourceEditorArgs } from '../sources/source'; import { DataRequestContext } from '../../actions'; @@ -46,65 +47,121 @@ import { IESSource } from '../sources/es_source'; export interface ILayer { getBounds(dataRequestContext: DataRequestContext): Promise; + getDataRequest(id: string): DataRequest | undefined; + getDisplayName(source?: ISource): Promise; + getId(): string; + getSourceDataRequest(): DataRequest | undefined; + getMetaFromTiles(): any; + getSource(): ISource; + getSourceForEditing(): ISource; + syncData(syncContext: DataRequestContext): void; + supportsElasticsearchFilters(): boolean; + supportsFitToBounds(): Promise; + getAttributions(): Promise; + getLabel(): string; + hasLegendDetails(): Promise; + renderLegendDetails(): ReactElement | null; + showAtZoomLevel(zoom: number): boolean; + getMinZoom(): number; + getMaxZoom(): number; + getMinSourceZoom(): number; + getAlpha(): number; + getQuery(): Query | null; + getStyle(): IStyle; + getStyleForEditing(): IStyle; + getCurrentStyle(): IStyle; + getImmutableSourceProperties(): Promise; + renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null; + isLayerLoading(): boolean; + isLoadingBounds(): boolean; + isFilteredByGlobalTime(): Promise; + hasErrors(): boolean; + getErrors(): string; + getMbLayerIds(): string[]; + ownsMbLayerId(mbLayerId: string): boolean; + ownsMbSourceId(mbSourceId: string): boolean; + syncLayerWithMB(mbMap: MbMap): void; + getLayerTypeIconName(): string; + isInitialDataLoadComplete(): boolean; + getIndexPatternIds(): string[]; + getQueryableIndexPatternIds(): string[]; + getType(): LAYER_TYPE | undefined; + isVisible(): boolean; + cloneDescriptor(): Promise; + renderStyleEditor( onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void ): ReactElement | null; + getInFlightRequestTokens(): symbol[]; + getPrevRequestToken(dataId: string): symbol | undefined; + destroy: () => void; isPreviewLayer: () => boolean; areLabelsOnTop: () => boolean; supportsLabelsOnTop: () => boolean; + showJoinEditor(): boolean; + getJoinsDisabledReason(): string | null; + isFittable(): Promise; + isIncludeInFitToBounds(): boolean; + getLicensedFeatures(): Promise; + getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; + queryForTileMeta(mbMap: MbMap): any; + getDescriptor(): LayerDescriptor; + getGeoFieldNames(): string[]; + + getStyleMetaDescriptor(): Promise; } export type CustomIconAndTooltipContent = { @@ -530,4 +587,8 @@ export class AbstractLayer implements ILayer { const source = this.getSource(); return source.isESSource() ? [(source as IESSource).getGeoFieldName()] : []; } + + async getStyleMetaDescriptor(): Promise { + return null; + } } 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 629fcc67352a3..58366b9e7bfb9 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 @@ -5,7 +5,6 @@ * 2.0. */ -import React from 'react'; import { GeoJSONSource as MbGeoJSONSource, Map as MbMap, @@ -26,6 +25,7 @@ import { VectorLayer, VectorLayerArguments } from '../vector_layer'; import { ITiledSingleLayerVectorSource } from '../../sources/tiled_single_layer_vector_source'; import { DataRequestContext } from '../../../actions'; import { + StyleMetaDescriptor, VectorLayerDescriptor, VectorSourceRequestMeta, } from '../../../../common/descriptor_types'; @@ -320,4 +320,14 @@ export class TiledVectorLayer extends VectorLayer { getFeatureById(id: string | number): Feature | null { return null; } + + async getStyleMetaDescriptor(): Promise { + const style = this.getCurrentStyle(); + if (!style) { + return null; + } + + const metaFromTiles = this.getMetaFromTiles(); + return await style.pluckStyleMetaFromTileMeta(metaFromTiles); + } } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index dd1d444e241f0..2f1b8ec3b9cb3 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -45,6 +45,7 @@ import { DynamicStylePropertyOptions, MapFilters, MapQuery, + StyleMetaDescriptor, VectorJoinSourceRequestMeta, VectorLayerDescriptor, VectorSourceRequestMeta, @@ -82,21 +83,30 @@ export interface VectorLayerArguments { export interface IVectorLayer extends ILayer { getFields(): Promise; + getStyleEditorFields(): Promise; + getJoins(): InnerJoin[]; + getValidJoins(): InnerJoin[]; + getSource(): IVectorSource; + getFeatureById(id: string | number): Feature | null; + getPropertiesForTooltip(properties: GeoJsonProperties): Promise; + hasJoins(): boolean; + canShowTooltip(): boolean; + getLeftJoinFields(): Promise; } export class VectorLayer extends AbstractLayer implements IVectorLayer { static type = LAYER_TYPE.VECTOR; - protected readonly _style: IVectorStyle; + protected readonly _style: VectorStyle; private readonly _joins: InnerJoin[]; static createDescriptor( @@ -149,7 +159,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { return this._style; } - getCurrentStyle(): IVectorStyle { + getCurrentStyle(): VectorStyle { return this._style; } @@ -1054,4 +1064,13 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { async getLicensedFeatures() { return await this._source.getLicensedFeatures(); } + + async getStyleMetaDescriptor(): Promise { + const sourceDataRequest = this.getSourceDataRequest(); + const style = this.getCurrentStyle(); + if (!style || !sourceDataRequest) { + return null; + } + return await style.pluckStyleMetaFromSourceDataRequest(sourceDataRequest); + } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 4663230fe06f8..924ee0870c285 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -90,8 +90,6 @@ export interface IVectorStyle extends IStyle { previousFields: IField[], mapColors: string[] ): Promise<{ hasChanges: boolean; nextStyleDescriptor?: VectorStyleDescriptor }>; - pluckStyleMetaFromTileMeta(foobar: any): Promise; - pluckStyleMetaFromSourceDataRequest(sourceDataRequest: DataRequest): Promise; isTimeAware: () => boolean; getIcon: () => ReactElement; getIconFromGeometryTypes: (isLinesOnly: boolean, isPointsOnly: boolean) => ReactElement; From 94f2a15bb49a6046a8204dd10e2d6fc7f3bc8bd8 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 26 May 2021 16:57:59 -0400 Subject: [PATCH 11/68] formatting snafu --- .../public/classes/fields/agg/agg_field.ts | 5 -- .../maps/public/classes/layers/layer.tsx | 55 ------------------- 2 files changed, 60 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts index 00b237dcd5561..6e88512a32c9f 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts @@ -34,11 +34,6 @@ export class AggField extends CountAggField { return !!this._esDocField; } - // supportsFieldMeta(): boolean { - // // count and sum aggregations are not within field bounds so they do not support field meta. - // // return !isMetricCountable(this._getAggType()); - // } - canValueBeFormatted(): boolean { return this._getAggType() !== AGG_TYPE.UNIQUE_COUNT; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index c16f9b4fe7f02..4e430faf6f320 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -47,120 +47,65 @@ import { IESSource } from '../sources/es_source'; export interface ILayer { getBounds(dataRequestContext: DataRequestContext): Promise; - getDataRequest(id: string): DataRequest | undefined; - getDisplayName(source?: ISource): Promise; - getId(): string; - getSourceDataRequest(): DataRequest | undefined; - getMetaFromTiles(): any; - getSource(): ISource; - getSourceForEditing(): ISource; - syncData(syncContext: DataRequestContext): void; - supportsElasticsearchFilters(): boolean; - supportsFitToBounds(): Promise; - getAttributions(): Promise; - getLabel(): string; - hasLegendDetails(): Promise; - renderLegendDetails(): ReactElement | null; - showAtZoomLevel(zoom: number): boolean; - getMinZoom(): number; - getMaxZoom(): number; - getMinSourceZoom(): number; - getAlpha(): number; - getQuery(): Query | null; - getStyle(): IStyle; - getStyleForEditing(): IStyle; - getCurrentStyle(): IStyle; - getImmutableSourceProperties(): Promise; - renderSourceSettingsEditor({ onChange }: SourceEditorArgs): ReactElement | null; - isLayerLoading(): boolean; - isLoadingBounds(): boolean; - isFilteredByGlobalTime(): Promise; - hasErrors(): boolean; - getErrors(): string; - getMbLayerIds(): string[]; - ownsMbLayerId(mbLayerId: string): boolean; - ownsMbSourceId(mbSourceId: string): boolean; - syncLayerWithMB(mbMap: MbMap): void; - getLayerTypeIconName(): string; - isInitialDataLoadComplete(): boolean; - getIndexPatternIds(): string[]; - getQueryableIndexPatternIds(): string[]; - getType(): LAYER_TYPE | undefined; - isVisible(): boolean; - cloneDescriptor(): Promise; - renderStyleEditor( onStyleDescriptorChange: (styleDescriptor: StyleDescriptor) => void ): ReactElement | null; - getInFlightRequestTokens(): symbol[]; - getPrevRequestToken(dataId: string): symbol | undefined; - destroy: () => void; isPreviewLayer: () => boolean; areLabelsOnTop: () => boolean; supportsLabelsOnTop: () => boolean; - showJoinEditor(): boolean; - getJoinsDisabledReason(): string | null; - isFittable(): Promise; - isIncludeInFitToBounds(): boolean; - getLicensedFeatures(): Promise; - getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; - queryForTileMeta(mbMap: MbMap): any; - getDescriptor(): LayerDescriptor; - getGeoFieldNames(): string[]; - getStyleMetaDescriptor(): Promise; } From ae19c618ec00a0252e3b9ac5eead89e5ed5c88d2 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 26 May 2021 17:07:00 -0400 Subject: [PATCH 12/68] improve typing --- .../plugins/maps/public/actions/layer_actions.ts | 3 ++- .../plugins/maps/public/classes/layers/layer.tsx | 6 +++--- .../tiled_vector_layer/tiled_vector_layer.tsx | 16 +++++++++------- .../public/connected_components/mb_map/index.ts | 5 +++-- .../connected_components/mb_map/mb_map.tsx | 7 +++++-- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index d61ee35fbf9f8..9fd955ba868cf 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -8,6 +8,7 @@ import { AnyAction, Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { Query } from 'src/plugins/data/public'; +import { Feature } from 'geojson'; import { MapStoreState } from '../reducers/store'; import { getLayerById, @@ -581,7 +582,7 @@ export function setAreTilesLoaded(layerId: string, areTilesLoaded: boolean) { }; } -export function updateCounts(layerId: string, mbMetaFeatures: any) { +export function updateCounts(layerId: string, mbMetaFeatures: Feature[]) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 4e430faf6f320..a0ef93469a3c1 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -13,7 +13,7 @@ import _ from 'lodash'; import React, { ReactElement, ReactNode } from 'react'; import { EuiIcon } from '@elastic/eui'; import uuid from 'uuid/v4'; -import { FeatureCollection } from 'geojson'; +import { FeatureCollection, Feature } from 'geojson'; import { DataRequest } from '../util/data_request'; import { AGG_TYPE, @@ -103,7 +103,7 @@ export interface ILayer { isIncludeInFitToBounds(): boolean; getLicensedFeatures(): Promise; getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; - queryForTileMeta(mbMap: MbMap): any; + queryForTileMeta(mbMap: MbMap): Feature[] | null; getDescriptor(): LayerDescriptor; getGeoFieldNames(): string[]; getStyleMetaDescriptor(): Promise; @@ -170,7 +170,7 @@ export class AbstractLayer implements ILayer { return this._descriptor; } - queryForTileMeta(mbMap: MbMap): any { + queryForTileMeta(mbMap: MbMap): Feature[] | null { return null; } 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 58366b9e7bfb9..3e212606411ff 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 @@ -61,7 +61,6 @@ export class TiledVectorLayer extends VectorLayer { getCustomIconAndTooltipContent() { const tileMetas = this.getMetaFromTiles(); - if (!tileMetas) { return { icon: this.getCurrentStyle().getIcon(), @@ -70,6 +69,8 @@ export class TiledVectorLayer extends VectorLayer { }; } + // todo - use no results icon + const shapeTypeCountMeta: IVectorShapeTypeCounts = tileMetas.reduce( (accumulator: IVectorShapeTypeCounts, tileMeta: any) => { if ( @@ -101,10 +102,11 @@ export class TiledVectorLayer extends VectorLayer { shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] === 0 && shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] > 0 && shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; + return { icon: this.getCurrentStyle().getIconFromGeometryTypes(isLinesOnly, isPointsOnly), - tooltipContent: 'foobar', - areResultsTrimmed: false, + tooltipContent: 'foobar', // todo - actually construct tooltip content + areResultsTrimmed: false, // todo - actually get trimmed info }; } @@ -232,7 +234,7 @@ export class TiledVectorLayer extends VectorLayer { this._setMbCentroidProperties(mbMap, sourceMeta.layerName); } - queryForTileMeta(mbMap: MbMap): any { + queryForTileMeta(mbMap: MbMap): Feature[] | null { // @ts-ignore const mbSource = mbMap.getSource(this._getMbSourceId()); if (!mbSource) { @@ -241,11 +243,11 @@ export class TiledVectorLayer extends VectorLayer { const sourceDataRequest = this.getSourceDataRequest(); if (!sourceDataRequest) { - return; + return null; } const sourceMeta: MVTSingleLayerVectorSourceConfig = sourceDataRequest.getData() as MVTSingleLayerVectorSourceConfig; if (sourceMeta.layerName === '') { - return; + return null; } const mbFeatures = mbMap.querySourceFeatures(this._getMbSourceId(), { @@ -253,7 +255,7 @@ export class TiledVectorLayer extends VectorLayer { filter: ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], }); - return mbFeatures; + return mbFeatures as Feature[]; } _requiresPrevSourceCleanup(mbMap: MbMap): boolean { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts index 89197b40d70f0..1dd47c608fb83 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts @@ -8,6 +8,7 @@ import { AnyAction } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { connect } from 'react-redux'; +import { Feature } from 'geojson'; import { MbMap } from './mb_map'; import { mapExtentChanged, @@ -74,8 +75,8 @@ function mapDispatchToProps(dispatch: ThunkDispatch void; - updateCounts: (layerId: string, foobar: any) => void; + updateCounts: (layerId: string, features: Feature[]) => void; } interface State { @@ -145,7 +146,9 @@ export class MbMap extends Component { if (this.state.mbMap) { if (layer.isVisible()) { const mbFeatures = layer.queryForTileMeta(this.state.mbMap); - this.props.updateCounts(layerId, mbFeatures); + if (mbFeatures !== null) { + this.props.updateCounts(layerId, mbFeatures); + } } } }); From f87ce95b38ea97876e858f5e229f97f3b7293106 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 26 May 2021 17:14:41 -0400 Subject: [PATCH 13/68] type fix --- .../public/classes/styles/vector/vector_style.tsx | 12 ++++++------ .../public/connected_components/mb_map/mb_map.tsx | 7 +------ .../mb_map/tile_status_tracker.ts | 8 ++++++-- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 924ee0870c285..ed1aecc7bdc4f 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -9,10 +9,10 @@ import _ from 'lodash'; import React, { ReactElement } from 'react'; import { FeatureIdentifier, Map as MbMap } from 'mapbox-gl'; import { FeatureCollection } from 'geojson'; +import { Feature } from 'geojson'; import { StyleProperties, VectorStyleEditor } from './components/vector_style_editor'; import { getDefaultStaticProperties, LINE_STYLES, POLYGON_STYLES } from './vector_style_defaults'; import { - COUNT_PROP_NAME, DEFAULT_ICON, FIELD_ORIGIN, GEO_JSON_TYPE, @@ -489,7 +489,7 @@ export class VectorStyle implements IVectorStyle { ); } - async pluckStyleMetaFromTileMeta(foobar: any): Promise { + async pluckStyleMetaFromTileMeta(features: Feature[]): Promise { const styleMeta = { geometryTypes: { isPointsOnly: false, @@ -500,7 +500,7 @@ export class VectorStyle implements IVectorStyle { } as StyleMetaDescriptor; const dynamicProperties = this.getDynamicPropertiesArray(); - if (dynamicProperties.length === 0 || !foobar) { + if (dynamicProperties.length === 0 || !features) { // no additional meta data to pull from source data request. return styleMeta; } @@ -515,9 +515,9 @@ export class VectorStyle implements IVectorStyle { let min = Infinity; let max = -Infinity; - for (let i = 0; i < foobar.length; i++) { - if (foobar[i].properties && foobar[i].properties[name]) { - const metaFromTiles = JSON.parse(foobar[i].properties[name]); + for (let i = 0; i < features.length; i++) { + if (features[i].properties && features[i].properties[name]) { + const metaFromTiles = JSON.parse(features[i].properties[name]); min = Math.min(metaFromTiles.min, min); max = Math.max(metaFromTiles.max, max); } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index bc9bd4c9b8f7e..8fbbfaef29203 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -164,11 +164,6 @@ export class MbMap extends Component { }; })(); - // _queryForMeta = _.debounce((layerId, layer) => { - // const mbFeatures = layer.queryForTileMeta(this.state.mbMap); - // this.props.updateCounts(layerId, mbFeatures); - // }, 1000); - _debouncedSync = _.debounce(() => { if (this._isMounted && this.props.isMapReady && this.state.mbMap) { if (!this.state.hasSyncedLayerList) { @@ -234,7 +229,7 @@ export class MbMap extends Component { options.bounds = [-170, -60, 170, 75]; } const mbMap = new mapboxgl.Map(options); - // mbMap.dragRotate.disable(); + mbMap.dragRotate.disable(); mbMap.touchZoomRotate.disableRotation(); this._tileStatusTracker = new TileStatusTracker({ diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts index aad8397562ad0..f69b42fff6041 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts @@ -24,7 +24,11 @@ interface Tile { export class TileStatusTracker { private _tileCache: Tile[]; private readonly _mbMap: MapboxMap; - private readonly _setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean) => void; + private readonly _setAreTilesLoaded: ( + layerId: string, + areTilesLoaded: boolean, + layer: ILayer + ) => void; private readonly _getCurrentLayerList: () => ILayer[]; private readonly _onSourceDataLoading = (e: MapSourceDataEvent) => { if ( @@ -80,7 +84,7 @@ export class TileStatusTracker { getCurrentLayerList, }: { mbMap: MapboxMap; - setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean) => void; + setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean, layer: ILayer) => void; getCurrentLayerList: () => ILayer[]; }) { this._tileCache = []; From 15cd4fd14cc2aa8a5b06b440ede73cac0699807f Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 14 Jun 2021 18:15:12 +0200 Subject: [PATCH 14/68] type fixes --- x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts | 1 - .../classes/layers/tiled_vector_layer/tiled_vector_layer.tsx | 1 - .../maps/public/classes/layers/vector_layer/vector_layer.tsx | 2 +- .../maps/public/classes/styles/vector/vector_style.tsx | 5 +++-- .../maps/public/connected_components/mb_map/mb_map.tsx | 2 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 2 +- x-pack/plugins/maps/server/mvt/mvt_routes.ts | 2 +- 7 files changed, 7 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts index 6e88512a32c9f..5ea6dc176faa3 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts @@ -8,7 +8,6 @@ import { IndexPattern } from 'src/plugins/data/public'; import { AGG_TYPE } from '../../../../common/constants'; import { CountAggField } from './count_agg_field'; -import { isMetricCountable } from '../../util/is_metric_countable'; import { CountAggFieldParams } from './agg_field_types'; import { addFieldToDSL, getField } from '../../../../common/elasticsearch_util'; import { IField } from '../field'; 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 2df1648c704d6..a2c52161bbee7 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 @@ -5,7 +5,6 @@ * 2.0. */ -import React from 'react'; import type { Map as MbMap, GeoJSONSource as MbGeoJSONSource, diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 2522233f87b74..72d46ca749466 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -163,7 +163,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { return this._style; } - getCurrentStyle(): VectorStyle { + getCurrentStyle(): IVectorStyle { return this._style; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 09ab4d147b097..bcb68b6d0a36e 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -516,8 +516,9 @@ export class VectorStyle implements IVectorStyle { let min = Infinity; let max = -Infinity; for (let i = 0; i < features.length; i++) { - if (features[i].properties && features[i].properties[name]) { - const metaFromTiles = JSON.parse(features[i].properties[name]); + const properties = features[i].properties; + if (properties && properties[name]) { + const metaFromTiles = JSON.parse(properties[name]); min = Math.min(metaFromTiles.min, min); max = Math.max(metaFromTiles.max, max); } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index e6ca08b27e538..a2927b89a8ae7 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -137,7 +137,7 @@ export class MbMap extends Component { _queryForMeta = (() => { const callMap = new Map(); - let timerId: number | null = null; + let timerId: ReturnType | null = null; const updateAllLayers = () => { callMap.forEach((layer: ILayer, layerId: string) => { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index e0b62f4d0d392..1071fd3dd5df4 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -140,7 +140,7 @@ export async function getGridTile({ } } - const metaDataFeature = { + const metaDataFeature: Feature = { type: 'Feature', properties: { [KBN_TOO_MANY_FEATURES_PROPERTY]: true, diff --git a/x-pack/plugins/maps/server/mvt/mvt_routes.ts b/x-pack/plugins/maps/server/mvt/mvt_routes.ts index b844d5400e2fc..01a89aff1a661 100644 --- a/x-pack/plugins/maps/server/mvt/mvt_routes.ts +++ b/x-pack/plugins/maps/server/mvt/mvt_routes.ts @@ -123,7 +123,7 @@ export function initMVTRoutes({ z: parseInt((params as any).z, 10) as number, index: query.index as string, requestBody: requestBodyDSL as any, - requestType: query.requestType as RENDER_AS, + requestType: query.requestType as RENDER_AS.POINT | RENDER_AS.GRID, geoFieldType: query.geoFieldType as ES_GEO_FIELD_TYPE, searchSessionId: query.searchSessionId, abortSignal: abortController.signal, From 2e5d037b036f571f02fb8aaed90f3c433ee20cc8 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 14 Jun 2021 18:36:32 +0200 Subject: [PATCH 15/68] more fixes --- .../layers/blended_vector_layer/blended_vector_layer.ts | 8 ++++---- .../public/classes/layers/vector_layer/vector_layer.tsx | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts index 6dd454137be7d..73094b817b9dc 100644 --- a/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts +++ b/x-pack/plugins/maps/public/classes/layers/blended_vector_layer/blended_vector_layer.ts @@ -188,9 +188,9 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { private readonly _isClustered: boolean; private readonly _clusterSource: ESGeoGridSource; - private readonly _clusterStyle: IVectorStyle; + private readonly _clusterStyle: VectorStyle; private readonly _documentSource: ESSearchSource; - private readonly _documentStyle: IVectorStyle; + private readonly _documentStyle: VectorStyle; constructor(options: BlendedVectorLayerArguments) { super({ @@ -199,7 +199,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { }); this._documentSource = this._source as ESSearchSource; // VectorLayer constructor sets _source as document source - this._documentStyle = this._style as IVectorStyle; // VectorLayer constructor sets _style as document source + this._documentStyle = this._style; // VectorLayer constructor sets _style as document source this._clusterSource = getClusterSource(this._documentSource, this._documentStyle); const clusterStyleDescriptor = getClusterStyleDescriptor( @@ -283,7 +283,7 @@ export class BlendedVectorLayer extends VectorLayer implements IVectorLayer { return this._documentSource; } - getCurrentStyle(): IVectorStyle { + getCurrentStyle(): VectorStyle { return this._isClustered ? this._clusterStyle : this._documentStyle; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 72d46ca749466..2522233f87b74 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -163,7 +163,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { return this._style; } - getCurrentStyle(): IVectorStyle { + getCurrentStyle(): VectorStyle { return this._style; } From 65543b7e7e45f4fca50da3e37b80cf172fe7d38b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 15 Jun 2021 17:59:15 +0200 Subject: [PATCH 16/68] add incomplete results icon --- .../maps/public/classes/layers/layer.tsx | 4 ++-- .../tiled_vector_layer/tiled_vector_layer.tsx | 20 +++++++++++++++---- .../layers/vector_layer/vector_layer.tsx | 9 --------- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 87d995fec760e..6a7b149ceff91 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -51,7 +51,7 @@ export interface ILayer { getDisplayName(source?: ISource): Promise; getId(): string; getSourceDataRequest(): DataRequest | undefined; - getMetaFromTiles(): any; + getMetaFromTiles(): Feature[]; getSource(): ISource; getSourceForEditing(): ISource; syncData(syncContext: DataRequestContext): void; @@ -174,7 +174,7 @@ export class AbstractLayer implements ILayer { return null; } - getMetaFromTiles(): any { + getMetaFromTiles(): Feature[] { return this._descriptor.__metaFromTiles; } 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 a2c52161bbee7..b93a39ec92621 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 @@ -13,8 +13,10 @@ import type { import { Feature } from 'geojson'; import uuid from 'uuid/v4'; import { parse as parseUrl } from 'url'; +import { i18n } from '@kbn/i18n'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { + KBN_IS_TILE_COMPLETE, KBN_TOO_MANY_FEATURES_PROPERTY, KBN_VECTOR_SHAPE_TYPE_COUNTS, LAYER_TYPE, @@ -69,10 +71,16 @@ export class TiledVectorLayer extends VectorLayer { }; } - // todo - use no results icon + const isComplete: boolean = tileMetas.every((tileMeta: Feature) => { + return tileMeta && tileMeta.properties && tileMeta.properties[KBN_IS_TILE_COMPLETE]; + }); const shapeTypeCountMeta: IVectorShapeTypeCounts = tileMetas.reduce( - (accumulator: IVectorShapeTypeCounts, tileMeta: any) => { + (accumulator: IVectorShapeTypeCounts, tileMeta: Feature) => { + if (!tileMeta || !tileMeta.properties) { + return accumulator; + } + if ( tileMeta.properties[KBN_TOO_MANY_FEATURES_PROPERTY] === true || typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string' @@ -105,8 +113,12 @@ export class TiledVectorLayer extends VectorLayer { return { icon: this.getCurrentStyle().getIconFromGeometryTypes(isLinesOnly, isPointsOnly), - tooltipContent: 'foobar', // todo - actually construct tooltip content - areResultsTrimmed: false, // todo - actually get trimmed info + tooltipContent: !isComplete + ? i18n.translate('xpack.maps.tiles.resultsTrimmedMsg', { + defaultMessage: `Layer shows incomplete results`, + }) + : null, + areResultsTrimmed: !isComplete, }; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 2522233f87b74..60e1e600f35d1 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -87,23 +87,14 @@ export interface VectorLayerArguments { export interface IVectorLayer extends ILayer { getFields(): Promise; - getStyleEditorFields(): Promise; - getJoins(): InnerJoin[]; - getValidJoins(): InnerJoin[]; - getSource(): IVectorSource; - getFeatureById(id: string | number): Feature | null; - getPropertiesForTooltip(properties: GeoJsonProperties): Promise; - hasJoins(): boolean; - canShowTooltip(): boolean; - getLeftJoinFields(): Promise; } From 50c49e46bfd05f506b938fc7e4241719204e48cf Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 15 Jun 2021 18:39:06 +0200 Subject: [PATCH 17/68] add no results icon --- x-pack/plugins/maps/common/constants.ts | 3 +- .../maps/common/get_centroid_features.ts | 8 ++--- .../tiled_vector_layer/tiled_vector_layer.tsx | 30 +++++++++++++++---- .../layers/vector_layer/vector_layer.tsx | 4 +-- .../classes/util/mb_filter_expressions.ts | 4 +-- x-pack/plugins/maps/server/mvt/get_tile.ts | 12 +++++--- 6 files changed, 41 insertions(+), 20 deletions(-) diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 4663657fbb379..20b1f8e7a5057 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -49,7 +49,8 @@ export const MVT_GETGRIDTILE_API_PATH = 'mvt/getGridTile'; export const MVT_SOURCE_LAYER_NAME = 'source_layer'; // Identifies vector tile "too many features" feature. // "too many features" feature is a box showing area that contains too many features for single ES search response -export const KBN_TOO_MANY_FEATURES_PROPERTY = '__kbn_too_many_features__'; +export const KBN_METADATA_FEATURE = '__kbn_metadata_feature__'; +export const KBN_FEATURE_COUNT = '__kbn_feature_count__'; export const KBN_IS_TILE_COMPLETE = '__kbn_is_tile_complete__'; export const KBN_VECTOR_SHAPE_TYPE_COUNTS = '__kbn_vector_shape_type_counts__'; export const KBN_TOO_MANY_FEATURES_IMAGE_ID = '__kbn_too_many_features_image_id__'; diff --git a/x-pack/plugins/maps/common/get_centroid_features.ts b/x-pack/plugins/maps/common/get_centroid_features.ts index ce82b7d875fbd..edf8167f9c15d 100644 --- a/x-pack/plugins/maps/common/get_centroid_features.ts +++ b/x-pack/plugins/maps/common/get_centroid_features.ts @@ -21,11 +21,7 @@ import turfArea from '@turf/area'; import turfCenterOfMass from '@turf/center-of-mass'; import turfLength from '@turf/length'; import { lineString, polygon } from '@turf/helpers'; -import { - GEO_JSON_TYPE, - KBN_IS_CENTROID_FEATURE, - KBN_TOO_MANY_FEATURES_PROPERTY, -} from './constants'; +import { GEO_JSON_TYPE, KBN_IS_CENTROID_FEATURE, KBN_METADATA_FEATURE } from './constants'; export function getCentroidFeatures(featureCollection: FeatureCollection): Feature[] { const centroids = []; @@ -33,7 +29,7 @@ export function getCentroidFeatures(featureCollection: FeatureCollection): Featu const feature = featureCollection.features[i]; // do not add centroid for kibana added features - if (feature.properties?.[KBN_TOO_MANY_FEATURES_PROPERTY]) { + if (feature.properties?.[KBN_METADATA_FEATURE]) { continue; } 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 b93a39ec92621..af8db157bc2eb 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 @@ -5,6 +5,8 @@ * 2.0. */ +import React from 'react'; + import type { Map as MbMap, GeoJSONSource as MbGeoJSONSource, @@ -14,10 +16,12 @@ import { Feature } from 'geojson'; import uuid from 'uuid/v4'; import { parse as parseUrl } from 'url'; import { i18n } from '@kbn/i18n'; +import { EuiIcon } from '@elastic/eui'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { + KBN_FEATURE_COUNT, KBN_IS_TILE_COMPLETE, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_METADATA_FEATURE, KBN_VECTOR_SHAPE_TYPE_COUNTS, LAYER_TYPE, SOURCE_DATA_REQUEST_ID, @@ -62,11 +66,27 @@ export class TiledVectorLayer extends VectorLayer { } getCustomIconAndTooltipContent() { + const noResultsIcon = ; const tileMetas = this.getMetaFromTiles(); if (!tileMetas) { return { - icon: this.getCurrentStyle().getIcon(), - tooltipContent: 'foobar', + icon: noResultsIcon, + tooltipContent: null, + areResultsTrimmed: false, + }; + } + + const totalFeatures: number = tileMetas.reduce((acc: number, tileMeta: Feature) => { + const count = !tileMeta || !tileMeta.properties ? 0 : tileMeta.properties[KBN_FEATURE_COUNT]; + return count + acc; + }, 0); + + if (totalFeatures === 0) { + return { + icon: noResultsIcon, + tooltipContent: i18n.translate('xpack.maps.tiledLayer.noResultsFoundTooltip', { + defaultMessage: `No results found.`, + }), areResultsTrimmed: false, }; } @@ -82,7 +102,7 @@ export class TiledVectorLayer extends VectorLayer { } if ( - tileMeta.properties[KBN_TOO_MANY_FEATURES_PROPERTY] === true || + tileMeta.properties[KBN_METADATA_FEATURE] === true || typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string' ) { return accumulator; @@ -264,7 +284,7 @@ export class TiledVectorLayer extends VectorLayer { const mbFeatures = mbMap.querySourceFeatures(this._getMbSourceId(), { sourceLayer: sourceMeta.layerName, - filter: ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], + filter: ['==', ['get', KBN_METADATA_FEATURE], true], }); return mbFeatures as Feature[]; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 60e1e600f35d1..a9d4028fb04c4 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -23,7 +23,7 @@ import { SOURCE_FORMATTERS_DATA_REQUEST_ID, FEATURE_VISIBLE_PROPERTY_NAME, EMPTY_FEATURE_COLLECTION, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_METADATA_FEATURE, LAYER_TYPE, FIELD_ORIGIN, KBN_TOO_MANY_FEATURES_IMAGE_ID, @@ -886,7 +886,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { mbMap.addLayer(mbLayer); mbMap.setFilter(tooManyFeaturesLayerId, [ 'all', - ['==', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true], + ['==', ['get', KBN_METADATA_FEATURE], true], ['==', ['get', KBN_IS_TILE_COMPLETE], false], ]); mbMap.setPaintProperty( diff --git a/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts b/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts index f5df741759cb3..7dadc7074ac4a 100644 --- a/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts +++ b/x-pack/plugins/maps/public/classes/util/mb_filter_expressions.ts @@ -9,10 +9,10 @@ import { GEO_JSON_TYPE, FEATURE_VISIBLE_PROPERTY_NAME, KBN_IS_CENTROID_FEATURE, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_METADATA_FEATURE, } from '../../../common/constants'; -export const EXCLUDE_TOO_MANY_FEATURES_BOX = ['!=', ['get', KBN_TOO_MANY_FEATURES_PROPERTY], true]; +export const EXCLUDE_TOO_MANY_FEATURES_BOX = ['!=', ['get', KBN_METADATA_FEATURE], true]; const EXCLUDE_CENTROID_FEATURES = ['!=', ['get', KBN_IS_CENTROID_FEATURE], true]; function getFilterExpression(geometryFilter: unknown[], hasJoins: boolean) { diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 1071fd3dd5df4..a8dd7c9a1ef33 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -18,8 +18,9 @@ import { ES_GEO_FIELD_TYPE, FEATURE_ID_PROPERTY_NAME, GEOTILE_GRID_AGG_NAME, + KBN_FEATURE_COUNT, KBN_IS_TILE_COMPLETE, - KBN_TOO_MANY_FEATURES_PROPERTY, + KBN_METADATA_FEATURE, KBN_VECTOR_SHAPE_TYPE_COUNTS, MAX_ZOOM, MVT_SOURCE_LAYER_NAME, @@ -143,7 +144,8 @@ export async function getGridTile({ const metaDataFeature: Feature = { type: 'Feature', properties: { - [KBN_TOO_MANY_FEATURES_PROPERTY]: true, + [KBN_METADATA_FEATURE]: true, + [KBN_FEATURE_COUNT]: features.length, [KBN_IS_TILE_COMPLETE]: true, [KBN_VECTOR_SHAPE_TYPE_COUNTS]: requestType === RENDER_AS.GRID @@ -268,8 +270,9 @@ export async function getTile({ { type: 'Feature', properties: { - [KBN_TOO_MANY_FEATURES_PROPERTY]: true, + [KBN_METADATA_FEATURE]: true, [KBN_IS_TILE_COMPLETE]: false, + [KBN_FEATURE_COUNT]: 0, }, geometry: esBboxToGeoJsonPolygon( // @ts-expect-error @elastic/elasticsearch no way to declare aggregations for search response @@ -321,9 +324,10 @@ export async function getTile({ const metadataFeature = { type: 'Feature', properties: { - [KBN_TOO_MANY_FEATURES_PROPERTY]: true, + [KBN_METADATA_FEATURE]: true, [KBN_IS_TILE_COMPLETE]: true, [KBN_VECTOR_SHAPE_TYPE_COUNTS]: counts, + [KBN_FEATURE_COUNT]: features.length, }, // todo - constrain to actual features geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), From 8578ba2e8bb53b59f6f6c1a368f87c846919aa02 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 15 Jun 2021 18:45:08 +0200 Subject: [PATCH 18/68] extract commonalities --- .../tiled_vector_layer/tiled_vector_layer.tsx | 22 ++++++------------- .../classes/layers/vector_layer/index.ts | 7 +++++- .../layers/vector_layer/vector_layer.tsx | 16 ++++++++------ 3 files changed, 22 insertions(+), 23 deletions(-) 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 af8db157bc2eb..7990748d08150 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 @@ -16,7 +16,6 @@ import { Feature } from 'geojson'; import uuid from 'uuid/v4'; import { parse as parseUrl } from 'url'; import { i18n } from '@kbn/i18n'; -import { EuiIcon } from '@elastic/eui'; import { IVectorStyle, VectorStyle } from '../../styles/vector/vector_style'; import { KBN_FEATURE_COUNT, @@ -27,7 +26,11 @@ import { SOURCE_DATA_REQUEST_ID, VECTOR_SHAPE_TYPE, } from '../../../../common/constants'; -import { VectorLayer, VectorLayerArguments } from '../vector_layer'; +import { + VectorLayer, + VectorLayerArguments, + NO_RESULTS_ICON_AND_TOOLTIPCONTENT, +} from '../vector_layer'; import { ITiledSingleLayerVectorSource } from '../../sources/tiled_single_layer_vector_source'; import { DataRequestContext } from '../../../actions'; import { @@ -66,14 +69,9 @@ export class TiledVectorLayer extends VectorLayer { } getCustomIconAndTooltipContent() { - const noResultsIcon = ; const tileMetas = this.getMetaFromTiles(); if (!tileMetas) { - return { - icon: noResultsIcon, - tooltipContent: null, - areResultsTrimmed: false, - }; + return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } const totalFeatures: number = tileMetas.reduce((acc: number, tileMeta: Feature) => { @@ -82,13 +80,7 @@ export class TiledVectorLayer extends VectorLayer { }, 0); if (totalFeatures === 0) { - return { - icon: noResultsIcon, - tooltipContent: i18n.translate('xpack.maps.tiledLayer.noResultsFoundTooltip', { - defaultMessage: `No results found.`, - }), - areResultsTrimmed: false, - }; + return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } const isComplete: boolean = tileMetas.every((tileMeta: Feature) => { diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts index b6777f8a5e454..3c8449c5aa4ae 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts @@ -6,4 +6,9 @@ */ export { addGeoJsonMbSource, getVectorSourceBounds, syncVectorSource } from './utils'; -export { IVectorLayer, VectorLayer, VectorLayerArguments } from './vector_layer'; +export { + IVectorLayer, + VectorLayer, + VectorLayerArguments, + NO_RESULTS_ICON_AND_TOOLTIPCONTENT, +} from './vector_layer'; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index a9d4028fb04c4..a859b86257562 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -98,6 +98,14 @@ export interface IVectorLayer extends ILayer { getLeftJoinFields(): Promise; } +const noResultsIcon = ; +export const NO_RESULTS_ICON_AND_TOOLTIPCONTENT = { + icon: noResultsIcon, + tooltipContent: i18n.translate('xpack.maps.vectorLayer.noResultsFoundTooltip', { + defaultMessage: `No results found.`, + }), +}; + export class VectorLayer extends AbstractLayer implements IVectorLayer { static type = LAYER_TYPE.VECTOR; @@ -201,14 +209,8 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { getCustomIconAndTooltipContent(): CustomIconAndTooltipContent { const featureCollection = this._getSourceFeatureCollection(); - const noResultsIcon = ; if (!featureCollection || featureCollection.features.length === 0) { - return { - icon: noResultsIcon, - tooltipContent: i18n.translate('xpack.maps.vectorLayer.noResultsFoundTooltip', { - defaultMessage: `No results found.`, - }), - }; + return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } if ( From 664ab18ca347cc964b0d19a01f3ec7e8158dc1c3 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 15 Jun 2021 19:18:49 +0200 Subject: [PATCH 19/68] remove typo --- .../classes/layers/tiled_vector_layer/tiled_vector_layer.tsx | 1 - 1 file changed, 1 deletion(-) 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 7990748d08150..174d3b2d9a272 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 @@ -94,7 +94,6 @@ export class TiledVectorLayer extends VectorLayer { } if ( - tileMeta.properties[KBN_METADATA_FEATURE] === true || typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string' ) { return accumulator; From c429b09e3fbca2c53cd761127f2a50ecaac6a27c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 15 Jun 2021 19:21:12 +0200 Subject: [PATCH 20/68] typo --- .../classes/layers/tiled_vector_layer/tiled_vector_layer.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 174d3b2d9a272..ecd4d5bf61ad2 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 @@ -93,9 +93,7 @@ export class TiledVectorLayer extends VectorLayer { return accumulator; } - if ( - typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string' - ) { + if (typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string') { return accumulator; } const counts = JSON.parse(tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS]); From 4c98eb75de2bca875080b7e71b119027e7aa6e9c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 15 Jun 2021 19:41:03 +0200 Subject: [PATCH 21/68] remove unused --- .../classes/layers/tiled_vector_layer/tiled_vector_layer.tsx | 2 -- 1 file changed, 2 deletions(-) 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 ecd4d5bf61ad2..45b10ae2fec56 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 @@ -5,8 +5,6 @@ * 2.0. */ -import React from 'react'; - import type { Map as MbMap, GeoJSONSource as MbGeoJSONSource, From b78fd7f3cc1cab2ad065c78490d12e0ebd54c885 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 16 Jun 2021 19:38:30 +0200 Subject: [PATCH 22/68] feedback --- .../common/descriptor_types/layer_descriptor_types.ts | 3 ++- .../plugins/maps/common/get_centroid_features.test.ts | 4 ++-- x-pack/plugins/maps/common/get_geometry_counts.ts | 6 +++--- x-pack/plugins/maps/public/actions/layer_actions.ts | 4 ---- x-pack/plugins/maps/public/classes/layers/layer.tsx | 5 ----- .../layers/tiled_vector_layer/tiled_vector_layer.tsx | 10 +++++++--- 6 files changed, 14 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 1ce5eaafd6a3e..3ed4f733a94c2 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -8,6 +8,7 @@ /* eslint-disable @typescript-eslint/consistent-type-definitions */ import { Query } from 'src/plugins/data/public'; +import { Feature } from 'geojson'; import { HeatmapStyleDescriptor, StyleDescriptor, @@ -33,7 +34,7 @@ export type LayerDescriptor = { __errorMessage?: string; __trackedLayerDescriptor?: LayerDescriptor; __areTilesLoaded?: boolean; - __metaFromTiles?: any; + __metaFromTiles?: Feature[]; alpha?: number; attribution?: Attribution; id: string; diff --git a/x-pack/plugins/maps/common/get_centroid_features.test.ts b/x-pack/plugins/maps/common/get_centroid_features.test.ts index 57879989644f1..0fac9dc3a355f 100644 --- a/x-pack/plugins/maps/common/get_centroid_features.test.ts +++ b/x-pack/plugins/maps/common/get_centroid_features.test.ts @@ -44,7 +44,7 @@ test('should not create centroid feature for point and multipoint', () => { expect(centroidFeatures.length).toBe(0); }); -test('should not create centroid for too many features polygon', () => { +test('should not create centroid for the metadata polygon', () => { const polygonFeature: Feature = { type: 'Feature', geometry: { @@ -60,7 +60,7 @@ test('should not create centroid for too many features polygon', () => { ], }, properties: { - __kbn_too_many_features__: true, + __kbn_metadata_feature__: true, prop0: 'value0', prop1: 0.0, }, diff --git a/x-pack/plugins/maps/common/get_geometry_counts.ts b/x-pack/plugins/maps/common/get_geometry_counts.ts index cafed7d864b13..2a3368560c762 100644 --- a/x-pack/plugins/maps/common/get_geometry_counts.ts +++ b/x-pack/plugins/maps/common/get_geometry_counts.ts @@ -8,14 +8,14 @@ import { Feature } from 'geojson'; import { GEO_JSON_TYPE, VECTOR_SHAPE_TYPE } from './constants'; -export interface IVectorShapeTypeCounts { +export interface VectorShapeTypeCounts { [VECTOR_SHAPE_TYPE.POINT]: number; [VECTOR_SHAPE_TYPE.LINE]: number; [VECTOR_SHAPE_TYPE.POLYGON]: number; } -export function countVectorShapeTypes(features: Feature[]): IVectorShapeTypeCounts { - const vectorShapeTypeCounts: IVectorShapeTypeCounts = { +export function countVectorShapeTypes(features: Feature[]): VectorShapeTypeCounts { + const vectorShapeTypeCounts: VectorShapeTypeCounts = { [VECTOR_SHAPE_TYPE.POINT]: 0, [VECTOR_SHAPE_TYPE.LINE]: 0, [VECTOR_SHAPE_TYPE.POLYGON]: 0, diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 9fd955ba868cf..6f57f2d700bdd 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -587,10 +587,6 @@ export function updateCounts(layerId: string, mbMetaFeatures: Feature[]) { dispatch: ThunkDispatch, getState: () => MapStoreState ) => { - if (!mbMetaFeatures) { - return; - } - const layer = getLayerById(layerId, getState()); if (!layer) { return; diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 6a7b149ceff91..53739d9986b22 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -51,7 +51,6 @@ export interface ILayer { getDisplayName(source?: ISource): Promise; getId(): string; getSourceDataRequest(): DataRequest | undefined; - getMetaFromTiles(): Feature[]; getSource(): ISource; getSourceForEditing(): ISource; syncData(syncContext: DataRequestContext): void; @@ -174,10 +173,6 @@ export class AbstractLayer implements ILayer { return null; } - getMetaFromTiles(): Feature[] { - return this._descriptor.__metaFromTiles; - } - async cloneDescriptor(): Promise { const clonedDescriptor = copyPersistentState(this._descriptor); // layer id is uuid used to track styles/layers in mapbox 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 45b10ae2fec56..ffafb73df8225 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 @@ -38,7 +38,7 @@ import { } from '../../../../common/descriptor_types'; import { MVTSingleLayerVectorSourceConfig } from '../../sources/mvt_single_layer_vector_source/types'; import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; -import { IVectorShapeTypeCounts } from '../../../../common/get_geometry_counts'; +import { VectorShapeTypeCounts } from '../../../../common/get_geometry_counts'; import { isRefreshOnlyQuery } from '../../util/is_refresh_only_query'; export class TiledVectorLayer extends VectorLayer { @@ -66,6 +66,10 @@ export class TiledVectorLayer extends VectorLayer { this._source = source as ITiledSingleLayerVectorSource; } + getMetaFromTiles(): Feature[] { + return this._descriptor.__metaFromTiles || []; + } + getCustomIconAndTooltipContent() { const tileMetas = this.getMetaFromTiles(); if (!tileMetas) { @@ -85,8 +89,8 @@ export class TiledVectorLayer extends VectorLayer { return tileMeta && tileMeta.properties && tileMeta.properties[KBN_IS_TILE_COMPLETE]; }); - const shapeTypeCountMeta: IVectorShapeTypeCounts = tileMetas.reduce( - (accumulator: IVectorShapeTypeCounts, tileMeta: Feature) => { + const shapeTypeCountMeta: VectorShapeTypeCounts = tileMetas.reduce( + (accumulator: VectorShapeTypeCounts, tileMeta: Feature) => { if (!tileMeta || !tileMeta.properties) { return accumulator; } From f0594ff66b3e00e575d93f4e1658fffa03fc10ef Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 23 Jun 2021 18:34:02 +0200 Subject: [PATCH 23/68] feedback --- .../plugins/maps/public/actions/layer_actions.ts | 2 +- .../plugins/maps/public/classes/layers/layer.tsx | 5 ----- .../public/connected_components/mb_map/index.ts | 6 +++--- .../connected_components/mb_map/mb_map.tsx | 16 ++++++++-------- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 174192a58868f..908e3d5736141 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -586,7 +586,7 @@ export function setAreTilesLoaded(layerId: string, areTilesLoaded: boolean) { }; } -export function updateCounts(layerId: string, mbMetaFeatures: Feature[]) { +export function updateMetaFromTiles(layerId: string, mbMetaFeatures: Feature[]) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 53739d9986b22..f1d48512bc53b 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -102,7 +102,6 @@ export interface ILayer { isIncludeInFitToBounds(): boolean; getLicensedFeatures(): Promise; getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; - queryForTileMeta(mbMap: MbMap): Feature[] | null; getDescriptor(): LayerDescriptor; getGeoFieldNames(): string[]; getStyleMetaDescriptor(): Promise; @@ -169,10 +168,6 @@ export class AbstractLayer implements ILayer { return this._descriptor; } - queryForTileMeta(mbMap: MbMap): Feature[] | null { - return null; - } - async cloneDescriptor(): Promise { const clonedDescriptor = copyPersistentState(this._descriptor); // layer id is uuid used to track styles/layers in mapbox diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts index 949317dca46e9..9bce43abe57ac 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts @@ -20,7 +20,7 @@ import { setAreTilesLoaded, setMapInitError, setMouseCoordinates, - updateCounts, + updateMetaFromTiles, } from '../../actions'; import { getGoto, @@ -79,8 +79,8 @@ function mapDispatchToProps(dispatch: ThunkDispatch void; renderTooltipContent?: RenderToolTipContent; setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean) => void; - updateCounts: (layerId: string, features: Feature[]) => void; + updateMetaFromTiles: (layerId: string, features: Feature[]) => void; featureModeActive: boolean; filterModeActive: boolean; } @@ -144,10 +144,10 @@ export class MbMap extends Component { const updateAllLayers = () => { callMap.forEach((layer: ILayer, layerId: string) => { if (this.state.mbMap) { - if (layer.isVisible()) { - const mbFeatures = layer.queryForTileMeta(this.state.mbMap); + if (layer.isVisible() && layer.getType() === LAYER_TYPE.TILED_VECTOR) { + const mbFeatures = (layer as TiledVectorLayer).queryForTileMeta(this.state.mbMap); if (mbFeatures !== null) { - this.props.updateCounts(layerId, mbFeatures); + this.props.updateMetaFromTiles(layerId, mbFeatures); } } } From 1bd388c0564d8bf9d931907c9b7794cc76271ce0 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 23 Jun 2021 19:01:18 +0200 Subject: [PATCH 24/68] feedback --- .../tiled_vector_layer/tiled_vector_layer.tsx | 12 +++--- .../classes/styles/vector/vector_style.tsx | 2 - .../connected_components/mb_map/mb_map.tsx | 39 +++++-------------- .../mb_map/tile_status_tracker.ts | 10 ++--- 4 files changed, 19 insertions(+), 44 deletions(-) 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 ffafb73df8225..f2251779acd90 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 @@ -72,12 +72,12 @@ export class TiledVectorLayer extends VectorLayer { getCustomIconAndTooltipContent() { const tileMetas = this.getMetaFromTiles(); - if (!tileMetas) { + if (!tileMetas.length) { return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } const totalFeatures: number = tileMetas.reduce((acc: number, tileMeta: Feature) => { - const count = !tileMeta || !tileMeta.properties ? 0 : tileMeta.properties[KBN_FEATURE_COUNT]; + const count = tileMeta && tileMeta.properties ? tileMeta.properties[KBN_FEATURE_COUNT] : 0; return count + acc; }, 0); @@ -85,8 +85,8 @@ export class TiledVectorLayer extends VectorLayer { return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } - const isComplete: boolean = tileMetas.every((tileMeta: Feature) => { - return tileMeta && tileMeta.properties && tileMeta.properties[KBN_IS_TILE_COMPLETE]; + const isIncomplete: boolean = tileMetas.some((tileMeta: Feature) => { + return !tileMeta?.properties?.[KBN_IS_TILE_COMPLETE]; }); const shapeTypeCountMeta: VectorShapeTypeCounts = tileMetas.reduce( @@ -124,12 +124,12 @@ export class TiledVectorLayer extends VectorLayer { return { icon: this.getCurrentStyle().getIconFromGeometryTypes(isLinesOnly, isPointsOnly), - tooltipContent: !isComplete + tooltipContent: isIncomplete ? i18n.translate('xpack.maps.tiles.resultsTrimmedMsg', { defaultMessage: `Layer shows incomplete results`, }) : null, - areResultsTrimmed: !isComplete, + areResultsTrimmed: !isIncomplete, }; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index bcb68b6d0a36e..b23efd94ebf57 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -511,8 +511,6 @@ export class VectorStyle implements IVectorStyle { styleMeta.fieldMeta[name] = {}; } - styleMeta.fieldMeta[name] = {}; - let min = Infinity; let max = -Infinity; for (let i = 0; i < features.length; i++) { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 01ad226877a46..a0e3dcdd60b27 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -136,33 +136,14 @@ export class MbMap extends Component { } // This keeps track of the latest update calls, per layerId - _queryForMeta = (() => { - const callMap = new Map(); - - let timerId: ReturnType | null = null; - - const updateAllLayers = () => { - callMap.forEach((layer: ILayer, layerId: string) => { - if (this.state.mbMap) { - if (layer.isVisible() && layer.getType() === LAYER_TYPE.TILED_VECTOR) { - const mbFeatures = (layer as TiledVectorLayer).queryForTileMeta(this.state.mbMap); - if (mbFeatures !== null) { - this.props.updateMetaFromTiles(layerId, mbFeatures); - } - } - } - }); - callMap.clear(); - timerId = null; - }; - - return (layerId: string, layer: ILayer) => { - callMap.set(layerId, layer); - if (!timerId) { - timerId = setTimeout(updateAllLayers, 1200); + _queryForMeta = (layer: ILayer) => { + if (this.state.mbMap && layer.isVisible() && layer.getType() === LAYER_TYPE.TILED_VECTOR) { + const mbFeatures = (layer as TiledVectorLayer).queryForTileMeta(this.state.mbMap); + if (mbFeatures !== null) { + this.props.updateMetaFromTiles(layer.getId(), mbFeatures); } - }; - })(); + } + }; _debouncedSync = _.debounce(() => { if (this._isMounted && this.props.isMapReady && this.state.mbMap) { @@ -235,9 +216,9 @@ export class MbMap extends Component { this._tileStatusTracker = new TileStatusTracker({ mbMap, getCurrentLayerList: () => this.props.layerList, - setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean, layer: ILayer) => { - this.props.setAreTilesLoaded(layerId, areTilesLoaded); - this._queryForMeta(layerId, layer); + setAreTilesLoaded: (layer: ILayer, areTilesLoaded: boolean) => { + this.props.setAreTilesLoaded(layer.getId(), areTilesLoaded); + this._queryForMeta(layer); }, }); diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts index 14f2f0425d849..e4a34231d98c4 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts @@ -24,11 +24,7 @@ interface Tile { export class TileStatusTracker { private _tileCache: Tile[]; private readonly _mbMap: MapboxMap; - private readonly _setAreTilesLoaded: ( - layerId: string, - areTilesLoaded: boolean, - layer: ILayer - ) => void; + private readonly _setAreTilesLoaded: (layer: ILayer, areTilesLoaded: boolean) => void; private readonly _getCurrentLayerList: () => ILayer[]; private readonly _onSourceDataLoading = (e: MapSourceDataEvent) => { if ( @@ -84,7 +80,7 @@ export class TileStatusTracker { getCurrentLayerList, }: { mbMap: MapboxMap; - setAreTilesLoaded: (layerId: string, areTilesLoaded: boolean, layer: ILayer) => void; + setAreTilesLoaded: (layer: ILayer, areTilesLoaded: boolean) => void; getCurrentLayerList: () => ILayer[]; }) { this._tileCache = []; @@ -112,7 +108,7 @@ export class TileStatusTracker { break; } } - this._setAreTilesLoaded(layer.getId(), !atLeastOnePendingTile, layer); + this._setAreTilesLoaded(layer, !atLeastOnePendingTile); } }, 100); From 58033f2409c3ccfc921aa9a556a52e0b2c29f170 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 12:21:57 +0200 Subject: [PATCH 25/68] type fixes --- x-pack/plugins/maps/public/classes/layers/layer.tsx | 2 +- .../maps/public/connected_components/mb_map/mb_map.tsx | 2 ++ .../connected_components/mb_map/tile_status_tracker.test.ts | 4 ++-- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 636d1fa4ce53b..644aebb545777 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -13,7 +13,7 @@ import _ from 'lodash'; import React, { ReactElement, ReactNode } from 'react'; import { EuiIcon } from '@elastic/eui'; import uuid from 'uuid/v4'; -import { FeatureCollection, Feature } from 'geojson'; +import { FeatureCollection } from 'geojson'; import { DataRequest } from '../util/data_request'; import { AGG_TYPE, diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 03b6d0fe843b1..3e60ef3317bbb 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -36,10 +36,12 @@ import { } from '../../../common/constants'; import { getGlyphUrl, isRetina } from '../../util'; import { syncLayerOrder } from './sort_layers'; + import { addSpriteSheetToMapFromImageData, loadSpriteSheetImageData, removeOrphanedSourcesAndLayers, + // @ts-expect-error } from './utils'; import { ResizeChecker } from '../../../../../../src/plugins/kibana_utils/public'; import { RenderToolTipContent } from '../../classes/tooltips/tooltip_property'; diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts index 6b47fe3e6e650..e6363cb051767 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts @@ -84,8 +84,8 @@ describe('TileStatusTracker', () => { const loadedMap: Map = new Map(); new TileStatusTracker({ mbMap: (mockMbMap as unknown) as MbMap, - setAreTilesLoaded: (layerId, areTilesLoaded) => { - loadedMap.set(layerId, areTilesLoaded); + setAreTilesLoaded: (layer, areTilesLoaded) => { + loadedMap.set(layer.getId(), areTilesLoaded); }, getCurrentLayerList: () => { return [ From 64702d297df1c91f7327fdc5f5bd99da79bf53fb Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 12:26:17 +0200 Subject: [PATCH 26/68] fix test --- .../classes/styles/vector/properties/test_helpers/test_util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts index f6abe86a85865..4b7d90ec0da1b 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts @@ -76,7 +76,7 @@ export class MockStyle implements IStyle { return LAYER_STYLE_TYPE.VECTOR; } - getStyleMeta(): StyleMetaFromLocal { + getStyleMetaFromLocal(): StyleMetaFromLocal { const geomTypes: GeometryTypes = { isPointsOnly: false, isLinesOnly: false, From f1f30607dbc9b94cd89565acbfd92e68ef6932bc Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 12:29:00 +0200 Subject: [PATCH 27/68] update snapshot --- .../__snapshots__/tiled_vector_layer.test.tsx.snap | 5 +++-- .../layers/tiled_vector_layer/tiled_vector_layer.test.tsx | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/__snapshots__/tiled_vector_layer.test.tsx.snap b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/__snapshots__/tiled_vector_layer.test.tsx.snap index 3a542ce9bca1e..d3b96936a85a1 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/__snapshots__/tiled_vector_layer.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/__snapshots__/tiled_vector_layer.test.tsx.snap @@ -1,8 +1,9 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`icon should use vector icon 1`] = ` +exports[`icon should use no data icon 1`] = ` `; diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.test.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.test.tsx index e71d32669a564..e1f134cdf2a85 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.test.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.test.tsx @@ -96,7 +96,7 @@ describe('visiblity', () => { }); describe('icon', () => { - it('should use vector icon', async () => { + it('should use no data icon', async () => { const layer: TiledVectorLayer = createLayer({}, {}); const iconAndTooltipContent = layer.getCustomIconAndTooltipContent(); From b5cf12a06fe11a6b67b9444280441c9469840764 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 12:33:02 +0200 Subject: [PATCH 28/68] fix tests --- .../maps/public/classes/fields/agg/agg_field.test.ts | 6 +++--- .../maps/public/classes/fields/agg/count_agg_field.test.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts index b78eb1355ad8e..f7c2f0e640bdb 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts @@ -29,13 +29,13 @@ describe('supportsFieldMeta', () => { expect(termsMetric.supportsFieldMeta()).toBe(true); }); - test('Counting aggregations should not support field meta', () => { + test('Counting aggregations should also support field meta', () => { const sumMetric = new AggField({ ...defaultParams, aggType: AGG_TYPE.SUM }); - expect(sumMetric.supportsFieldMeta()).toBe(false); + expect(sumMetric.supportsFieldMeta()).toBe(true); const uniqueCountMetric = new AggField({ ...defaultParams, aggType: AGG_TYPE.UNIQUE_COUNT, }); - expect(uniqueCountMetric.supportsFieldMeta()).toBe(false); + expect(uniqueCountMetric.supportsFieldMeta()).toBe(true); }); }); diff --git a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts index 664ac32edf6df..2f95d8cdf1ac4 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts @@ -19,8 +19,8 @@ const defaultParams = { }; describe('supportsFieldMeta', () => { - test('Counting aggregations should not support field meta', () => { + test('Count aggs should support field meta', () => { const countMetric = new CountAggField({ ...defaultParams }); - expect(countMetric.supportsFieldMeta()).toBe(false); + expect(countMetric.supportsFieldMeta()).toBe(true); }); }); From 9a64f915c9b2066537654869c8db4806de956521 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 12:36:02 +0200 Subject: [PATCH 29/68] update functional test --- x-pack/test/api_integration/apis/maps/get_tile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index f75d43cf0cee3..1fdb8f20a297a 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -29,7 +29,7 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(2); + expect(layer.length).to.be(3); // 2 docs + the metadata feature const feature = layer.feature(0); expect(feature.type).to.be(1); expect(feature.extent).to.be(4096); From 0609f57faa30031e7670c5150f508fc6b27ed010 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 13:52:59 +0200 Subject: [PATCH 30/68] rename --- api_docs/maps.json | 8 ++++---- x-pack/test/api_integration/apis/maps/get_tile.js | 2 +- x-pack/test/functional/apps/maps/mapbox_styles.js | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/api_docs/maps.json b/api_docs/maps.json index 9c1c7243a41bc..2b375b72c2922 100644 --- a/api_docs/maps.json +++ b/api_docs/maps.json @@ -3026,13 +3026,13 @@ }, { "parentPluginId": "maps", - "id": "def-common.KBN_TOO_MANY_FEATURES_PROPERTY", + "id": "def-common.KBN_METADATA_FEATURE", "type": "string", "tags": [], - "label": "KBN_TOO_MANY_FEATURES_PROPERTY", + "label": "KBN_METADATA_FEATURE", "description": [], "signature": [ - "\"__kbn_too_many_features__\"" + "\"__kbn_metadata_feature__\"" ], "source": { "path": "x-pack/plugins/maps/common/constants.ts", @@ -3506,4 +3506,4 @@ } ] } -} \ No newline at end of file +} diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 1fdb8f20a297a..e61d50ec1bab9 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -65,7 +65,7 @@ export default function ({ getService }) { expect(feature.type).to.be(3); expect(feature.extent).to.be(4096); expect(feature.id).to.be(undefined); - expect(feature.properties).to.eql({ __kbn_too_many_features__: true }); + expect(feature.properties).to.eql({ __kbn_metadata_feature__: true }); expect(feature.loadGeometry()).to.eql([ [ { x: 44, y: 2382 }, diff --git a/x-pack/test/functional/apps/maps/mapbox_styles.js b/x-pack/test/functional/apps/maps/mapbox_styles.js index 31cb366f826c8..408024a293270 100644 --- a/x-pack/test/functional/apps/maps/mapbox_styles.js +++ b/x-pack/test/functional/apps/maps/mapbox_styles.js @@ -40,7 +40,7 @@ export default function ({ getPageObjects, getService }) { maxzoom: 24, filter: [ 'all', - ['!=', ['get', '__kbn_too_many_features__'], true], + ['!=', ['get', '__kbn_metadata_feature__'], true], ['!=', ['get', '__kbn_is_centroid_feature__'], true], ['any', ['==', ['geometry-type'], 'Point'], ['==', ['geometry-type'], 'MultiPoint']], ['==', ['get', '__kbn_isvisibleduetojoin__'], true], @@ -121,7 +121,7 @@ export default function ({ getPageObjects, getService }) { maxzoom: 24, filter: [ 'all', - ['!=', ['get', '__kbn_too_many_features__'], true], + ['!=', ['get', '__kbn_metadata_feature__'], true], ['!=', ['get', '__kbn_is_centroid_feature__'], true], ['any', ['==', ['geometry-type'], 'Polygon'], ['==', ['geometry-type'], 'MultiPolygon']], ['==', ['get', '__kbn_isvisibleduetojoin__'], true], @@ -198,7 +198,7 @@ export default function ({ getPageObjects, getService }) { maxzoom: 24, filter: [ 'all', - ['!=', ['get', '__kbn_too_many_features__'], true], + ['!=', ['get', '__kbn_metadata_feature__'], true], ['!=', ['get', '__kbn_is_centroid_feature__'], true], [ 'any', @@ -224,7 +224,7 @@ export default function ({ getPageObjects, getService }) { source: 'n1t6f', minzoom: 0, maxzoom: 24, - filter: ['==', ['get', '__kbn_too_many_features__'], true], + filter: ['==', ['get', '__kbn_metadata_feature__'], true], layout: { visibility: 'visible' }, paint: { 'fill-pattern': '__kbn_too_many_features_image_id__', 'fill-opacity': 0.75 }, }); From 3ea92fcd05ef2e47f4836760ff19bfb36c6f38e8 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 15:11:59 +0200 Subject: [PATCH 31/68] fix tests --- x-pack/test/api_integration/apis/maps/get_tile.js | 2 +- x-pack/test/functional/apps/maps/mapbox_styles.js | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index e61d50ec1bab9..6b8118912aee0 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -60,7 +60,7 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(1); + expect(layer.length).to.be(2); const feature = layer.feature(0); expect(feature.type).to.be(3); expect(feature.extent).to.be(4096); diff --git a/x-pack/test/functional/apps/maps/mapbox_styles.js b/x-pack/test/functional/apps/maps/mapbox_styles.js index 408024a293270..a0a858c303722 100644 --- a/x-pack/test/functional/apps/maps/mapbox_styles.js +++ b/x-pack/test/functional/apps/maps/mapbox_styles.js @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { KBN_IS_TILE_COMPLETE, KBN_METADATA_FEATURE } from '../../../../plugins/maps/common'; export default function ({ getPageObjects, getService }) { const PageObjects = getPageObjects(['maps']); @@ -224,7 +225,11 @@ export default function ({ getPageObjects, getService }) { source: 'n1t6f', minzoom: 0, maxzoom: 24, - filter: ['==', ['get', '__kbn_metadata_feature__'], true], + filter: [ + 'all', + ['==', ['get', KBN_METADATA_FEATURE], true], + ['==', ['get', KBN_IS_TILE_COMPLETE], false], + ], layout: { visibility: 'visible' }, paint: { 'fill-pattern': '__kbn_too_many_features_image_id__', 'fill-opacity': 0.75 }, }); From 150c8dde1061e9bb615d3121827f269521bb83fe Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 18:26:42 +0200 Subject: [PATCH 32/68] update test --- x-pack/test/api_integration/apis/maps/get_tile.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 6b8118912aee0..e10b6f6e24b07 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -65,7 +65,11 @@ export default function ({ getService }) { expect(feature.type).to.be(3); expect(feature.extent).to.be(4096); expect(feature.id).to.be(undefined); - expect(feature.properties).to.eql({ __kbn_metadata_feature__: true }); + expect(feature.properties).to.eql({ + __kbn_metadata_feature__: true, + __kbn_feature_count__: 0, + __kbn_is_tile_complete__: false, + }); expect(feature.loadGeometry()).to.eql([ [ { x: 44, y: 2382 }, From 80fa1a0074ca088ffe5a8fca39c1d7b3b04a054b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 24 Jun 2021 19:54:14 +0200 Subject: [PATCH 33/68] fix test --- x-pack/test/api_integration/apis/maps/get_grid_tile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index c929a1af7b150..76836d8810220 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -35,7 +35,7 @@ export default function ({ getService }) { const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; expect(layer.length).to.be(1); const clusterFeature = layer.feature(0); - expect(clusterFeature.type).to.be(1); + expect(clusterFeature.type).to.be(2); expect(clusterFeature.extent).to.be(4096); expect(clusterFeature.id).to.be(undefined); expect(clusterFeature.properties).to.eql({ doc_count: 1, avg_of_bytes: 9252 }); From 2ffb088ef694b84ca83aad5b4b2fc6097f5ee90f Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 12:39:23 +0200 Subject: [PATCH 34/68] fix test --- x-pack/test/api_integration/apis/maps/get_grid_tile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index 76836d8810220..0168e483e8cfc 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -33,9 +33,9 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(1); + expect(layer.length).to.be(2); const clusterFeature = layer.feature(0); - expect(clusterFeature.type).to.be(2); + expect(clusterFeature.type).to.be(1); expect(clusterFeature.extent).to.be(4096); expect(clusterFeature.id).to.be(undefined); expect(clusterFeature.properties).to.eql({ doc_count: 1, avg_of_bytes: 9252 }); From 6cc7b824ad82e1b2e732e15b3411fd4d5253cf54 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 12:44:19 +0200 Subject: [PATCH 35/68] fix test --- x-pack/test/api_integration/apis/maps/get_grid_tile.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index 0168e483e8cfc..be6187632c665 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -58,7 +58,7 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(2); + expect(layer.length).to.be(3); const gridFeature = layer.feature(0); expect(gridFeature.type).to.be(3); @@ -75,7 +75,7 @@ export default function ({ getService }) { ], ]); - const clusterFeature = layer.feature(1); + const clusterFeature = layer.feature(2); expect(clusterFeature.type).to.be(1); expect(clusterFeature.extent).to.be(4096); expect(clusterFeature.id).to.be(undefined); From 90f00cffe707f1a15cd1c617d36beb6fee449929 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 13:04:25 +0200 Subject: [PATCH 36/68] feedback --- .../plugins/maps/public/actions/layer_actions.ts | 2 +- .../tiled_vector_layer/tiled_vector_layer.tsx | 15 +++++++++++++++ .../classes/styles/vector/vector_style.tsx | 2 +- .../connected_components/mb_map/mb_map.tsx | 2 +- .../mb_map/tile_status_tracker.test.ts | 4 ++-- .../mb_map/tile_status_tracker.ts | 16 ++++++++-------- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index 1fd71ea57ddc0..360f77fd6e3f3 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -602,7 +602,7 @@ export function updateMetaFromTiles(layerId: string, mbMetaFeatures: Feature[]) return; } - await dispatch({ + dispatch({ type: UPDATE_LAYER_PROP, id: layerId, propName: '__metaFromTiles', 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 f4f5228830cb3..b08206e8e0ea8 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 @@ -283,6 +283,21 @@ export class TiledVectorLayer extends VectorLayer { filter: ['==', ['get', KBN_METADATA_FEATURE], true], }); + const parsedProperties: Feature[] = mbFeatures.map((mbFeature: Feature) => { + const properties: Record = {}; + for (const key in mbFeature.properties) { + if (mbFeature.properties.hasOwnProperty(key)) { + properties[key] = JSON.parse(mbFeature.properties[key]); // mvt properties cannot be nested geojson + } + } + return { + type: 'Feature', + id: mbFeature.id, + geometry: mbFeature.geometry, + properties: parsedProperties, + }; + }); + return mbFeatures as Feature[]; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index b23efd94ebf57..3001ac693b521 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -516,7 +516,7 @@ export class VectorStyle implements IVectorStyle { for (let i = 0; i < features.length; i++) { const properties = features[i].properties; if (properties && properties[name]) { - const metaFromTiles = JSON.parse(properties[name]); + const metaFromTiles = properties[name]; min = Math.min(metaFromTiles.min, min); max = Math.max(metaFromTiles.max, max); } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx index 3e60ef3317bbb..ef558f57432db 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/mb_map.tsx @@ -199,7 +199,7 @@ export class MbMap extends Component { this._tileStatusTracker = new TileStatusTracker({ mbMap, getCurrentLayerList: () => this.props.layerList, - setAreTilesLoaded: (layer: ILayer, areTilesLoaded: boolean) => { + updateTileStatus: (layer: ILayer, areTilesLoaded: boolean) => { this.props.setAreTilesLoaded(layer.getId(), areTilesLoaded); this._queryForMeta(layer); }, diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts index e6363cb051767..c2995802339c7 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.test.ts @@ -84,7 +84,7 @@ describe('TileStatusTracker', () => { const loadedMap: Map = new Map(); new TileStatusTracker({ mbMap: (mockMbMap as unknown) as MbMap, - setAreTilesLoaded: (layer, areTilesLoaded) => { + updateTileStatus: (layer, areTilesLoaded) => { loadedMap.set(layer.getId(), areTilesLoaded); }, getCurrentLayerList: () => { @@ -127,7 +127,7 @@ describe('TileStatusTracker', () => { const mockMbMap = new MockMbMap(); const tileStatusTracker = new TileStatusTracker({ mbMap: (mockMbMap as unknown) as MbMap, - setAreTilesLoaded: () => {}, + updateTileStatus: () => {}, getCurrentLayerList: () => { return []; }, diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts index e4a34231d98c4..b25bbf63a1e44 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tile_status_tracker.ts @@ -24,7 +24,7 @@ interface Tile { export class TileStatusTracker { private _tileCache: Tile[]; private readonly _mbMap: MapboxMap; - private readonly _setAreTilesLoaded: (layer: ILayer, areTilesLoaded: boolean) => void; + private readonly _updateTileStatus: (layer: ILayer, areTilesLoaded: boolean) => void; private readonly _getCurrentLayerList: () => ILayer[]; private readonly _onSourceDataLoading = (e: MapSourceDataEvent) => { if ( @@ -47,7 +47,7 @@ export class TileStatusTracker { mbSourceId: e.sourceId, mbTile: e.tile, }); - this._updateTileStatus(); + this._updateTileStatusForAllLayers(); } } }; @@ -76,15 +76,15 @@ export class TileStatusTracker { constructor({ mbMap, - setAreTilesLoaded, + updateTileStatus, getCurrentLayerList, }: { mbMap: MapboxMap; - setAreTilesLoaded: (layer: ILayer, areTilesLoaded: boolean) => void; + updateTileStatus: (layer: ILayer, areTilesLoaded: boolean) => void; getCurrentLayerList: () => ILayer[]; }) { this._tileCache = []; - this._setAreTilesLoaded = setAreTilesLoaded; + this._updateTileStatus = updateTileStatus; this._getCurrentLayerList = getCurrentLayerList; this._mbMap = mbMap; @@ -93,7 +93,7 @@ export class TileStatusTracker { this._mbMap.on('sourcedata', this._onSourceData); } - _updateTileStatus = _.debounce(() => { + _updateTileStatusForAllLayers = _.debounce(() => { this._tileCache = this._tileCache.filter((tile) => { return typeof tile.mbTile.aborted === 'boolean' ? !tile.mbTile.aborted : true; }); @@ -108,7 +108,7 @@ export class TileStatusTracker { break; } } - this._setAreTilesLoaded(layer, !atLeastOnePendingTile); + this._updateTileStatus(layer, !atLeastOnePendingTile); } }, 100); @@ -119,7 +119,7 @@ export class TileStatusTracker { if (trackedIndex >= 0) { this._tileCache.splice(trackedIndex, 1); - this._updateTileStatus(); + this._updateTileStatusForAllLayers(); } }; From 09d4fe75b966ceb4982aaf8def10b76d2d5e3798 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 13:19:52 +0200 Subject: [PATCH 37/68] fix typo --- .../layers/tiled_vector_layer/tiled_vector_layer.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 b08206e8e0ea8..d2d61735bd231 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 @@ -283,11 +283,11 @@ export class TiledVectorLayer extends VectorLayer { filter: ['==', ['get', KBN_METADATA_FEATURE], true], }); - const parsedProperties: Feature[] = mbFeatures.map((mbFeature: Feature) => { - const properties: Record = {}; + const metaFeatures: Feature[] = mbFeatures.map((mbFeature: Feature) => { + const parsedProperties: Record = {}; for (const key in mbFeature.properties) { if (mbFeature.properties.hasOwnProperty(key)) { - properties[key] = JSON.parse(mbFeature.properties[key]); // mvt properties cannot be nested geojson + parsedProperties[key] = JSON.parse(mbFeature.properties[key]); // mvt properties cannot be nested geojson } } return { @@ -298,7 +298,7 @@ export class TiledVectorLayer extends VectorLayer { }; }); - return mbFeatures as Feature[]; + return metaFeatures as Feature[]; } _requiresPrevSourceCleanup(mbMap: MbMap): boolean { From 99d3eddf76e2e4847bddd2cfa65b47132d96ebdc Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 13:23:59 +0200 Subject: [PATCH 38/68] add comment --- .../classes/layers/tiled_vector_layer/tiled_vector_layer.tsx | 2 ++ 1 file changed, 2 insertions(+) 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 d2d61735bd231..0b8eca9486688 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 @@ -278,6 +278,8 @@ export class TiledVectorLayer extends VectorLayer { return null; } + // querySourceFeatures can return duplicated features when features cross tile boundaries. + // Tile meta will never have duplicated features since by there nature, tile meta is a feature contained within a single tile const mbFeatures = mbMap.querySourceFeatures(this._getMbSourceId(), { sourceLayer: sourceMeta.layerName, filter: ['==', ['get', KBN_METADATA_FEATURE], true], From c7f463dba296ec293d9e618899f5f1f5741765c6 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 13:37:49 +0200 Subject: [PATCH 39/68] add unit test --- .../apis/maps/get_grid_tile.js | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index be6187632c665..0351a8b9b141a 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -34,12 +34,36 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; expect(layer.length).to.be(2); + + // Cluster feature const clusterFeature = layer.feature(0); expect(clusterFeature.type).to.be(1); expect(clusterFeature.extent).to.be(4096); expect(clusterFeature.id).to.be(undefined); expect(clusterFeature.properties).to.eql({ doc_count: 1, avg_of_bytes: 9252 }); expect(clusterFeature.loadGeometry()).to.eql([[{ x: 87, y: 667 }]]); + + // Metadata feature + const metadataFeature = layer.feature(1); + expect(metadataFeature.type).to.be(3); + expect(metadataFeature.extent).to.be(4096); + expect(metadataFeature.properties).to.eql({ + __kbn_metadata_feature__: true, + __kbn_feature_count__: 1, + __kbn_is_tile_complete__: true, + __kbn_vector_shape_type_counts__: '{"POINT":1,"LINE":0,"POLYGON":0}', + doc_count: '{"min":1,"max":1}', + avg_of_bytes: '{"min":9252,"max":9252}', + }); + expect(metadataFeature.loadGeometry()).to.eql([ + [ + { x: 0, y: 0 }, + { x: 4096, y: 0 }, + { x: 4096, y: 4096 }, + { x: 0, y: 4096 }, + { x: 0, y: 0 }, + ], + ]); }); it('should return vector tile containing grid features', async () => { @@ -75,6 +99,28 @@ export default function ({ getService }) { ], ]); + // Metadata feature + const metadataFeature = layer.feature(1); + expect(metadataFeature.type).to.be(3); + expect(metadataFeature.extent).to.be(4096); + expect(metadataFeature.properties).to.eql({ + __kbn_metadata_feature__: true, + __kbn_feature_count__: 1, + __kbn_is_tile_complete__: true, + __kbn_vector_shape_type_counts__: '{"POINT":0,"LINE":0,"POLYGON":1}', + doc_count: '{"min":1,"max":1}', + avg_of_bytes: '{"min":9252,"max":9252}', + }); + expect(metadataFeature.loadGeometry()).to.eql([ + [ + { x: 0, y: 0 }, + { x: 4096, y: 0 }, + { x: 4096, y: 4096 }, + { x: 0, y: 4096 }, + { x: 0, y: 0 }, + ], + ]); + const clusterFeature = layer.feature(2); expect(clusterFeature.type).to.be(1); expect(clusterFeature.extent).to.be(4096); From 5999da53e74f0b149a9f292423b39f9ed7ce6c77 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 14:35:58 +0200 Subject: [PATCH 40/68] add test --- .../api_integration/apis/maps/get_tile.js | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index e10b6f6e24b07..d967c3771146e 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -30,6 +30,8 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; expect(layer.length).to.be(3); // 2 docs + the metadata feature + + // 1st doc const feature = layer.feature(0); expect(feature.type).to.be(1); expect(feature.extent).to.be(4096); @@ -42,6 +44,27 @@ export default function ({ getService }) { ['machine.os.raw']: 'ios', }); expect(feature.loadGeometry()).to.eql([[{ x: 44, y: 2382 }]]); + + // Metadata feature + const metadataFeature = layer.feature(2); + expect(metadataFeature.type).to.be(3); + expect(metadataFeature.extent).to.be(4096); + expect(metadataFeature.id).to.be(undefined); + expect(metadataFeature.properties).to.eql({ + __kbn_feature_count__: 2, + __kbn_is_tile_complete__: true, + __kbn_metadata_feature__: true, + __kbn_vector_shape_type_counts__: '{"POINT":2,"LINE":0,"POLYGON":0}', + }); + expect(metadataFeature.loadGeometry()).to.eql([ + [ + { x: 0, y: 4096 }, + { x: 0, y: 0 }, + { x: 4096, y: 0 }, + { x: 4096, y: 4096 }, + { x: 0, y: 4096 }, + ], + ]); }); it('should return vector tile containing bounds when count exceeds size', async () => { From 2b9d5451ec51c1818eb5083d09f83d15152efbe0 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 14:38:18 +0200 Subject: [PATCH 41/68] fix impl/test --- x-pack/plugins/maps/server/mvt/get_tile.ts | 30 +++++++++---------- .../api_integration/apis/maps/get_tile.js | 15 +++++----- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 1e3c272a17a7f..a0f4c188c30f7 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -319,23 +319,23 @@ export async function getTile({ props[FEATURE_ID_PROPERTY_NAME] = features[i].id; } } - } - const counts = countVectorShapeTypes(features); - const metadataFeature = { - type: 'Feature', - properties: { - [KBN_METADATA_FEATURE]: true, - [KBN_IS_TILE_COMPLETE]: true, - [KBN_VECTOR_SHAPE_TYPE_COUNTS]: counts, - [KBN_FEATURE_COUNT]: features.length, - }, - // todo - constrain to actual features - geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), - }; + const counts = countVectorShapeTypes(features); + const metadataFeature = { + type: 'Feature', + properties: { + [KBN_METADATA_FEATURE]: true, + [KBN_IS_TILE_COMPLETE]: true, + [KBN_VECTOR_SHAPE_TYPE_COUNTS]: counts, + [KBN_FEATURE_COUNT]: features.length, + }, + // todo - constrain to actual features + geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), + }; - // @ts-expect-error - features.push(metadataFeature); + // @ts-expect-error + features.push(metadataFeature); + } const featureCollection: FeatureCollection = { features, diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index d967c3771146e..3770366c35c4c 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -83,17 +83,18 @@ export default function ({ getService }) { const jsonTile = new VectorTile(new Protobuf(resp.body)); const layer = jsonTile.layers[MVT_SOURCE_LAYER_NAME]; - expect(layer.length).to.be(2); - const feature = layer.feature(0); - expect(feature.type).to.be(3); - expect(feature.extent).to.be(4096); - expect(feature.id).to.be(undefined); - expect(feature.properties).to.eql({ + expect(layer.length).to.be(1); + + const metadataFeature = layer.feature(0); + expect(metadataFeature.type).to.be(3); + expect(metadataFeature.extent).to.be(4096); + expect(metadataFeature.id).to.be(undefined); + expect(metadataFeature.properties).to.eql({ __kbn_metadata_feature__: true, __kbn_feature_count__: 0, __kbn_is_tile_complete__: false, }); - expect(feature.loadGeometry()).to.eql([ + expect(metadataFeature.loadGeometry()).to.eql([ [ { x: 44, y: 2382 }, { x: 44, y: 1913 }, From 72d8f1f93c8c116f9123ce7f6c7dd4fd90a23bc4 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 14:48:31 +0200 Subject: [PATCH 42/68] fix trimmed icon --- .../layers/tiled_vector_layer/tiled_vector_layer.tsx | 2 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) 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 0b8eca9486688..e3a1080c95e25 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 @@ -130,7 +130,7 @@ export class TiledVectorLayer extends VectorLayer { defaultMessage: `Layer shows incomplete results`, }) : null, - areResultsTrimmed: !isIncomplete, + areResultsTrimmed: isIncomplete, }; } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index a0f4c188c30f7..d0b9bda7e65f7 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -274,6 +274,11 @@ export async function getTile({ [KBN_METADATA_FEATURE]: true, [KBN_IS_TILE_COMPLETE]: false, [KBN_FEATURE_COUNT]: 0, + [KBN_VECTOR_SHAPE_TYPE_COUNTS]: { + [VECTOR_SHAPE_TYPE.POINT]: 0, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POLYGON]: 0, + }, }, geometry: esBboxToGeoJsonPolygon( // @ts-expect-error @elastic/elasticsearch no way to declare aggregations for search response @@ -329,7 +334,6 @@ export async function getTile({ [KBN_VECTOR_SHAPE_TYPE_COUNTS]: counts, [KBN_FEATURE_COUNT]: features.length, }, - // todo - constrain to actual features geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), }; From e3d4095e617a5bdfd58600a36324178e3c9edf76 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 15:27:46 +0200 Subject: [PATCH 43/68] hide data-mapper ux for counts --- .../plugins/maps/public/classes/fields/agg/count_agg_field.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts index efc761fd595d3..7f5cd577e928b 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.ts @@ -70,7 +70,7 @@ export class CountAggField implements IESAggField { } supportsFieldMeta(): boolean { - return true; + return false; } getBucketCount() { @@ -94,7 +94,7 @@ export class CountAggField implements IESAggField { } supportsAutoDomain(): boolean { - return this._canReadFromGeoJson ? true : this.supportsFieldMeta(); + return true; } canReadFromGeoJson(): boolean { From e695621559a1f6a046389ce4715aa313036f857e Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 16:30:21 +0200 Subject: [PATCH 44/68] fieldMeta fix --- .../maps/public/classes/fields/agg/agg_field.test.ts | 6 +++--- x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts | 6 ++++++ .../maps/public/classes/fields/agg/count_agg_field.test.ts | 4 ++-- .../styles/vector/properties/dynamic_style_property.tsx | 2 +- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts index f7c2f0e640bdb..b78eb1355ad8e 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.test.ts @@ -29,13 +29,13 @@ describe('supportsFieldMeta', () => { expect(termsMetric.supportsFieldMeta()).toBe(true); }); - test('Counting aggregations should also support field meta', () => { + test('Counting aggregations should not support field meta', () => { const sumMetric = new AggField({ ...defaultParams, aggType: AGG_TYPE.SUM }); - expect(sumMetric.supportsFieldMeta()).toBe(true); + expect(sumMetric.supportsFieldMeta()).toBe(false); const uniqueCountMetric = new AggField({ ...defaultParams, aggType: AGG_TYPE.UNIQUE_COUNT, }); - expect(uniqueCountMetric.supportsFieldMeta()).toBe(true); + expect(uniqueCountMetric.supportsFieldMeta()).toBe(false); }); }); diff --git a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts index 5ea6dc176faa3..70d5cea6e4620 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/agg_field.ts @@ -8,6 +8,7 @@ import { IndexPattern } from 'src/plugins/data/public'; import { AGG_TYPE } from '../../../../common/constants'; import { CountAggField } from './count_agg_field'; +import { isMetricCountable } from '../../util/is_metric_countable'; import { CountAggFieldParams } from './agg_field_types'; import { addFieldToDSL, getField } from '../../../../common/elasticsearch_util'; import { IField } from '../field'; @@ -33,6 +34,11 @@ export class AggField extends CountAggField { return !!this._esDocField; } + supportsFieldMeta(): boolean { + // count and sum aggregations are not within field bounds so they do not support field meta. + return !isMetricCountable(this._getAggType()); + } + canValueBeFormatted(): boolean { return this._getAggType() !== AGG_TYPE.UNIQUE_COUNT; } diff --git a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts index 2f95d8cdf1ac4..664ac32edf6df 100644 --- a/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts +++ b/x-pack/plugins/maps/public/classes/fields/agg/count_agg_field.test.ts @@ -19,8 +19,8 @@ const defaultParams = { }; describe('supportsFieldMeta', () => { - test('Count aggs should support field meta', () => { + test('Counting aggregations should not support field meta', () => { const countMetric = new CountAggField({ ...defaultParams }); - expect(countMetric.supportsFieldMeta()).toBe(true); + expect(countMetric.supportsFieldMeta()).toBe(false); }); }); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 8b2fe62d7a1dc..d691c0d1e145f 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -400,7 +400,7 @@ export class DynamicStyleProperty return null; } - const switchDisabled = !!this._field && !this._field.canReadFromGeoJson(); + const switchDisabled = !!this._field && !this._field.supportsFieldMeta(); return this.isCategorical() ? ( From 15730d629b38595877c216715830bf8204b0931a Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 18:20:29 +0200 Subject: [PATCH 45/68] do not allow for toggling get-from-data switch --- .../data_mapping/categorical_data_mapping_popover.tsx | 2 -- .../data_mapping/ordinal_data_mapping_popover.tsx | 2 -- .../__snapshots__/dynamic_color_property.test.tsx.snap | 6 ++---- .../vector/properties/dynamic_color_property.test.tsx | 10 +++++----- .../vector/properties/dynamic_style_property.tsx | 8 -------- 5 files changed, 7 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/components/data_mapping/categorical_data_mapping_popover.tsx b/x-pack/plugins/maps/public/classes/styles/vector/components/data_mapping/categorical_data_mapping_popover.tsx index e03dda06a3ef9..3fb36364bee4c 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/components/data_mapping/categorical_data_mapping_popover.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/components/data_mapping/categorical_data_mapping_popover.tsx @@ -15,7 +15,6 @@ import { FieldMetaOptions } from '../../../../../../common/descriptor_types'; interface Props { fieldMetaOptions: FieldMetaOptions; onChange: (updatedOptions: DynamicOptions) => void; - switchDisabled: boolean; } export function CategoricalDataMappingPopover(props: Props) { @@ -40,7 +39,6 @@ export function CategoricalDataMappingPopover(props: Props{' '} { fieldMetaOptions: FieldMetaOptions; styleName: VECTOR_STYLES; onChange: (updatedOptions: DynamicOptions) => void; - switchDisabled: boolean; dataMappingFunction: DATA_MAPPING_FUNCTION; supportedDataMappingFunctions: DATA_MAPPING_FUNCTION[]; } @@ -169,7 +168,6 @@ export function OrdinalDataMappingPopover(props: Props{' '} `; -exports[`renderDataMappingPopover Should enable toggle when field is backed by geojson-source 1`] = ` +exports[`renderDataMappingPopover Switch toggle should always be enabled 1`] = ` `; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx index b7e0133881ee1..7d5b9cf0007a7 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx @@ -642,7 +642,7 @@ test('Should read out ordinal type correctly', async () => { }); describe('renderDataMappingPopover', () => { - test('Should enable toggle when field is backed by geojson-source', () => { + test('Switch toggle should always be enabled', () => { const colorStyle = makeProperty( { color: 'Blues', @@ -657,9 +657,9 @@ describe('renderDataMappingPopover', () => { expect(legendRow).toMatchSnapshot(); }); - test('Should disable toggle when field is not backed by geojson source', () => { - const nonGeoJsonField = Object.create(mockField); - nonGeoJsonField.canReadFromGeoJson = () => { + test('Should not render when autodomain not supported', () => { + const noAutoDomainField = Object.create(mockField); + noAutoDomainField.supportsAutoDomain = () => { return false; }; const colorStyle = makeProperty( @@ -669,7 +669,7 @@ describe('renderDataMappingPopover', () => { fieldMetaOptions, }, undefined, - nonGeoJsonField + noAutoDomainField ); const legendRow = colorStyle.renderDataMappingPopover(() => {}); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index d691c0d1e145f..2c841f4160260 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -396,24 +396,16 @@ export class DynamicStyleProperty } renderDataMappingPopover(onChange: (updatedOptions: Partial) => void) { - if (!this.supportsFieldMeta()) { - return null; - } - - const switchDisabled = !!this._field && !this._field.supportsFieldMeta(); - return this.isCategorical() ? ( fieldMetaOptions={this.getFieldMetaOptions()} onChange={onChange} - switchDisabled={switchDisabled} /> ) : ( fieldMetaOptions={this.getFieldMetaOptions()} styleName={this.getStyleName()} onChange={onChange} - switchDisabled={switchDisabled} dataMappingFunction={this.getDataMappingFunction()} supportedDataMappingFunctions={this._getSupportedDataMappingFunctions()} /> From 32ab71f2836bd777bdccdfed8aa3a516a9f9961c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Mon, 28 Jun 2021 19:53:55 +0200 Subject: [PATCH 46/68] fix tests --- x-pack/test/api_integration/apis/maps/get_tile.js | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 3770366c35c4c..13c64b48a9f6a 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -93,6 +93,7 @@ export default function ({ getService }) { __kbn_metadata_feature__: true, __kbn_feature_count__: 0, __kbn_is_tile_complete__: false, + __kbn_vector_shape_type_counts__: '{"POINT":0,"LINE":0,"POLYGON":0}', }); expect(metadataFeature.loadGeometry()).to.eql([ [ From 10eb35f7b84c36158c9ed24ec51e03c40a86e511 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 29 Jun 2021 20:03:21 +0200 Subject: [PATCH 47/68] fix edge cases --- .../tiled_vector_layer/tiled_vector_layer.tsx | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) 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 e3a1080c95e25..ebc8fe773772f 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 @@ -92,18 +92,20 @@ export class TiledVectorLayer extends VectorLayer { const shapeTypeCountMeta: VectorShapeTypeCounts = tileMetas.reduce( (accumulator: VectorShapeTypeCounts, tileMeta: Feature) => { - if (!tileMeta || !tileMeta.properties) { + if ( + !tileMeta || + !tileMeta.properties || + !tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] + ) { return accumulator; } - if (typeof tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] !== 'string') { - return accumulator; - } - const counts = JSON.parse(tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS]); - - accumulator[VECTOR_SHAPE_TYPE.POINT] += counts[VECTOR_SHAPE_TYPE.POINT]; - accumulator[VECTOR_SHAPE_TYPE.LINE] += counts[VECTOR_SHAPE_TYPE.LINE]; - accumulator[VECTOR_SHAPE_TYPE.POLYGON] += counts[VECTOR_SHAPE_TYPE.POLYGON]; + accumulator[VECTOR_SHAPE_TYPE.POINT] += + tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.POINT]; + accumulator[VECTOR_SHAPE_TYPE.LINE] += + tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.LINE]; + accumulator[VECTOR_SHAPE_TYPE.POLYGON] += + tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.POLYGON]; return accumulator; }, From bad69218a5e9674940a05e4211c1ceec90cfc584 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 29 Jun 2021 20:15:29 +0200 Subject: [PATCH 48/68] remove obsolete test --- .../dynamic_color_property.test.tsx.snap | 21 +------------------ .../dynamic_color_property.test.tsx | 21 +------------------ 2 files changed, 2 insertions(+), 40 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap index 24263d495123e..e350f29f3d820 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap @@ -1,25 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renderDataMappingPopover Should not render when autodomain not supported 1`] = ` - -`; - -exports[`renderDataMappingPopover Switch toggle should always be enabled 1`] = ` +exports[`renderDataMappingPopover Switch toggle should be enabled 1`] = ` { }); describe('renderDataMappingPopover', () => { - test('Switch toggle should always be enabled', () => { + test('Switch toggle should be enabled', () => { const colorStyle = makeProperty( { color: 'Blues', @@ -656,23 +656,4 @@ describe('renderDataMappingPopover', () => { const legendRow = colorStyle.renderDataMappingPopover(() => {}); expect(legendRow).toMatchSnapshot(); }); - - test('Should not render when autodomain not supported', () => { - const noAutoDomainField = Object.create(mockField); - noAutoDomainField.supportsAutoDomain = () => { - return false; - }; - const colorStyle = makeProperty( - { - color: 'Blues', - type: undefined, - fieldMetaOptions, - }, - undefined, - noAutoDomainField - ); - - const legendRow = colorStyle.renderDataMappingPopover(() => {}); - expect(legendRow).toMatchSnapshot(); - }); }); From 6aa0f51f267b5ea5781c2223a54bb16e2c3c168f Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 30 Jun 2021 15:02:04 +0200 Subject: [PATCH 49/68] extract style-meta code to common --- .../maps/common/pluck_category_field_meta.ts | 42 +++++++++++++++ .../maps/common/pluck_range_field_meta.ts | 30 +++++++++++ .../properties/dynamic_style_property.tsx | 52 +++---------------- .../classes/styles/vector/vector_style.tsx | 8 +-- 4 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 x-pack/plugins/maps/common/pluck_category_field_meta.ts create mode 100644 x-pack/plugins/maps/common/pluck_range_field_meta.ts diff --git a/x-pack/plugins/maps/common/pluck_category_field_meta.ts b/x-pack/plugins/maps/common/pluck_category_field_meta.ts new file mode 100644 index 0000000000000..7741df9daea05 --- /dev/null +++ b/x-pack/plugins/maps/common/pluck_category_field_meta.ts @@ -0,0 +1,42 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Feature } from 'geojson'; +import { CategoryFieldMeta } from './descriptor_types'; + +export function pluckCategoryFieldMeta( + features: Feature[], + name: string, + size: number +): CategoryFieldMeta | null { + const counts = new Map(); + for (let i = 0; i < features.length; i++) { + const feature = features[i]; + const term = feature.properties ? feature.properties[name] : undefined; + // properties object may be sparse, so need to check if the field is effectively present + if (typeof term !== undefined) { + if (counts.has(term)) { + counts.set(term, counts.get(term) + 1); + } else { + counts.set(term, 1); + } + } + } + + const ordered = []; + for (const [key, value] of counts) { + ordered.push({ key, count: value }); + } + + ordered.sort((a, b) => { + return b.count - a.count; + }); + const truncated = ordered.slice(0, size); + return { + categories: truncated, + } as CategoryFieldMeta; +} diff --git a/x-pack/plugins/maps/common/pluck_range_field_meta.ts b/x-pack/plugins/maps/common/pluck_range_field_meta.ts new file mode 100644 index 0000000000000..f9cf823d02466 --- /dev/null +++ b/x-pack/plugins/maps/common/pluck_range_field_meta.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Feature } from 'geojson'; +import { RangeFieldMeta } from './descriptor_types'; + +export function pluckRangeFieldMeta(features: Feature[], name: string): RangeFieldMeta | null { + let min = Infinity; + let max = -Infinity; + for (let i = 0; i < features.length; i++) { + const feature = features[i]; + const newValue = parseFloat(feature.properties ? feature.properties[name] : null); + if (!isNaN(newValue)) { + min = Math.min(min, newValue); + max = Math.max(max, newValue); + } + } + + return min === Infinity || max === -Infinity + ? null + : ({ + min, + max, + delta: max - min, + } as RangeFieldMeta); +} diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 2c841f4160260..223f62052f948 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -38,6 +38,8 @@ import { IVectorLayer } from '../../../layers/vector_layer'; import { InnerJoin } from '../../../joins/inner_join'; import { IVectorStyle } from '../vector_style'; import { getComputedFieldName } from '../style_util'; +import { pluckRangeFieldMeta } from '../../../../../common/pluck_range_field_meta'; +import { pluckCategoryFieldMeta } from '../../../../../common/pluck_category_field_meta'; export interface IDynamicStyleProperty extends IStyleProperty { getFieldMetaOptions(): FieldMetaOptions; @@ -277,64 +279,22 @@ export class DynamicStyleProperty : DATA_MAPPING_FUNCTION.INTERPOLATE; } - pluckOrdinalStyleMetaFromFeatures(features: Feature[]) { + pluckOrdinalStyleMetaFromFeatures(features: Feature[]): RangeFieldMeta | null { if (!this.isOrdinal()) { return null; } const name = this.getFieldName(); - let min = Infinity; - let max = -Infinity; - for (let i = 0; i < features.length; i++) { - const feature = features[i]; - const newValue = parseFloat(feature.properties ? feature.properties[name] : null); - if (!isNaN(newValue)) { - min = Math.min(min, newValue); - max = Math.max(max, newValue); - } - } - - return min === Infinity || max === -Infinity - ? null - : ({ - min, - max, - delta: max - min, - } as RangeFieldMeta); + return pluckRangeFieldMeta(features, name); } - pluckCategoricalStyleMetaFromFeatures(features: Feature[]) { + pluckCategoricalStyleMetaFromFeatures(features: Feature[]): CategoryFieldMeta | null { const size = this.getNumberOfCategories(); if (!this.isCategorical() || size <= 0) { return null; } - const counts = new Map(); - for (let i = 0; i < features.length; i++) { - const feature = features[i]; - const term = feature.properties ? feature.properties[this.getFieldName()] : undefined; - // properties object may be sparse, so need to check if the field is effectively present - if (typeof term !== undefined) { - if (counts.has(term)) { - counts.set(term, counts.get(term) + 1); - } else { - counts.set(term, 1); - } - } - } - - const ordered = []; - for (const [key, value] of counts) { - ordered.push({ key, count: value }); - } - - ordered.sort((a, b) => { - return b.count - a.count; - }); - const truncated = ordered.slice(0, size); - return { - categories: truncated, - } as CategoryFieldMeta; + return pluckCategoryFieldMeta(features, this.getFieldName(), size); } _pluckOrdinalStyleMetaFromFieldMetaData(styleMetaData: StyleMetaData) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 3001ac693b521..c38856c57eee9 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -489,7 +489,7 @@ export class VectorStyle implements IVectorStyle { ); } - async pluckStyleMetaFromTileMeta(features: Feature[]): Promise { + async pluckStyleMetaFromTileMeta(metaFeatures: Feature[]): Promise { const styleMeta = { geometryTypes: { isPointsOnly: false, @@ -500,7 +500,7 @@ export class VectorStyle implements IVectorStyle { } as StyleMetaDescriptor; const dynamicProperties = this.getDynamicPropertiesArray(); - if (dynamicProperties.length === 0 || !features) { + if (dynamicProperties.length === 0 || !metaFeatures) { // no additional meta data to pull from source data request. return styleMeta; } @@ -513,8 +513,8 @@ export class VectorStyle implements IVectorStyle { let min = Infinity; let max = -Infinity; - for (let i = 0; i < features.length; i++) { - const properties = features[i].properties; + for (let i = 0; i < metaFeatures.length; i++) { + const properties = metaFeatures[i].properties; if (properties && properties[name]) { const metaFromTiles = properties[name]; min = Math.min(metaFromTiles.min, min); From b7dc39183949b2681efe539b6c770909454b348c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 30 Jun 2021 17:34:13 +0200 Subject: [PATCH 50/68] reuse in tile-gen --- x-pack/plugins/maps/server/mvt/get_tile.ts | 49 +++++++--------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index d0b9bda7e65f7..e564cfffe0281 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -40,6 +40,8 @@ import { import { flattenHit } from './util'; import { ESBounds, tileToESBbox } from '../../common/geo_tile_utils'; import { getCentroidFeatures } from '../../common/get_centroid_features'; +import { pluckRangeFieldMeta } from '../../common/pluck_range_field_meta'; +import { RangeFieldMeta } from '../../common/descriptor_types'; function isAbortError(error: Error) { return error.message === 'Request aborted' || error.message === 'Aborted'; @@ -106,41 +108,22 @@ export async function getGridTile({ minLon: tileBounds.top_left.lon, }); - const rangeMeta: { [key: string]: { min: number; max: number } } = {}; - for (let i = 0; i < features.length; i++) { - const feature = features[i]; - - if (feature.properties) { - for (const key in feature.properties) { - if (feature.properties.hasOwnProperty(key)) { - if (key !== 'key' && key !== 'gridCentroid') { - const rawValue = feature.properties[key]; - let numberValue: number; - if (key === COUNT_PROP_NAME) { - numberValue = parseFloat(rawValue); - } else if (typeof rawValue === 'number') { - numberValue = rawValue; - } else if (rawValue) { - numberValue = parseFloat(rawValue.value); - } else { - continue; - } - if (!isNaN(numberValue)) { - if (!rangeMeta[key]) { - rangeMeta[key] = { - min: Infinity, - max: -Infinity, - }; - } - - rangeMeta[key].min = Math.min(rangeMeta[key].min, numberValue); - rangeMeta[key].max = Math.max(rangeMeta[key].max, numberValue); - } - } - } + const fieldNames = new Set(); + features.forEach((feature) => { + for (const key in feature.properties) { + if (feature.properties.hasOwnProperty(key) && key !== 'key' && key !== 'gridCentroid') { + fieldNames.add(key); } } - } + }); + + const rangeMeta: { [key: string]: RangeFieldMeta } = {}; + fieldNames.forEach((fieldName: string) => { + const metaForField = pluckRangeFieldMeta(features, fieldName); + if (metaForField) { + rangeMeta[fieldName] = metaForField; + } + }); const metaDataFeature: Feature = { type: 'Feature', From a047002b1c59a778745ca43d6b960be1fb87c81a Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 30 Jun 2021 20:04:20 +0200 Subject: [PATCH 51/68] improve typing --- .../maps/common/pluck_range_field_meta.ts | 8 +++-- .../public/actions/data_request_actions.ts | 2 +- .../maps/public/classes/layers/layer.tsx | 4 +-- .../tiled_vector_layer/tiled_vector_layer.tsx | 2 +- .../layers/vector_layer/vector_layer.tsx | 2 +- .../properties/dynamic_style_property.tsx | 14 +++++---- .../classes/styles/vector/vector_style.tsx | 30 +++++++++++-------- x-pack/plugins/maps/server/mvt/get_tile.ts | 12 +++++++- 8 files changed, 48 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/maps/common/pluck_range_field_meta.ts b/x-pack/plugins/maps/common/pluck_range_field_meta.ts index f9cf823d02466..b0bf03896892f 100644 --- a/x-pack/plugins/maps/common/pluck_range_field_meta.ts +++ b/x-pack/plugins/maps/common/pluck_range_field_meta.ts @@ -8,12 +8,16 @@ import { Feature } from 'geojson'; import { RangeFieldMeta } from './descriptor_types'; -export function pluckRangeFieldMeta(features: Feature[], name: string): RangeFieldMeta | null { +export function pluckRangeFieldMeta( + features: Feature[], + name: string, + parseValue: (rawValue: unknown) => number +): RangeFieldMeta | null { let min = Infinity; let max = -Infinity; for (let i = 0; i < features.length; i++) { const feature = features[i]; - const newValue = parseFloat(feature.properties ? feature.properties[name] : null); + const newValue = feature.properties ? parseValue(feature.properties[name]) : NaN; if (!isNaN(newValue)) { min = Math.min(min, newValue); max = Math.max(max, newValue); 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 21b1280f17278..89e82bdb1cf77 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -94,7 +94,7 @@ export function updateStyleMeta(layerId: string | null) { return; } - const styleMeta = await layer.getStyleMetaDescriptor(); + const styleMeta = await layer.getStyleMetaDescriptorFromLocal(); if (!styleMeta) { return; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 644aebb545777..d7018a9f01afa 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -105,7 +105,7 @@ export interface ILayer { getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; getDescriptor(): LayerDescriptor; getGeoFieldNames(): string[]; - getStyleMetaDescriptor(): Promise; + getStyleMetaDescriptorFromLocal(): Promise; } export type CustomIconAndTooltipContent = { @@ -524,7 +524,7 @@ export class AbstractLayer implements ILayer { return source.isESSource() ? [(source as IESSource).getGeoFieldName()] : []; } - async getStyleMetaDescriptor(): Promise { + async getStyleMetaDescriptorFromLocal(): Promise { return null; } } 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 ebc8fe773772f..f4cd334f003bc 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 @@ -370,7 +370,7 @@ export class TiledVectorLayer extends VectorLayer { return null; } - async getStyleMetaDescriptor(): Promise { + async getStyleMetaDescriptorFromLocal(): Promise { const style = this.getCurrentStyle(); if (!style) { return null; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index 59cf4438c0242..a159c46a637c0 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -1174,7 +1174,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { await layerSource.deleteFeature(featureId); } - async getStyleMetaDescriptor(): Promise { + async getStyleMetaDescriptorFromLocal(): Promise { const sourceDataRequest = this.getSourceDataRequest(); const style = this.getCurrentStyle(); if (!style || !sourceDataRequest) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 223f62052f948..84b6e6622d2c6 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -173,8 +173,8 @@ export class DynamicStyleProperty } const data = styleMetaDataRequest.getData() as StyleMetaData; - const rangeFieldMeta = this._pluckCategoricalStyleMetaFromFieldMetaData(data); - return rangeFieldMeta ? rangeFieldMeta : categoryFieldMetaFromLocalFeatures; + const categoricalFieldMeta = this._pluckCategoricalStyleMetaFromFieldMetaData(data); + return categoricalFieldMeta ? categoricalFieldMeta : categoryFieldMetaFromLocalFeatures; } getField() { @@ -285,7 +285,9 @@ export class DynamicStyleProperty } const name = this.getFieldName(); - return pluckRangeFieldMeta(features, name); + return pluckRangeFieldMeta(features, name, (rawValue: unknown) => { + return parseFloat(rawValue as string); + }); } pluckCategoricalStyleMetaFromFeatures(features: Feature[]): CategoryFieldMeta | null { @@ -297,7 +299,7 @@ export class DynamicStyleProperty return pluckCategoryFieldMeta(features, this.getFieldName(), size); } - _pluckOrdinalStyleMetaFromFieldMetaData(styleMetaData: StyleMetaData) { + _pluckOrdinalStyleMetaFromFieldMetaData(styleMetaData: StyleMetaData): RangeFieldMeta | null { if (!this.isOrdinal() || !this._field) { return null; } @@ -321,7 +323,9 @@ export class DynamicStyleProperty }; } - _pluckCategoricalStyleMetaFromFieldMetaData(styleMetaData: StyleMetaData) { + _pluckCategoricalStyleMetaFromFieldMetaData( + styleMetaData: StyleMetaData + ): CategoryFieldMeta | null { if (!this.isCategorical() || !this._field) { return null; } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index c38856c57eee9..eda72335c6f05 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -595,21 +595,25 @@ export class VectorStyle implements IVectorStyle { return styleMeta; } - dynamicProperties.forEach((dynamicProperty) => { - const categoricalStyleMeta = dynamicProperty.pluckCategoricalStyleMetaFromFeatures(features); - const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromFeatures(features); - const name = dynamicProperty.getFieldName(); - if (!styleMeta.fieldMeta[name]) { - styleMeta.fieldMeta[name] = {}; - } - if (categoricalStyleMeta) { - styleMeta.fieldMeta[name].categories = categoricalStyleMeta; - } + dynamicProperties.forEach( + (dynamicProperty: IDynamicStyleProperty) => { + const categoricalStyleMeta = dynamicProperty.pluckCategoricalStyleMetaFromFeatures( + features + ); + const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromFeatures(features); + const name = dynamicProperty.getFieldName(); + if (!styleMeta.fieldMeta[name]) { + styleMeta.fieldMeta[name] = {}; + } + if (categoricalStyleMeta) { + styleMeta.fieldMeta[name].categories = categoricalStyleMeta; + } - if (ordinalStyleMeta) { - styleMeta.fieldMeta[name].range = ordinalStyleMeta; + if (ordinalStyleMeta) { + styleMeta.fieldMeta[name].range = ordinalStyleMeta; + } } - }); + ); return styleMeta; } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index e564cfffe0281..24455a715bcc8 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -119,7 +119,17 @@ export async function getGridTile({ const rangeMeta: { [key: string]: RangeFieldMeta } = {}; fieldNames.forEach((fieldName: string) => { - const metaForField = pluckRangeFieldMeta(features, fieldName); + const metaForField = pluckRangeFieldMeta(features, fieldName, (rawValue: unknown) => { + if (fieldName === COUNT_PROP_NAME) { + return parseFloat(rawValue as string); + } else if (typeof rawValue === 'number') { + return rawValue; + } else if (rawValue) { + return parseFloat((rawValue as { value: string }).value); + } else { + return NaN; + } + }); if (metaForField) { rangeMeta[fieldName] = metaForField; } From fb8b836dc5e30d95731f0ad5f48b98a05e406dff Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 30 Jun 2021 20:22:33 +0200 Subject: [PATCH 52/68] rewrite for clarity --- .../properties/dynamic_style_property.tsx | 60 ++++++++++++------- 1 file changed, 39 insertions(+), 21 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 84b6e6622d2c6..d54be1a98ac01 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -105,29 +105,37 @@ export class DynamicStyleProperty return join ? join.getSourceMetaDataRequestId() : null; } - getRangeFieldMeta() { + _getRangeFieldMetaFromLocalFeatures() { const style = this._layer.getStyle() as IVectorStyle; const styleMeta = style.getStyleMetaFromLocal(); const fieldName = this.getFieldName(); - const rangeFieldMetaFromLocalFeatures = styleMeta.getRangeFieldMetaDescriptor(fieldName); - - if (!this.isFieldMetaEnabled()) { - return rangeFieldMetaFromLocalFeatures; - } + return styleMeta.getRangeFieldMetaDescriptor(fieldName); + } - const dataRequestId = this._getStyleMetaDataRequestId(fieldName); + _getRangeFieldMetaFromStyleMetaRequest(): RangeFieldMeta | null { + const dataRequestId = this._getStyleMetaDataRequestId(this.getFieldName()); if (!dataRequestId) { - return rangeFieldMetaFromLocalFeatures; + return null; } const styleMetaDataRequest = this._layer.getDataRequest(dataRequestId); if (!styleMetaDataRequest || !styleMetaDataRequest.hasData()) { - return rangeFieldMetaFromLocalFeatures; + return null; } const data = styleMetaDataRequest.getData() as StyleMetaData; const rangeFieldMeta = this._pluckOrdinalStyleMetaFromFieldMetaData(data); - return rangeFieldMeta ? rangeFieldMeta : rangeFieldMetaFromLocalFeatures; + return rangeFieldMeta ? rangeFieldMeta : null; + } + + getRangeFieldMeta(): RangeFieldMeta | null { + const rangeFieldMetaFromLocalFeatures = this._getRangeFieldMetaFromLocalFeatures(); + if (!this.isFieldMetaEnabled()) { + return rangeFieldMetaFromLocalFeatures; + } + + const rangeFieldMetaFromServer = this._getRangeFieldMetaFromStyleMetaRequest(); + return rangeFieldMetaFromServer ? rangeFieldMetaFromServer : rangeFieldMetaFromLocalFeatures; } getPercentilesFieldMeta() { @@ -152,29 +160,39 @@ export class DynamicStyleProperty return percentilesValuesToFieldMeta(percentiles); } - getCategoryFieldMeta() { + _getCategoryFieldMetaFromLocalFeatures() { const style = this._layer.getStyle() as IVectorStyle; const styleMeta = style.getStyleMetaFromLocal(); const fieldName = this.getFieldName(); - const categoryFieldMetaFromLocalFeatures = styleMeta.getCategoryFieldMetaDescriptor(fieldName); - - if (!this.isFieldMetaEnabled()) { - return categoryFieldMetaFromLocalFeatures; - } + return styleMeta.getCategoryFieldMetaDescriptor(fieldName); + } - const dataRequestId = this._getStyleMetaDataRequestId(fieldName); + _getCategoryFieldMetaFromStyleMetaRequest() { + const dataRequestId = this._getStyleMetaDataRequestId(this.getFieldName()); if (!dataRequestId) { - return categoryFieldMetaFromLocalFeatures; + return null; } const styleMetaDataRequest = this._layer.getDataRequest(dataRequestId); if (!styleMetaDataRequest || !styleMetaDataRequest.hasData()) { - return categoryFieldMetaFromLocalFeatures; + return null; } const data = styleMetaDataRequest.getData() as StyleMetaData; - const categoricalFieldMeta = this._pluckCategoricalStyleMetaFromFieldMetaData(data); - return categoricalFieldMeta ? categoricalFieldMeta : categoryFieldMetaFromLocalFeatures; + return this._pluckCategoricalStyleMetaFromFieldMetaData(data); + } + + getCategoryFieldMeta(): CategoryFieldMeta | null { + const categoryFieldMetaFromLocalFeatures = this._getCategoryFieldMetaFromLocalFeatures(); + + if (!this.isFieldMetaEnabled()) { + return categoryFieldMetaFromLocalFeatures; + } + + const categoricalFieldMetaFromServer = this._getCategoryFieldMetaFromStyleMetaRequest(); + return categoricalFieldMetaFromServer + ? categoricalFieldMetaFromServer + : categoryFieldMetaFromLocalFeatures; } getField() { From 90377ccfe7f5a3bea67beba4b699ed3bc3e07656 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 11:42:01 +0200 Subject: [PATCH 53/68] fix delete --- .../styles/vector/properties/dynamic_style_property.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index d54be1a98ac01..836bd24296771 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -378,6 +378,9 @@ export class DynamicStyleProperty } renderDataMappingPopover(onChange: (updatedOptions: Partial) => void) { + if (!this.supportsFieldMeta()) { + return null; + } return this.isCategorical() ? ( fieldMetaOptions={this.getFieldMetaOptions()} From 5872b08693587c5c728f212b2263d673031303a7 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 13:03:05 +0200 Subject: [PATCH 54/68] type field-stylemeta --- .../style_property_descriptor_types.ts | 14 ++++++----- .../classes/styles/vector/vector_style.tsx | 8 +++---- x-pack/plugins/maps/server/mvt/get_tile.ts | 24 ++++++++++++++----- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.ts index fb44c9443c797..9c14dd088665a 100644 --- a/x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/style_property_descriptor_types.ts @@ -225,14 +225,16 @@ export type GeometryTypes = { isPolygonsOnly: boolean; }; +export type FieldMeta = { + [key: string]: { + range?: RangeFieldMeta; + categories?: CategoryFieldMeta; + }; +}; + export type StyleMetaDescriptor = { geometryTypes?: GeometryTypes; - fieldMeta: { - [key: string]: { - range?: RangeFieldMeta; - categories?: CategoryFieldMeta; - }; - }; + fieldMeta: FieldMeta; }; export type VectorStyleDescriptor = StyleDescriptor & { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index eda72335c6f05..b71796da68a30 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -515,10 +515,10 @@ export class VectorStyle implements IVectorStyle { let max = -Infinity; for (let i = 0; i < metaFeatures.length; i++) { const properties = metaFeatures[i].properties; - if (properties && properties[name]) { - const metaFromTiles = properties[name]; - min = Math.min(metaFromTiles.min, min); - max = Math.max(metaFromTiles.max, max); + if (properties && properties[name] && properties[name].range) { + const metaFromTile = properties[name]; + min = Math.min(metaFromTile.range.min, min); + max = Math.max(metaFromTile.range.max, max); } } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 24455a715bcc8..bae2a92ddbf31 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -41,7 +41,8 @@ import { flattenHit } from './util'; import { ESBounds, tileToESBbox } from '../../common/geo_tile_utils'; import { getCentroidFeatures } from '../../common/get_centroid_features'; import { pluckRangeFieldMeta } from '../../common/pluck_range_field_meta'; -import { RangeFieldMeta } from '../../common/descriptor_types'; +import { FieldMeta } from '../../common/descriptor_types'; +import { pluckCategoryFieldMeta } from '../../common/pluck_category_field_meta'; function isAbortError(error: Error) { return error.message === 'Request aborted' || error.message === 'Aborted'; @@ -117,9 +118,9 @@ export async function getGridTile({ } }); - const rangeMeta: { [key: string]: RangeFieldMeta } = {}; + const fieldMeta: FieldMeta = {}; fieldNames.forEach((fieldName: string) => { - const metaForField = pluckRangeFieldMeta(features, fieldName, (rawValue: unknown) => { + const rangeMeta = pluckRangeFieldMeta(features, fieldName, (rawValue: unknown) => { if (fieldName === COUNT_PROP_NAME) { return parseFloat(rawValue as string); } else if (typeof rawValue === 'number') { @@ -130,8 +131,19 @@ export async function getGridTile({ return NaN; } }); - if (metaForField) { - rangeMeta[fieldName] = metaForField; + + const categoryMeta = pluckCategoryFieldMeta(features, fieldName, 20); + + if (!fieldMeta[fieldName]) { + fieldMeta[fieldName] = {}; + } + + if (rangeMeta) { + fieldMeta[fieldName].range = rangeMeta; + } + + if (categoryMeta) { + fieldMeta[fieldName].categories = categoryMeta; } }); @@ -153,7 +165,7 @@ export async function getGridTile({ [VECTOR_SHAPE_TYPE.LINE]: 0, [VECTOR_SHAPE_TYPE.POLYGON]: 0, }, - ...rangeMeta, + ...fieldMeta, }, geometry: bounds, }; From 1d3a2761ef292892b70aabcde356765b32ae2689 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 14:34:59 +0200 Subject: [PATCH 55/68] add tilemetafeature type for clarity --- .../layer_descriptor_types.ts | 13 +++++- .../maps/public/actions/layer_actions.ts | 4 +- .../tiled_vector_layer/tiled_vector_layer.tsx | 11 ++--- .../connected_components/mb_map/index.ts | 4 +- .../connected_components/mb_map/mb_map.tsx | 12 ++++-- x-pack/plugins/maps/server/mvt/get_tile.ts | 42 +++++++++---------- 6 files changed, 50 insertions(+), 36 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 3ed4f733a94c2..3f886218c4078 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -10,12 +10,14 @@ import { Query } from 'src/plugins/data/public'; import { Feature } from 'geojson'; import { + FieldMeta, HeatmapStyleDescriptor, StyleDescriptor, VectorStyleDescriptor, } from './style_property_descriptor_types'; import { DataRequestDescriptor } from './data_request_descriptor_types'; import { AbstractSourceDescriptor, TermJoinSourceDescriptor } from './source_descriptor_types'; +import { VectorShapeTypeCounts } from '../get_geometry_counts'; export type Attribution = { label: string; @@ -27,6 +29,15 @@ export type JoinDescriptor = { right: TermJoinSourceDescriptor; }; +export type TileMetaFeature = Feature & { + properties: { + __kbn_metadata_feature__: true; + __kbn_is_tile_complete__: boolean; + __kbn_feature_count__: number; + __kbn_vector_shape_type_counts__: VectorShapeTypeCounts; + } & FieldMeta; +}; + export type LayerDescriptor = { __dataRequests?: DataRequestDescriptor[]; __isInErrorState?: boolean; @@ -34,7 +45,7 @@ export type LayerDescriptor = { __errorMessage?: string; __trackedLayerDescriptor?: LayerDescriptor; __areTilesLoaded?: boolean; - __metaFromTiles?: Feature[]; + __metaFromTiles?: TileMetaFeature[]; alpha?: number; attribution?: Attribution; id: string; diff --git a/x-pack/plugins/maps/public/actions/layer_actions.ts b/x-pack/plugins/maps/public/actions/layer_actions.ts index ac5a9083e31cc..eef325ca67cc5 100644 --- a/x-pack/plugins/maps/public/actions/layer_actions.ts +++ b/x-pack/plugins/maps/public/actions/layer_actions.ts @@ -8,7 +8,6 @@ import { AnyAction, Dispatch } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { Query } from 'src/plugins/data/public'; -import { Feature } from 'geojson'; import { MapStoreState } from '../reducers/store'; import { createLayerInstance, @@ -48,6 +47,7 @@ import { JoinDescriptor, LayerDescriptor, StyleDescriptor, + TileMetaFeature, } from '../../common/descriptor_types'; import { ILayer } from '../classes/layers/layer'; import { IVectorLayer } from '../classes/layers/vector_layer'; @@ -593,7 +593,7 @@ export function setAreTilesLoaded(layerId: string, areTilesLoaded: boolean) { }; } -export function updateMetaFromTiles(layerId: string, mbMetaFeatures: Feature[]) { +export function updateMetaFromTiles(layerId: string, mbMetaFeatures: TileMetaFeature[]) { return async ( dispatch: ThunkDispatch, getState: () => MapStoreState 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 f4cd334f003bc..bea221a7900f2 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 @@ -36,6 +36,7 @@ import { StyleMetaDescriptor, VectorLayerDescriptor, VectorSourceRequestMeta, + TileMetaFeature, } from '../../../../common/descriptor_types'; import { MVTSingleLayerVectorSourceConfig } from '../../sources/mvt_single_layer_vector_source/types'; import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; @@ -67,7 +68,7 @@ export class TiledVectorLayer extends VectorLayer { this._source = source as ITiledSingleLayerVectorSource; } - getMetaFromTiles(): Feature[] { + getMetaFromTiles(): TileMetaFeature[] { return this._descriptor.__metaFromTiles || []; } @@ -264,7 +265,7 @@ export class TiledVectorLayer extends VectorLayer { this._setMbCentroidProperties(mbMap, sourceMeta.layerName); } - queryForTileMeta(mbMap: MbMap): Feature[] | null { + queryTileMetaFeatures(mbMap: MbMap): TileMetaFeature[] | null { // @ts-ignore const mbSource = mbMap.getSource(this._getMbSourceId()); if (!mbSource) { @@ -287,7 +288,7 @@ export class TiledVectorLayer extends VectorLayer { filter: ['==', ['get', KBN_METADATA_FEATURE], true], }); - const metaFeatures: Feature[] = mbFeatures.map((mbFeature: Feature) => { + const metaFeatures: TileMetaFeature[] = mbFeatures.map((mbFeature: Feature) => { const parsedProperties: Record = {}; for (const key in mbFeature.properties) { if (mbFeature.properties.hasOwnProperty(key)) { @@ -299,10 +300,10 @@ export class TiledVectorLayer extends VectorLayer { id: mbFeature.id, geometry: mbFeature.geometry, properties: parsedProperties, - }; + } as TileMetaFeature; }); - return metaFeatures as Feature[]; + return metaFeatures as TileMetaFeature[]; } _requiresPrevSourceCleanup(mbMap: MbMap): boolean { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts index 29e9bea225efb..3084d3b9c9f3f 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/index.ts +++ b/x-pack/plugins/maps/public/connected_components/mb_map/index.ts @@ -8,7 +8,6 @@ import { AnyAction } from 'redux'; import { ThunkDispatch } from 'redux-thunk'; import { connect } from 'react-redux'; -import { Feature } from 'geojson'; import { MbMap } from './mb_map'; import { clearGoto, @@ -35,6 +34,7 @@ import { getDrawMode, getIsFullScreen } from '../../selectors/ui_selectors'; import { getInspectorAdapters } from '../../reducers/non_serializable_instances'; import { MapStoreState } from '../../reducers/store'; import { DRAW_MODE } from '../../../common'; +import { TileMetaFeature } from '../../../common/descriptor_types'; function mapStateToProps(state: MapStoreState) { return { @@ -81,7 +81,7 @@ function mapDispatchToProps(dispatch: ThunkDispatch void; timeslice?: Timeslice; - updateMetaFromTiles: (layerId: string, features: Feature[]) => void; + updateMetaFromTiles: (layerId: string, features: TileMetaFeature[]) => void; featureModeActive: boolean; filterModeActive: boolean; } @@ -124,7 +128,7 @@ export class MbMap extends Component { // This keeps track of the latest update calls, per layerId _queryForMeta = (layer: ILayer) => { if (this.state.mbMap && layer.isVisible() && layer.getType() === LAYER_TYPE.TILED_VECTOR) { - const mbFeatures = (layer as TiledVectorLayer).queryForTileMeta(this.state.mbMap); + const mbFeatures = (layer as TiledVectorLayer).queryTileMetaFeatures(this.state.mbMap); if (mbFeatures !== null) { this.props.updateMetaFromTiles(layer.getId(), mbFeatures); } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index bae2a92ddbf31..70d85f4220471 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -41,7 +41,7 @@ import { flattenHit } from './util'; import { ESBounds, tileToESBbox } from '../../common/geo_tile_utils'; import { getCentroidFeatures } from '../../common/get_centroid_features'; import { pluckRangeFieldMeta } from '../../common/pluck_range_field_meta'; -import { FieldMeta } from '../../common/descriptor_types'; +import { FieldMeta, TileMetaFeature } from '../../common/descriptor_types'; import { pluckCategoryFieldMeta } from '../../common/pluck_category_field_meta'; function isAbortError(error: Error) { @@ -147,7 +147,7 @@ export async function getGridTile({ } }); - const metaDataFeature: Feature = { + const metaDataFeature: TileMetaFeature = { type: 'Feature', properties: { [KBN_METADATA_FEATURE]: true, @@ -272,26 +272,25 @@ export async function getTile({ ) .toPromise(); - features = [ - { - type: 'Feature', - properties: { - [KBN_METADATA_FEATURE]: true, - [KBN_IS_TILE_COMPLETE]: false, - [KBN_FEATURE_COUNT]: 0, - [KBN_VECTOR_SHAPE_TYPE_COUNTS]: { - [VECTOR_SHAPE_TYPE.POINT]: 0, - [VECTOR_SHAPE_TYPE.LINE]: 0, - [VECTOR_SHAPE_TYPE.POLYGON]: 0, - }, + const metaDataFeature: TileMetaFeature = { + type: 'Feature', + properties: { + [KBN_METADATA_FEATURE]: true, + [KBN_IS_TILE_COMPLETE]: false, + [KBN_FEATURE_COUNT]: 0, + [KBN_VECTOR_SHAPE_TYPE_COUNTS]: { + [VECTOR_SHAPE_TYPE.POINT]: 0, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POLYGON]: 0, }, - geometry: esBboxToGeoJsonPolygon( - // @ts-expect-error @elastic/elasticsearch no way to declare aggregations for search response - bboxResponse.rawResponse.aggregations.data_bounds.bounds, - tileToESBbox(x, y, z) - ), }, - ]; + geometry: esBboxToGeoJsonPolygon( + // @ts-expect-error @elastic/elasticsearch no way to declare aggregations for search response + bboxResponse.rawResponse.aggregations.data_bounds.bounds, + tileToESBbox(x, y, z) + ), + }; + features = [metaDataFeature]; } else { const documentsResponse = await context .search!.search( @@ -331,7 +330,7 @@ export async function getTile({ } const counts = countVectorShapeTypes(features); - const metadataFeature = { + const metadataFeature: TileMetaFeature = { type: 'Feature', properties: { [KBN_METADATA_FEATURE]: true, @@ -342,7 +341,6 @@ export async function getTile({ geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), }; - // @ts-expect-error features.push(metadataFeature); } From 33fde427aa5497fc360728bf6226e0da21b098ed Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 14:46:34 +0200 Subject: [PATCH 56/68] tighten types --- .../descriptor_types/layer_descriptor_types.ts | 3 ++- .../public/classes/styles/vector/vector_style.tsx | 13 ++++++------- x-pack/plugins/maps/server/mvt/get_tile.ts | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index 3f886218c4078..a0727fbbe8c05 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -35,7 +35,8 @@ export type TileMetaFeature = Feature & { __kbn_is_tile_complete__: boolean; __kbn_feature_count__: number; __kbn_vector_shape_type_counts__: VectorShapeTypeCounts; - } & FieldMeta; + fieldMeta?: FieldMeta; + }; }; export type LayerDescriptor = { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index b71796da68a30..8c29523e2ee41 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -9,7 +9,6 @@ import _ from 'lodash'; import React, { ReactElement } from 'react'; import { FeatureIdentifier, Map as MbMap } from '@kbn/mapbox-gl'; import { FeatureCollection } from 'geojson'; -import { Feature } from 'geojson'; import { StyleProperties, VectorStyleEditor } from './components/vector_style_editor'; import { getDefaultStaticProperties, LINE_STYLES, POLYGON_STYLES } from './vector_style_defaults'; import { @@ -64,6 +63,7 @@ import { StyleMetaDescriptor, StylePropertyField, StylePropertyOptions, + TileMetaFeature, VectorStyleDescriptor, VectorStylePropertiesDescriptor, } from '../../../../common/descriptor_types'; @@ -489,7 +489,7 @@ export class VectorStyle implements IVectorStyle { ); } - async pluckStyleMetaFromTileMeta(metaFeatures: Feature[]): Promise { + async pluckStyleMetaFromTileMeta(metaFeatures: TileMetaFeature[]): Promise { const styleMeta = { geometryTypes: { isPointsOnly: false, @@ -514,11 +514,10 @@ export class VectorStyle implements IVectorStyle { let min = Infinity; let max = -Infinity; for (let i = 0; i < metaFeatures.length; i++) { - const properties = metaFeatures[i].properties; - if (properties && properties[name] && properties[name].range) { - const metaFromTile = properties[name]; - min = Math.min(metaFromTile.range.min, min); - max = Math.max(metaFromTile.range.max, max); + const fieldMeta = metaFeatures[i].properties.fieldMeta; + if (fieldMeta && fieldMeta[name] && fieldMeta[name].range) { + min = Math.min(fieldMeta[name].range?.min as number, min); + max = Math.max(fieldMeta[name].range?.max as number, max); } } diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 70d85f4220471..57a101827df90 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -165,7 +165,7 @@ export async function getGridTile({ [VECTOR_SHAPE_TYPE.LINE]: 0, [VECTOR_SHAPE_TYPE.POLYGON]: 0, }, - ...fieldMeta, + fieldMeta, }, geometry: bounds, }; From cf77f83940dfbb2156dfbce82ee25aaedb2b344f Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 14:55:13 +0200 Subject: [PATCH 57/68] align implementations --- .../properties/dynamic_style_property.tsx | 40 +++++++++++++++++++ .../classes/styles/vector/vector_style.tsx | 23 ++++------- 2 files changed, 47 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 836bd24296771..ea9b14d4b5b18 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -32,6 +32,7 @@ import { PercentilesFieldMeta, RangeFieldMeta, StyleMetaData, + TileMetaFeature, } from '../../../../../common/descriptor_types'; import { IField } from '../../../fields/field'; import { IVectorLayer } from '../../../layers/vector_layer'; @@ -58,6 +59,10 @@ export interface IDynamicStyleProperty extends IStyleProperty { getFieldMetaRequest(): Promise; pluckOrdinalStyleMetaFromFeatures(features: Feature[]): RangeFieldMeta | null; pluckCategoricalStyleMetaFromFeatures(features: Feature[]): CategoryFieldMeta | null; + pluckOrdinalStyleMetaFromTileMetaFeatures(features: TileMetaFeature[]): RangeFieldMeta | null; + pluckCategoricalStyleMetaFromTileMetaFeatures( + features: TileMetaFeature[] + ): CategoryFieldMeta | null; getValueSuggestions(query: string): Promise; enrichGeoJsonAndMbFeatureState( featureCollection: FeatureCollection, @@ -297,6 +302,41 @@ export class DynamicStyleProperty : DATA_MAPPING_FUNCTION.INTERPOLATE; } + pluckOrdinalStyleMetaFromTileMetaFeatures( + metaFeatures: TileMetaFeature[] + ): RangeFieldMeta | null { + if (!this.isOrdinal()) { + return null; + } + + const name = this.getFieldName(); + let min = Infinity; + let max = -Infinity; + for (let i = 0; i < metaFeatures.length; i++) { + const fieldMeta = metaFeatures[i].properties.fieldMeta; + if (fieldMeta && fieldMeta[name] && fieldMeta[name].range) { + min = Math.min(fieldMeta[name].range?.min as number, min); + max = Math.max(fieldMeta[name].range?.max as number, max); + } + } + return { + min, + max, + delta: max - min, + }; + } + + pluckCategoricalStyleMetaFromTileMetaFeatures( + features: TileMetaFeature[] + ): CategoryFieldMeta | null { + const size = this.getNumberOfCategories(); + if (!this.isCategorical() || size <= 0) { + return null; + } + + throw new Error('not implemented'); + } + pluckOrdinalStyleMetaFromFeatures(features: Feature[]): RangeFieldMeta | null { if (!this.isOrdinal()) { return null; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 8c29523e2ee41..8eafe51cddf8c 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -507,27 +507,18 @@ export class VectorStyle implements IVectorStyle { dynamicProperties.forEach((dynamicProperty) => { const name = dynamicProperty.getFieldName(); + + const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromTileMetaFeatures( + metaFeatures + ); + if (!styleMeta.fieldMeta[name]) { styleMeta.fieldMeta[name] = {}; } - let min = Infinity; - let max = -Infinity; - for (let i = 0; i < metaFeatures.length; i++) { - const fieldMeta = metaFeatures[i].properties.fieldMeta; - if (fieldMeta && fieldMeta[name] && fieldMeta[name].range) { - min = Math.min(fieldMeta[name].range?.min as number, min); - max = Math.max(fieldMeta[name].range?.max as number, max); - } + if (ordinalStyleMeta) { + styleMeta.fieldMeta[name].range = ordinalStyleMeta; } - - styleMeta.fieldMeta[name] = { - range: { - min, - max, - delta: max - min, - }, - }; }); return styleMeta; From ba79ed5756a9c8d22867666a64afe095bdcbdb9e Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 15:25:48 +0200 Subject: [PATCH 58/68] get categories from tilemeta --- .../maps/common/pluck_category_field_meta.ts | 4 +++ .../properties/dynamic_style_property.tsx | 33 +++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/maps/common/pluck_category_field_meta.ts b/x-pack/plugins/maps/common/pluck_category_field_meta.ts index 7741df9daea05..c71316f864a84 100644 --- a/x-pack/plugins/maps/common/pluck_category_field_meta.ts +++ b/x-pack/plugins/maps/common/pluck_category_field_meta.ts @@ -27,6 +27,10 @@ export function pluckCategoryFieldMeta( } } + return trimCategories(counts, size); +} + +export function trimCategories(counts: Map, size: number): CategoryFieldMeta { const ordered = []; for (const [key, value] of counts) { ordered.push({ key, count: value }); diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index ea9b14d4b5b18..fa1e62ca88faa 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -9,6 +9,7 @@ import _ from 'lodash'; import React from 'react'; import { Feature, FeatureCollection } from 'geojson'; import type { FeatureIdentifier, Map as MbMap } from '@kbn/mapbox-gl'; +import { Map } from '@kbn/mapbox-gl'; import { AbstractStyleProperty, IStyleProperty } from './style_property'; import { DEFAULT_SIGMA } from '../vector_style_defaults'; import { @@ -27,6 +28,7 @@ import { OrdinalDataMappingPopover, } from '../components/data_mapping'; import { + Category, CategoryFieldMeta, FieldMetaOptions, PercentilesFieldMeta, @@ -40,7 +42,10 @@ import { InnerJoin } from '../../../joins/inner_join'; import { IVectorStyle } from '../vector_style'; import { getComputedFieldName } from '../style_util'; import { pluckRangeFieldMeta } from '../../../../../common/pluck_range_field_meta'; -import { pluckCategoryFieldMeta } from '../../../../../common/pluck_category_field_meta'; +import { + pluckCategoryFieldMeta, + trimCategories, +} from '../../../../../common/pluck_category_field_meta'; export interface IDynamicStyleProperty extends IStyleProperty { getFieldMetaOptions(): FieldMetaOptions; @@ -327,14 +332,36 @@ export class DynamicStyleProperty } pluckCategoricalStyleMetaFromTileMetaFeatures( - features: TileMetaFeature[] + metaFeatures: TileMetaFeature[] ): CategoryFieldMeta | null { const size = this.getNumberOfCategories(); if (!this.isCategorical() || size <= 0) { return null; } - throw new Error('not implemented'); + const name = this.getFieldName(); + + const counts = new Map(); + for (let i = 0; i < metaFeatures.length; i++) { + const fieldMeta = metaFeatures[i].properties.fieldMeta; + if (fieldMeta && fieldMeta[name] && fieldMeta[name].categories) { + const categoryFieldMeta: CategoryFieldMeta = fieldMeta[name] + .categories as CategoryFieldMeta; + for (let c = 0; c < categoryFieldMeta.categories.length; c++) { + const category: Category = categoryFieldMeta.categories[c]; + // properties object may be sparse, so need to check if the field is effectively present + if (typeof category.key !== undefined) { + if (counts.has(category.key)) { + counts.set(category.key, counts.get(category.key) + category.count); + } else { + counts.set(category.key, category.count); + } + } + } + } + } + + return trimCategories(counts, size); } pluckOrdinalStyleMetaFromFeatures(features: Feature[]): RangeFieldMeta | null { From 4ad1ae7c7701adb7d3867fbed1473b913ff7ad43 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 15:34:14 +0200 Subject: [PATCH 59/68] add category-rollups --- .../styles/vector/properties/dynamic_style_property.tsx | 5 ++--- .../maps/public/classes/styles/vector/vector_style.tsx | 9 +++++++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index fa1e62ca88faa..1bee8573d7282 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -9,7 +9,6 @@ import _ from 'lodash'; import React from 'react'; import { Feature, FeatureCollection } from 'geojson'; import type { FeatureIdentifier, Map as MbMap } from '@kbn/mapbox-gl'; -import { Map } from '@kbn/mapbox-gl'; import { AbstractStyleProperty, IStyleProperty } from './style_property'; import { DEFAULT_SIGMA } from '../vector_style_defaults'; import { @@ -341,7 +340,7 @@ export class DynamicStyleProperty const name = this.getFieldName(); - const counts = new Map(); + const counts = new Map(); for (let i = 0; i < metaFeatures.length; i++) { const fieldMeta = metaFeatures[i].properties.fieldMeta; if (fieldMeta && fieldMeta[name] && fieldMeta[name].categories) { @@ -352,7 +351,7 @@ export class DynamicStyleProperty // properties object may be sparse, so need to check if the field is effectively present if (typeof category.key !== undefined) { if (counts.has(category.key)) { - counts.set(category.key, counts.get(category.key) + category.count); + counts.set(category.key, (counts.get(category.key) as number) + category.count); } else { counts.set(category.key, category.count); } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index 8eafe51cddf8c..a9edb19a305f3 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -506,15 +506,20 @@ export class VectorStyle implements IVectorStyle { } dynamicProperties.forEach((dynamicProperty) => { - const name = dynamicProperty.getFieldName(); - const ordinalStyleMeta = dynamicProperty.pluckOrdinalStyleMetaFromTileMetaFeatures( metaFeatures ); + const categoricalStyleMeta = dynamicProperty.pluckCategoricalStyleMetaFromTileMetaFeatures( + metaFeatures + ); + const name = dynamicProperty.getFieldName(); if (!styleMeta.fieldMeta[name]) { styleMeta.fieldMeta[name] = {}; } + if (categoricalStyleMeta) { + styleMeta.fieldMeta[name].categories = categoricalStyleMeta; + } if (ordinalStyleMeta) { styleMeta.fieldMeta[name].range = ordinalStyleMeta; From 382867185219273701e3da4e686cdd61f7746ab8 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 17:58:10 +0200 Subject: [PATCH 60/68] move shape-counts --- .../public/actions/data_request_actions.ts | 2 +- .../maps/public/classes/layers/layer.tsx | 4 +- .../tiled_vector_layer/tiled_vector_layer.tsx | 45 ++------------ .../layers/vector_layer/vector_layer.tsx | 2 +- .../properties/dynamic_style_property.tsx | 4 +- .../properties/test_helpers/test_util.ts | 6 +- .../classes/styles/vector/style_meta.ts | 2 +- .../classes/styles/vector/vector_style.tsx | 61 ++++++++++++++++--- 8 files changed, 65 insertions(+), 61 deletions(-) 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 89e82bdb1cf77..47350474eef04 100644 --- a/x-pack/plugins/maps/public/actions/data_request_actions.ts +++ b/x-pack/plugins/maps/public/actions/data_request_actions.ts @@ -94,7 +94,7 @@ export function updateStyleMeta(layerId: string | null) { return; } - const styleMeta = await layer.getStyleMetaDescriptorFromLocal(); + const styleMeta = await layer.getStyleMetaDescriptorFromLocalFeatures(); if (!styleMeta) { return; } diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index d7018a9f01afa..386548e922764 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -105,7 +105,7 @@ export interface ILayer { getCustomIconAndTooltipContent(): CustomIconAndTooltipContent; getDescriptor(): LayerDescriptor; getGeoFieldNames(): string[]; - getStyleMetaDescriptorFromLocal(): Promise; + getStyleMetaDescriptorFromLocalFeatures(): Promise; } export type CustomIconAndTooltipContent = { @@ -524,7 +524,7 @@ export class AbstractLayer implements ILayer { return source.isESSource() ? [(source as IESSource).getGeoFieldName()] : []; } - async getStyleMetaDescriptorFromLocal(): Promise { + async getStyleMetaDescriptorFromLocalFeatures(): Promise { return null; } } 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 bea221a7900f2..5916d90890981 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 @@ -19,10 +19,8 @@ import { KBN_FEATURE_COUNT, KBN_IS_TILE_COMPLETE, KBN_METADATA_FEATURE, - KBN_VECTOR_SHAPE_TYPE_COUNTS, LAYER_TYPE, SOURCE_DATA_REQUEST_ID, - VECTOR_SHAPE_TYPE, } from '../../../../common/constants'; import { VectorLayer, @@ -40,8 +38,8 @@ import { } from '../../../../common/descriptor_types'; import { MVTSingleLayerVectorSourceConfig } from '../../sources/mvt_single_layer_vector_source/types'; import { canSkipSourceUpdate } from '../../util/can_skip_fetch'; -import { VectorShapeTypeCounts } from '../../../../common/get_geometry_counts'; import { isRefreshOnlyQuery } from '../../util/is_refresh_only_query'; +import { CustomIconAndTooltipContent } from '../layer'; export class TiledVectorLayer extends VectorLayer { static type = LAYER_TYPE.TILED_VECTOR; @@ -72,7 +70,7 @@ export class TiledVectorLayer extends VectorLayer { return this._descriptor.__metaFromTiles || []; } - getCustomIconAndTooltipContent() { + getCustomIconAndTooltipContent(): CustomIconAndTooltipContent { const tileMetas = this.getMetaFromTiles(); if (!tileMetas.length) { return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; @@ -91,43 +89,8 @@ export class TiledVectorLayer extends VectorLayer { return !tileMeta?.properties?.[KBN_IS_TILE_COMPLETE]; }); - const shapeTypeCountMeta: VectorShapeTypeCounts = tileMetas.reduce( - (accumulator: VectorShapeTypeCounts, tileMeta: Feature) => { - if ( - !tileMeta || - !tileMeta.properties || - !tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] - ) { - return accumulator; - } - - accumulator[VECTOR_SHAPE_TYPE.POINT] += - tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.POINT]; - accumulator[VECTOR_SHAPE_TYPE.LINE] += - tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.LINE]; - accumulator[VECTOR_SHAPE_TYPE.POLYGON] += - tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.POLYGON]; - - return accumulator; - }, - { - [VECTOR_SHAPE_TYPE.POLYGON]: 0, - [VECTOR_SHAPE_TYPE.LINE]: 0, - [VECTOR_SHAPE_TYPE.POINT]: 0, - } - ); - - const isLinesOnly = - shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] > 0 && - shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] === 0 && - shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; - const isPointsOnly = - shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] === 0 && - shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] > 0 && - shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; - return { - icon: this.getCurrentStyle().getIconFromGeometryTypes(isLinesOnly, isPointsOnly), + icon: this.getCurrentStyle().getIcon(), tooltipContent: isIncomplete ? i18n.translate('xpack.maps.tiles.resultsTrimmedMsg', { defaultMessage: `Layer shows incomplete results`, @@ -371,7 +334,7 @@ export class TiledVectorLayer extends VectorLayer { return null; } - async getStyleMetaDescriptorFromLocal(): Promise { + async getStyleMetaDescriptorFromLocalFeatures(): Promise { const style = this.getCurrentStyle(); if (!style) { return null; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index a159c46a637c0..959064b3daab2 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -1174,7 +1174,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { await layerSource.deleteFeature(featureId); } - async getStyleMetaDescriptorFromLocal(): Promise { + async getStyleMetaDescriptorFromLocalFeatures(): Promise { const sourceDataRequest = this.getSourceDataRequest(); const style = this.getCurrentStyle(); if (!style || !sourceDataRequest) { diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx index 1bee8573d7282..7f0e6027e7af6 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_style_property.tsx @@ -116,7 +116,7 @@ export class DynamicStyleProperty _getRangeFieldMetaFromLocalFeatures() { const style = this._layer.getStyle() as IVectorStyle; - const styleMeta = style.getStyleMetaFromLocal(); + const styleMeta = style.getStyleMeta(); const fieldName = this.getFieldName(); return styleMeta.getRangeFieldMetaDescriptor(fieldName); } @@ -171,7 +171,7 @@ export class DynamicStyleProperty _getCategoryFieldMetaFromLocalFeatures() { const style = this._layer.getStyle() as IVectorStyle; - const styleMeta = style.getStyleMetaFromLocal(); + const styleMeta = style.getStyleMeta(); const fieldName = this.getFieldName(); return styleMeta.getCategoryFieldMetaDescriptor(fieldName); } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts b/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts index 4b7d90ec0da1b..ff2811f2b3df0 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/test_helpers/test_util.ts @@ -7,7 +7,7 @@ // eslint-disable-next-line max-classes-per-file import { FIELD_ORIGIN, LAYER_STYLE_TYPE } from '../../../../../../common/constants'; -import { StyleMetaFromLocal } from '../../style_meta'; +import { StyleMeta } from '../../style_meta'; import { CategoryFieldMeta, GeometryTypes, @@ -76,7 +76,7 @@ export class MockStyle implements IStyle { return LAYER_STYLE_TYPE.VECTOR; } - getStyleMetaFromLocal(): StyleMetaFromLocal { + getStyleMeta(): StyleMeta { const geomTypes: GeometryTypes = { isPointsOnly: false, isLinesOnly: false, @@ -110,7 +110,7 @@ export class MockStyle implements IStyle { }, }; - return new StyleMetaFromLocal(styleMetaDescriptor); + return new StyleMeta(styleMetaDescriptor); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts b/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts index 88a1891df2b28..14fab5ca93748 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts +++ b/x-pack/plugins/maps/public/classes/styles/vector/style_meta.ts @@ -11,7 +11,7 @@ import { CategoryFieldMeta, } from '../../../../common/descriptor_types'; -export class StyleMetaFromLocal { +export class StyleMeta { private readonly _descriptor: StyleMetaDescriptor; constructor(styleMetaDescriptor: StyleMetaDescriptor | null | undefined) { this._descriptor = styleMetaDescriptor ? styleMetaDescriptor : { fieldMeta: {} }; diff --git a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx index a9edb19a305f3..695ae95b1b438 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/vector_style.tsx @@ -16,13 +16,14 @@ import { FIELD_ORIGIN, GEO_JSON_TYPE, KBN_IS_CENTROID_FEATURE, + KBN_VECTOR_SHAPE_TYPE_COUNTS, LAYER_STYLE_TYPE, SOURCE_FORMATTERS_DATA_REQUEST_ID, STYLE_TYPE, VECTOR_SHAPE_TYPE, VECTOR_STYLES, } from '../../../../common/constants'; -import { StyleMetaFromLocal } from './style_meta'; +import { StyleMeta } from './style_meta'; import { VectorIcon } from './components/legend/vector_icon'; import { VectorStyleLegend } from './components/legend/vector_style_legend'; import { isOnlySingleFeatureType } from './style_util'; @@ -75,6 +76,7 @@ import { IVectorLayer } from '../../layers/vector_layer'; import { IVectorSource } from '../../sources/vector_source'; import { createStyleFieldsHelper, StyleFieldsHelper } from './style_fields_helper'; import { IESAggField } from '../../fields/agg'; +import { VectorShapeTypeCounts } from '../../../../common/get_geometry_counts'; const POINTS = [GEO_JSON_TYPE.POINT, GEO_JSON_TYPE.MULTI_POINT]; const LINES = [GEO_JSON_TYPE.LINE_STRING, GEO_JSON_TYPE.MULTI_LINE_STRING]; @@ -84,7 +86,7 @@ export interface IVectorStyle extends IStyle { getAllStyleProperties(): Array>; getDynamicPropertiesArray(): Array>; getSourceFieldNames(): string[]; - getStyleMetaFromLocal(): StyleMetaFromLocal; + getStyleMeta(): StyleMeta; getDescriptorWithUpdatedStyleProps( nextFields: IField[], previousFields: IField[], @@ -146,7 +148,7 @@ export class VectorStyle implements IVectorStyle { private readonly _descriptor: VectorStyleDescriptor; private readonly _layer: IVectorLayer; private readonly _source: IVectorSource; - private readonly _styleMeta: StyleMetaFromLocal; + private readonly _styleMeta: StyleMeta; private readonly _symbolizeAsStyleProperty: SymbolizeAsProperty; private readonly _lineColorStyleProperty: StaticColorProperty | DynamicColorProperty; @@ -191,7 +193,7 @@ export class VectorStyle implements IVectorStyle { } : VectorStyle.createDescriptor(); - this._styleMeta = new StyleMetaFromLocal(this._descriptor.__styleMeta); + this._styleMeta = new StyleMeta(this._descriptor.__styleMeta); this._symbolizeAsStyleProperty = new SymbolizeAsProperty( this._descriptor.properties[VECTOR_STYLES.SYMBOLIZE_AS].options, @@ -490,14 +492,53 @@ export class VectorStyle implements IVectorStyle { } async pluckStyleMetaFromTileMeta(metaFeatures: TileMetaFeature[]): Promise { - const styleMeta = { + const shapeTypeCountMeta: VectorShapeTypeCounts = metaFeatures.reduce( + (accumulator: VectorShapeTypeCounts, tileMeta: TileMetaFeature) => { + if ( + !tileMeta || + !tileMeta.properties || + !tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS] + ) { + return accumulator; + } + + accumulator[VECTOR_SHAPE_TYPE.POINT] += + tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.POINT]; + accumulator[VECTOR_SHAPE_TYPE.LINE] += + tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.LINE]; + accumulator[VECTOR_SHAPE_TYPE.POLYGON] += + tileMeta.properties[KBN_VECTOR_SHAPE_TYPE_COUNTS][VECTOR_SHAPE_TYPE.POLYGON]; + + return accumulator; + }, + { + [VECTOR_SHAPE_TYPE.POLYGON]: 0, + [VECTOR_SHAPE_TYPE.LINE]: 0, + [VECTOR_SHAPE_TYPE.POINT]: 0, + } + ); + + const isLinesOnly = + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] > 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] === 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; + const isPointsOnly = + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] === 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] > 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] === 0; + const isPolygonsOnly = + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.LINE] === 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POINT] === 0 && + shapeTypeCountMeta[VECTOR_SHAPE_TYPE.POLYGON] > 0; + + const styleMeta: StyleMetaDescriptor = { geometryTypes: { - isPointsOnly: false, - isLinesOnly: false, - isPolygonsOnly: false, + isPointsOnly, + isLinesOnly, + isPolygonsOnly, }, fieldMeta: {}, - } as StyleMetaDescriptor; + }; const dynamicProperties = this.getDynamicPropertiesArray(); if (dynamicProperties.length === 0 || !metaFeatures) { @@ -657,7 +698,7 @@ export class VectorStyle implements IVectorStyle { }); } - getStyleMetaFromLocal() { + getStyleMeta() { return this._styleMeta; } From f80aa2ad11eed45417c849b0f801aca15b1f4986 Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 19:29:16 +0200 Subject: [PATCH 61/68] type fix --- x-pack/plugins/maps/public/classes/layers/layer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/layers/layer.tsx b/x-pack/plugins/maps/public/classes/layers/layer.tsx index 386548e922764..5244882d41e03 100644 --- a/x-pack/plugins/maps/public/classes/layers/layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/layer.tsx @@ -10,7 +10,7 @@ import type { Map as MbMap } from '@kbn/mapbox-gl'; import { Query } from 'src/plugins/data/public'; import _ from 'lodash'; -import React, { ReactElement, ReactNode } from 'react'; +import React, { ReactElement } from 'react'; import { EuiIcon } from '@elastic/eui'; import uuid from 'uuid/v4'; import { FeatureCollection } from 'geojson'; @@ -109,7 +109,7 @@ export interface ILayer { } export type CustomIconAndTooltipContent = { - icon: ReactNode; + icon: ReactElement; tooltipContent?: string | null; areResultsTrimmed?: boolean; }; From 35a5b60ebb1d2567d8d4444ec7a928a306cd415c Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Thu, 1 Jul 2021 19:39:03 +0200 Subject: [PATCH 62/68] add metadata to features --- x-pack/plugins/maps/server/mvt/get_tile.ts | 32 +++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 57a101827df90..4eb49eeeb41f1 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -307,7 +307,6 @@ export async function getTile({ ) .toPromise(); - // Todo: pass in epochMillies-fields const featureCollection = hitsToGeoJson( // @ts-expect-error hitsToGeoJson should be refactored to accept estypes.SearchHit documentsResponse.rawResponse.hits.hits, @@ -330,6 +329,36 @@ export async function getTile({ } const counts = countVectorShapeTypes(features); + + const fieldNames = new Set(); + features.forEach((feature) => { + for (const key in feature.properties) { + if (feature.properties.hasOwnProperty(key) && key !== 'key' && key !== 'gridCentroid') { + fieldNames.add(key); + } + } + }); + + const fieldMeta: FieldMeta = {}; + fieldNames.forEach((fieldName: string) => { + const rangeMeta = pluckRangeFieldMeta(features, fieldName, (rawValue: unknown) => { + return typeof rawValue === 'number' ? rawValue : NaN; + }); + const categoryMeta = pluckCategoryFieldMeta(features, fieldName, 20); + + if (!fieldMeta[fieldName]) { + fieldMeta[fieldName] = {}; + } + + if (rangeMeta) { + fieldMeta[fieldName].range = rangeMeta; + } + + if (categoryMeta) { + fieldMeta[fieldName].categories = categoryMeta; + } + }); + const metadataFeature: TileMetaFeature = { type: 'Feature', properties: { @@ -337,6 +366,7 @@ export async function getTile({ [KBN_IS_TILE_COMPLETE]: true, [KBN_VECTOR_SHAPE_TYPE_COUNTS]: counts, [KBN_FEATURE_COUNT]: features.length, + fieldMeta, }, geometry: esBboxToGeoJsonPolygon(tileToESBbox(x, y, z), tileToESBbox(x, y, z)), }; From 415959a45d024ada37c1b7a5f4081233de9b929a Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 6 Jul 2021 12:03:56 +0200 Subject: [PATCH 63/68] fix test --- x-pack/test/api_integration/apis/maps/get_grid_tile.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index 0351a8b9b141a..fdb8b2187bbbb 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -52,8 +52,8 @@ export default function ({ getService }) { __kbn_feature_count__: 1, __kbn_is_tile_complete__: true, __kbn_vector_shape_type_counts__: '{"POINT":1,"LINE":0,"POLYGON":0}', - doc_count: '{"min":1,"max":1}', - avg_of_bytes: '{"min":9252,"max":9252}', + fieldMeta: + '{"doc_count":{"range":{"min":1,"max":1,"delta":0},"categories":{"categories":[{"key":1,"count":1}]}},"avg_of_bytes":{"range":{"min":9252,"max":9252,"delta":0},"categories":{"categories":[{"key":9252,"count":1}]}}}', }); expect(metadataFeature.loadGeometry()).to.eql([ [ @@ -108,8 +108,8 @@ export default function ({ getService }) { __kbn_feature_count__: 1, __kbn_is_tile_complete__: true, __kbn_vector_shape_type_counts__: '{"POINT":0,"LINE":0,"POLYGON":1}', - doc_count: '{"min":1,"max":1}', - avg_of_bytes: '{"min":9252,"max":9252}', + fieldMeta: + '{"doc_count":{"range":{"min":1,"max":1,"delta":0},"categories":{"categories":[{"key":1,"count":1}]}},"avg_of_bytes":{"range":{"min":9252,"max":9252,"delta":0},"categories":{"categories":[{"key":9252,"count":1}]}}}', }); expect(metadataFeature.loadGeometry()).to.eql([ [ From bbd14037efc1fb8005b17794d95186256796a3bb Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 6 Jul 2021 12:06:43 +0200 Subject: [PATCH 64/68] fix test --- x-pack/test/api_integration/apis/maps/get_tile.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 13c64b48a9f6a..2b50a4f65a190 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -55,6 +55,8 @@ export default function ({ getService }) { __kbn_is_tile_complete__: true, __kbn_metadata_feature__: true, __kbn_vector_shape_type_counts__: '{"POINT":2,"LINE":0,"POLYGON":0}', + fieldMeta: + '{"machine.os.raw":{"categories":{"categories":[{"key":"ios","count":1},{"count":1}]}},"bytes":{"range":{"min":9252,"max":9583,"delta":331},"categories":{"categories":[{"key":9252,"count":1},{"key":9583,"count":1}]}},"_index":{"categories":{"categories":[{"key":"logstash-2015.09.20","count":2}]}},"_id":{"categories":{"categories":[{"key":"AU_x3_BsGFA8no6Qjjug","count":1},{"key":"AU_x3_g3GFA8no6QjkGu","count":1}]}},"__kbn__feature_id__":{"categories":{"categories":[{"key":"logstash-2015.09.20:AU_x3_BsGFA8no6Qjjug:0","count":1},{"key":"logstash-2015.09.20:AU_x3_g3GFA8no6QjkGu:0","count":1}]}}}', }); expect(metadataFeature.loadGeometry()).to.eql([ [ From ff94926e1d5a4f656ae8735e2415d4c95effbb6b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 7 Jul 2021 13:20:45 +0200 Subject: [PATCH 65/68] feedback --- .../tiled_vector_layer/tiled_vector_layer.tsx | 22 +++++++++++++------ .../dynamic_color_property.test.tsx | 2 +- x-pack/plugins/maps/server/mvt/get_tile.ts | 15 +++++++++++-- .../api_integration/apis/maps/get_tile.js | 2 +- 4 files changed, 30 insertions(+), 11 deletions(-) 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 5916d90890981..880a47d0981cb 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,22 +66,22 @@ export class TiledVectorLayer extends VectorLayer { this._source = source as ITiledSingleLayerVectorSource; } - getMetaFromTiles(): TileMetaFeature[] { + _getMetaFromTiles(): TileMetaFeature[] { return this._descriptor.__metaFromTiles || []; } getCustomIconAndTooltipContent(): CustomIconAndTooltipContent { - const tileMetas = this.getMetaFromTiles(); + const tileMetas = this._getMetaFromTiles(); if (!tileMetas.length) { return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } - const totalFeatures: number = tileMetas.reduce((acc: number, tileMeta: Feature) => { + const totalFeaturesCount: number = tileMetas.reduce((acc: number, tileMeta: Feature) => { const count = tileMeta && tileMeta.properties ? tileMeta.properties[KBN_FEATURE_COUNT] : 0; return count + acc; }, 0); - if (totalFeatures === 0) { + if (totalFeaturesCount === 0) { return NO_RESULTS_ICON_AND_TOOLTIPCONTENT; } @@ -93,9 +93,17 @@ export class TiledVectorLayer extends VectorLayer { icon: this.getCurrentStyle().getIcon(), tooltipContent: isIncomplete ? i18n.translate('xpack.maps.tiles.resultsTrimmedMsg', { - defaultMessage: `Layer shows incomplete results`, + defaultMessage: `Results limited to {count} documents.`, + values: { + count: totalFeaturesCount, + }, }) - : null, + : i18n.translate('xpack.maps.tiles.resultsCompleteMsg', { + defaultMessage: `Found {count} documents.`, + values: { + count: totalFeaturesCount, + }, + }), areResultsTrimmed: isIncomplete, }; } @@ -340,7 +348,7 @@ export class TiledVectorLayer extends VectorLayer { return null; } - const metaFromTiles = this.getMetaFromTiles(); + const metaFromTiles = this._getMetaFromTiles(); return await style.pluckStyleMetaFromTileMeta(metaFromTiles); } } diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx index f5266efbd983e..dfe358586cb94 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/dynamic_color_property.test.tsx @@ -642,7 +642,7 @@ test('Should read out ordinal type correctly', async () => { }); describe('renderDataMappingPopover', () => { - test('Switch toggle should be enabled', () => { + test('Should render OrdinalDataMappingPopover', () => { const colorStyle = makeProperty( { color: 'Blues', diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index 4eb49eeeb41f1..db9b4bab248a9 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -44,6 +44,9 @@ import { pluckRangeFieldMeta } from '../../common/pluck_range_field_meta'; import { FieldMeta, TileMetaFeature } from '../../common/descriptor_types'; import { pluckCategoryFieldMeta } from '../../common/pluck_category_field_meta'; +// heuristic. largest color-palette has 30 colors. 1 color is used for 'other'. +const TERM_COUNT = 30 - 1; + function isAbortError(error: Error) { return error.message === 'Request aborted' || error.message === 'Aborted'; } @@ -132,7 +135,7 @@ export async function getGridTile({ } }); - const categoryMeta = pluckCategoryFieldMeta(features, fieldName, 20); + const categoryMeta = pluckCategoryFieldMeta(features, fieldName, TERM_COUNT); if (!fieldMeta[fieldName]) { fieldMeta[fieldName] = {}; @@ -341,10 +344,18 @@ export async function getTile({ const fieldMeta: FieldMeta = {}; fieldNames.forEach((fieldName: string) => { + if ( + fieldName === '_index' || + fieldName === '_id' || + fieldName === FEATURE_ID_PROPERTY_NAME + ) { + return; + } + const rangeMeta = pluckRangeFieldMeta(features, fieldName, (rawValue: unknown) => { return typeof rawValue === 'number' ? rawValue : NaN; }); - const categoryMeta = pluckCategoryFieldMeta(features, fieldName, 20); + const categoryMeta = pluckCategoryFieldMeta(features, fieldName, TERM_COUNT); if (!fieldMeta[fieldName]) { fieldMeta[fieldName] = {}; diff --git a/x-pack/test/api_integration/apis/maps/get_tile.js b/x-pack/test/api_integration/apis/maps/get_tile.js index 2b50a4f65a190..03a16175931a5 100644 --- a/x-pack/test/api_integration/apis/maps/get_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_tile.js @@ -56,7 +56,7 @@ export default function ({ getService }) { __kbn_metadata_feature__: true, __kbn_vector_shape_type_counts__: '{"POINT":2,"LINE":0,"POLYGON":0}', fieldMeta: - '{"machine.os.raw":{"categories":{"categories":[{"key":"ios","count":1},{"count":1}]}},"bytes":{"range":{"min":9252,"max":9583,"delta":331},"categories":{"categories":[{"key":9252,"count":1},{"key":9583,"count":1}]}},"_index":{"categories":{"categories":[{"key":"logstash-2015.09.20","count":2}]}},"_id":{"categories":{"categories":[{"key":"AU_x3_BsGFA8no6Qjjug","count":1},{"key":"AU_x3_g3GFA8no6QjkGu","count":1}]}},"__kbn__feature_id__":{"categories":{"categories":[{"key":"logstash-2015.09.20:AU_x3_BsGFA8no6Qjjug:0","count":1},{"key":"logstash-2015.09.20:AU_x3_g3GFA8no6QjkGu:0","count":1}]}}}', + '{"machine.os.raw":{"categories":{"categories":[{"key":"ios","count":1},{"count":1}]}},"bytes":{"range":{"min":9252,"max":9583,"delta":331},"categories":{"categories":[{"key":9252,"count":1},{"key":9583,"count":1}]}}}', }); expect(metadataFeature.loadGeometry()).to.eql([ [ From 83a728b804be49ba7865c8ad9b356958bdb0020e Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 7 Jul 2021 13:26:35 +0200 Subject: [PATCH 66/68] type cleanup --- .../descriptor_types/layer_descriptor_types.ts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts index a0727fbbe8c05..740da8493c53c 100644 --- a/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts +++ b/x-pack/plugins/maps/common/descriptor_types/layer_descriptor_types.ts @@ -18,6 +18,12 @@ import { import { DataRequestDescriptor } from './data_request_descriptor_types'; import { AbstractSourceDescriptor, TermJoinSourceDescriptor } from './source_descriptor_types'; import { VectorShapeTypeCounts } from '../get_geometry_counts'; +import { + KBN_FEATURE_COUNT, + KBN_IS_TILE_COMPLETE, + KBN_METADATA_FEATURE, + KBN_VECTOR_SHAPE_TYPE_COUNTS, +} from '../constants'; export type Attribution = { label: string; @@ -31,10 +37,10 @@ export type JoinDescriptor = { export type TileMetaFeature = Feature & { properties: { - __kbn_metadata_feature__: true; - __kbn_is_tile_complete__: boolean; - __kbn_feature_count__: number; - __kbn_vector_shape_type_counts__: VectorShapeTypeCounts; + [KBN_METADATA_FEATURE]: true; + [KBN_IS_TILE_COMPLETE]: boolean; + [KBN_FEATURE_COUNT]: number; + [KBN_VECTOR_SHAPE_TYPE_COUNTS]: VectorShapeTypeCounts; fieldMeta?: FieldMeta; }; }; From 778775eddaa34f0b2267b017e93a0990bf84606b Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Wed, 7 Jul 2021 15:30:44 +0200 Subject: [PATCH 67/68] update snapshot --- .../__snapshots__/dynamic_color_property.test.tsx.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap index e350f29f3d820..3f1cddf944374 100644 --- a/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap +++ b/x-pack/plugins/maps/public/classes/styles/vector/properties/__snapshots__/dynamic_color_property.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`renderDataMappingPopover Switch toggle should be enabled 1`] = ` +exports[`renderDataMappingPopover Should render OrdinalDataMappingPopover 1`] = ` Date: Wed, 7 Jul 2021 18:38:08 +0200 Subject: [PATCH 68/68] feedback --- x-pack/plugins/maps/server/mvt/get_tile.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/maps/server/mvt/get_tile.ts b/x-pack/plugins/maps/server/mvt/get_tile.ts index db9b4bab248a9..41a2c550198f0 100644 --- a/x-pack/plugins/maps/server/mvt/get_tile.ts +++ b/x-pack/plugins/maps/server/mvt/get_tile.ts @@ -336,7 +336,12 @@ export async function getTile({ const fieldNames = new Set(); features.forEach((feature) => { for (const key in feature.properties) { - if (feature.properties.hasOwnProperty(key) && key !== 'key' && key !== 'gridCentroid') { + if ( + feature.properties.hasOwnProperty(key) && + key !== '_index' && + key !== '_id' && + key !== FEATURE_ID_PROPERTY_NAME + ) { fieldNames.add(key); } } @@ -344,14 +349,6 @@ export async function getTile({ const fieldMeta: FieldMeta = {}; fieldNames.forEach((fieldName: string) => { - if ( - fieldName === '_index' || - fieldName === '_id' || - fieldName === FEATURE_ID_PROPERTY_NAME - ) { - return; - } - const rangeMeta = pluckRangeFieldMeta(features, fieldName, (rawValue: unknown) => { return typeof rawValue === 'number' ? rawValue : NaN; });