diff --git a/packages/openlayers/lib/map/create-map.test.ts b/packages/openlayers/lib/map/create-map.test.ts index 7007928..80dcf8d 100644 --- a/packages/openlayers/lib/map/create-map.test.ts +++ b/packages/openlayers/lib/map/create-map.test.ts @@ -25,7 +25,6 @@ import { MapContextLayer, MapContextLayerGeojson, MapContextLayerWms, - SourceLoadErrorEvent, } from "@geospatial-sdk/core"; import Layer from "ol/layer/Layer"; import { @@ -39,17 +38,18 @@ import { VectorTile } from "ol/source"; import { MapboxVectorLayer } from "ol-mapbox-style"; import { handleEndpointError, - tileLoadErrorCatchFunction, + imageTileLoadErrorCatchFunction, } from "./handle-errors"; import { ImageTile } from "ol"; import TileState from "ol/TileState.js"; import VectorTileLayer from "ol/layer/VectorTile"; +import MVT from "ol/format/MVT"; vi.mock("./handle-errors", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, - tileLoadErrorCatchFunction: vi.fn(), + imageTileLoadErrorCatchFunction: vi.fn(), handleEndpointError: vi.fn(), }; }); @@ -85,7 +85,7 @@ describe("MapContextService", () => { "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png", ); }); - it("should set tileLoadErrorCatchFunction to handle errors", () => { + it("should set imageTileLoadErrorCatchFunction to handle errors", () => { const source = layer.getSource() as XYZ; const tileLoadFunction = source.getTileLoadFunction(); expect(tileLoadFunction).toBeInstanceOf(Function); @@ -97,7 +97,11 @@ describe("MapContextService", () => { () => {}, ); tileLoadFunction(tile, "http://example.com/tile"); - expect(tileLoadErrorCatchFunction).toHaveBeenCalled(); + expect(imageTileLoadErrorCatchFunction).toHaveBeenCalledWith( + layer, + tile, + "http://example.com/tile", + ); }); }); describe("OGCAPI", () => { @@ -166,7 +170,7 @@ describe("MapContextService", () => { const gutter = source["gutter_"]; expect(gutter).toBe(20); }); - it("should set tileLoadErrorCatchFunction to handle errors", () => { + it("should set imageTileLoadErrorCatchFunction to handle errors", () => { const source = layer.getSource() as TileWMS; const tileLoadFunction = source.getTileLoadFunction(); expect(tileLoadFunction).toBeInstanceOf(Function); @@ -178,7 +182,7 @@ describe("MapContextService", () => { () => {}, ); tileLoadFunction(tile, "http://example.com/tile"); - expect(tileLoadErrorCatchFunction).toHaveBeenCalled(); + expect(imageTileLoadErrorCatchFunction).toHaveBeenCalled(); }); }); @@ -415,6 +419,16 @@ describe("MapContextService", () => { expect(layer.getOpacity()).toBe(1); expect(layer.get("label")).toBeUndefined(); }); + it("should set imageTileLoadErrorCatchFunction to handle errors", () => { + const source = layer.getSource() as VectorTile; + const tileLoadFunction = source.getTileLoadFunction(); + expect(tileLoadFunction).toBeInstanceOf(Function); + const tile = new VectorTile({ + format: new MVT(), + }); + tileLoadFunction(tile, "http://example.com/tms/tile"); + expect(imageTileLoadErrorCatchFunction).toHaveBeenCalled(); + }); }); }); diff --git a/packages/openlayers/lib/map/create-map.ts b/packages/openlayers/lib/map/create-map.ts index 1313024..5da1885 100644 --- a/packages/openlayers/lib/map/create-map.ts +++ b/packages/openlayers/lib/map/create-map.ts @@ -33,13 +33,16 @@ import { MapboxVectorLayer } from "ol-mapbox-style"; import { Tile } from "ol"; import { handleEndpointError, - tileLoadErrorCatchFunction, + imageTileLoadErrorCatchFunction, + vectorTileLoadErrorCatchFunction, } from "./handle-errors"; import VectorTile from "ol/source/VectorTile"; const GEOJSON = new GeoJSON(); const WFS_MAX_FEATURES = 10000; +type TileSource = VectorTile | XYZ; + export async function createLayer(layerModel: MapContextLayer): Promise { const { type } = layerModel; let layer: Layer | undefined; @@ -54,20 +57,21 @@ export async function createLayer(layerModel: MapContextLayer): Promise { attributions: layerModel.attributions, }), }); + const source = layer.getSource(); + source.setTileLoadFunction((tile: Tile, src: string) => + vectorTileLoadErrorCatchFunction(layer, tile, src), + ); } else { - layer = new TileLayer({}); - const source = new XYZ({ - url: layerModel.url, - attributions: layerModel.attributions, - }); - source.setTileLoadFunction(function (tile: Tile, src: string) { - return tileLoadErrorCatchFunction( - layer as TileLayer, - tile, - src, - ); + layer = new TileLayer({ + source: new XYZ({ + url: layerModel.url, + attributions: layerModel.attributions, + }), }); - layer.setSource(source); + const source = layer.getSource(); + source.setTileLoadFunction((tile: Tile, src: string) => + imageTileLoadErrorCatchFunction(layer, tile, src), + ); } } break; @@ -84,7 +88,7 @@ export async function createLayer(layerModel: MapContextLayer): Promise { attributions: layerModel.attributions, }); source.setTileLoadFunction(function (tile: Tile, src: string) { - return tileLoadErrorCatchFunction( + return imageTileLoadErrorCatchFunction( layer as TileLayer, tile, src, diff --git a/packages/openlayers/lib/map/handle-errors.test.ts b/packages/openlayers/lib/map/handle-errors.test.ts index 4f76c09..e5667cf 100644 --- a/packages/openlayers/lib/map/handle-errors.test.ts +++ b/packages/openlayers/lib/map/handle-errors.test.ts @@ -1,7 +1,10 @@ import { ImageTile, Tile } from "ol"; import TileState from "ol/TileState.js"; import { SourceLoadErrorEvent } from "@geospatial-sdk/core"; -import { handleTileError, tileLoadErrorCatchFunction } from "./handle-errors"; +import { + handleTileError, + imageTileLoadErrorCatchFunction, +} from "./handle-errors"; import { Map } from "ol"; import { describe } from "node:test"; import TileLayer from "ol/layer/Tile"; @@ -35,7 +38,7 @@ describe("handle-errors", () => { TileState.IDLE, "", null, - () => tileLoadErrorCatchFunction, + () => imageTileLoadErrorCatchFunction, ); }); diff --git a/packages/openlayers/lib/map/handle-errors.ts b/packages/openlayers/lib/map/handle-errors.ts index 227d50d..3c519b2 100644 --- a/packages/openlayers/lib/map/handle-errors.ts +++ b/packages/openlayers/lib/map/handle-errors.ts @@ -1,11 +1,12 @@ import { EndpointError } from "@camptocamp/ogc-client"; import { SourceLoadErrorEvent } from "@geospatial-sdk/core"; -import { ImageTile, Tile } from "ol"; +import { ImageTile, Tile, VectorTile } from "ol"; import { Layer } from "ol/layer"; import TileLayer from "ol/layer/Tile"; import VectorLayer from "ol/layer/Vector"; import TileSource from "ol/source/Tile"; import VectorSource from "ol/source/Vector"; +import { defaultLoadFunction } from "ol/source/VectorTile"; import TileState from "ol/TileState.js"; export function handleEndpointError( @@ -26,7 +27,20 @@ export function handleTileError( layer.dispatchEvent(new SourceLoadErrorEvent(response)); } -export function tileLoadErrorCatchFunction( +export function vectorTileLoadErrorCatchFunction( + layer: Layer, + tile: Tile, + url: string, +) { + try { + // TODO: WIP override? + defaultLoadFunction(tile, url); + } catch (e) { + handleTileError(e, tile, layer); + } +} + +export function imageTileLoadErrorCatchFunction( layer: Layer, tile: Tile, src: string,