diff --git a/conf/default.toml b/conf/default.toml index c65612c55d..c71521cea9 100644 --- a/conf/default.toml +++ b/conf/default.toml @@ -12,30 +12,34 @@ geonetwork4_api_url = "/geonetwork/srv/api" proxy_path = "" ### MAP SETTINGS -# The map section allows to override default settings of the map view. -# Example: -# + +# The map section allows to customize how maps are configured. [map] +# Optional; Will limit the possibility to zoom in past a certain zoom level # max_zoom = 10 + +# Optional; will limit the possibility to pan or zoom out outside of an extent +# Expressed in the map view projection (EPSG:3857) # max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855] -# use_basemap_from_layers = false -# -# Layers (basemaps, overlays, masks) can be added to the map view with three properties: + +# Optional; if true, the default basemap will not be added to the map. +# Use [[map_layer]] sections to define your own custom layers (see below) +# do_not_use_default_basemap = false + +# One or several layers (as background or overlay) can be added to the map with the following properties: # - type (mandatory): Indicates the layer type. Possible values are 'xyz', 'wms', 'wfs'. # - url (mandatory): Layer endpoint URL. -# - name: Mandatory for 'wms', 'wfs' types where it indicates the layer name. +# - name: Mandatory for 'wms', 'wfs' types where it indicates the layer name or feature type. # Layer order in the config is the same as in the map, the first one being the bottom one. -# If you want to override the default basemap with the first layer of your config set use_basemap_from_layers = true (default: false) -# Each layer is defined in its own [[layers]] section. +# Each layer is defined in its own [[map_layer]] section. # Example: -# [[layers]] +# [[map_layer]] # type = "xyz" # url = "https://{a-c}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png" -# [[layers]] +# [[map_layer]] # type = "wfs" # url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" # name = "masque_hdf_ign_carto_latin1" -# ### VISUAL THEME diff --git a/libs/feature/map/src/lib/map-context/map-context.service.spec.ts b/libs/feature/map/src/lib/map-context/map-context.service.spec.ts index 61ed2ef849..c2322f05e8 100644 --- a/libs/feature/map/src/lib/map-context/map-context.service.spec.ts +++ b/libs/feature/map/src/lib/map-context/map-context.service.spec.ts @@ -194,7 +194,7 @@ describe('MapContextService', () => { const mapContext = MAP_CTX_FIXTURE const mapConfig = MAP_CONFIG_FIXTURE beforeEach(() => { - mapConfig.USE_BASEMAP_FROM_LAYERS = true + mapConfig.DO_NOT_USE_DEFAULT_BASEMAP = true service.resetMapFromContext(map, mapContext, mapConfig) }) it('set maxZoom', () => { @@ -219,7 +219,7 @@ describe('MapContextService', () => { const mapContext = MAP_CTX_FIXTURE const mapConfig = MAP_CONFIG_FIXTURE beforeEach(() => { - mapConfig.USE_BASEMAP_FROM_LAYERS = false + mapConfig.DO_NOT_USE_DEFAULT_BASEMAP = false service.resetMapFromContext(map, mapContext, mapConfig) }) it('set first layer as baselayer', () => { @@ -232,7 +232,7 @@ describe('MapContextService', () => { const mapContext = MAP_CTX_FIXTURE const mapConfig = MAP_CONFIG_FIXTURE beforeEach(() => { - mapConfig.USE_BASEMAP_FROM_LAYERS = true + mapConfig.DO_NOT_USE_DEFAULT_BASEMAP = true }) it('merges mapconfig into existing mapcontext', () => { const mergedMapContext = service.mergeMapConfigWithContext( @@ -240,7 +240,7 @@ describe('MapContextService', () => { mapConfig ) const layersContext = service.getLayersContextFromConfig( - MAP_CONFIG_FIXTURE.LAYERS + MAP_CONFIG_FIXTURE.MAP_LAYERS ) expect(mergedMapContext).toEqual({ diff --git a/libs/feature/map/src/lib/map-context/map-context.service.ts b/libs/feature/map/src/lib/map-context/map-context.service.ts index 9faa700288..2c5aee6e71 100644 --- a/libs/feature/map/src/lib/map-context/map-context.service.ts +++ b/libs/feature/map/src/lib/map-context/map-context.service.ts @@ -132,11 +132,11 @@ export class MapContextService { }), }, layers: [ - ...(mapConfig.USE_BASEMAP_FROM_LAYERS + ...(mapConfig.DO_NOT_USE_DEFAULT_BASEMAP ? [] : [DEFAULT_BASELAYER_CONTEXT]), - ...(mapConfig.LAYERS - ? this.getLayersContextFromConfig(mapConfig.LAYERS) + ...(mapConfig.MAP_LAYERS + ? this.getLayersContextFromConfig(mapConfig.MAP_LAYERS) : []), ...mapContext.layers, ], diff --git a/libs/feature/record/src/lib/data-view-map/data-view-map.component.spec.ts b/libs/feature/record/src/lib/data-view-map/data-view-map.component.spec.ts index fb136e3aab..d8c92b1a14 100644 --- a/libs/feature/record/src/lib/data-view-map/data-view-map.component.spec.ts +++ b/libs/feature/record/src/lib/data-view-map/data-view-map.component.spec.ts @@ -41,8 +41,8 @@ import { MapConfig } from '@geonetwork-ui/util/app-config' const mapConfigMock = { MAX_ZOOM: 10, MAX_EXTENT: [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855], - USE_BASEMAP_FROM_LAYERS: false, - CUSTOMLAYERS: [ + DO_NOT_USE_DEFAULT_BASEMAP: false, + MAP_LAYERS: [ { TYPE: 'wms', URL: 'https://some-wms-server', diff --git a/libs/util/app-config/src/lib/app-config.spec.ts b/libs/util/app-config/src/lib/app-config.spec.ts index 72a0d5de61..879247579e 100644 --- a/libs/util/app-config/src/lib/app-config.spec.ts +++ b/libs/util/app-config/src/lib/app-config.spec.ts @@ -32,13 +32,13 @@ another_path = '/whatever' [map] max_zoom = 10 max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855] -use_basemap_from_layers = false +do_not_use_default_basemap = false another_zoom = 15 -[[layers]] +[[map_layer]] type = "wms" url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" name = "masque_hdf_ign_carto_latin1" -[[layers]] +[[map_layer]] type = "wfs" url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" name = "masque_hdf_ign_carto_latin1" @@ -150,29 +150,6 @@ describe('app config utils', () => { }) }) }) - describe('getMapConfig', () => { - it('returns the map config', () => { - expect(getMapConfig()).toEqual({ - MAX_ZOOM: 10, - MAX_EXTENT: [ - -418263.418776, 5251529.591305, 961272.067714, 6706890.609855, - ], - USE_BASEMAP_FROM_LAYERS: false, - LAYERS: [ - { - TYPE: 'wms', - URL: 'https://www.geo2france.fr/geoserver/cr_hdf/ows', - NAME: 'masque_hdf_ign_carto_latin1', - }, - { - TYPE: 'wfs', - URL: 'https://www.geo2france.fr/geoserver/cr_hdf/ows', - NAME: 'masque_hdf_ign_carto_latin1', - }, - ], - }) - }) - }) describe('getThemeConfig', () => { it('returns the theme config', () => { expect(getThemeConfig()).toEqual({ @@ -206,4 +183,83 @@ describe('app config utils', () => { }) }) }) + + describe('getMapConfig', () => { + const baseConfig = ` + [global] + geonetwork4_api_url = "/geonetwork/srv/api" + [theme] + primary_color = "#093564" + secondary_color = "#c2e9dc" + main_color = "#212029" # All-purpose text color + background_color = "#fdfbff" +` + + describe('when all properties are present', () => { + beforeEach(async () => { + fetchMock.get( + 'end:default.toml', + () => + baseConfig + + ` + [map] + max_zoom = 10 + max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855] + do_not_use_default_basemap = true + [[map_layer]] + type = "wms" + url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" + name = "masque_hdf_ign_carto_latin1" + [[map_layer]] + type = "wfs" + url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" + name = "masque_hdf_ign_carto_latin1"` + ) + await loadAppConfig() + }) + + it('returns the map config', () => { + expect(getMapConfig()).toEqual({ + MAX_ZOOM: 10, + MAX_EXTENT: [ + -418263.418776, 5251529.591305, 961272.067714, 6706890.609855, + ], + DO_NOT_USE_DEFAULT_BASEMAP: true, + MAP_LAYERS: [ + { + TYPE: 'wms', + URL: 'https://www.geo2france.fr/geoserver/cr_hdf/ows', + NAME: 'masque_hdf_ign_carto_latin1', + }, + { + TYPE: 'wfs', + URL: 'https://www.geo2france.fr/geoserver/cr_hdf/ows', + NAME: 'masque_hdf_ign_carto_latin1', + }, + ], + }) + }) + }) + describe('when all properties are missing', () => { + beforeEach(async () => { + fetchMock.get( + 'end:default.toml', + () => + baseConfig + + ` + [map]` + ) + await loadAppConfig() + }) + + it('returns the map config', () => { + expect(getMapConfig()).toEqual({ + MAX_ZOOM: undefined, + MAX_EXTENT: undefined, + DO_NOT_USE_DEFAULT_BASEMAP: false, + MAP_LAYERS: [], + }) + }) + }) + }) }) diff --git a/libs/util/app-config/src/lib/app-config.ts b/libs/util/app-config/src/lib/app-config.ts index 22d793214e..fb26d5447e 100644 --- a/libs/util/app-config/src/lib/app-config.ts +++ b/libs/util/app-config/src/lib/app-config.ts @@ -1,5 +1,4 @@ import * as TOML from '@ltd/j-toml' -import { Extent } from 'ol/extent' const MISSING_CONFIG_ERROR = `Application configuration was not initialized correctly. This error might show up in case of an invalid/malformed configuration file. @@ -24,9 +23,9 @@ export interface LayerConfig { } export interface MapConfig { MAX_ZOOM?: number - MAX_EXTENT?: Extent - USE_BASEMAP_FROM_LAYERS?: boolean - LAYERS?: LayerConfig[] + MAX_EXTENT?: [number, number, number, number] // Expressed as [minx, miny, maxx, maxy] + DO_NOT_USE_DEFAULT_BASEMAP: boolean + MAP_LAYERS: LayerConfig[] } let mapConfig: MapConfig = null @@ -98,7 +97,7 @@ export function loadAppConfig() { const { global, map, - layers, + map_layer, theme, translations: translationsNested, } = parsed @@ -122,7 +121,7 @@ export function loadAppConfig() { const mapCheck = checkKeys( map || {}, [], - ['max_zoom', 'max_extent', 'baselayer', 'use_basemap_from_layers'] + ['max_zoom', 'max_extent', 'baselayer', 'do_not_use_default_basemap'] ) if (mapCheck.missing.length) { errors.push(`In the [map] section: ${mapCheck.missing.join(', ')}`) @@ -133,8 +132,8 @@ export function loadAppConfig() { } let layersCheck = { missing: [], unrecognized: [] } - if (layers) { - layers.forEach((layer) => { + if (map_layer) { + map_layer.forEach((layer) => { const { missing, unrecognized } = checkKeys( layer || {}, ['type', 'url'], @@ -153,11 +152,13 @@ export function loadAppConfig() { }) if (layersCheck.missing.length) { errors.push( - `In some [layers] definition: ${layersCheck.missing.join(', ')}` + `In one of the [map_layer] definitions: ${layersCheck.missing.join( + ', ' + )}` ) } else if (layersCheck.unrecognized.length) { warnings.push( - `In some [layers] definition: ${layersCheck.unrecognized.join( + `In one of the [map_layer] definitions: ${layersCheck.unrecognized.join( ', ' )}` ) @@ -205,8 +206,8 @@ ${warnings.join('\n')}`) PROXY_PATH: global.proxy_path, } const layersConfig: LayerConfig[] = [] - if (layers) { - layers.forEach((layerConfig) => { + if (map_layer) { + map_layer.forEach((layerConfig) => { layersConfig.push({ TYPE: layerConfig.type, URL: layerConfig.url, @@ -214,16 +215,12 @@ ${warnings.join('\n')}`) }) }) } - mapConfig = map - ? { - MAX_ZOOM: map.max_zoom, - MAX_EXTENT: map.max_extent, - USE_BASEMAP_FROM_LAYERS: map.use_basemap_from_layers, - ...(layersConfig.length && { - LAYERS: layersConfig, - }), - } - : {} + mapConfig = { + MAX_ZOOM: map.max_zoom, + MAX_EXTENT: map.max_extent, + DO_NOT_USE_DEFAULT_BASEMAP: !!map.do_not_use_default_basemap, + MAP_LAYERS: layersConfig, + } themeConfig = { PRIMARY_COLOR: theme.primary_color, SECONDARY_COLOR: theme.secondary_color, diff --git a/libs/util/app-config/src/lib/fixtures.ts b/libs/util/app-config/src/lib/fixtures.ts index 38aa8a8805..eafaa71df4 100644 --- a/libs/util/app-config/src/lib/fixtures.ts +++ b/libs/util/app-config/src/lib/fixtures.ts @@ -6,12 +6,12 @@ proxy_path = "/proxy/?url=" [map] max_zoom = 10 max_extent = [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855] -use_basemap_from_layers = false -[[layers]] +do_not_use_default_basemap = false +[[map_layer]] type = "wms" url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" name = "masque_hdf_ign_carto_latin1" -[[layers]] +[[map_layer]] type = "wfs" url = "https://www.geo2france.fr/geoserver/cr_hdf/ows" name = "masque_hdf_ign_carto_latin1" @@ -42,8 +42,8 @@ my.sample.text = "Un bon exemple de texte." export const MAP_CONFIG_FIXTURE = { MAX_ZOOM: 10, MAX_EXTENT: [-418263.418776, 5251529.591305, 961272.067714, 6706890.609855], - USE_BASEMAP_FROM_LAYERS: false, - LAYERS: [ + DO_NOT_USE_DEFAULT_BASEMAP: false, + MAP_LAYERS: [ { TYPE: 'xyz', URL: 'https://some-basemap-server',