diff --git a/packages/geoview-core/src/core/components/common/layer-icon.tsx b/packages/geoview-core/src/core/components/common/layer-icon.tsx index 499f6acfe66..57d82c1d3f2 100644 --- a/packages/geoview-core/src/core/components/common/layer-icon.tsx +++ b/packages/geoview-core/src/core/components/common/layer-icon.tsx @@ -121,7 +121,7 @@ export const LayerIcon = memo(function LayerIcon({ layer }: LayerIconProps): JSX const isError = layer.layerStatus === 'error' || ('queryStatus' in layer && layer.queryStatus === 'error'); const isLoading = - layer.layerStatus === 'processing' || layer.layerStatus === 'loading' || ('queryStatus' in layer && layer.queryStatus === 'processing'); + (layer.layerStatus !== 'loaded' && layer.layerStatus !== 'error') || ('queryStatus' in layer && layer.queryStatus === 'processing'); const hasChildren = 'children' in layer && layer?.children.length; diff --git a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts index a1660e794c4..eafbf48716a 100644 --- a/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts +++ b/packages/geoview-core/src/geo/layer/geoview-layers/esri-layer-common.ts @@ -347,14 +347,17 @@ export function commonProcessInitialSettings( ] as Extent; // Transform to latlon extent - const latlonExtent = Projection.transformExtentFromObj( - layerExtent, - layerMetadata.extent.spatialReference, - Projection.PROJECTION_NAMES.LNGLAT - ); - layerConfig.initialSettings!.bounds = latlonExtent; + if (layerExtent) { + const latlonExtent = Projection.transformExtentFromObj( + layerExtent, + layerMetadata.extent.spatialReference, + Projection.PROJECTION_NAMES.LNGLAT + ); + layerConfig.initialSettings!.bounds = latlonExtent; + } } - layerConfig.initialSettings!.bounds = validateExtent(layerConfig.initialSettings!.bounds); + + layerConfig.initialSettings!.bounds = validateExtent(layerConfig.initialSettings!.bounds || [-180, -90, 180, 90]); } /** *************************************************************************************************************************** diff --git a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts index 7a3815254f8..8956173cfed 100644 --- a/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts +++ b/packages/geoview-core/src/geo/layer/gv-layers/raster/gv-esri-dynamic.ts @@ -1011,13 +1011,14 @@ export class GVEsriDynamic extends AbstractGVRaster { const responseJson = await response.json(); const { extent } = responseJson; - const projExtent = Projection.transformExtentFromProj( - [extent.xmin, extent.ymin, extent.xmax, extent.ymax], - `EPSG:${extent.spatialReference.wkid}`, - this.getMapViewer().getProjection().getCode() - ); - - return projExtent; + if (extent) { + const projExtent = Projection.transformExtentFromProj( + [extent.xmin, extent.ymin, extent.xmax, extent.ymax], + `EPSG:${extent.spatialReference.wkid}`, + this.getMapViewer().getProjection().getCode() + ); + return validateExtent(projExtent, this.getMapViewer().getProjection().getCode()); + } } catch (error) { logger.logError(`Error fetching geometry from ${queryUrl}`, error); } diff --git a/packages/geoview-core/src/geo/layer/layer.ts b/packages/geoview-core/src/geo/layer/layer.ts index 3fc2fa6d18d..372faa9acd1 100644 --- a/packages/geoview-core/src/geo/layer/layer.ts +++ b/packages/geoview-core/src/geo/layer/layer.ts @@ -713,10 +713,17 @@ export class LayerApi { gvLayer.onIndividualLayerLoaded((sender, payload) => { // Log logger.logDebug(`${payload.layerPath} loaded on map ${this.getMapId()}`); + + const legendLayerInfo = LegendEventProcessor.getLegendLayerInfo(this.getMapId(), payload.layerPath); + // Ensure that the layer bounds are set when the layer is loaded + if (legendLayerInfo && !legendLayerInfo.bounds) LegendEventProcessor.getLayerBounds(this.getMapId(), payload.layerPath); + this.#emitLayerLoaded({ layer: sender, layerPath: payload.layerPath }); }); + return gvLayer.getOLLayer(); } + throw new Error('Error, no corresponding GV layer'); }); @@ -1637,9 +1644,11 @@ export class LayerApi { // Get the layer const layer = this.getGeoviewLayer(layerConfig.layerPath) as AbstractGVLayer; - // Get the bounds of the layer - const calculatedBounds = layer.getBounds(); - if (calculatedBounds) bounds.push(calculatedBounds); + if (layer) { + // Get the bounds of the layer + const calculatedBounds = layer.getBounds(); + if (calculatedBounds) bounds.push(calculatedBounds); + } } else { // Is a group layerConfig.listOfLayerEntryConfig.forEach((subLayerConfig) => { diff --git a/packages/geoview-core/src/geo/utils/projection.ts b/packages/geoview-core/src/geo/utils/projection.ts index b5dde4d2366..2e14897d437 100644 --- a/packages/geoview-core/src/geo/utils/projection.ts +++ b/packages/geoview-core/src/geo/utils/projection.ts @@ -150,6 +150,10 @@ export abstract class Projection { * @returns The new extent transformed in the destination projection. */ static transformExtentFromProj(extent: Extent, source: ProjectionLike, destination: ProjectionLike, stops?: number | undefined): Extent { + // This is included for certain outliers. + // TODO Refactor: invalid extents should be handled before this point, test and remove - 5a65ad7c-561a-466a-8375-8d876624df9d + if (typeof extent[0] !== 'number') + return olTransformExtent([-180, 90, 180, 90], Projection.PROJECTION_NAMES.LNGLAT, destination, stops); // Project return olTransformExtent(extent, source, destination, stops); } diff --git a/packages/geoview-core/src/geo/utils/utilities.ts b/packages/geoview-core/src/geo/utils/utilities.ts index c32a0422097..66084d1eeed 100644 --- a/packages/geoview-core/src/geo/utils/utilities.ts +++ b/packages/geoview-core/src/geo/utils/utilities.ts @@ -406,19 +406,19 @@ export function validateExtent(extent: Extent, code: string = 'EPSG:4326'): Exte 'EPSG:3978': [-7192737.96, -3004297.73, 5183275.29, 4484204.83], }; - // Replace any invalid entries with maximum value - const minX = extent[0] < maxExtents[code][0] || extent[0] === -Infinity || Number.isNaN(extent[0]) ? maxExtents[code][0] : extent[0]; - const minY = extent[1] < maxExtents[code][1] || extent[1] === -Infinity || Number.isNaN(extent[1]) ? maxExtents[code][1] : extent[1]; - const maxX = extent[2] > maxExtents[code][2] || extent[2] === Infinity || Number.isNaN(extent[2]) ? maxExtents[code][2] : extent[2]; - const maxY = extent[3] > maxExtents[code][3] || extent[3] === Infinity || Number.isNaN(extent[3]) ? maxExtents[code][3] : extent[3]; - - // Check the order - const validatedExtent: Extent = [ - minX < maxX ? minX : maxX, - minY < maxY ? minY : maxY, - maxX > minX ? maxX : minX, - maxY > minY ? maxY : minY, - ]; + let validatedExtent: Extent; + // In rare cases, services return 'NaN' as extents, not picked up by Number.isNan + if (typeof extent[0] !== 'number') validatedExtent = maxExtents[code]; + else { + // Replace any invalid entries with maximum value + const minX = extent[0] < maxExtents[code][0] || extent[0] === -Infinity || Number.isNaN(extent[0]) ? maxExtents[code][0] : extent[0]; + const minY = extent[1] < maxExtents[code][1] || extent[1] === -Infinity || Number.isNaN(extent[1]) ? maxExtents[code][1] : extent[1]; + const maxX = extent[2] > maxExtents[code][2] || extent[2] === Infinity || Number.isNaN(extent[2]) ? maxExtents[code][2] : extent[2]; + const maxY = extent[3] > maxExtents[code][3] || extent[3] === Infinity || Number.isNaN(extent[3]) ? maxExtents[code][3] : extent[3]; + + // Check the order + validatedExtent = [minX < maxX ? minX : maxX, minY < maxY ? minY : maxY, maxX > minX ? maxX : minX, maxY > minY ? maxY : minY]; + } return validatedExtent; }