Adhere to geo_span setting from tenant if one is defined#1492
Adhere to geo_span setting from tenant if one is defined#1492jeslefcourt merged 5 commits intodevelopfrom
Conversation
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| export const buildGeoSpanFilter = (geoSpan) => { | ||
| if (!geoSpan) return null; | ||
|
|
||
| const { lon, lat } = geoSpan; | ||
|
|
||
| if (!Array.isArray(lon) || !Array.isArray(lat) || lon.length < 2 || lat.length < 2) { | ||
| return null; | ||
| } | ||
|
|
||
| const [minLon, maxLon] = lon; | ||
| const [minLat, maxLat] = lat; | ||
|
|
||
| if ( | ||
| !Number.isFinite(minLon) || | ||
| !Number.isFinite(maxLon) || | ||
| !Number.isFinite(minLat) || | ||
| !Number.isFinite(maxLat) | ||
| ) { | ||
| return null; | ||
| } | ||
| return [minLon, minLat, maxLon, maxLat]; | ||
| }; |
There was a problem hiding this comment.
buildGeoSpanFilter is new behavior in src/utils/map.js, but there are no unit tests covering valid/invalid geoSpan inputs (missing keys, wrong types, inverted ranges, etc.). Since this file already has a dedicated src/utils/map.test.js, adding focused tests there would help prevent regressions and clarify expected input handling.
There was a problem hiding this comment.
You can add a new describe block in src/utils/map.test.js and ask an agent to add some coverage to this new method:
describe('buildGeoSpanFilter', () => {
// TODO: Claude, add unit tests for buildGeoSpanFilter here.
});| useEffect(() => { | ||
| if (!map) return; | ||
|
|
||
| if (!map.getSource(SPATIAL_FEATURES_SOURCE)) { | ||
| const geoSpanFilter = buildGeoSpanFilter(geoSpan); | ||
| map.addSource(SPATIAL_FEATURES_SOURCE, { | ||
| type: 'vector', | ||
| tiles: [VECTOR_TILE_URL], | ||
| minzoom: 0, | ||
| maxzoom: 22, | ||
| ...(geoSpanFilter && { bounds: geoSpanFilter }), | ||
| transformRequest: (url, resourceType) => { |
There was a problem hiding this comment.
The new geo-span behavior (adding bounds to the vector source when tenant config is present) isn’t covered by the existing SpatialFeaturesLayer tests. It would be good to add a test case where useSelector returns a non-null geoSpan and buildGeoSpanFilter returns a bbox, then assert map.addSource is called with a bounds field so this feature doesn’t silently regress.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
luixlive
left a comment
There was a problem hiding this comment.
Great idea 💯 A simple way to avoid unnecessary network calls.
I added one non-blocking suggestion, but the code seems good.
|
|
||
|
|
||
| export const buildGeoSpanFilter = (geoSpan) => { | ||
| if (!geoSpan) return null; |
There was a problem hiding this comment.
The validation steps in this method take more lines than its actual logic. We have a couple handy utilities isValidLatitude and isValidLongitude in src/utils/location/index.js that you can export / import and simplify these validations a bit:
import { isValidLatitude, isValidLongitude } from 'utils/location;
const areLatitudeValuesValid = Array.isArray(geoSpan?.lat)
&& geoSpan.lat.length === 2
&& geoSpan.lat.every((latitude) => isValidLatitude(latitude));
const areLongitudeValuesValid = Array.isArray(geoSpan?.lng)
&& geoSpan.lng.length === 2
&& geoSpan.lng.every((longitude) => isValidLongitude(longitude));
if (!areLatitudeValuesValid || !areLongitudeValuesValid) {
return null;
}
...| export const buildGeoSpanFilter = (geoSpan) => { | ||
| if (!geoSpan) return null; | ||
|
|
||
| const { lon, lat } = geoSpan; | ||
|
|
||
| if (!Array.isArray(lon) || !Array.isArray(lat) || lon.length < 2 || lat.length < 2) { | ||
| return null; | ||
| } | ||
|
|
||
| const [minLon, maxLon] = lon; | ||
| const [minLat, maxLat] = lat; | ||
|
|
||
| if ( | ||
| !Number.isFinite(minLon) || | ||
| !Number.isFinite(maxLon) || | ||
| !Number.isFinite(minLat) || | ||
| !Number.isFinite(maxLat) | ||
| ) { | ||
| return null; | ||
| } | ||
| return [minLon, minLat, maxLon, maxLat]; | ||
| }; |
There was a problem hiding this comment.
You can add a new describe block in src/utils/map.test.js and ask an agent to add some coverage to this new method:
describe('buildGeoSpanFilter', () => {
// TODO: Claude, add unit tests for buildGeoSpanFilter here.
});
What does this PR do?
Note for developers of the other vector tiles: See the way geoSpanFilter is defined and used around line 100 in src/SpatialFeaturesLayer/index.js
The bounds are defined as part of a tenant's envSettings in the TMS in the form:
One known oddity of the behavior is that it won't load features that intersect, but aren't entirely contained in, the bounding box. For example, if you define a country as a feature and the bounding box being within that country but around the protected area, once you zoom in enough that you no longer see the edges of the country (+/-), the rest of the country or any formatting of the country will disappear. This can't be fixed with a reasonable amount of work, so we'll accept this and give guidance to make the bounding box big enough to encompass all features you care about.
Relevant link(s)
Where / how to start reviewing (optional)