diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js index 6c04f7c19ac7d..ccbc8a1c21324 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.js @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import turf from 'turf'; import React from 'react'; import { AbstractLayer } from '../layer'; import { VectorStyle } from '../../styles/vector/vector_style'; @@ -30,6 +29,7 @@ import { canSkipFormattersUpdate, } from '../../util/can_skip_fetch'; import { assignFeatureIds } from '../../util/assign_feature_ids'; +import { getFeatureCollectionBounds } from '../../util/get_feature_collection_bounds'; import { getFillFilterExpression, getLineFilterExpression, @@ -153,31 +153,10 @@ export class VectorLayer extends AbstractLayer { return this.getCurrentStyle().renderLegendDetails(); } - _getBoundsBasedOnData() { - const featureCollection = this._getSourceFeatureCollection(); - if (!featureCollection) { - return null; - } - - const visibleFeatures = featureCollection.features.filter( - feature => feature.properties[FEATURE_VISIBLE_PROPERTY_NAME] - ); - const bbox = turf.bbox({ - type: 'FeatureCollection', - features: visibleFeatures, - }); - return { - minLon: bbox[0], - minLat: bbox[1], - maxLon: bbox[2], - maxLat: bbox[3], - }; - } - async getBounds(dataFilters) { const isStaticLayer = !this.getSource().isBoundsAware(); if (isStaticLayer) { - return this._getBoundsBasedOnData(); + return getFeatureCollectionBounds(this._getSourceFeatureCollection(), this._hasJoins()); } const searchFilters = this._getSearchFilters( diff --git a/x-pack/plugins/maps/public/classes/util/get_feature_collection_bounds.test.tsx b/x-pack/plugins/maps/public/classes/util/get_feature_collection_bounds.test.tsx new file mode 100644 index 0000000000000..ad8b8d37f1310 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/util/get_feature_collection_bounds.test.tsx @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { getFeatureCollectionBounds } from './get_feature_collection_bounds'; +import { FeatureCollection, Feature, Point } from 'geojson'; +import { FEATURE_VISIBLE_PROPERTY_NAME } from '../../../common/constants'; + +const visibleFeature: Feature = { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [0, 0], + } as Point, + properties: { + [FEATURE_VISIBLE_PROPERTY_NAME]: true, + }, +}; + +const nonVisibleFeature: Feature = { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [10, 0], + } as Point, + properties: { + [FEATURE_VISIBLE_PROPERTY_NAME]: false, + }, +}; + +const featureWithoutVisibilityProp: Feature = { + type: 'Feature', + geometry: { + type: 'Point', + coordinates: [-10, 0], + } as Point, + properties: {}, +}; + +const featureCollection: FeatureCollection = { + type: 'FeatureCollection', + features: [visibleFeature, nonVisibleFeature, featureWithoutVisibilityProp], +}; + +test('should return bounding box for visible features with join', () => { + expect(getFeatureCollectionBounds(featureCollection, true)).toEqual({ + maxLat: 0, + maxLon: 0, + minLat: 0, + minLon: 0, + }); +}); + +test('should return bounding box for all features without join', () => { + expect(getFeatureCollectionBounds(featureCollection, false)).toEqual({ + maxLat: 0, + maxLon: 10, + minLat: 0, + minLon: -10, + }); +}); + +test('should return null when there are no features', () => { + const featureCollectionWithNoVisibileFeatures: FeatureCollection = { + type: 'FeatureCollection', + features: [nonVisibleFeature, featureWithoutVisibilityProp], + }; + expect(getFeatureCollectionBounds(featureCollectionWithNoVisibileFeatures, true)).toBeNull(); +}); diff --git a/x-pack/plugins/maps/public/classes/util/get_feature_collection_bounds.ts b/x-pack/plugins/maps/public/classes/util/get_feature_collection_bounds.ts new file mode 100644 index 0000000000000..4247233b295e1 --- /dev/null +++ b/x-pack/plugins/maps/public/classes/util/get_feature_collection_bounds.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +// @ts-ignore +import turf from 'turf'; +import { FeatureCollection } from 'geojson'; +import { MapExtent } from '../../../common/descriptor_types'; +import { FEATURE_VISIBLE_PROPERTY_NAME } from '../../../common/constants'; + +export function getFeatureCollectionBounds( + featureCollection: FeatureCollection | null, + hasJoins: boolean +): MapExtent | null { + if (!featureCollection) { + return null; + } + + const visibleFeatures = hasJoins + ? featureCollection.features.filter(feature => { + return feature.properties && feature.properties[FEATURE_VISIBLE_PROPERTY_NAME]; + }) + : featureCollection.features; + + if (visibleFeatures.length === 0) { + return null; + } + + const bbox = turf.bbox({ + type: 'FeatureCollection', + features: visibleFeatures, + }); + return { + minLon: bbox[0], + minLat: bbox[1], + maxLon: bbox[2], + maxLat: bbox[3], + }; +}