@masterportal/masterportalapi 2.7.0 → 2.9.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 +25 -0
- package/README.md +7 -0
- package/example/config/services.json +1 -1
- package/example/index.js +17 -2
- package/package.json +1 -1
- package/src/crs.js +17 -7
- package/src/index.js +2 -0
- package/src/layer/wms.js +2 -2
- package/src/lib/ping.js +63 -0
- package/src/maps/map.js +1 -0
- package/src/maps/ol/olMap.js +57 -8
- package/src/rawLayerList.js +12 -4
- package/test/layer/wmts.test.js +1 -1
- package/test/lib/ping.test.js +69 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,13 +5,38 @@
|
|
|
5
5
|
|
|
6
6
|
## Unreleased - in development
|
|
7
7
|
### Added
|
|
8
|
+
|
|
8
9
|
### Changed
|
|
9
10
|
|
|
10
11
|
### Deprecated
|
|
11
12
|
|
|
12
13
|
### Removed
|
|
14
|
+
|
|
13
15
|
### Fixed
|
|
14
16
|
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## 2.9.0 - 2022-10-25
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- Exports in src/rawLayerList and src/crs.js changed to module.exports to provide the possibility to stub the functions with sinon in masterportal.
|
|
24
|
+
|
|
25
|
+
### Deprecated
|
|
26
|
+
|
|
27
|
+
### Removed
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 2.8.0 - 2022-10-04
|
|
34
|
+
### Added
|
|
35
|
+
- Issue #814: Adding optional error callbacks and availability detection to layers.
|
|
36
|
+
- Added possibility to set initial features for layer vectorBase.
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
15
40
|
## 2.7.0 - 2022-09-14
|
|
16
41
|
### Changed
|
|
17
42
|
- The following packages have been updated:
|
package/README.md
CHANGED
|
@@ -10,6 +10,13 @@ If you want to create a 3d map, you have to provide the peer dependency cesium.
|
|
|
10
10
|
|
|
11
11
|
By importing the project by module name like ``import ... from "masterportalAPI"``, most bundlers and bundler configurations will include the whole masterportalAPI. If you only need a subset of the provided functions and want to keep your build clean, directly import the needed functions like ``import {createMap} from "masterportalAPI/src/map.js``.
|
|
12
12
|
|
|
13
|
+
## Error Handling
|
|
14
|
+
|
|
15
|
+
1. Error event callback: The methods `createMap` and `addLayer` both optionally accept error event callbacks that are called with OpenLayers error events (tileloaderror, imageloaderror, featuresloaderror, error).
|
|
16
|
+
2. Ping: A method that returns a Promise. This resolves to the status code of the layer's GetCapabilities request, which can be used to decide if the service is reachable and usable at all.
|
|
17
|
+
|
|
18
|
+
Both methods may be required for useful user feedback. For example, a WMS may answer a tile request with 404 if no tile is available for a region, but may be fully available within its specification. This may throw an error while the service itself is available as specified. It is up to the using implementation how to react, how often to ping, and so on.
|
|
19
|
+
|
|
13
20
|
## Scripts
|
|
14
21
|
|
|
15
22
|
|Script|Effect|
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
{
|
|
48
48
|
"id": "4001",
|
|
49
49
|
"name": "Gelaende",
|
|
50
|
-
"url": "https://daten-hamburg.de/gdi3d/datasource-data/Gelaende
|
|
50
|
+
"url": "https://daten-hamburg.de/gdi3d/datasource-data/Gelaende",
|
|
51
51
|
"typ": "Terrain3D",
|
|
52
52
|
"cesiumTerrainProviderOptions": {
|
|
53
53
|
"requestVertexNormals": true
|
package/example/index.js
CHANGED
|
@@ -11,6 +11,10 @@ import portalConfig from "./config/portal.json";
|
|
|
11
11
|
import localGeoJSON from "./config/localGeoJSON.js";
|
|
12
12
|
import {load3DScript} from "../src/lib/load3DScript";
|
|
13
13
|
|
|
14
|
+
function errorCallback (errorEvent) {
|
|
15
|
+
console.error("This is an error event:", errorEvent);
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
//* Add elements to window to play with API in console
|
|
15
19
|
window.mpapi = {
|
|
16
20
|
...mpapi,
|
|
@@ -94,7 +98,7 @@ document.getElementById("layer-visibility").addEventListener("click", function (
|
|
|
94
98
|
});
|
|
95
99
|
});
|
|
96
100
|
|
|
97
|
-
map2D = mapsAPI.map.createMap(config, "2D");
|
|
101
|
+
map2D = mapsAPI.map.createMap(config, "2D", {errorCallback});
|
|
98
102
|
services.push(localService);
|
|
99
103
|
// */
|
|
100
104
|
|
|
@@ -148,7 +152,18 @@ services.find(({id}) => id === "5001").style = styleOaf;
|
|
|
148
152
|
//* SYNCHRONOUS EXAMPLE: layerConf is known
|
|
149
153
|
window.mpapi.map = map2D;
|
|
150
154
|
|
|
151
|
-
["2001", "2002", "1002", "3001", "5001"].forEach(id => window.mpapi.map.addLayer(id));
|
|
155
|
+
["2001", "2002", "1002", "3001", "5001"].forEach(id => window.mpapi.map.addLayer(id, {errorCallback}));
|
|
156
|
+
|
|
157
|
+
// ping all layers
|
|
158
|
+
services
|
|
159
|
+
.map(service => ({
|
|
160
|
+
ping: mpapi.ping(service),
|
|
161
|
+
service
|
|
162
|
+
}))
|
|
163
|
+
.forEach(({ping, service}) => ping
|
|
164
|
+
// eslint-disable-next-line no-console
|
|
165
|
+
.then(statusCode => console.log(`Service ${service.id} pinged; returned ${statusCode}.`))
|
|
166
|
+
.catch(console.error));
|
|
152
167
|
|
|
153
168
|
// */
|
|
154
169
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masterportal/masterportalapi",
|
|
3
3
|
"author": "Implementierungspartnerschaft Masterportal <info@masterportal.org> (https://www.masterportal.org)",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.9.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Basic functions of the Masterportal as api",
|
|
7
7
|
"repository": {
|
package/src/crs.js
CHANGED
|
@@ -22,7 +22,7 @@ function addAliasForWFSFromGeoserver (epsgCode) {
|
|
|
22
22
|
* @param {string} name - projection name as written in [0] position of namedProjections
|
|
23
23
|
* @returns {(object|undefined)} proj4 projection object or undefined
|
|
24
24
|
*/
|
|
25
|
-
|
|
25
|
+
function getProjection (name) {
|
|
26
26
|
return proj4.defs(name);
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -33,7 +33,7 @@ export function getProjection (name) {
|
|
|
33
33
|
]] - projection name, projection definition string
|
|
34
34
|
* @returns {undefined}
|
|
35
35
|
*/
|
|
36
|
-
|
|
36
|
+
function registerProjections (namedProjections = defaults.namedProjections) {
|
|
37
37
|
proj4.defs(namedProjections);
|
|
38
38
|
register(proj4);
|
|
39
39
|
namedProjections.forEach(projection => {
|
|
@@ -48,7 +48,7 @@ export function registerProjections (namedProjections = defaults.namedProjection
|
|
|
48
48
|
* Returns all known projections.
|
|
49
49
|
* @returns {object[]} array of projection objects with their name added
|
|
50
50
|
*/
|
|
51
|
-
|
|
51
|
+
function getProjections () {
|
|
52
52
|
const projections = Object
|
|
53
53
|
.keys(proj4.defs)
|
|
54
54
|
.map(name => Object.assign(proj4.defs(name), {name}));
|
|
@@ -64,7 +64,7 @@ export function getProjections () {
|
|
|
64
64
|
* @param {ol.Map} map - map to get projection of
|
|
65
65
|
* @returns {string} active projection name of map
|
|
66
66
|
*/
|
|
67
|
-
|
|
67
|
+
function getMapProjection (map) {
|
|
68
68
|
return map.getView().getProjection().getCode();
|
|
69
69
|
}
|
|
70
70
|
|
|
@@ -87,7 +87,7 @@ function getProj4Projection (projection) {
|
|
|
87
87
|
* @param {number[]} point - point to project
|
|
88
88
|
* @returns {number[]|undefined} transformed point
|
|
89
89
|
*/
|
|
90
|
-
|
|
90
|
+
function transform (sourceProjection, targetProjection, point) {
|
|
91
91
|
const source = getProj4Projection(sourceProjection),
|
|
92
92
|
target = getProj4Projection(targetProjection);
|
|
93
93
|
|
|
@@ -106,7 +106,7 @@ export function transform (sourceProjection, targetProjection, point) {
|
|
|
106
106
|
* @param {number[]} point - point to project
|
|
107
107
|
* @returns {number[]|undefined} new point or undefined
|
|
108
108
|
*/
|
|
109
|
-
|
|
109
|
+
function transformToMapProjection (map, sourceProjection, point) {
|
|
110
110
|
return transform(sourceProjection, getMapProjection(map), point);
|
|
111
111
|
}
|
|
112
112
|
|
|
@@ -117,6 +117,16 @@ export function transformToMapProjection (map, sourceProjection, point) {
|
|
|
117
117
|
* @param {number[]} point - point to project
|
|
118
118
|
* @returns {(number[]|undefined)} new point or undefined
|
|
119
119
|
*/
|
|
120
|
-
|
|
120
|
+
function transformFromMapProjection (map, targetProjection, point) {
|
|
121
121
|
return transform(getMapProjection(map), targetProjection, point);
|
|
122
122
|
}
|
|
123
|
+
|
|
124
|
+
module.exports = {
|
|
125
|
+
transformFromMapProjection,
|
|
126
|
+
transformToMapProjection,
|
|
127
|
+
transform,
|
|
128
|
+
getMapProjection,
|
|
129
|
+
getProjections,
|
|
130
|
+
registerProjections,
|
|
131
|
+
getProjection
|
|
132
|
+
};
|
package/src/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import Tileset from "./layer/tileset";
|
|
|
14
14
|
import * as layerLib from "./layer/lib";
|
|
15
15
|
import {search, setGazetteerUrl} from "./searchAddress";
|
|
16
16
|
import setBackgroundImage from "./lib/setBackgroundImage";
|
|
17
|
+
import ping from "./lib/ping";
|
|
17
18
|
|
|
18
19
|
export {
|
|
19
20
|
createMapView,
|
|
@@ -31,6 +32,7 @@ export {
|
|
|
31
32
|
setBackgroundImage,
|
|
32
33
|
setGazetteerUrl,
|
|
33
34
|
rawLayerList,
|
|
35
|
+
ping,
|
|
34
36
|
search,
|
|
35
37
|
crs
|
|
36
38
|
};
|
package/src/layer/wms.js
CHANGED
|
@@ -5,7 +5,7 @@ import TileGrid from "ol/tilegrid/TileGrid";
|
|
|
5
5
|
import ImageWMS from "ol/source/ImageWMS.js";
|
|
6
6
|
import {get as getProjection} from "ol/proj";
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {rawLayerList} from "../index.js";
|
|
9
9
|
|
|
10
10
|
const OLCS_DEFAULT_OLCS_PROJECTION_CRS = "EPSG:3857";
|
|
11
11
|
|
|
@@ -176,7 +176,7 @@ export function updateSource (layer) {
|
|
|
176
176
|
* @returns {(string|undefined)} the gfiURL, or undefined if it could not be constructed
|
|
177
177
|
*/
|
|
178
178
|
export function getGfiURL (layer, map, coordinate) {
|
|
179
|
-
const rawLayer = getLayerWhere({Id: layer.get("id")}),
|
|
179
|
+
const rawLayer = rawLayerList.getLayerWhere({Id: layer.get("id")}),
|
|
180
180
|
resolution = map.getView().getResolution(),
|
|
181
181
|
projection = map.getView().getProjection(),
|
|
182
182
|
params = Object.assign({
|
package/src/lib/ping.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper function to detect layer availability/usability. Depending on layer
|
|
3
|
+
* type, the method to infer availability broadly varies.
|
|
4
|
+
* @param {Object} layerSpecification services.json layer specification
|
|
5
|
+
* @returns {Promise} resolves to status code of a layer-specific default
|
|
6
|
+
* request as Number, or null if no request could be made, which should
|
|
7
|
+
* indicate misconfiguration; defaults to 900 if the request itself failed for
|
|
8
|
+
* arbitrary reasons (usually CORS-related)
|
|
9
|
+
*/
|
|
10
|
+
export default function ({url, typ, capabilitiesUrl, ...rest}) {
|
|
11
|
+
const statusCheckUrls = [];
|
|
12
|
+
|
|
13
|
+
if (capabilitiesUrl) {
|
|
14
|
+
statusCheckUrls.push(capabilitiesUrl);
|
|
15
|
+
}
|
|
16
|
+
else if (typ === "OAF") {
|
|
17
|
+
statusCheckUrls.push(url);
|
|
18
|
+
}
|
|
19
|
+
else if (typ === "Entities3D") {
|
|
20
|
+
rest.entities
|
|
21
|
+
.forEach(entity => entity.url ? statusCheckUrls.push(entity.url) : null);
|
|
22
|
+
}
|
|
23
|
+
else if (typ === "TileSet3D" || typ === "Terrain3D") {
|
|
24
|
+
statusCheckUrls.push(url);
|
|
25
|
+
}
|
|
26
|
+
else if (typ === "GeoJSON") {
|
|
27
|
+
if (!url && rest.features) {
|
|
28
|
+
// may be a local layer without source url – that's equal to 200
|
|
29
|
+
return Promise.resolve(200);
|
|
30
|
+
}
|
|
31
|
+
if (url) {
|
|
32
|
+
statusCheckUrls.push(url);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
else if (typ === "VectorTile") {
|
|
36
|
+
statusCheckUrls.push(url.replaceAll(/\{[xyz]\}/ig, "0"));
|
|
37
|
+
}
|
|
38
|
+
else if (typ === "WMTS") {
|
|
39
|
+
const arbitraryTileRequests = (url ? [url] : rest.urls)
|
|
40
|
+
.map(entry => entry
|
|
41
|
+
.replace(/\{Style\}/ig, rest.style)
|
|
42
|
+
.replace(/\{TileMatrixSet\}/ig, rest.tileMatrixSet)
|
|
43
|
+
.replaceAll(/\{(TileMatrix|TileRow|TileCol)\}/ig, "0"));
|
|
44
|
+
|
|
45
|
+
statusCheckUrls.push(...arbitraryTileRequests);
|
|
46
|
+
}
|
|
47
|
+
else if (url) {
|
|
48
|
+
statusCheckUrls.push(`${url}?service=${typ}&request=GetCapabilities`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (!statusCheckUrls.length) {
|
|
52
|
+
return Promise.resolve(null);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return Promise
|
|
56
|
+
.allSettled(statusCheckUrls
|
|
57
|
+
.map(statusCheckUrl => new Promise((resolve) => fetch(statusCheckUrl, {method: "HEAD"})
|
|
58
|
+
.then(({status}) => resolve(status))
|
|
59
|
+
// usually from CORS, treated as 900 here ("proprietary" status code)
|
|
60
|
+
.catch(() => resolve(900)))))
|
|
61
|
+
// return highest status code (will indicate erroneous behaviour)
|
|
62
|
+
.then(codes => Math.max(...codes.map(({value}) => value)));
|
|
63
|
+
}
|
package/src/maps/map.js
CHANGED
|
@@ -20,6 +20,7 @@ export default {
|
|
|
20
20
|
* @param {object} [settings={}] - settings object
|
|
21
21
|
* @param {object} [settings.mapParams] - additional parameter object that is spread into the ol.Map constructor object
|
|
22
22
|
* @param {function} [settings.callback] - optional callback for layer list loading
|
|
23
|
+
* @param {function} [settings.errorCallback] - optional callback for layer error events
|
|
23
24
|
* @returns {module:ol/Map~Map} The map.
|
|
24
25
|
*/
|
|
25
26
|
createMap: function (config, mapMode = "2D", settings = {}) {
|
package/src/maps/ol/olMap.js
CHANGED
|
@@ -11,7 +11,7 @@ import * as vectorBase from "../../layer/vectorBase";
|
|
|
11
11
|
import * as vectortile from "../../layer/vectorTile";
|
|
12
12
|
import * as oaf from "../../layer/oaf";
|
|
13
13
|
import {createMapView} from "../../maps/mapView";
|
|
14
|
-
import {
|
|
14
|
+
import {rawLayerList} from "../../index.js";
|
|
15
15
|
import {registerProjections} from "../../crs";
|
|
16
16
|
import {setGazetteerUrl} from "../../searchAddress";
|
|
17
17
|
|
|
@@ -32,6 +32,48 @@ const layerBuilderMap = {
|
|
|
32
32
|
},
|
|
33
33
|
originalAddLayer = Map.prototype.addLayer;
|
|
34
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Flattens a Layer/LayerGroup to an array of non-group instances.
|
|
37
|
+
* @param {ol/layer/Base} layer any layer, possibly a LayerGroup
|
|
38
|
+
* @returns {ol/layer/Base[]} array of all given layers
|
|
39
|
+
*/
|
|
40
|
+
function flattenLayerGroups (layer) {
|
|
41
|
+
return layer.getLayers
|
|
42
|
+
? layer
|
|
43
|
+
.getLayers()
|
|
44
|
+
.getArray()
|
|
45
|
+
.map(l => flattenLayerGroups(l))
|
|
46
|
+
.flat(1)
|
|
47
|
+
: [layer];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Adds an error handling function to an arbitrary layer. The event will be
|
|
52
|
+
* registered to the tileloaderror, imageloaderror, featuresloaderror, and
|
|
53
|
+
* generic error event. Depending on the type of layer and error, only one of
|
|
54
|
+
* these events will fire.
|
|
55
|
+
* @param {ol/layer/Base} layer Any type of layer implemented.
|
|
56
|
+
* @param {Function} errorCallback Error callback, called from OL event.
|
|
57
|
+
* @returns {void} side-effect to layer
|
|
58
|
+
*/
|
|
59
|
+
function injectErrorCallback (layer, errorCallback) {
|
|
60
|
+
const layers = flattenLayerGroups(layer);
|
|
61
|
+
|
|
62
|
+
layers.forEach(l => {
|
|
63
|
+
const source = l.getSource?.();
|
|
64
|
+
|
|
65
|
+
if (source) {
|
|
66
|
+
source.on?.("tileloaderror", errorCallback);
|
|
67
|
+
source.on?.("imageloaderror", errorCallback);
|
|
68
|
+
source.on?.("featuresloaderror", errorCallback);
|
|
69
|
+
source.on?.("error", errorCallback);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.error("Could not register error callback on layer:", l);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
35
77
|
/**
|
|
36
78
|
* Adds a layer to the map, or adds a layer to the map by id.
|
|
37
79
|
* This id is looked up within the array of all known services.
|
|
@@ -40,18 +82,22 @@ const layerBuilderMap = {
|
|
|
40
82
|
* if you request the services from the internet.
|
|
41
83
|
*
|
|
42
84
|
* This function is available on all ol/Map instances.
|
|
43
|
-
* @param {(string|ol/
|
|
85
|
+
* @param {(string|ol/layer/Base)} layerOrId - if of layer to add to map
|
|
44
86
|
* @param {object} [params] - optional parameter object
|
|
45
87
|
* @param {boolean} [params.visibility=true] - whether added layer is initially visible
|
|
46
88
|
* @param {Number} [params.transparency=0] - how visible the layer is initially
|
|
89
|
+
* @param {Function} [params.errorCallback=console.error] - callback for layer source error events
|
|
47
90
|
* @returns {?ol.Layer} added layer
|
|
48
91
|
*/
|
|
49
|
-
function addLayer (layerOrId, params = {visibility: true, transparency: 0}) {
|
|
50
|
-
|
|
92
|
+
function addLayer (layerOrId, params = {visibility: true, transparency: 0, errorCallback: console.error}) {
|
|
93
|
+
const errorCallback = typeof params.errorCallback === "function"
|
|
94
|
+
? params.errorCallback
|
|
95
|
+
: console.error;
|
|
96
|
+
let layer, layerBuilder;
|
|
51
97
|
|
|
52
98
|
// if parameter is id, create and add layer with masterportalAPI mechanisms
|
|
53
99
|
if (typeof layerOrId === "string") {
|
|
54
|
-
const rawLayer = getLayerWhere({id: layerOrId});
|
|
100
|
+
const rawLayer = rawLayerList.getLayerWhere({id: layerOrId});
|
|
55
101
|
|
|
56
102
|
if (!rawLayer) {
|
|
57
103
|
console.error("Layer with id '" + layerOrId + "' not found. No layer added to map.");
|
|
@@ -65,11 +111,13 @@ function addLayer (layerOrId, params = {visibility: true, transparency: 0}) {
|
|
|
65
111
|
layer = layerBuilder.createLayer(rawLayer, {}, {map: this});
|
|
66
112
|
layer.setVisible(typeof params.visibility === "boolean" ? params.visibility : true);
|
|
67
113
|
layer.setOpacity(typeof params.transparency === "number" ? (100 - params.transparency) / 100 : 1);
|
|
114
|
+
injectErrorCallback(layer, errorCallback);
|
|
68
115
|
originalAddLayer.call(this, layer);
|
|
69
116
|
return layer;
|
|
70
117
|
}
|
|
71
118
|
|
|
72
119
|
// else use original function
|
|
120
|
+
injectErrorCallback(layerOrId, errorCallback);
|
|
73
121
|
return originalAddLayer.call(this, layerOrId);
|
|
74
122
|
}
|
|
75
123
|
|
|
@@ -93,10 +141,11 @@ Map.prototype.addLayer = addLayer;
|
|
|
93
141
|
* @param {object} [settings={}] - setings object
|
|
94
142
|
* @param {object} [settings.mapParams] - additional parameter object that is spread into the ol.Map constructor object
|
|
95
143
|
* @param {function} [settings.callback] - optional callback for layer list loading
|
|
144
|
+
* @param {function} [settings.errorCallback] – method called on error events
|
|
96
145
|
* @param {String} [mapMode = "2D"] The map mode. '2D' to craete a 2D-map and '3D' to create a 3D-map.
|
|
97
146
|
* @returns {object} map object from ol
|
|
98
147
|
*/
|
|
99
|
-
export function createMap (config = defaults, {mapParams, callback} = {}) {
|
|
148
|
+
export function createMap (config = defaults, {mapParams, callback, errorCallback} = {}) {
|
|
100
149
|
registerProjections(config.namedProjections);
|
|
101
150
|
setBackgroundImage(config);
|
|
102
151
|
setGazetteerUrl(config.gazetteerUrl);
|
|
@@ -111,10 +160,10 @@ export function createMap (config = defaults, {mapParams, callback} = {}) {
|
|
|
111
160
|
map.set("id", `map2D_${mapIdCounter++}`);
|
|
112
161
|
|
|
113
162
|
// extend callback to load configured initial layers
|
|
114
|
-
initializeLayerList(config.layerConf, (param, error) => {
|
|
163
|
+
rawLayerList.initializeLayerList(config.layerConf, (param, error) => {
|
|
115
164
|
getInitialLayers(config)
|
|
116
165
|
.forEach(layer => {
|
|
117
|
-
map.addLayer(layer.id,
|
|
166
|
+
map.addLayer(layer.id, {errorCallback});
|
|
118
167
|
});
|
|
119
168
|
|
|
120
169
|
if (typeof callback === "function") {
|
package/src/rawLayerList.js
CHANGED
|
@@ -14,7 +14,7 @@ let layerList = [];
|
|
|
14
14
|
* @param {function} [callback] - called with services after loaded; called with false and error on error
|
|
15
15
|
* @returns {undefined} nothing, add callback to receive layerList
|
|
16
16
|
*/
|
|
17
|
-
|
|
17
|
+
function initializeLayerList (layerConf = defaults.layerConf, callback) {
|
|
18
18
|
if (Array.isArray(layerConf)) {
|
|
19
19
|
// case: parameter was services.json contents
|
|
20
20
|
layerList = layerConf;
|
|
@@ -55,14 +55,14 @@ export function initializeLayerList (layerConf = defaults.layerConf, callback) {
|
|
|
55
55
|
* @param {object} searchAttributes - key/value-pairs to be searched for, e.g. { typ: "WMS" } to get the first WMS
|
|
56
56
|
* @returns {?object} first layer matching the searchAttributes or null if none was found
|
|
57
57
|
*/
|
|
58
|
-
|
|
58
|
+
function getLayerWhere (searchAttributes) {
|
|
59
59
|
const keys = Object.keys(searchAttributes);
|
|
60
60
|
|
|
61
61
|
return layerList.find(entry => keys.every(key => entry[key] === searchAttributes[key])) || null;
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
/** @returns {object[]} complete layerList as initialized */
|
|
65
|
-
|
|
65
|
+
function getLayerList () {
|
|
66
66
|
return layerList;
|
|
67
67
|
}
|
|
68
68
|
|
|
@@ -72,7 +72,7 @@ export function getLayerList () {
|
|
|
72
72
|
* @param {string} [featureAttribute] - if given, only one entry of map is returned
|
|
73
73
|
* @returns {?(object|string)} - map of originalName->displayName or name of featureAttribute if specified; if layer or featureAttribute not found, null
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
function getDisplayNamesOfFeatureAttributes (layerId, featureAttribute) {
|
|
76
76
|
const attributes = getLayerWhere({id: layerId});
|
|
77
77
|
|
|
78
78
|
if (attributes && typeof featureAttribute === "string") {
|
|
@@ -86,3 +86,11 @@ export function getDisplayNamesOfFeatureAttributes (layerId, featureAttribute) {
|
|
|
86
86
|
|
|
87
87
|
return null;
|
|
88
88
|
}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
module.exports = {
|
|
92
|
+
getLayerWhere,
|
|
93
|
+
getDisplayNamesOfFeatureAttributes,
|
|
94
|
+
initializeLayerList,
|
|
95
|
+
getLayerList
|
|
96
|
+
};
|
package/test/layer/wmts.test.js
CHANGED
|
@@ -3,7 +3,7 @@ import {getWidth} from "ol/extent";
|
|
|
3
3
|
|
|
4
4
|
import * as wmts from "../../src/layer/wmts";
|
|
5
5
|
|
|
6
|
-
describe
|
|
6
|
+
describe("wmts.js", function () {
|
|
7
7
|
describe("generateArrays", function () {
|
|
8
8
|
it("should fill the arrays resolutions and matrixIds with numbers", function () {
|
|
9
9
|
const size = getWidth(getProjection("EPSG:3857").getExtent()) / 256,
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import ping from "../../src/lib/ping";
|
|
2
|
+
|
|
3
|
+
const originalFetch = global.fetch;
|
|
4
|
+
|
|
5
|
+
describe("ping.js", function () {
|
|
6
|
+
let mockFetch;
|
|
7
|
+
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
mockFetch = jest.fn(() => Promise.resolve({
|
|
10
|
+
status: 200
|
|
11
|
+
}));
|
|
12
|
+
global.fetch = mockFetch;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterAll(() => {
|
|
16
|
+
global.fetch = originalFetch;
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("ping", function () {
|
|
20
|
+
it("calls an url from the service definition", async function () {
|
|
21
|
+
const status = await ping({url: "www.example.com", typ: "WMS"});
|
|
22
|
+
|
|
23
|
+
expect(status).toBe(200);
|
|
24
|
+
expect(mockFetch).toHaveBeenCalledWith("www.example.com?service=WMS&request=GetCapabilities", {method: "HEAD"});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("calls 0/0/0 tile for VectorTile services", async function () {
|
|
28
|
+
const status = await ping({url: "www.example.com/{x}/{y}/{z}", typ: "VectorTile"});
|
|
29
|
+
|
|
30
|
+
expect(status).toBe(200);
|
|
31
|
+
expect(mockFetch).toHaveBeenCalledWith("www.example.com/0/0/0", {method: "HEAD"});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("calls the URL directly for OAF services", async function () {
|
|
35
|
+
const status = await ping({url: "www.example.com", typ: "OAF"});
|
|
36
|
+
|
|
37
|
+
expect(status).toBe(200);
|
|
38
|
+
expect(mockFetch).toHaveBeenCalledWith("www.example.com", {method: "HEAD"});
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("returns 900 on network errors", async function () {
|
|
42
|
+
mockFetch = jest.fn(() => Promise.resolve({status: 900}));
|
|
43
|
+
global.fetch = mockFetch;
|
|
44
|
+
|
|
45
|
+
const status = await ping({url: "www.example.com", typ: "OAF"});
|
|
46
|
+
|
|
47
|
+
expect(status).toBe(900);
|
|
48
|
+
expect(mockFetch).toHaveBeenCalledWith("www.example.com", {method: "HEAD"});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("returns highest status code on multiple urls", async function () {
|
|
52
|
+
let counter = 200;
|
|
53
|
+
|
|
54
|
+
mockFetch = jest.fn(() => Promise.resolve({status: counter++}));
|
|
55
|
+
global.fetch = mockFetch;
|
|
56
|
+
|
|
57
|
+
const status = await ping({urls: [
|
|
58
|
+
"www.example.com",
|
|
59
|
+
"www.example.com/but"
|
|
60
|
+
], typ: "WMTS"});
|
|
61
|
+
|
|
62
|
+
expect(status).toBe(201);
|
|
63
|
+
expect(mockFetch)
|
|
64
|
+
.toHaveBeenCalledWith("www.example.com", {method: "HEAD"});
|
|
65
|
+
expect(mockFetch)
|
|
66
|
+
.toHaveBeenCalledWith("www.example.com/but", {method: "HEAD"});
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
});
|