@open-pioneer/map 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -3
- package/MapRegistryImpl.d.ts +6 -4
- package/MapRegistryImpl.js +5 -3
- package/MapRegistryImpl.js.map +1 -1
- package/README.md +111 -9
- package/api/MapModel.d.ts +33 -0
- package/api/MapRegistry.d.ts +2 -8
- package/api/index.d.ts +1 -0
- package/api/layers/WMSLayer.d.ts +3 -3
- package/api/layers/WMSLayer.js.map +1 -1
- package/api/layers/base.d.ts +8 -0
- package/assets/images/mapMarker.png +0 -0
- package/index.js +1 -1
- package/layers/BkgTopPlusOpen.js +1 -1
- package/layers/BkgTopPlusOpen.js.map +1 -1
- package/model/AbstractLayer.js +74 -15
- package/model/AbstractLayer.js.map +1 -1
- package/model/AbstractLayerBase.d.ts +2 -2
- package/model/AbstractLayerBase.js.map +1 -1
- package/model/Highlights.d.ts +16 -0
- package/model/Highlights.js +128 -0
- package/model/Highlights.js.map +1 -0
- package/model/MapModelImpl.d.ts +13 -1
- package/model/MapModelImpl.js +17 -0
- package/model/MapModelImpl.js.map +1 -1
- package/model/createMapModel.d.ts +2 -1
- package/model/createMapModel.js +8 -5
- package/model/createMapModel.js.map +1 -1
- package/model/layers/WMSLayerImpl.js +20 -0
- package/model/layers/WMSLayerImpl.js.map +1 -1
- package/package.json +13 -7
- package/ui/useMapModel.js.map +1 -1
- package/util/geometry-utils.d.ts +7 -0
- package/util/geometry-utils.js +25 -0
- package/util/geometry-utils.js.map +1 -0
- package/util/ol-test-support.js.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,32 @@
|
|
|
1
1
|
# @open-pioneer/map
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 70349a8: Update to new core packages major versions
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [70349a8]
|
|
12
|
+
- @open-pioneer/react-utils@0.2.0
|
|
13
|
+
|
|
14
|
+
## 0.1.1
|
|
15
|
+
|
|
16
|
+
### Patch Changes
|
|
17
|
+
|
|
18
|
+
- 08bffbc: MapModel API has got new methods for zooming/highlighting
|
|
19
|
+
- a58546b: Use `HttpService` for default health checks made by the map model.
|
|
20
|
+
- a58546b: Use `HttpService` when loading images in WMSLayer.
|
|
21
|
+
- 0c4ce04: Add OGC API Tiles (vector tiles) support
|
|
22
|
+
|
|
3
23
|
## 0.1.0
|
|
4
24
|
|
|
5
25
|
### Minor Changes
|
|
6
26
|
|
|
7
|
-
-
|
|
27
|
+
- bb2f27a: Initial release.
|
|
8
28
|
|
|
9
29
|
### Patch Changes
|
|
10
30
|
|
|
11
|
-
-
|
|
12
|
-
|
|
31
|
+
- Updated dependencies [182da1c]
|
|
32
|
+
- @open-pioneer/react-utils@0.1.0
|
package/MapRegistryImpl.d.ts
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
import { Service, ServiceOptions
|
|
1
|
+
import { Service, ServiceOptions } from "@open-pioneer/runtime";
|
|
2
2
|
import OlMap from "ol/Map";
|
|
3
|
-
import { MapModel, MapRegistry } from "./api";
|
|
3
|
+
import { MapConfigProvider, MapModel, MapRegistry } from "./api";
|
|
4
|
+
import { HttpService } from "@open-pioneer/http";
|
|
4
5
|
interface References {
|
|
5
|
-
providers:
|
|
6
|
+
providers: MapConfigProvider[];
|
|
7
|
+
httpService: HttpService;
|
|
6
8
|
}
|
|
7
9
|
export declare class MapRegistryImpl implements Service, MapRegistry {
|
|
8
10
|
#private;
|
|
9
|
-
constructor(
|
|
11
|
+
constructor({ references }: ServiceOptions<References>);
|
|
10
12
|
destroy(): void;
|
|
11
13
|
getMapModel(mapId: string): Promise<MapModel | undefined>;
|
|
12
14
|
expectMapModel(mapId: string): Promise<MapModel>;
|
package/MapRegistryImpl.js
CHANGED
|
@@ -3,13 +3,15 @@ import { createMapModel } from './model/createMapModel.js';
|
|
|
3
3
|
|
|
4
4
|
const LOG = createLogger("map:MapRegistry");
|
|
5
5
|
class MapRegistryImpl {
|
|
6
|
+
#httpService;
|
|
6
7
|
#configProviders = /* @__PURE__ */ new Map();
|
|
7
8
|
#entries = /* @__PURE__ */ new Map();
|
|
8
9
|
#modelCreationJobs = /* @__PURE__ */ new Map();
|
|
9
10
|
#modelsByOlMap = /* @__PURE__ */ new WeakMap();
|
|
10
11
|
#destroyed = false;
|
|
11
|
-
constructor(
|
|
12
|
-
|
|
12
|
+
constructor({ references }) {
|
|
13
|
+
this.#httpService = references.httpService;
|
|
14
|
+
const providers = references.providers;
|
|
13
15
|
for (const provider of providers) {
|
|
14
16
|
this.#configProviders.set(provider.mapId, provider);
|
|
15
17
|
}
|
|
@@ -66,7 +68,7 @@ class MapRegistryImpl {
|
|
|
66
68
|
async #createModel(mapId, provider) {
|
|
67
69
|
LOG.info(`Creating map with id '${mapId}'`);
|
|
68
70
|
const mapConfig = await provider.getMapConfig();
|
|
69
|
-
const mapModel = await createMapModel(mapId, mapConfig);
|
|
71
|
+
const mapModel = await createMapModel(mapId, mapConfig, this.#httpService);
|
|
70
72
|
if (this.#destroyed) {
|
|
71
73
|
mapModel.destroy();
|
|
72
74
|
throw new Error(`MapRegistry has been destroyed.`);
|
package/MapRegistryImpl.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MapRegistryImpl.js","sources":["MapRegistryImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger } from \"@open-pioneer/core\";\nimport { Service, ServiceOptions
|
|
1
|
+
{"version":3,"file":"MapRegistryImpl.js","sources":["MapRegistryImpl.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger } from \"@open-pioneer/core\";\nimport { Service, ServiceOptions } from \"@open-pioneer/runtime\";\nimport OlMap from \"ol/Map\";\nimport { MapModelImpl } from \"./model/MapModelImpl\";\nimport { MapConfigProvider, MapModel, MapRegistry } from \"./api\";\nimport { createMapModel } from \"./model/createMapModel\";\nimport { HttpService } from \"@open-pioneer/http\";\n\nconst LOG = createLogger(\"map:MapRegistry\");\n\ninterface References {\n providers: MapConfigProvider[];\n httpService: HttpService;\n}\n\ntype ModelJobResult = { kind: \"model\"; model: MapModelImpl } | { kind: \"error\"; error: Error };\n\nexport class MapRegistryImpl implements Service, MapRegistry {\n #httpService: HttpService;\n\n #configProviders = new Map<string, MapConfigProvider>();\n #entries = new Map<string, ModelJobResult>();\n #modelCreationJobs = new Map<string, Promise<ModelJobResult>>();\n #modelsByOlMap = new WeakMap<OlMap, MapModel>();\n #destroyed = false;\n\n constructor({ references }: ServiceOptions<References>) {\n this.#httpService = references.httpService;\n\n const providers = references.providers;\n for (const provider of providers) {\n this.#configProviders.set(provider.mapId, provider);\n }\n }\n\n destroy(): void {\n if (this.#destroyed) {\n return;\n }\n\n LOG.info(`Destroy map registry and all maps`);\n this.#destroyed = true;\n this.#entries.forEach((model) => {\n model.kind === \"model\" && model.model.destroy();\n });\n this.#entries.clear();\n this.#modelCreationJobs.clear();\n }\n\n async getMapModel(mapId: string): Promise<MapModel | undefined> {\n if (this.#destroyed) {\n throw new Error(\"MapRegistry has already been destroyed.\");\n }\n\n const creationJob = this.#modelCreationJobs.get(mapId);\n if (creationJob) {\n return unbox(await creationJob);\n }\n\n const entry = this.#entries.get(mapId);\n if (entry) {\n return unbox(entry);\n }\n\n const provider = this.#configProviders.get(mapId);\n if (!provider) {\n LOG.debug(`Failed to find a config provider for map id '${mapId}'.`);\n return undefined;\n }\n\n const modelPromise = this.#createModel(mapId, provider).catch((cause) => {\n const error = new Error(`Failed to construct map '${mapId}'`, { cause });\n const entry: ModelJobResult = { kind: \"error\", error };\n this.#modelCreationJobs.delete(mapId);\n this.#entries.set(mapId, entry);\n return entry;\n });\n this.#modelCreationJobs.set(mapId, modelPromise);\n return unbox(await modelPromise);\n }\n\n async expectMapModel(mapId: string): Promise<MapModel> {\n const model = await this.getMapModel(mapId);\n if (!model) {\n throw new Error(`No configuration available for map with id '${mapId}'.`);\n }\n return model;\n }\n\n getMapModelByRawInstance(olMap: OlMap): MapModel | undefined {\n return this.#modelsByOlMap.get(olMap);\n }\n\n async #createModel(mapId: string, provider: MapConfigProvider): Promise<ModelJobResult> {\n LOG.info(`Creating map with id '${mapId}'`);\n const mapConfig = await provider.getMapConfig();\n const mapModel = await createMapModel(mapId, mapConfig, this.#httpService);\n\n if (this.#destroyed) {\n mapModel.destroy();\n throw new Error(`MapRegistry has been destroyed.`);\n }\n\n const entry: ModelJobResult = { kind: \"model\", model: mapModel };\n this.#entries.set(mapId, entry);\n this.#modelCreationJobs.delete(mapId);\n this.#modelsByOlMap.set(mapModel.olMap, mapModel);\n return entry;\n }\n}\n\nfunction unbox(entry: ModelJobResult): MapModelImpl {\n if (entry.kind === \"error\") {\n throw entry.error;\n }\n return entry.model;\n}\n"],"names":["entry"],"mappings":"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"}
|
package/README.md
CHANGED
|
@@ -258,6 +258,65 @@ layer.updateAttributes({
|
|
|
258
258
|
layer.deleteAttribute("foo");
|
|
259
259
|
```
|
|
260
260
|
|
|
261
|
+
An optional property `healthCheck` allows to determine the availability status of a layer (e.g. map service down). The health check is performed asynchronous.
|
|
262
|
+
|
|
263
|
+
It is possible to provide
|
|
264
|
+
|
|
265
|
+
- either a URL to perform a test request check the returned HTTP status
|
|
266
|
+
- or a `HealthCheckFunction` performing a custom check and returning the state
|
|
267
|
+
|
|
268
|
+
**Important**: The availability of a layer is only checked once during initialization to reduce the load on server side. If a service becomes available again later, the application will need to be reloaded in order to update the availability status.
|
|
269
|
+
|
|
270
|
+
The availability status of a layer can be accessed with the property `loadState`. Its value depends on the result of the health check and the OpenLayers `Source` of the layer. If at least one of both checks returns the state `error`, the `loadState` will be set to `error`.
|
|
271
|
+
|
|
272
|
+
Example: Check of layer availability ("health check")
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
// YOUR-APP/MapConfigProviderImpl.ts
|
|
276
|
+
import { MapConfig, MapConfigProvider, SimpleLayer } from "@open-pioneer/map";
|
|
277
|
+
import TileLayer from "ol/layer/Tile";
|
|
278
|
+
import OSM from "ol/source/OSM";
|
|
279
|
+
|
|
280
|
+
export class MapConfigProviderImpl implements MapConfigProvider {
|
|
281
|
+
async getMapConfig(): Promise<MapConfig> {
|
|
282
|
+
return {
|
|
283
|
+
layers: [
|
|
284
|
+
new SimpleLayer({
|
|
285
|
+
id: "1",
|
|
286
|
+
title: "Layer 1",
|
|
287
|
+
olLayer: new TileLayer({
|
|
288
|
+
source: new OSM()
|
|
289
|
+
}),
|
|
290
|
+
// check layer availability by requesting the provided URL
|
|
291
|
+
healthCheck:
|
|
292
|
+
"https://sgx.geodatenzentrum.de/wmts_topplus_open/1.0.0/WMTSCapabilities.xml",
|
|
293
|
+
isBaseLayer: false,
|
|
294
|
+
visible: true
|
|
295
|
+
}),
|
|
296
|
+
new SimpleLayer({
|
|
297
|
+
id: "2",
|
|
298
|
+
title: "Layer 2",
|
|
299
|
+
olLayer: new TileLayer({
|
|
300
|
+
source: new OSM()
|
|
301
|
+
}),
|
|
302
|
+
// check layer availability by providing a custom health check function
|
|
303
|
+
healthCheck: async () => {
|
|
304
|
+
function wait(milliseconds: number): Promise<void> {
|
|
305
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
await wait(3000);
|
|
309
|
+
return "error";
|
|
310
|
+
},
|
|
311
|
+
isBaseLayer: false,
|
|
312
|
+
visible: false
|
|
313
|
+
})
|
|
314
|
+
]
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
261
320
|
> NOTE: The visibility of base layers cannot be changed through the method `setVisible`.
|
|
262
321
|
> Call `activateBaseLayer` instead.
|
|
263
322
|
|
|
@@ -266,7 +325,7 @@ layer.deleteAttribute("foo");
|
|
|
266
325
|
To create an OGC API Features layer, use the `ogc-features` package.
|
|
267
326
|
Details about the necessary steps are described in the package's [README](../ogc-features/README.md) file.
|
|
268
327
|
|
|
269
|
-
|
|
328
|
+
###### Mapbox / MapLibre styles
|
|
270
329
|
|
|
271
330
|
To use layers of a Mapbox / MapLibre style document, use the class `MapboxVectorLayer` from the package `ol-mapbox-style` as in the following sample:
|
|
272
331
|
|
|
@@ -294,8 +353,7 @@ export class MapConfigProviderImpl implements MapConfigProvider {
|
|
|
294
353
|
{
|
|
295
354
|
title: "Abschnitte/Äste mit Unfällen (Mapbox Style)",
|
|
296
355
|
layer: new MapboxVectorLayer({
|
|
297
|
-
styleUrl: "https://demo.ldproxy.net/strassen/styles/default?f=mbs"
|
|
298
|
-
accessToken: null
|
|
356
|
+
styleUrl: "https://demo.ldproxy.net/strassen/styles/default?f=mbs"
|
|
299
357
|
})
|
|
300
358
|
}
|
|
301
359
|
]
|
|
@@ -304,12 +362,56 @@ export class MapConfigProviderImpl implements MapConfigProvider {
|
|
|
304
362
|
}
|
|
305
363
|
```
|
|
306
364
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
365
|
+
Because of the changed license of Mapbox as of version 2.0, we recommend to override the implementation with the code of MapLibre (see the main package.json of this repository for a sample).
|
|
366
|
+
|
|
367
|
+
##### OGC API Tiles
|
|
368
|
+
|
|
369
|
+
OpenLayers supports OGC API Tiles (vector tiles) by default (see [OpenLayers API](https://openlayers.org/en/latest/apidoc/module-ol_source_OGCVectorTile-OGCVectorTile.html)).
|
|
370
|
+
|
|
371
|
+
> IMPORTANT: The configured vector tile layer must have the same projection like the map. Otherwise OGC API Tiles cannot be displayed correctly in a map.
|
|
372
|
+
|
|
373
|
+
Example: How to configure a vector tile layer:
|
|
311
374
|
|
|
312
|
-
|
|
375
|
+
```ts
|
|
376
|
+
// YOUR-APP/MapConfigProviderImpl.ts
|
|
377
|
+
export class MapConfigProviderImpl implements MapConfigProvider {
|
|
378
|
+
async getMapConfig(): Promise<MapConfig> {
|
|
379
|
+
return {
|
|
380
|
+
projection: "EPSG:3857",
|
|
381
|
+
initialView: {
|
|
382
|
+
kind: "position",
|
|
383
|
+
center: {
|
|
384
|
+
x: 848890,
|
|
385
|
+
y: 6793350
|
|
386
|
+
},
|
|
387
|
+
zoom: 13
|
|
388
|
+
},
|
|
389
|
+
layers: [
|
|
390
|
+
new SimpleLayer({
|
|
391
|
+
title: "Pendleratlas",
|
|
392
|
+
visible: true,
|
|
393
|
+
olLayer: new VectorTileLayer({
|
|
394
|
+
source: new VectorTileSource({
|
|
395
|
+
url: "https://pendleratlas.statistikportal.de/_vector_tiles/2022/vg250/{z}/{x}/{y}.pbf",
|
|
396
|
+
format: new MVT(),
|
|
397
|
+
projection: "EPSG:3857"
|
|
398
|
+
}),
|
|
399
|
+
style: new Style({
|
|
400
|
+
fill: new Fill({
|
|
401
|
+
color: "rgba(173, 209, 158, 0.6)"
|
|
402
|
+
}),
|
|
403
|
+
stroke: new Stroke({
|
|
404
|
+
color: "#2d7d9f",
|
|
405
|
+
width: 3
|
|
406
|
+
})
|
|
407
|
+
})
|
|
408
|
+
})
|
|
409
|
+
})
|
|
410
|
+
]
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
```
|
|
313
415
|
|
|
314
416
|
##### OGC Web Map Tile Service (WMTS)
|
|
315
417
|
|
|
@@ -435,7 +537,7 @@ registerProjections({
|
|
|
435
537
|
const mapModel: MapModel = ... // retrieved via MapRegistry service
|
|
436
538
|
await mapModel.whenDisplayed();
|
|
437
539
|
|
|
438
|
-
const response = await fetch("https://sgx.geodatenzentrum.de/wmts_topplus_open/1.0.0/WMTSCapabilities.xml");
|
|
540
|
+
const response = await httpService.fetch("https://sgx.geodatenzentrum.de/wmts_topplus_open/1.0.0/WMTSCapabilities.xml");
|
|
439
541
|
const responseText = await response.text();
|
|
440
542
|
|
|
441
543
|
const wmtsParser = new WMTSCapabilities();
|
package/api/MapModel.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type OlBaseLayer from "ol/layer/Base";
|
|
|
4
4
|
import type { ExtentConfig } from "./MapConfig";
|
|
5
5
|
import type { Layer, LayerBase } from "./layers";
|
|
6
6
|
import type { LayerRetrievalOptions } from "./shared";
|
|
7
|
+
import type { Geometry } from "ol/geom";
|
|
8
|
+
import type { StyleLike } from "ol/style/Style";
|
|
7
9
|
/** Events emitted by the {@link MapModel}. */
|
|
8
10
|
export interface MapModelEvents {
|
|
9
11
|
"changed": void;
|
|
@@ -11,6 +13,26 @@ export interface MapModelEvents {
|
|
|
11
13
|
"changed:initialExtent": void;
|
|
12
14
|
"destroy": void;
|
|
13
15
|
}
|
|
16
|
+
/** Options supported by the map model's {@link MapModel.highlightAndZoom | highlightAndZoom} method. */
|
|
17
|
+
export interface HighlightOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Optional styles to override the default styles.
|
|
20
|
+
*/
|
|
21
|
+
highlightStyle?: HighlightStyle;
|
|
22
|
+
/**
|
|
23
|
+
* The zoom-level used if there is no valid extend (such as for single points).
|
|
24
|
+
*/
|
|
25
|
+
pointZoom?: number;
|
|
26
|
+
/**
|
|
27
|
+
* The maximum zoom-level for line or polygon results.
|
|
28
|
+
*/
|
|
29
|
+
maxZoom?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface HighlightStyle {
|
|
32
|
+
Point?: StyleLike;
|
|
33
|
+
LineString?: StyleLike;
|
|
34
|
+
Polygon?: StyleLike;
|
|
35
|
+
}
|
|
14
36
|
/**
|
|
15
37
|
* Represents a map.
|
|
16
38
|
*/
|
|
@@ -52,6 +74,17 @@ export interface MapModel extends EventSource<MapModelEvents> {
|
|
|
52
74
|
* Returns a promise that resolves when the map has mounted in the DOM.
|
|
53
75
|
*/
|
|
54
76
|
whenDisplayed(): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Highlights the given geometries on the map.
|
|
79
|
+
* Centers and zooms the view on the geometries.
|
|
80
|
+
*
|
|
81
|
+
* Removes any previous highlights.
|
|
82
|
+
*/
|
|
83
|
+
highlightAndZoom(geometries: Geometry[], options?: HighlightOptions): void;
|
|
84
|
+
/**
|
|
85
|
+
* Removes any existing highlights from the map.
|
|
86
|
+
*/
|
|
87
|
+
removeHighlight(): void;
|
|
55
88
|
}
|
|
56
89
|
/** Events emitted by the {@link LayerCollection}. */
|
|
57
90
|
export interface LayerCollectionEvents {
|
package/api/MapRegistry.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type OlMap from "ol/Map";
|
|
2
2
|
import type { MapConfig } from "./MapConfig";
|
|
3
3
|
import type { MapModel } from "./MapModel";
|
|
4
|
+
import type { DeclaredService } from "@open-pioneer/runtime";
|
|
4
5
|
/**
|
|
5
6
|
* Provides access to registered map instances.
|
|
6
7
|
*
|
|
@@ -8,7 +9,7 @@ import type { MapModel } from "./MapModel";
|
|
|
8
9
|
*
|
|
9
10
|
* Inject an instance of this service by referencing the interface name `"map.MapRegistry"`.
|
|
10
11
|
*/
|
|
11
|
-
export interface MapRegistry {
|
|
12
|
+
export interface MapRegistry extends DeclaredService<"map.MapRegistry"> {
|
|
12
13
|
/**
|
|
13
14
|
* Returns the map model associated with the given id.
|
|
14
15
|
* Returns undefined if there is no such model.
|
|
@@ -45,10 +46,3 @@ export interface MapConfigProvider {
|
|
|
45
46
|
*/
|
|
46
47
|
getMapConfig(): Promise<MapConfig>;
|
|
47
48
|
}
|
|
48
|
-
import "@open-pioneer/runtime";
|
|
49
|
-
declare module "@open-pioneer/runtime" {
|
|
50
|
-
interface ServiceRegistry {
|
|
51
|
-
"map.MapRegistry": MapRegistry;
|
|
52
|
-
"map.MapConfigProvider": MapConfigProvider;
|
|
53
|
-
}
|
|
54
|
-
}
|
package/api/index.d.ts
CHANGED
|
@@ -9,4 +9,5 @@ export { useCenter, useProjection, useResolution, useScale } from "../ui/hooks";
|
|
|
9
9
|
export { MapAnchor, type MapAnchorProps, type MapAnchorPosition } from "../ui/MapAnchor";
|
|
10
10
|
export { MapContainer, type MapContainerProps, type MapPadding } from "../ui/MapContainer";
|
|
11
11
|
export { useMapModel, type UseMapModelResult, type UseMapModelLoading, type UseMapModelResolved, type UseMapModelRejected } from "../ui/useMapModel";
|
|
12
|
+
export { calculateBufferedExtent } from "../util/geometry-utils";
|
|
12
13
|
export { TOPMOST_LAYER_Z } from "../model/LayerCollectionImpl";
|
package/api/layers/WMSLayer.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { Options as WMSSourceOptions } from "ol/source/ImageWMS";
|
|
2
|
-
import type { LayerBaseConfig, Layer, SublayersCollection } from "./base";
|
|
2
|
+
import type { LayerBaseConfig, Layer, SublayersCollection, LayerConfig } from "./base";
|
|
3
3
|
/**
|
|
4
4
|
* Configuration options to construct a WMS layer.
|
|
5
5
|
*/
|
|
6
|
-
export interface WMSLayerConfig extends
|
|
6
|
+
export interface WMSLayerConfig extends LayerConfig {
|
|
7
7
|
/** URL of the WMS service. */
|
|
8
8
|
url: string;
|
|
9
9
|
/** Configures the layer's sublayers. */
|
|
@@ -12,7 +12,7 @@ export interface WMSLayerConfig extends LayerBaseConfig {
|
|
|
12
12
|
* Additional source options for the layer's WMS source.
|
|
13
13
|
*
|
|
14
14
|
* NOTE: These options are intended for advanced configuration:
|
|
15
|
-
* the WMS Layer manages some of the
|
|
15
|
+
* the WMS Layer manages some of the OpenLayers source options itself.
|
|
16
16
|
*/
|
|
17
17
|
sourceOptions?: Partial<WMSSourceOptions>;
|
|
18
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WMSLayer.js","sources":["WMSLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport { WMSLayerImpl } from \"../../model/layers/WMSLayerImpl\";\nimport type { LayerBaseConfig, Layer, SublayersCollection } from \"./base\";\n\n/**\n * Configuration options to construct a WMS layer.\n */\nexport interface WMSLayerConfig extends
|
|
1
|
+
{"version":3,"file":"WMSLayer.js","sources":["WMSLayer.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport type { Options as WMSSourceOptions } from \"ol/source/ImageWMS\";\nimport { WMSLayerImpl } from \"../../model/layers/WMSLayerImpl\";\nimport type { LayerBaseConfig, Layer, SublayersCollection, LayerConfig } from \"./base\";\n\n/**\n * Configuration options to construct a WMS layer.\n */\nexport interface WMSLayerConfig extends LayerConfig {\n /** URL of the WMS service. */\n url: string;\n\n /** Configures the layer's sublayers. */\n sublayers?: WMSSublayerConfig[];\n\n /**\n * Additional source options for the layer's WMS source.\n *\n * NOTE: These options are intended for advanced configuration:\n * the WMS Layer manages some of the OpenLayers source options itself.\n */\n sourceOptions?: Partial<WMSSourceOptions>;\n}\n\n/**\n * Configuration options to construct the sublayers of a WMS layer.\n */\nexport interface WMSSublayerConfig extends LayerBaseConfig {\n /** The name of the WMS sublayer in the service's capabilities. */\n name: string;\n\n /** Configuration for nested sublayers. */\n sublayers?: WMSSublayerConfig[];\n}\n\n/** Represents a WMS layer. */\nexport interface WMSLayer extends Layer {\n readonly sublayers: SublayersCollection;\n\n /** The URL of the WMS service that was used during layer construction. */\n readonly url: string;\n}\n\n/**\n * Constructor for {@link WMSLayer}.\n */\nexport interface WMSLayerConstructor {\n prototype: WMSLayer;\n\n /** Creates a new {@link WMSLayer}. */\n new (config: WMSLayerConfig): WMSLayer;\n}\n\nexport const WMSLayer: WMSLayerConstructor = WMSLayerImpl;\n"],"names":[],"mappings":";;AAsDO,MAAM,QAAgC,GAAA;;;;"}
|
package/api/layers/base.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export interface LayerBaseEvents {
|
|
|
14
14
|
}
|
|
15
15
|
/** The load state of a layer. */
|
|
16
16
|
export type LayerLoadState = "not-loaded" | "loading" | "loaded" | "error";
|
|
17
|
+
/** Custom function to check the state of a layer and returning a "loaded" or "error". */
|
|
18
|
+
export type HealthCheckFunction = (layer: LayerBase) => Promise<"loaded" | "error">;
|
|
17
19
|
/**
|
|
18
20
|
* Configuration options supported by all layer types (layers and sublayers).
|
|
19
21
|
*/
|
|
@@ -116,6 +118,12 @@ export interface LayerConfig extends LayerBaseConfig {
|
|
|
116
118
|
* Defaults to `false`.
|
|
117
119
|
*/
|
|
118
120
|
isBaseLayer?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Optional property to check the availability of the layer.
|
|
123
|
+
* It is possible to provide either a URL which indicates the state of the service (2xx response meaning "ok")
|
|
124
|
+
* or a {@link HealthCheckFunction} performing a custom check and returning the state.
|
|
125
|
+
*/
|
|
126
|
+
healthCheck?: string | HealthCheckFunction;
|
|
119
127
|
}
|
|
120
128
|
/**
|
|
121
129
|
* Represents an operational layer in the map.
|
|
Binary file
|
package/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import '@open-pioneer/runtime';
|
|
2
1
|
export { SimpleLayer } from './api/layers/SimpleLayer.js';
|
|
3
2
|
export { WMSLayer } from './api/layers/WMSLayer.js';
|
|
4
3
|
export { getProjection, registerProjections } from './projections.js';
|
|
@@ -7,5 +6,6 @@ export { useCenter, useProjection, useResolution, useScale } from './ui/hooks.js
|
|
|
7
6
|
export { MapAnchor } from './ui/MapAnchor.js';
|
|
8
7
|
export { MapContainer } from './ui/MapContainer.js';
|
|
9
8
|
export { useMapModel } from './ui/useMapModel.js';
|
|
9
|
+
export { calculateBufferedExtent } from './util/geometry-utils.js';
|
|
10
10
|
export { TOPMOST_LAYER_Z } from './model/LayerCollectionImpl.js';
|
|
11
11
|
//# sourceMappingURL=index.js.map
|
package/layers/BkgTopPlusOpen.js
CHANGED
|
@@ -52,7 +52,7 @@ class BkgTopPlusOpen extends WMTS {
|
|
|
52
52
|
matrixIds
|
|
53
53
|
}),
|
|
54
54
|
style: "default",
|
|
55
|
-
attributions: `Kartendarstellung und Pr\xE4sentationsgraphiken: \xA9 Bundesamt f\xFCr Kartographie und Geod\xE4sie ${( new Date()).getFullYear()}, <a href="https://sg.geodatenzentrum.de/web_public/gdz/datenquellen/Datenquellen_TopPlusOpen.html" target="_blank">Datenquellen</a>`
|
|
55
|
+
attributions: `Kartendarstellung und Pr\xE4sentationsgraphiken: \xA9 Bundesamt f\xFCr Kartographie und Geod\xE4sie ${(/* @__PURE__ */ new Date()).getFullYear()}, <a href="https://sg.geodatenzentrum.de/web_public/gdz/datenquellen/Datenquellen_TopPlusOpen.html" target="_blank">Datenquellen</a>`
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BkgTopPlusOpen.js","sources":["BkgTopPlusOpen.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport WMTS from \"ol/source/WMTS\";\nimport WMTSTileGrid from \"ol/tilegrid/WMTS\";\n\n/** @internal */\nexport interface BkgTopPlusOpenProps {\n /**\n * The name of the requesting layer.\n * @default \"web\"\n */\n layer?: \"web\" | \"web_grau\" | \"web_light\";\n}\n\n/**\n * Layer source for BKG TopPlus Open.\n *\n * Used for @open-pioneer unit tests: not part of the public interface.\n *\n * @see https://gdz.bkg.bund.de/index.php/default/wmts-topplusopen-wmts-topplus-open.html\n *\n * @internal\n */\nexport class BkgTopPlusOpen extends WMTS {\n constructor(options?: BkgTopPlusOpenProps) {\n const topLeftCorner = [-3803165.98427299, 8805908.08284866];\n\n /**\n * Resolutions taken from AdV WMTS-Profil\n * @see https://www.adv-online.de/AdV-Produkte/Standards-und-Produktblaetter/AdV-Profile/\n */\n const resolutions = [\n 4891.96981025128, // AdV-Level 0 (1:17471320.7508974)\n 2445.98490512564, // AdV-Level 1 (1:8735660.37544872)\n 1222.99245256282, // AdV-Level 2 (1:4367830.18772436)\n 611.49622628141, // AdV-Level 3 (1:2183915.09386218)\n 305.748113140705, // AdV-Level 4 (1:1091957.54693109)\n 152.874056570353, // AdV-Level 5 (1:545978.773465545)\n 76.4370282851763, // AdV-Level 6 (1:272989,386732772)\n 38.2185141425881, // AdV-Level 7 (1:136494,693366386)\n 19.1092570712941, // AdV-Level 8 (1:68247,3466831931)\n 9.55462853564703, // AdV-Level 9 (1:34123,6733415966)\n 4.77731426782352, // AdV-Level 10 (1:17061,8366707983)\n 2.38865713391176, // AdV-Level 11 (1:8530,91833539914)\n 1.19432856695588, // AdV-Level 12 (1:4265,45916769957)\n 0.59716428347794 // AdV-Level 13 (1:2132,72958384978)\n ];\n\n /**\n * The length of matrixIds needs to match the length of the resolutions array\n * @see https://openlayers.org/en/latest/apidoc/module-ol_tilegrid_WMTS-WMTSTileGrid.html\n */\n const matrixIds = new Array(resolutions.length);\n for (let i = 0; i < resolutions.length; i++) {\n matrixIds[i] = i;\n }\n\n const layer = options?.layer ?? \"web\";\n\n super({\n url: `https://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/${layer}/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png`,\n layer: layer,\n matrixSet: \"EU_EPSG_25832_TOPPLUS\",\n format: \"image/png\",\n projection: \"EPSG:25832\",\n requestEncoding: \"REST\",\n tileGrid: new WMTSTileGrid({\n origin: topLeftCorner,\n resolutions: resolutions,\n matrixIds: matrixIds\n }),\n style: \"default\",\n attributions: `Kartendarstellung und Präsentationsgraphiken: © Bundesamt für Kartographie und Geodäsie ${new Date().getFullYear()}, <a href=\"https://sg.geodatenzentrum.de/web_public/gdz/datenquellen/Datenquellen_TopPlusOpen.html\" target=\"_blank\">Datenquellen</a>`\n });\n }\n}\n"],"names":[],"mappings":";;;AAuBO,MAAM,uBAAuB,IAAK,CAAA;AAAA,EACrC,YAAY,OAA+B,EAAA;AACvC,IAAM,MAAA,aAAA,GAAgB,CAAC,CAAA,kBAAA,EAAmB,kBAAgB,CAAA,CAAA;AAM1D,IAAA,MAAM,WAAc,GAAA;AAAA,MAChB,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,eAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,KACJ,CAAA;AAMA,IAAA,MAAM,SAAY,GAAA,IAAI,KAAM,CAAA,WAAA,CAAY,MAAM,CAAA,CAAA;AAC9C,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,CAAY,QAAQ,CAAK,EAAA,EAAA;AACzC,MAAA,SAAA,CAAU,CAAC,CAAI,GAAA,CAAA,CAAA;AAAA,KACnB;AAEA,IAAM,MAAA,KAAA,GAAQ,SAAS,KAAS,IAAA,KAAA,CAAA;AAEhC,IAAM,KAAA,CAAA;AAAA,MACF,GAAA,EAAK,+DAA+D,KAAK,CAAA,6DAAA,CAAA;AAAA,MACzE,KAAA;AAAA,MACA,SAAW,EAAA,uBAAA;AAAA,MACX,MAAQ,EAAA,WAAA;AAAA,MACR,UAAY,EAAA,YAAA;AAAA,MACZ,eAAiB,EAAA,MAAA;AAAA,MACjB,QAAA,EAAU,IAAI,YAAa,CAAA;AAAA,QACvB,MAAQ,EAAA,aAAA;AAAA,QACR,WAAA;AAAA,QACA,SAAA;AAAA,OACH,CAAA;AAAA,MACD,KAAO,EAAA,SAAA;AAAA,MACP,cAAc,CAA2F,oGAAA,EAAA,
|
|
1
|
+
{"version":3,"file":"BkgTopPlusOpen.js","sources":["BkgTopPlusOpen.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport WMTS from \"ol/source/WMTS\";\nimport WMTSTileGrid from \"ol/tilegrid/WMTS\";\n\n/** @internal */\nexport interface BkgTopPlusOpenProps {\n /**\n * The name of the requesting layer.\n * @default \"web\"\n */\n layer?: \"web\" | \"web_grau\" | \"web_light\";\n}\n\n/**\n * Layer source for BKG TopPlus Open.\n *\n * Used for @open-pioneer unit tests: not part of the public interface.\n *\n * @see https://gdz.bkg.bund.de/index.php/default/wmts-topplusopen-wmts-topplus-open.html\n *\n * @internal\n */\nexport class BkgTopPlusOpen extends WMTS {\n constructor(options?: BkgTopPlusOpenProps) {\n const topLeftCorner = [-3803165.98427299, 8805908.08284866];\n\n /**\n * Resolutions taken from AdV WMTS-Profil\n * @see https://www.adv-online.de/AdV-Produkte/Standards-und-Produktblaetter/AdV-Profile/\n */\n const resolutions = [\n 4891.96981025128, // AdV-Level 0 (1:17471320.7508974)\n 2445.98490512564, // AdV-Level 1 (1:8735660.37544872)\n 1222.99245256282, // AdV-Level 2 (1:4367830.18772436)\n 611.49622628141, // AdV-Level 3 (1:2183915.09386218)\n 305.748113140705, // AdV-Level 4 (1:1091957.54693109)\n 152.874056570353, // AdV-Level 5 (1:545978.773465545)\n 76.4370282851763, // AdV-Level 6 (1:272989,386732772)\n 38.2185141425881, // AdV-Level 7 (1:136494,693366386)\n 19.1092570712941, // AdV-Level 8 (1:68247,3466831931)\n 9.55462853564703, // AdV-Level 9 (1:34123,6733415966)\n 4.77731426782352, // AdV-Level 10 (1:17061,8366707983)\n 2.38865713391176, // AdV-Level 11 (1:8530,91833539914)\n 1.19432856695588, // AdV-Level 12 (1:4265,45916769957)\n 0.59716428347794 // AdV-Level 13 (1:2132,72958384978)\n ];\n\n /**\n * The length of matrixIds needs to match the length of the resolutions array\n * @see https://openlayers.org/en/latest/apidoc/module-ol_tilegrid_WMTS-WMTSTileGrid.html\n */\n const matrixIds = new Array(resolutions.length);\n for (let i = 0; i < resolutions.length; i++) {\n matrixIds[i] = i;\n }\n\n const layer = options?.layer ?? \"web\";\n\n super({\n url: `https://sgx.geodatenzentrum.de/wmts_topplus_open/tile/1.0.0/${layer}/{Style}/{TileMatrixSet}/{TileMatrix}/{TileRow}/{TileCol}.png`,\n layer: layer,\n matrixSet: \"EU_EPSG_25832_TOPPLUS\",\n format: \"image/png\",\n projection: \"EPSG:25832\",\n requestEncoding: \"REST\",\n tileGrid: new WMTSTileGrid({\n origin: topLeftCorner,\n resolutions: resolutions,\n matrixIds: matrixIds\n }),\n style: \"default\",\n attributions: `Kartendarstellung und Präsentationsgraphiken: © Bundesamt für Kartographie und Geodäsie ${new Date().getFullYear()}, <a href=\"https://sg.geodatenzentrum.de/web_public/gdz/datenquellen/Datenquellen_TopPlusOpen.html\" target=\"_blank\">Datenquellen</a>`\n });\n }\n}\n"],"names":[],"mappings":";;;AAuBO,MAAM,uBAAuB,IAAK,CAAA;AAAA,EACrC,YAAY,OAA+B,EAAA;AACvC,IAAM,MAAA,aAAA,GAAgB,CAAC,CAAA,kBAAA,EAAmB,kBAAgB,CAAA,CAAA;AAM1D,IAAA,MAAM,WAAc,GAAA;AAAA,MAChB,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,eAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MACA,gBAAA;AAAA;AAAA,KACJ,CAAA;AAMA,IAAA,MAAM,SAAY,GAAA,IAAI,KAAM,CAAA,WAAA,CAAY,MAAM,CAAA,CAAA;AAC9C,IAAA,KAAA,IAAS,CAAI,GAAA,CAAA,EAAG,CAAI,GAAA,WAAA,CAAY,QAAQ,CAAK,EAAA,EAAA;AACzC,MAAA,SAAA,CAAU,CAAC,CAAI,GAAA,CAAA,CAAA;AAAA,KACnB;AAEA,IAAM,MAAA,KAAA,GAAQ,SAAS,KAAS,IAAA,KAAA,CAAA;AAEhC,IAAM,KAAA,CAAA;AAAA,MACF,GAAA,EAAK,+DAA+D,KAAK,CAAA,6DAAA,CAAA;AAAA,MACzE,KAAA;AAAA,MACA,SAAW,EAAA,uBAAA;AAAA,MACX,MAAQ,EAAA,WAAA;AAAA,MACR,UAAY,EAAA,YAAA;AAAA,MACZ,eAAiB,EAAA,MAAA;AAAA,MACjB,QAAA,EAAU,IAAI,YAAa,CAAA;AAAA,QACvB,MAAQ,EAAA,aAAA;AAAA,QACR,WAAA;AAAA,QACA,SAAA;AAAA,OACH,CAAA;AAAA,MACD,KAAO,EAAA,SAAA;AAAA,MACP,cAAc,CAA2F,oGAAA,EAAA,iBAAA,IAAI,IAAK,EAAA,EAAE,aAAa,CAAA,oIAAA,CAAA;AAAA,KACpI,CAAA,CAAA;AAAA,GACL;AACJ;;;;"}
|
package/model/AbstractLayer.js
CHANGED
|
@@ -7,6 +7,7 @@ const LOG = createLogger("map:AbstractLayer");
|
|
|
7
7
|
class AbstractLayer extends AbstractLayerBase {
|
|
8
8
|
#olLayer;
|
|
9
9
|
#isBaseLayer;
|
|
10
|
+
#healthCheck;
|
|
10
11
|
#visible;
|
|
11
12
|
#loadState;
|
|
12
13
|
#stateWatchResource;
|
|
@@ -14,16 +15,9 @@ class AbstractLayer extends AbstractLayerBase {
|
|
|
14
15
|
super(config);
|
|
15
16
|
this.#olLayer = config.olLayer;
|
|
16
17
|
this.#isBaseLayer = config.isBaseLayer ?? false;
|
|
18
|
+
this.#healthCheck = config.healthCheck;
|
|
17
19
|
this.#visible = config.visible ?? true;
|
|
18
|
-
|
|
19
|
-
this.#olLayer,
|
|
20
|
-
(state) => {
|
|
21
|
-
this.#loadState = state;
|
|
22
|
-
this.__emitChangeEvent("changed:loadState");
|
|
23
|
-
}
|
|
24
|
-
);
|
|
25
|
-
this.#loadState = initialState;
|
|
26
|
-
this.#stateWatchResource = stateWatchResource;
|
|
20
|
+
this.#loadState = getSourceState(getSource(this.#olLayer));
|
|
27
21
|
}
|
|
28
22
|
get visible() {
|
|
29
23
|
return this.#visible;
|
|
@@ -50,6 +44,15 @@ class AbstractLayer extends AbstractLayerBase {
|
|
|
50
44
|
*/
|
|
51
45
|
__attach(map) {
|
|
52
46
|
super.__attachToMap(map);
|
|
47
|
+
const { initial: initialState, resource: stateWatchResource } = watchLoadState(
|
|
48
|
+
this,
|
|
49
|
+
this.#healthCheck,
|
|
50
|
+
(state) => {
|
|
51
|
+
this.#setLoadState(state);
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
this.#stateWatchResource = stateWatchResource;
|
|
55
|
+
this.#setLoadState(initialState);
|
|
53
56
|
}
|
|
54
57
|
setVisible(newVisibility) {
|
|
55
58
|
if (this.isBaseLayer) {
|
|
@@ -71,8 +74,15 @@ class AbstractLayer extends AbstractLayerBase {
|
|
|
71
74
|
}
|
|
72
75
|
changed && this.__emitChangeEvent("changed:visible");
|
|
73
76
|
}
|
|
77
|
+
#setLoadState(loadState) {
|
|
78
|
+
if (loadState !== this.#loadState) {
|
|
79
|
+
this.#loadState = loadState;
|
|
80
|
+
this.__emitChangeEvent("changed:loadState");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
74
83
|
}
|
|
75
|
-
function watchLoadState(
|
|
84
|
+
function watchLoadState(layer, healthCheck, onChange) {
|
|
85
|
+
const olLayer = layer.olLayer;
|
|
76
86
|
if (!(olLayer instanceof OlLayer)) {
|
|
77
87
|
return {
|
|
78
88
|
initial: "loaded",
|
|
@@ -82,10 +92,19 @@ function watchLoadState(olLayer, onChange) {
|
|
|
82
92
|
}
|
|
83
93
|
};
|
|
84
94
|
}
|
|
85
|
-
let currentSource =
|
|
86
|
-
|
|
95
|
+
let currentSource = getSource(olLayer);
|
|
96
|
+
const currentOlLayerState = getSourceState(currentSource);
|
|
97
|
+
let currentLoadState = currentOlLayerState;
|
|
98
|
+
let currentHealthState = "loading";
|
|
99
|
+
if (currentOlLayerState !== "error") {
|
|
100
|
+
doHealthCheck(layer, healthCheck).then((state) => {
|
|
101
|
+
currentHealthState = state;
|
|
102
|
+
updateState();
|
|
103
|
+
});
|
|
104
|
+
}
|
|
87
105
|
const updateState = () => {
|
|
88
|
-
const
|
|
106
|
+
const olLayerState = getSourceState(currentSource);
|
|
107
|
+
const nextLoadState = currentHealthState === "error" ? "error" : olLayerState;
|
|
89
108
|
if (currentLoadState !== nextLoadState) {
|
|
90
109
|
currentLoadState = nextLoadState;
|
|
91
110
|
onChange(currentLoadState);
|
|
@@ -98,7 +117,7 @@ function watchLoadState(olLayer, onChange) {
|
|
|
98
117
|
const sourceHandle = olLayer.on("change:source", () => {
|
|
99
118
|
stateHandle && unByKey(stateHandle);
|
|
100
119
|
stateHandle = void 0;
|
|
101
|
-
currentSource =
|
|
120
|
+
currentSource = getSource(olLayer);
|
|
102
121
|
stateHandle = currentSource?.on("change", () => {
|
|
103
122
|
updateState();
|
|
104
123
|
});
|
|
@@ -114,7 +133,47 @@ function watchLoadState(olLayer, onChange) {
|
|
|
114
133
|
}
|
|
115
134
|
};
|
|
116
135
|
}
|
|
117
|
-
function
|
|
136
|
+
async function doHealthCheck(layer, healthCheck) {
|
|
137
|
+
if (healthCheck == null) {
|
|
138
|
+
return "loaded";
|
|
139
|
+
}
|
|
140
|
+
let healthCheckFn;
|
|
141
|
+
if (typeof healthCheck === "function") {
|
|
142
|
+
healthCheckFn = healthCheck;
|
|
143
|
+
} else if (typeof healthCheck === "string") {
|
|
144
|
+
healthCheckFn = async () => {
|
|
145
|
+
const httpService = layer.map.__sharedDependencies.httpService;
|
|
146
|
+
const response = await httpService.fetch(healthCheck);
|
|
147
|
+
if (response.ok) {
|
|
148
|
+
return "loaded";
|
|
149
|
+
}
|
|
150
|
+
LOG.warn(
|
|
151
|
+
`Health check failed for layer '${layer.id}' (http status ${response.status})`
|
|
152
|
+
);
|
|
153
|
+
return "error";
|
|
154
|
+
};
|
|
155
|
+
} else {
|
|
156
|
+
LOG.error(
|
|
157
|
+
`Unexpected object for 'healthCheck' parameter of layer '${layer.id}'`,
|
|
158
|
+
healthCheck
|
|
159
|
+
);
|
|
160
|
+
return "error";
|
|
161
|
+
}
|
|
162
|
+
try {
|
|
163
|
+
return await healthCheckFn(layer);
|
|
164
|
+
} catch (e) {
|
|
165
|
+
LOG.warn(`Health check failed for layer '${layer.id}'`, e);
|
|
166
|
+
return "error";
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function getSource(olLayer) {
|
|
170
|
+
if (!(olLayer instanceof OlLayer)) {
|
|
171
|
+
return void 0;
|
|
172
|
+
}
|
|
173
|
+
return olLayer?.getSource() ?? void 0;
|
|
174
|
+
}
|
|
175
|
+
function getSourceState(olSource) {
|
|
176
|
+
const state = olSource?.getState();
|
|
118
177
|
switch (state) {
|
|
119
178
|
case void 0:
|
|
120
179
|
return "loaded";
|