Skip to content

Commit

Permalink
#8334 Review mapType configuration and docs (#9012)
Browse files Browse the repository at this point in the history
Co-authored-by: Lorenzo Natali <[email protected]>
  • Loading branch information
allyoucanmap and offtherailz authored Mar 13, 2023
1 parent c6fad76 commit 736dee2
Show file tree
Hide file tree
Showing 7 changed files with 79 additions and 70 deletions.
24 changes: 15 additions & 9 deletions docs/developer-guide/local-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,18 +99,24 @@ This is the main structure:
"leaflet": { ... },
"cesium": { ... }
},
// allow to define which 2D or 3D map library should be used based on the device
// allow to define the default visualization mode of the app and
// which 2D or 3D map library should be used based on the device
// the configuration below is the default one
// structure -> { mapType: { [visualizationMode]: { [deviceType]: mapLibrary } } }
// note: this configuration does not support expressions
"mapType": {
"2D": {
"desktop": "openlayers",
"mobile": "leaflet"
},
"3D": {
"desktop": "cesium",
"mobile": "cesium"
// the default visualization mode of the app, it could be "2D" or "3D"
"defaultVisualizationMode": "2D",
// map library to use based on the visualization mode and device
// structure -> { visualizationModes: { [visualizationMode]: { [deviceType]: mapLibrary } } }
"visualizationModes": {
"2D": {
"desktop": "openlayers",
"mobile": "leaflet"
},
"3D": {
"desktop": "cesium",
"mobile": "cesium"
}
}
},
"plugins": {
Expand Down
48 changes: 24 additions & 24 deletions docs/developer-guide/map-query-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ The parameters can be passed in a query-string-like section, after the `#<path>?
Example:

```text
#/viewer/openlayers/new?center=0,0&zoom=5
#/viewer/new?center=0,0&zoom=5
```

!!! note
Expand All @@ -23,8 +23,8 @@ Example:

Sometimes the request parameters can be too big to be passed in the URL, for instance when dealing with an entire map, or complex data. To overcome this kind of situations, an adhoc `POST` service available at `<mapstore-base-path>/rest/config/setParams` allows to pass the parameters in the request payload `application/x-www-form-urlencoded`.
The parameters will be then passed to the client (using a temporary `queryParams-{random-UUID}` variable in `sessionStorage`).
Near the parameters, an additional `page` value can be passed together with the params to specify to which url be redirect. If no page attribute is specified by default redirection happens to `#/viewer/openlayers/config`.
The UUID used in the `queryParams-{random-UUID}` variable name is being added to the redirect URL in a query parameter named `queryParamsID=`. Assuming to use the default redirect value, the url will then look like the following: `#/viewer/openlayers/config?queryParamsID={random-UUID}`.
Near the parameters, an additional `page` value can be passed together with the params to specify to which url be redirect. If no page attribute is specified by default redirection happens to `#/viewer/config`.
The UUID used in the `queryParams-{random-UUID}` variable name is being added to the redirect URL in a query parameter named `queryParamsID=`. Assuming to use the default redirect value, the url will then look like the following: `#/viewer/config?queryParamsID={random-UUID}`.

Example `application/x-www-form-urlencoded` request payload (URL encoded):

Expand All @@ -39,7 +39,7 @@ Here a sample page you can create to test the service:
<script>
const POST_PATH = "rest/config/setParams";
const queryParameters = {
"page": '../../#/viewer/openlayers/config',
"page": '../../#/viewer/config',
"map": {"version":2,"map":{"projection":"EPSG:900913","units":"m","center":{"x":1250000,"y":5370000,"crs":"EPSG:900913"},"zoom":5,"maxExtent":[-20037508.34,-20037508.34,20037508.34,20037508.34],"layers":[{"type":"osm","title":"Open Street Map","name":"mapnik","source":"osm","group":"background","visibility":true}]}},
"featureinfo": '',
"bbox": '',
Expand Down Expand Up @@ -121,7 +121,7 @@ Here a sample page you can create to test the service:
<fieldset>
<legend>Params:</legend>
<label for="map">map:</label><br/><textarea id="map" name="map"></textarea><br/>
<label for="page">page:</label><br/><input type="text" id="page" name="page" value="../../#/viewer/openlayers/config"></input><br/>
<label for="page">page:</label><br/><input type="text" id="page" name="page" value="../../#/viewer/config"></input><br/>
<label for="featureinfo">featureinfo:</label><br/><textarea id="featureinfo" name="featureinfo"></textarea><br/>
<label for="bbox">bbox:</label><br/><input type="text" id="bbox" name="bbox"></input><br/>
<label for="center">center:</label><br/><input type="text" id="center" name="center"></input><br/>
Expand All @@ -145,13 +145,13 @@ Optional parameter "filterNameList" allows limiting request to the specific laye
It will be effectively used only if it's passed as non-empty array of layer names.
Omitting or passing an empty array will have the same effect.
GET: `#/viewer/openlayers/config?featureinfo={"lat": 43.077, "lng": 12.656, "filterNameList": []}`
GET: `#/viewer/config?featureinfo={"lat": 43.077, "lng": 12.656, "filterNameList": []}`
GET: `#/viewer/openlayers/config?featureinfo={"lat": 43.077, "lng": 12.656, "filterNameList": ["layerName1", "layerName2"]}`
GET: `#/viewer/config?featureinfo={"lat": 43.077, "lng": 12.656, "filterNameList": ["layerName1", "layerName2"]}`
#### Simplified syntax
GET: `#/viewer/openlayers/config?featureInfo=38.72,-95.625`
GET: `#/viewer/config?featureInfo=38.72,-95.625`
Where lon,lat values are comma-separated respecting order.
Expand All @@ -162,40 +162,40 @@ Allows to pass the entire map JSON definition (see the map configuration format
GET:
```text
#/viewer/openlayers/config?map={"version":2,"map":{"projection":"EPSG:900913","units":"m","center":{"x":1250000,"y":5370000,"crs":"EPSG:900913"},"zoom":5,"maxExtent":[-20037508.34,-20037508.34,20037508.34,20037508.34],"layers":[{"type":"osm","title":"Open Street Map","name":"mapnik","source":"osm","group":"background","visibility":true}]}}
#/viewer/config?map={"version":2,"map":{"projection":"EPSG:900913","units":"m","center":{"x":1250000,"y":5370000,"crs":"EPSG:900913"},"zoom":5,"maxExtent":[-20037508.34,-20037508.34,20037508.34,20037508.34],"layers":[{"type":"osm","title":"Open Street Map","name":"mapnik","source":"osm","group":"background","visibility":true}]}}
```
It also allows partial overriding of existing map configuration by passing only specific properties of the root object and/or the internal "map" object.
Following example will override "catalogServices" and "mapInfoConfiguration":
```text
#/viewer/openlayers/config?map={"mapInfoConfiguration":{"trigger":"click","infoFormat":"text/html"},"catalogServices":{"services": {"wms": {"url": "http://example.com/geoserver/wms","type": "wms","title": "WMS","autoload": true}},"selectedService": "wms"}}
#/viewer/config?map={"mapInfoConfiguration":{"trigger":"click","infoFormat":"text/html"},"catalogServices":{"services": {"wms": {"url": "http://example.com/geoserver/wms","type": "wms","title": "WMS","autoload": true}},"selectedService": "wms"}}
```
### Center / Zoom
GET: `#/viewer/openlayers/config?center=0,0&zoom=5`
GET: `#/viewer/config?center=0,0&zoom=5`
Where lon,lat values are comma-separated respecting order.
### Marker / Zoom
GET: `#/viewer/openlayers/config?marker=0,0&zoom=5`
GET: `#/viewer/config?marker=0,0&zoom=5`
Where lon,lat values are comma-separated respecting order.
### Bbox
GET: `#/viewer/openlayers/config?bbox=8,8,53,53`
GET: `#/viewer/config?bbox=8,8,53,53`
Where values are `minLongitude, minLatitude, maxLongitude, maxLatitude` respecting order.
### AddLayers
This is a shortened syntax for `CATALOG:ADD_LAYERS_FROM_CATALOGS` action described down below.
GET: `#/viewer/openlayers/config?addLayers=layer1;service,layer2&layerFilters=attributeLayer1='value';attributeLayer2='value2'`
GET: `#/viewer/config?addLayers=layer1;service,layer2&layerFilters=attributeLayer1='value';attributeLayer2='value2'`
`addLayers` parameter is a comma separated list of `<layerName>;<service>` (`service` is optional, and if present is separated
from the layerName by a `;`.
Expand All @@ -217,7 +217,7 @@ In this case search execution will be postponed up to the moment when layer is a
If so, it will postpone search to ensure that layer is added to the map. Otherwise, in case of no matches, search will execute
immediately.
GET: `#/viewer/openlayers/new?addLayers=layer1;service&mapinfo=layer1&mapInfoFilter=BB='cc'`
GET: `#/viewer/new?addLayers=layer1;service&mapinfo=layer1&mapInfoFilter=BB='cc'`
Where:
Expand All @@ -231,11 +231,11 @@ Allows to dynamically add background to the map and activate it.
Supports default backgrounds provided by static service defined in `localConfig.json` (`default_map_backgrounds`) as well
as other layers:
`#/viewer/openlayers/new?background=Sentinel;default_map_backgrounds`
`#/viewer/new?background=Sentinel;default_map_backgrounds`
`#/viewer/openlayers/new?background=layer1;service`
`#/viewer/new?background=layer1;service`
`#/viewer/openlayers/new?background=layer2`
`#/viewer/new?background=layer2`
Where:
Expand Down Expand Up @@ -275,7 +275,7 @@ Example:
}
```
GET: `#/viewer/openlayers/config?actions=[{"type": "ZOOM_TO_EXTENT","extent": [1,2,3,4],"crs": "EPSG:4326","maxZoom": 8}]`
GET: `#/viewer/config?actions=[{"type": "ZOOM_TO_EXTENT","extent": [1,2,3,4],"crs": "EPSG:4326","maxZoom": 8}]`
For more details check out the [zoomToExtent](https://mapstore.geosolutionsgroup.com/mapstore/docs/#actions.map.zoomToExtent) in the framework documentation.
Expand All @@ -302,12 +302,12 @@ Example:
}
```
GET: `#/viewer/openlayers/config?actions=[{"type":"SEARCH:SEARCH_WITH_FILTER","cql_filter":"ID=75","layer":"WORKSPACE:LAYER_NAME"}]`
GET: `#/viewer/config?actions=[{"type":"SEARCH:SEARCH_WITH_FILTER","cql_filter":"ID=75","layer":"WORKSPACE:LAYER_NAME"}]`
The sample request below illustrates how two actions can be concatenated:
```text
https://dev-mapstore.geosolutionsgroup.com/mapstore/#/viewer/openlayers/4093?actions=[{"type":"SEARCH:SEARCH_WITH_FILTER","cql_filter":"STATE_FIPS=34","layer":"topp:states"},{"type":"ZOOM_TO_EXTENT","extent":[-77.48202256347649,38.74612266051003,-72.20858506347648,40.66664704515103],"crs":"EPSG:4326","maxZoom":8}]
https://dev-mapstore.geosolutionsgroup.com/mapstore/#/viewer/4093?actions=[{"type":"SEARCH:SEARCH_WITH_FILTER","cql_filter":"STATE_FIPS=34","layer":"topp:states"},{"type":"ZOOM_TO_EXTENT","extent":[-77.48202256347649,38.74612266051003,-72.20858506347648,40.66664704515103],"crs":"EPSG:4326","maxZoom":8}]
```
The MapStore invocation URL above executes the following operations:
Expand All @@ -332,7 +332,7 @@ Example:
}
```
GET: `#/viewer/openlayers/config?actions=[{"type":"SEARCH:SCHEDULE_SEARCH_WITH_FILTER","cql_filter":"ID=75","layer":"WORKSPACE:LAYER_NAME"},{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["WORKSPACE:LAYER_NAME"],"sources":["catalog1"]}]`
GET: `#/viewer/config?actions=[{"type":"SEARCH:SCHEDULE_SEARCH_WITH_FILTER","cql_filter":"ID=75","layer":"WORKSPACE:LAYER_NAME"},{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["WORKSPACE:LAYER_NAME"],"sources":["catalog1"]}]`
#### Add Layers
Expand All @@ -355,7 +355,7 @@ Example:
}
```
GET: `#/viewer/openlayers/config?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["layer1", "layer2", "workspace:externallayername"],"sources":["catalog1", "catalog2", {"type":"WMS","url":"https://example.com/wms"}]}]`
GET: `#/viewer/config?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["layer1", "layer2", "workspace:externallayername"],"sources":["catalog1", "catalog2", {"type":"WMS","url":"https://example.com/wms"}]}]`
Data of resulting layer can be additionally filtered by passing "CQL_FILTER" into the options array. Each element of array corresponds to the layer defined in action:
Expand All @@ -368,6 +368,6 @@ Data of resulting layer can be additionally filtered by passing "CQL_FILTER" int
}
```
GET `#/viewer/openlayers/config?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["layer1","layer2","workspace:externallayername"],"sources":["catalog1","catalog2",{"type":"WMS","url":"https://example.com/wms"}],"options": [{"params":{"CQL_FILTER":"NAME='value'"}}, {}, {"params":{"CQL_FILTER":"NAME='value2'"}}]}]`
GET `#/viewer/config?actions=[{"type":"CATALOG:ADD_LAYERS_FROM_CATALOGS","layers":["layer1","layer2","workspace:externallayername"],"sources":["catalog1","catalog2",{"type":"WMS","url":"https://example.com/wms"}],"options": [{"params":{"CQL_FILTER":"NAME='value'"}}, {}, {"params":{"CQL_FILTER":"NAME='value2'"}}]}]`
Number of objects passed to the options can be different to the number of layers, in this case options will be applied to the first X layers, where X is the length of options array.
21 changes: 1 addition & 20 deletions docs/developer-guide/mapstore-migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ This is a list of things to check if you want to update from a previous version
The map configuration stores the information related to the visualization mode 2D or 3D after saving a map.
This update include also following changes:

- `maptype` configuration inside the initialState of localConfig needs to be removed in favor of the global mapType configuration
- `maptype` default state configuration inside the initialState of `localConfig.json` needs to be removed. If a MapStore project needs a particular setup (eg. use only OpenLayers for 2D maps, initialize the app in 3D, ...) it is possible to override the default map libraries configuration with the new `mapType` property in the `localConfig.json` file, see documentation [here](local-config.md#application-configuration).

```diff
{
Expand All @@ -49,25 +49,6 @@ This update include also following changes:

- the application does not expose the pathname of the viewer with `mapType` anymore. Example: the old path `/viewer/openlayers/1` becomes `/viewer/1`

- it is possible to change the map library based on the device using the new `mapType` configuration in localConfig.json. This configuration is only needed for project with custom map library settings. The downstream projects based on the MapStore product don't need this update

```diff
{
// ...
+ "mapType": {
+ "2D": {
+ "desktop": "openlayers",
+ "mobile": "leaflet"
+ },
+ "3D": {
+ "desktop": "cesium",
+ "mobile": "cesium"
+ }
+ },
// ...
}
```

- the app pages inside a MapStore project must be updated with a new entry, only for projects with custom pages and that are using context applications, here an example:

```js
Expand Down
4 changes: 2 additions & 2 deletions web/client/components/map/enhancers/autoMapType.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
*/

import React from 'react';
import { getMapLibraryFromVisualizationMode, VisualizationModes } from '../../../utils/MapTypeUtils';
import { getMapLibraryFromVisualizationMode } from '../../../utils/MapTypeUtils';

const autoMapType = (Component) => props => (
<Component
mapType={getMapLibraryFromVisualizationMode(props?.map?.visualizationMode || VisualizationModes._2D)}
mapType={getMapLibraryFromVisualizationMode(props?.map?.visualizationMode)}
{...props}
/>
);
Expand Down
7 changes: 3 additions & 4 deletions web/client/reducers/maptype.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ import { MAP_PLUGIN_LOAD } from '../actions/map';
import { MAP_CONFIG_LOADED } from '../actions/config';

import {
getMapLibraryFromVisualizationMode,
VisualizationModes
getMapLibraryFromVisualizationMode
} from '../utils/MapTypeUtils';

/**
Expand All @@ -27,11 +26,11 @@ import {
* }
*/
function maptype(state = {
mapType: getMapLibraryFromVisualizationMode(VisualizationModes._2D)
mapType: getMapLibraryFromVisualizationMode()
}, action) {
switch (action.type) {
case MAP_CONFIG_LOADED:
const visualizationMode = action?.config?.map?.visualizationMode || VisualizationModes._2D;
const visualizationMode = action?.config?.map?.visualizationMode;
return {
...state,
mapType: getMapLibraryFromVisualizationMode(visualizationMode)
Expand Down
17 changes: 12 additions & 5 deletions web/client/utils/MapTypeUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const mapLibrariesConfiguration = {
}
};

const DEFAULT_MAP_TYPE_CONFIG = {
const DEFAULT_VISUALIZATION_MODES_CONFIG = {
[VisualizationModes._2D]: {
mobile: MapLibraries.LEAFLET,
desktop: MapLibraries.OPENLAYERS
Expand All @@ -35,6 +35,12 @@ const DEFAULT_MAP_TYPE_CONFIG = {
}
};

const getDefaultVisualizationMode = () => {
const customMapTypeConfig = getConfigProp('mapType') || {};
const { defaultVisualizationMode = VisualizationModes._2D } = customMapTypeConfig;
return defaultVisualizationMode;
};

/**
* Check if a map configuration is in 3D mode
* @param {object} map map configuration
Expand All @@ -48,7 +54,7 @@ export const is3DVisualizationMode = (map) => map?.visualizationMode === Visuali
* @returns {string} "2D" or "3D" value
*/
export const getVisualizationModeFromMapLibrary = (mapLibrary) => {
const { visualizationMode = VisualizationModes._2D } = mapLibrariesConfiguration[mapLibrary] || {};
const { visualizationMode = getDefaultVisualizationMode() } = mapLibrariesConfiguration[mapLibrary] || {};
return visualizationMode;
};

Expand All @@ -57,12 +63,13 @@ export const getVisualizationModeFromMapLibrary = (mapLibrary) => {
* @param {string} visualizationMode the name of the visualization mode, one of "2D" or "3D"
* @returns {string} leaflet", "openlayers" or "cesium" value
*/
export const getMapLibraryFromVisualizationMode = (visualizationMode = VisualizationModes._2D) => {
export const getMapLibraryFromVisualizationMode = (visualizationMode = getDefaultVisualizationMode()) => {
const { mobile } = getBrowserProperties();
const customMapTypeConfig = getConfigProp('mapType') || {};
const { visualizationModes = {} } = customMapTypeConfig;
const config = {
...DEFAULT_MAP_TYPE_CONFIG[visualizationMode],
...customMapTypeConfig[visualizationMode]
...DEFAULT_VISUALIZATION_MODES_CONFIG[visualizationMode],
...visualizationModes[visualizationMode]
};
const device = mobile ? 'mobile' : 'desktop';
return config[device];
Expand Down
28 changes: 22 additions & 6 deletions web/client/utils/__tests__/MapTypeUtils-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ import {
replaceMapType,
removeMapType,
getVisualizationModeFromMapLibrary,
getMapLibraryFromVisualizationMode
getMapLibraryFromVisualizationMode,
VisualizationModes,
MapLibraries
} from '../MapTypeUtils';

import { setConfigProp } from '../ConfigUtils';

const testHashes = [
["/viewer/openlayers/1234", "openlayers"],
["/viewer/openlayers/new", "openlayers"],
Expand Down Expand Up @@ -123,12 +127,24 @@ describe('MapTypeUtils', () => {
});
});
it('testing getVisualizationModeFromMapLibrary', () => {
expect(getVisualizationModeFromMapLibrary('leaflet')).toBe('2D');
expect(getVisualizationModeFromMapLibrary('openlayers')).toBe('2D');
expect(getVisualizationModeFromMapLibrary('cesium')).toBe('3D');
expect(getVisualizationModeFromMapLibrary()).toBe(VisualizationModes._2D);
expect(getVisualizationModeFromMapLibrary(MapLibraries.LEAFLET)).toBe(VisualizationModes._2D);
expect(getVisualizationModeFromMapLibrary(MapLibraries.OPENLAYERS)).toBe(VisualizationModes._2D);
expect(getVisualizationModeFromMapLibrary(MapLibraries.CESIUM)).toBe(VisualizationModes._3D);
setConfigProp('mapType', {
defaultVisualizationMode: VisualizationModes._3D
});
expect(getVisualizationModeFromMapLibrary()).toBe(VisualizationModes._3D);
setConfigProp('mapType', undefined);
});
it('testing getMapLibraryFromVisualizationMode (default)', () => {
expect(getMapLibraryFromVisualizationMode('2D')).toBe('openlayers');
expect(getMapLibraryFromVisualizationMode('3D')).toBe('cesium');
expect(getMapLibraryFromVisualizationMode()).toBe(MapLibraries.OPENLAYERS);
expect(getMapLibraryFromVisualizationMode(VisualizationModes._2D)).toBe(MapLibraries.OPENLAYERS);
expect(getMapLibraryFromVisualizationMode(VisualizationModes._3D)).toBe(MapLibraries.CESIUM);
setConfigProp('mapType', {
defaultVisualizationMode: VisualizationModes._3D
});
expect(getMapLibraryFromVisualizationMode()).toBe(MapLibraries.CESIUM);
setConfigProp('mapType', undefined);
});
});

0 comments on commit 736dee2

Please sign in to comment.