Skip to content

Commit

Permalink
Merge pull request #745 from geoadmin/feat_PB-368_selected_features_r…
Browse files Browse the repository at this point in the history
…ework

PB-368 : selected features tooltip/infobox rework
  • Loading branch information
pakb authored Apr 12, 2024
2 parents 1d65eb3 + 4c167b0 commit ceaddcd
Show file tree
Hide file tree
Showing 75 changed files with 1,750 additions and 1,010 deletions.
22 changes: 12 additions & 10 deletions adr/2021_03_16_url_param_structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
> Date: 16.03.2021
> Updated: 17.11.2023
> Updated: 10.04.2024
## Context

Expand Down Expand Up @@ -95,17 +95,19 @@ The layer ID of the external Layers are in the following format (note that only

- an external WMS: `WMS|GET_CAP_BASE_URL|LAYER_ID`
- The WMS version is taken from the Get Capabilities
- an external group of WMS layer : `WMS|GET_CAP_BASE_URL|LAYER_ID`
- We don't differentiate between group of layers and regular WMS layer in the URL. This differentiation was neither done in the legacy viewer.
- an external WMTS: `WMTS|GET_CAP_BASE_URL|LAYER_ID`
- The WMTS version is taken from the Get Capabilities
- an external KML: `KML|URL|TITLE`
- TITLE is optional and used as display in the active layers, if omitted then it will be displayed as `KML`
- a geoadmin KML: `KML|URL|TITLE`
- TITLE is set to `Drawing` upon drawing creation and in the current language at that time
- a geoadmin KML with adminId: `KML|URL|TITLE@adminId=ADMIN_ID`
- an external GPX: `GPX|GPX|TITLE`
- TITLE is optional and used as display in the active layers, if omitted then it will be displayed as `GPX`
- an external KMZ: `KMZ|KMZ|TITLE` (needs to pass by proxy to be unzipped)
- TITLE is optional and used as display in the active layers, if omitted then it will be displayed as `KMZ`
- an external KML: `KML|URL`
- The title is read from the metadata
- a geoadmin KML: `KML|URL`
- The title is read from the metadata
- a geoadmin KML with adminId: `KML|URL@adminId=ADMIN_ID`
- The title is read from the metadata
- an external GPX: `GPX|URL`
- The title is read from the metadata
- an external KMZ: `KMZ|URL` (needs to pass by proxy to be unzipped)

## Consequences

Expand Down
5 changes: 1 addition & 4 deletions src/api/features/LayerFeature.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@ export default class LayerFeature extends SelectableFeature {
super({
id,
coordinates,
// using the layer name as title (so that user can differentiate the source)
title: layer.name,
// and the name as description (so that we do not lose track of this data)
description: name,
title: name,
extent,
geometry,
isEditable: false,
Expand Down
18 changes: 15 additions & 3 deletions src/api/features/features.api.js
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,13 @@ async function identifyOnExternalWmsLayer(config) {
SERVICE: 'WMS',
VERSION: layer.wmsVersion ?? '1.3.0',
REQUEST: 'GetFeatureInfo',
LAYERS: layer.externalLayerId,
LAYERS: layer.id,
STYLES: null,
CRS: projection.epsg,
BBOX: requestExtent.join(','),
WIDTH: GET_FEATURE_INFO_FAKE_VIEWPORT_SIZE,
HEIGHT: GET_FEATURE_INFO_FAKE_VIEWPORT_SIZE,
QUERY_LAYERS: layer.externalLayerId,
QUERY_LAYERS: layer.id,
INFO_FORMAT: outputFormat,
FEATURE_COUNT: featureCount,
LANG: lang,
Expand Down Expand Up @@ -369,6 +369,7 @@ async function identifyOnExternalWmsLayer(config) {
return new LayerFeature({
layer,
id: feature.id,
name: feature.title ?? feature.name ?? feature.id,
data: feature.properties,
coordinates: getGeoJsonFeatureCoordinates(
geometry,
Expand Down Expand Up @@ -521,7 +522,18 @@ const getFeature = (layer, featureID, outputProjection, lang = 'en') => {
if (featureMetadata.bbox) {
featureExtent.push(...featureMetadata.bbox)
}
const featureName = featureMetadata?.properties?.name
let featureName = featureID
if (featureMetadata.properties) {
const { name = null, title = null } = featureMetadata.properties
const titleInCurrentLang = featureMetadata.properties[`title_${lang}`]
if (name) {
featureName = name
} else if (title) {
featureName = title
} else if (titleInCurrentLang) {
featureName = titleInCurrentLang
}
}

if (outputProjection.epsg !== LV95.epsg) {
if (featureExtent.length === 4) {
Expand Down
11 changes: 3 additions & 8 deletions src/api/layers/ExternalGroupOfLayers.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@ import LayerTypes from '@/api/layers/LayerTypes.enum'
*/
export default class ExternalGroupOfLayers extends ExternalLayer {
/**
* @param {String} externalLayerData.id Layer ID of the group to be found in GetCapabilities
* @param {String} externalLayerData.name Name of this layer to be shown to the user
* @param {number} [externalLayerData.opacity=1.0] The opacity of this layer, between 0.0
* (transparent) and 1.0 (opaque). Default is `1.0`
* @param {boolean} [externalLayerData.visible=true] If the layer should be shown on the map.
* Default is `true`
* @param {String} externalLayerData.baseUrl GetCapabilities base URL
* @param {String} externalLayerData.externalLayerId Layer ID of the group to be found in
* GetCapabilities
* @param {ExternalLayer[]} externalLayerData.layers Description of the layers being part of
* this group (they will all be displayed at the same time, in contrast to an aggregate
* layer)
Expand All @@ -53,11 +52,11 @@ export default class ExternalGroupOfLayers extends ExternalLayer {
throw new InvalidLayerDataError('Missing external layer data', externalLayerData)
}
const {
id = null,
name = null,
opacity = 1.0,
visible = true,
baseUrl = null,
externalLayerId = null,
layers = [],
attributions = null,
abstract = '',
Expand All @@ -74,13 +73,9 @@ export default class ExternalGroupOfLayers extends ExternalLayer {
)
}
super({
id,
name,
// format coming from https://github.com/geoadmin/web-mapviewer/blob/develop/adr/2021_03_16_url_param_structure.md
// NOTE we don't differentiate between group of layers and regular WMS layer. This differentiation was not
// done the legacy parameter and is not required.
id: `WMS|${baseUrl}|${externalLayerId}`,
type: LayerTypes.GROUP,
externalLayerId,
baseUrl,
opacity,
visible,
Expand Down
8 changes: 1 addition & 7 deletions src/api/layers/ExternalLayer.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,9 @@ export class LayerLegend {
export default class ExternalLayer extends AbstractLayer {
/**
* @param {String} externalLayerData.name Name of this layer to be shown to the user
* @param {String} externalLayerData.id The unique ID of this layer that will be used in the URL
* to identify it. It should typically contain the type of external layer we are dealing with,
* with the URL to get the capabilites or data of this layer.
* @param {String} externalLayerData.id Layer ID to use when requesting the tiles on the server
* @param {LayerTypes} externalLayerData.type The type of layer in GeoAdmin sense (WMTS, WMS,
* GeoJson, etc...)
* @param {String} externalLayerData.externalLayerId Layer ID to use when requesting the tiles
* on the server
* @param {String} externalLayerData.baseUrl Base URL to build the request to the data
* @param {number} [externalLayerData.opacity=1.0] The opacity of this layer, between 0.0
* (transparent) and 1.0 (opaque). Default is `1.0`
Expand Down Expand Up @@ -108,7 +104,6 @@ export default class ExternalLayer extends AbstractLayer {
name = null,
id = null,
type = null,
externalLayerId = null,
baseUrl = null,
opacity = 1.0,
visible = true,
Expand Down Expand Up @@ -141,7 +136,6 @@ export default class ExternalLayer extends AbstractLayer {
hasDescription: abstract?.length > 0 || legends?.length > 0,
hasLegend: legends?.length > 0,
})
this.externalLayerId = externalLayerId
this.abstract = abstract
this.extent = extent
this.legends = legends
Expand Down
12 changes: 3 additions & 9 deletions src/api/layers/ExternalWMSLayer.class.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import ExternalLayer from '@/api/layers/ExternalLayer.class'
import { InvalidLayerDataError } from '@/api/layers/InvalidLayerData.error'
import { encodeExternalLayerParam } from '@/api/layers/layers-external.api'
import LayerTypes from '@/api/layers/LayerTypes.enum'

/**
Expand All @@ -16,15 +15,14 @@ import LayerTypes from '@/api/layers/LayerTypes.enum'
*/
export default class ExternalWMSLayer extends ExternalLayer {
/**
* @param {String} externalWmsData.id Layer ID to use when requesting the tiles on the server
* @param {String} externalWmsData.name Name of this layer to be shown to the user
* @param {Number} [externalWmsData.opacity=1.0] The opacity of this layer, between 0.0
* (transparent) and 1.0 (opaque). Default is `1.0`
* @param {Boolean} [externalWmsData.visible=true] If the layer should be shown on the map.
* Default is `true`
* @param {String} externalWmsData.baseUrl Base URL to build WMS requests (no endpoint / URL
* param defined)
* @param {String} externalWmsData.externalLayerId Layer ID to use when requesting the tiles on
* the server
* @param {String} [externalWmsData.wmsVersion='1.3.0'] WMS protocol version to be used when
* querying this server. Default is `'1.3.0'`
* @param {LayerAttribution[]} [externalWmsData.attributions=null] Description of the data
Expand Down Expand Up @@ -54,11 +52,11 @@ export default class ExternalWMSLayer extends ExternalLayer {
throw new InvalidLayerDataError('Missing external WMS layer data', externalWmsData)
}
const {
id = null,
name = null,
opacity = 1.0,
visible = true,
baseUrl = null,
externalLayerId = null,
attributions = null,
wmsVersion = '1.3.0',
format = 'png',
Expand All @@ -72,12 +70,8 @@ export default class ExternalWMSLayer extends ExternalLayer {
} = externalWmsData
super({
name,
// format coming from https://github.com/geoadmin/web-mapviewer/blob/develop/adr/2021_03_16_url_param_structure.md
// base URL and name must be URL encoded (no & signs or other reserved URL chars must pass, or it could break URL param parsing)
// NOTE the pipe character needs to be encoded in order to not break the parsing
id: `WMS|${encodeExternalLayerParam(baseUrl)}|${encodeExternalLayerParam(externalLayerId)}`,
id,
type: LayerTypes.WMS,
externalLayerId,
baseUrl,
opacity,
visible,
Expand Down
11 changes: 3 additions & 8 deletions src/api/layers/ExternalWMTSLayer.class.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import ExternalLayer from '@/api/layers/ExternalLayer.class'
import { InvalidLayerDataError } from '@/api/layers/InvalidLayerData.error'
import { encodeExternalLayerParam } from '@/api/layers/layers-external.api'
import LayerTypes from '@/api/layers/LayerTypes.enum'

/**
Expand All @@ -17,15 +16,14 @@ import LayerTypes from '@/api/layers/LayerTypes.enum'
*/
export default class ExternalWMTSLayer extends ExternalLayer {
/**
* @param {String} externalWmtsData.id Layer ID to use when requesting the tiles on the server
* @param {String} externalWmtsData.name Name of this layer to be shown to the user
* @param {number} [externalWmtsData.opacity=1.0] The opacity of this layer, between 0.0
* (transparent) and 1.0 (opaque). Default is `1.0`
* @param {boolean} [externalWmtsData.visible=true] If the layer should be shown on the map or
* be hidden. Default is `true`
* @param {String} externalWmtsData.baseUrl To the getCapabilities.xml endpoint of the server
* for this layer
* @param {String} externalWmtsData.externalLayerId Layer ID to use when requesting the tiles on
* the server
* @param {LayerAttribution[]} [externalWmtsData.attributions=null] Description of the data
* owner(s) for this layer. When `null` is given it uses the default attribution which is
* based on the hostname of the GetCapabilities server. Default is `null`
Expand All @@ -46,11 +44,11 @@ export default class ExternalWMTSLayer extends ExternalLayer {
throw new InvalidLayerDataError('Missing external WMTS layer data', externalWmtsData)
}
const {
id = null,
name = null,
opacity = 1.0,
visible = true,
baseUrl = null,
externalLayerId = null,
attributions = null,
abstract = '',
extent = null,
Expand All @@ -61,11 +59,8 @@ export default class ExternalWMTSLayer extends ExternalLayer {
} = externalWmtsData
super({
name,
// format coming from https://github.com/geoadmin/web-mapviewer/blob/develop/adr/2021_03_16_url_param_structure.md
// NOTE the pipe character needs to be encoded in order to not break the parsing
id: `WMTS|${encodeExternalLayerParam(baseUrl)}|${encodeExternalLayerParam(externalLayerId)}`,
id,
type: LayerTypes.WMTS,
externalLayerId,
baseUrl,
ensureTrailingSlashInBaseUrl: true,
opacity,
Expand Down
5 changes: 1 addition & 4 deletions src/api/layers/KMLLayer.class.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import AbstractLayer, { LayerAttribution } from '@/api/layers/AbstractLayer.class'
import { InvalidLayerDataError } from '@/api/layers/InvalidLayerData.error'
import { encodeExternalLayerParam } from '@/api/layers/layers-external.api'
import LayerTypes from '@/api/layers/LayerTypes.enum'
import { API_SERVICE_KML_BASE_URL } from '@/config'
import { parseKmlName } from '@/utils/kmlUtils'
Expand Down Expand Up @@ -52,9 +51,7 @@ export default class KMLLayer extends AbstractLayer {
const isExternal = kmlFileUrl.indexOf(API_SERVICE_KML_BASE_URL) === -1
super({
name: 'KML',
// format coming from https://github.com/geoadmin/web-mapviewer/blob/develop/adr/2021_03_16_url_param_structure.md
// NOTE the pipe character needs to be encoded in order to not break the parsing
id: `KML|${encodeExternalLayerParam(kmlFileUrl)}`,
id: kmlFileUrl,
type: LayerTypes.KML,
baseUrl: kmlFileUrl,
opacity: opacity ?? 1.0,
Expand Down
16 changes: 8 additions & 8 deletions src/api/layers/LayerTypes.enum.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@
* @enum {String}
*/
const LayerTypes = {
WMTS: 'wmts',
WMS: 'wms',
GEOJSON: 'geojson',
AGGREGATE: 'aggregate',
KML: 'kml',
GPX: 'gpx',
VECTOR: 'vector',
GROUP: 'group',
WMTS: 'WMTS',
WMS: 'WMS',
GEOJSON: 'GEOJSON',
AGGREGATE: 'AGGREGATE',
KML: 'KML',
GPX: 'GPX',
VECTOR: 'VECTOR',
GROUP: 'GROUP',
}
export default LayerTypes
4 changes: 2 additions & 2 deletions src/api/layers/WMSCapabilitiesParser.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,11 +187,11 @@ export default class WMSCapabilitiesParser {
)
).filter((layer) => !!layer)
return new ExternalGroupOfLayers({
id: layerId,
name: title,
opacity,
visible,
baseUrl: url,
externalLayerId: layerId,
layers,
attributions,
abstract,
Expand All @@ -203,11 +203,11 @@ export default class WMSCapabilitiesParser {
})
}
return new ExternalWMSLayer({
id: layerId,
name: title,
opacity,
visible,
baseUrl: url,
externalLayerId: layerId,
attributions,
wmsVersion: version,
format: 'png',
Expand Down
2 changes: 1 addition & 1 deletion src/api/layers/WMTSCapabilitiesParser.class.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,11 +109,11 @@ export default class WMTSCapabilitiesParser {
})

return new ExternalWMTSLayer({
id: attributes.layerId,
name: attributes.title,
opacity,
visible,
baseUrl: attributes.url,
externalLayerId: attributes.layerId,
attributions: attributes.attributions,
abstract: attributes.abstract,
extent: attributes.extent,
Expand Down
4 changes: 2 additions & 2 deletions src/api/layers/__tests__/KMLLayer.class.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ describe('KMLLayer', () => {
const fileId = '-uQyFMtTSCWC_9rZE3EJ6B'
const kmlFileUrl = `https://sys-public.dev.bgdi.ch/api/kml/files/${fileId}`
const kmlLayer = new KMLLayer({ kmlFileUrl })
const expectedID = `KML|${kmlFileUrl}`
expect(kmlLayer.id).toBe(expectedID)
expect(kmlLayer.id).toBe(kmlFileUrl)
expect(kmlLayer.baseUrl).toBe(kmlFileUrl)
})

it('should identify legacy KML', () => {
Expand Down
Loading

0 comments on commit ceaddcd

Please sign in to comment.