diff --git a/libs/feature/map/src/lib/layers-panel/layers-panel.component.ts b/libs/feature/map/src/lib/layers-panel/layers-panel.component.ts
index 389f8561d0..f0cb32051d 100644
--- a/libs/feature/map/src/lib/layers-panel/layers-panel.component.ts
+++ b/libs/feature/map/src/lib/layers-panel/layers-panel.component.ts
@@ -9,9 +9,14 @@ import { MapFacade } from '../+state/map.facade'
})
export class LayersPanelComponent {
layers$ = this.mapFacade.layers$
+ ogcUrl = ''
constructor(private mapFacade: MapFacade) {}
deleteLayer(index: number) {
this.mapFacade.removeLayer(index)
}
+
+ addLayer(layer) {
+ this.mapFacade.addLayer(layer)
+ }
}
diff --git a/libs/feature/map/src/lib/map-context/map-context.model.ts b/libs/feature/map/src/lib/map-context/map-context.model.ts
index e005842a20..12f07631ee 100644
--- a/libs/feature/map/src/lib/map-context/map-context.model.ts
+++ b/libs/feature/map/src/lib/map-context/map-context.model.ts
@@ -1,7 +1,6 @@
import type { FeatureCollection } from 'geojson'
import { Coordinate } from 'ol/coordinate'
import type { Extent } from 'ol/extent'
-import { Options } from 'ol/source/WMTS'
export enum MapContextLayerTypeEnum {
XYZ = 'xyz',
@@ -9,6 +8,7 @@ export enum MapContextLayerTypeEnum {
WMTS = 'wmts',
WFS = 'wfs',
GEOJSON = 'geojson',
+ OGCAPI = 'ogcapi',
}
export interface MapContextModel {
@@ -24,8 +24,8 @@ export interface MapContextLayerWmsModel {
export interface MapContextLayerWmtsModel {
type: 'wmts'
- options: Options
- extent?: Extent
+ url: string
+ name: string
}
interface MapContextLayerWfsModel {
@@ -34,6 +34,12 @@ interface MapContextLayerWfsModel {
name: string
}
+export interface MapContextLayerOgcapiModel {
+ type: 'ogcapi'
+ url: string
+ name: string
+}
+
interface LayerXyzModel {
type: 'xyz'
name?: string
@@ -71,6 +77,7 @@ export type MapContextLayerModel =
| MapContextLayerWfsModel
| MapContextLayerXyzModel
| MapContextLayerGeojsonModel
+ | MapContextLayerOgcapiModel
export interface MapContextViewModel {
center?: Coordinate // expressed in long/lat (EPSG:4326)
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 f522e93b7a..9de1279924 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
@@ -41,6 +41,48 @@ const mapStyleServiceMock = {
defaultHL: DEFAULT_STYLE_HL_FIXTURE,
},
}
+
+jest.mock('@camptocamp/ogc-client', () => ({
+ WmtsEndpoint: class {
+ constructor(private url) {}
+ isReady() {
+ return Promise.resolve({
+ getLayerByName: (name) => {
+ if (this.url.indexOf('error') > -1) {
+ throw new Error('Something went wrong')
+ }
+ return {
+ name,
+ latLonBoundingBox: [1.33, 48.81, 4.3, 51.1],
+ }
+ },
+ })
+ }
+ },
+ WfsEndpoint: class {
+ constructor(private url) {}
+ isReady() {
+ return Promise.resolve({
+ getLayerByName: (name) => {
+ if (this.url.indexOf('error') > -1) {
+ throw new Error('Something went wrong')
+ }
+ return {
+ name,
+ latLonBoundingBox: [1.33, 48.81, 4.3, 51.1],
+ }
+ },
+ getSingleFeatureTypeName: () => {
+ return 'ms:commune_actuelle_3857'
+ },
+ getFeatureUrl: () => {
+ return 'https://www.geograndest.fr/geoserver/region-grand-est/ows?service=WFS&version=1.1.0&request=GetFeature&outputFormat=application%2Fjson&typename=ms%3Acommune_actuelle_3857&srsname=EPSG%3A3857&bbox=10%2C20%2C30%2C40%2CEPSG%3A3857&maxFeatures=10000'
+ },
+ })
+ }
+ },
+}))
+
describe('MapContextService', () => {
let service: MapContextService
@@ -110,7 +152,7 @@ describe('MapContextService', () => {
const urls = source.getUrls()
expect(urls.length).toBe(1)
expect(urls[0]).toBe(
- 'https://www.geograndest.fr/geoserver/region-grand-est/ows'
+ 'https://www.geograndest.fr/geoserver/region-grand-est/ows?REQUEST=GetCapabilities&SERVICE=WMS'
)
})
it('set WMS gutter of 20px', () => {
@@ -322,7 +364,7 @@ describe('MapContextService', () => {
const layerWMSUrl = (map.getLayers().item(1) as TileLayer)
.getSource()
.getUrls()[0]
- expect(layerWMSUrl).toEqual('https://some-wms-server/')
+ expect(layerWMSUrl).toEqual('https://some-wms-server')
})
it('add one WFS layer from config on top of baselayer', () => {
const layerWFSSource = (
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 6b2d53fc94..5e723badbe 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
@@ -22,9 +22,9 @@ import { LayerConfig, MapConfig } from '@geonetwork-ui/util/app-config'
import { FeatureCollection } from 'geojson'
import { fromLonLat } from 'ol/proj'
import WMTS from 'ol/source/WMTS'
-import { removeSearchParams } from '@geonetwork-ui/util/shared'
import { Geometry } from 'ol/geom'
import Feature from 'ol/Feature'
+import { WfsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
export const DEFAULT_BASELAYER_CONTEXT: MapContextLayerXyzModel = {
type: MapContextLayerTypeEnum.XYZ,
@@ -77,6 +77,15 @@ export class MapContextService {
const { type } = layerModel
const style = this.styleService.styles.default
switch (type) {
+ case MapContextLayerTypeEnum.OGCAPI:
+ return new VectorLayer({
+ source: new VectorSource({
+ format: new GeoJSON(),
+ url: layerModel.url,
+ }),
+ style,
+ })
+
case MapContextLayerTypeEnum.XYZ:
return new TileLayer({
source: new XYZ({
@@ -87,44 +96,63 @@ export class MapContextService {
case MapContextLayerTypeEnum.WMS:
return new TileLayer({
source: new TileWMS({
- url: removeSearchParams(layerModel.url, ['request', 'service']),
+ url: layerModel.url,
params: { LAYERS: layerModel.name },
gutter: 20,
}),
})
- case MapContextLayerTypeEnum.WMTS:
- return new TileLayer({
- source: new WMTS(layerModel.options),
+ case MapContextLayerTypeEnum.WMTS: {
+ // TODO: isolate this in utils service
+ const olLayer = new TileLayer({})
+ const endpoint = new WmtsEndpoint(layerModel.url)
+ endpoint.isReady().then(async (endpoint) => {
+ const layerName = endpoint.getSingleLayerName() ?? layerModel.name
+ const layer = endpoint.getLayerByName(layerName)
+ const matrixSet = layer.matrixSets[0]
+ const tileGrid = await endpoint.getOpenLayersTileGrid(layer.name)
+ const resourceUrl = layer.resourceLinks[0]
+ const dimensions = endpoint.getDefaultDimensions(layer.name)
+ olLayer.setSource(
+ new WMTS({
+ layer: layer.name,
+ style: layer.defaultStyle,
+ matrixSet: matrixSet.identifier,
+ format: resourceUrl.format,
+ url: resourceUrl.url,
+ requestEncoding: resourceUrl.encoding,
+ tileGrid,
+ projection: matrixSet.crs,
+ dimensions,
+ })
+ )
})
- case MapContextLayerTypeEnum.WFS:
- return new VectorLayer({
- source: new VectorSource({
- format: new GeoJSON(),
- url: function (extent) {
- const urlObj = new URL(
- removeSearchParams(layerModel.url, [
- 'service',
- 'version',
- 'request',
- ])
- )
- urlObj.searchParams.set('service', 'WFS')
- urlObj.searchParams.set('version', '1.1.0')
- urlObj.searchParams.set('request', 'GetFeature')
- urlObj.searchParams.set('outputFormat', 'application/json')
- urlObj.searchParams.set('typename', layerModel.name)
- urlObj.searchParams.set('srsname', 'EPSG:3857')
- urlObj.searchParams.set('bbox', `${extent.join(',')},EPSG:3857`)
- urlObj.searchParams.set(
- 'maxFeatures',
- WFS_MAX_FEATURES.toString()
- )
- return urlObj.toString()
- },
- strategy: bboxStrategy,
- }),
+ return olLayer
+ }
+ case MapContextLayerTypeEnum.WFS: {
+ const olLayer = new VectorLayer({
style,
})
+ new WfsEndpoint(layerModel.url).isReady().then((endpoint) => {
+ const featureType =
+ endpoint.getSingleFeatureTypeName() ?? layerModel.name
+ olLayer.setSource(
+ new VectorSource({
+ format: new GeoJSON(),
+ url: function (extent: [number, number, number, number]) {
+ return endpoint.getFeatureUrl(featureType, {
+ maxFeatures: WFS_MAX_FEATURES,
+ asJson: true,
+ outputCrs: 'EPSG:3857',
+ extent,
+ extentCrs: 'EPSG:3857',
+ })
+ },
+ strategy: bboxStrategy,
+ })
+ )
+ })
+ return olLayer
+ }
case MapContextLayerTypeEnum.GEOJSON: {
if ('url' in layerModel) {
return new VectorLayer({
diff --git a/libs/feature/map/src/lib/utils/map-utils.service.spec.ts b/libs/feature/map/src/lib/utils/map-utils.service.spec.ts
index 72419148ae..50afc5f787 100644
--- a/libs/feature/map/src/lib/utils/map-utils.service.spec.ts
+++ b/libs/feature/map/src/lib/utils/map-utils.service.spec.ts
@@ -46,17 +46,17 @@ jest.mock('@camptocamp/ogc-client', () => ({
boundingBoxes = {}
} else if (name.includes('4326')) {
boundingBoxes = {
- 'EPSG:4326': ['1', '2.6', '3.3', '4.2'],
- 'CRS:84': ['2.3', '50.6', '2.8', '50.9'],
+ 'EPSG:4326': [1, 2.6, 3.3, 4.2],
+ 'CRS:84': [2.3, 50.6, 2.8, 50.9],
}
} else if (name.includes('2154')) {
boundingBoxes = {
- 'EPSG:2154': ['650796.4', '7060330.6', '690891.3', '7090402.2'],
+ 'EPSG:2154': [650796.4, 7060330.6, 690891.3, 7090402.2],
}
} else {
boundingBoxes = {
- 'CRS:84': ['2.3', '50.6', '2.8', '50.9'],
- 'EPSG:2154': ['650796.4', '7060330.6', '690891.3', '7090402.2'],
+ 'CRS:84': [2.3, 50.6, 2.8, 50.9],
+ 'EPSG:2154': [650796.4, 7060330.6, 690891.3, 7090402.2],
}
}
return {
@@ -406,317 +406,4 @@ describe('MapUtilsService', () => {
expect(dragPanCondition.bind(interaction)(event)).toBe(false)
})
})
-
- const SAMPLE_WMTS_LINK = {
- name: 'GEOGRAPHICALGRIDSYSTEMS.ETATMAJOR10',
- url: new URL('http://my.server.org/wmts'),
- type: 'service',
- accessServiceProtocol: 'wmts',
- } as DatasetServiceDistribution
- const SAMPLE_WMTS_CAPABILITIES = `
-
-
-
-
-
-
-
-
- KVP
-
-
-
-
-
-
-
-
-
- Carte de l'état-major - environs de Paris (1818 - 1824)
- Carte des environs de Paris au 1 : 10 000 établie entre 1818 et 1824.
-
- 1.82682 48.3847
- 2.79738 49.5142
-
- GEOGRAPHICALGRIDSYSTEMS.ETATMAJOR10
- image/jpeg
-
-
- PM
-
-
- 6
- 21
- 22
- 32
- 32
-
-
- 7
- 43
- 44
- 64
- 64
-
-
- 8
- 87
- 88
- 129
- 129
-
-
-
-
-
- PM
- EPSG:3857
-
- 0
- 559082264.0287178958533332
-
- -20037508.3427892476320267 20037508.3427892476320267
-
- 256
- 256
- 1
- 1
-
-
- 1
- 279541132.0143588959472254
-
- -20037508.3427892476320267 20037508.3427892476320267
-
- 256
- 256
- 2
- 2
-
-
- 2
- 139770566.0071793960087234
-
- -20037508.3427892476320267 20037508.3427892476320267
-
- 256
- 256
- 4
- 4
-
-
- 3
- 69885283.0035897239868063
-
- -20037508.3427892476320267 20037508.3427892476320267
-
- 256
- 256
- 8
- 8
-
-
-
-`
-
- describe('#getWmtsOptionsFromCapabilities', () => {
- let originalFetch
- beforeEach(() => {
- originalFetch = window.fetch
- })
- afterEach(() => {
- window.fetch = originalFetch
- })
- describe('nominal', () => {
- let wmtsLayer: MapContextLayerWmtsModel
- beforeEach(async () => {
- ;(window as any).fetch = jest.fn(() =>
- Promise.resolve({
- ok: true,
- status: 200,
- text: () => Promise.resolve(SAMPLE_WMTS_CAPABILITIES),
- })
- )
- wmtsLayer = await firstValueFrom(
- service.getWmtsLayerFromCapabilities(SAMPLE_WMTS_LINK)
- )
- })
- it('appends query params to the URL', () => {
- expect(window.fetch).toHaveBeenCalledWith(
- 'http://my.server.org/wmts?SERVICE=WMTS&REQUEST=GetCapabilities'
- )
- })
- it('returns appropriate WMTS options', () => {
- expect(wmtsLayer).toMatchObject({
- type: 'wmts',
- options: {
- format: 'image/jpeg',
- layer: 'GEOGRAPHICALGRIDSYSTEMS.ETATMAJOR10',
- matrixSet: 'PM',
- requestEncoding: 'KVP',
- style: 'normal',
- urls: ['https://wxs.ign.fr/cartes/geoportail/wmts?'],
- },
- })
- })
- describe('layer extent', () => {
- describe('when the WGS84BoundingBox is defined', () => {
- it('set the WGS84BoundingBox', () => {
- expect(wmtsLayer.extent).toEqual([
- 1.82682, 48.3847, 2.79738, 49.5142,
- ])
- })
- })
- describe('when the WGS84BoundingBox is not defined', () => {
- beforeEach(async () => {
- ;(window as any).fetch = jest.fn(() =>
- Promise.resolve({
- ok: true,
- status: 200,
- text: () =>
- Promise.resolve(
- SAMPLE_WMTS_CAPABILITIES.replace(
- /WGS84BoundingBox/g,
- 'NoWGS84BoundingBox'
- )
- ),
- })
- )
- wmtsLayer = await firstValueFrom(
- service.getWmtsLayerFromCapabilities(SAMPLE_WMTS_LINK)
- )
- })
-
- it('set the WGS84BoundingBox', () => {
- expect(wmtsLayer.extent).toBeUndefined()
- })
- })
- })
- })
- describe('http error', () => {
- let error
- beforeEach(async () => {
- ;(window as any).fetch = jest.fn(() =>
- Promise.resolve({
- ok: false,
- status: 403,
- text: () => `
-
- Le service est inconnu pour ce serveur.
-
-`,
- })
- )
- try {
- await firstValueFrom(
- service.getWmtsLayerFromCapabilities(SAMPLE_WMTS_LINK)
- )
- } catch (e) {
- error = e
- }
- })
- it('throws an explicit error', () => {
- expect(error).toBeInstanceOf(Error)
- expect(error.message).toMatch('request failed')
- })
- })
- describe('parsing error', () => {
- let error
- beforeEach(async () => {
- ;(window as any).fetch = jest.fn(() =>
- Promise.resolve({
- ok: true,
- status: 200,
- text: () =>
- Promise.resolve(
- '{ "response": "This is probably not what you expected!" }'
- ),
- })
- )
- try {
- await firstValueFrom(
- service.getWmtsLayerFromCapabilities(SAMPLE_WMTS_LINK)
- )
- } catch (e) {
- error = e
- }
- })
- it('throws an explicit error', () => {
- expect(error).toBeInstanceOf(Error)
- expect(error.message).toMatch('parsing failed')
- })
- })
- })
-
- describe('#getRecordExtent', () => {
- it('returns the extent of the record', () => {
- const record = {
- spatialExtents: [
- {
- description: 'Rheinfelden',
- geometry: {
- type: 'Polygon',
- coordinates: [
- [
- [7.7638, 47.543],
- [7.7637, 47.543],
- [7.7636, 47.543],
- [7.7635, 47.543],
- [7.7633, 47.5429],
- [7.763, 47.5429],
- [7.7638, 47.543],
- ],
- ],
- },
- },
- {
- description: 'Kaiseraugst',
- geometry: {
- type: 'Polygon',
- coordinates: [
- [
- [7.764, 47.5429],
- [7.7641, 47.5423],
- [7.7643, 47.5421],
- [7.7645, 47.5415],
- [7.7646, 47.5411],
- [7.7646, 47.5405],
- [7.7645, 47.5398],
- [7.7634, 47.5402],
- [7.7621, 47.5401],
- [7.7623, 47.5396],
- [7.764, 47.5429],
- ],
- ],
- },
- },
- {
- description: 'Möhlin',
- geometry: {
- type: 'Polygon',
- coordinates: [
- [
- [7.8335, 47.5357],
- [7.8319, 47.5358],
- [7.831, 47.536],
- [7.8301, 47.5363],
- [7.829, 47.5364],
- [7.8335, 47.5357],
- ],
- ],
- },
- },
- ],
- } as Partial
- const extent = service.getRecordExtent(record)
- expect(extent).toEqual([7.7621, 47.5357, 7.8335, 47.543])
- })
- })
})
diff --git a/libs/feature/map/src/lib/utils/map-utils.service.ts b/libs/feature/map/src/lib/utils/map-utils.service.ts
index 743d90d445..6e388204ea 100644
--- a/libs/feature/map/src/lib/utils/map-utils.service.ts
+++ b/libs/feature/map/src/lib/utils/map-utils.service.ts
@@ -12,7 +12,6 @@ import Source from 'ol/source/Source'
import ImageWMS from 'ol/source/ImageWMS'
import TileWMS from 'ol/source/TileWMS'
import VectorSource from 'ol/source/Vector'
-import { optionsFromCapabilities } from 'ol/source/WMTS'
import { defaults, DragPan, Interaction, MouseWheelZoom } from 'ol/interaction'
import {
mouseOnly,
@@ -20,23 +19,17 @@ import {
platformModifierKeyOnly,
primaryAction,
} from 'ol/events/condition'
-import WMTSCapabilities from 'ol/format/WMTSCapabilities'
-import { from, Observable } from 'rxjs'
+import { Observable } from 'rxjs'
import { map } from 'rxjs/operators'
import {
MapContextLayerModel,
- MapContextLayerTypeEnum,
MapContextLayerWmsModel,
- MapContextLayerWmtsModel,
} from '../map-context/map-context.model'
import Collection from 'ol/Collection'
import MapBrowserEvent from 'ol/MapBrowserEvent'
-import {
- CatalogRecord,
- DatasetDistribution,
-} from '@geonetwork-ui/common/domain/model/record'
+import { CatalogRecord } from '@geonetwork-ui/common/domain/model/record'
import { ProxyService } from '@geonetwork-ui/util/shared'
-import { WmsEndpoint } from '@camptocamp/ogc-client'
+import { WmsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
import { LONLAT_CRS_CODES } from '../constant/projections'
import { fromEPSGCode, register } from 'ol/proj/proj4'
import proj4 from 'proj4/dist/proj4'
@@ -152,11 +145,14 @@ export class MapUtilsService {
} else if (layer && layer.type === 'wms') {
latLonExtent = await this.getWmsLayerExtent(layer)
} else if (layer && layer.type === 'wmts') {
- if (layer.extent) {
- latLonExtent = layer.extent
- } else {
- return layer.options.tileGrid.getExtent()
- }
+ // TODO: isolate this in utils service
+ latLonExtent = await new WmtsEndpoint(layer.url)
+ .isReady()
+ .then((endpoint) => {
+ const layerName = endpoint.getSingleLayerName() ?? layer.name
+ const wmtsLayer = endpoint.getLayerByName(layerName)
+ return wmtsLayer.latLonBoundingBox
+ })
} else {
return null
}
@@ -180,59 +176,19 @@ export class MapUtilsService {
LONLAT_CRS_CODES.includes(crs)
)
if (lonLatCRS) {
- return boundingBoxes[lonLatCRS].map(parseFloat)
+ return boundingBoxes[lonLatCRS]
} else {
const availableEPSGCode = Object.keys(boundingBoxes)[0]
register(proj4)
const proj = await fromEPSGCode(availableEPSGCode)
- const bboxWithFiniteNumbers =
- boundingBoxes[availableEPSGCode].map(parseFloat)
- return transformExtent(bboxWithFiniteNumbers, proj, 'EPSG:4326')
+ return transformExtent(
+ boundingBoxes[availableEPSGCode],
+ proj,
+ 'EPSG:4326'
+ )
}
}
- getWmtsLayerFromCapabilities(
- link: DatasetDistribution
- ): Observable {
- const getCapabilitiesUrl = new URL(link.url, window.location.toString())
- getCapabilitiesUrl.searchParams.set('SERVICE', 'WMTS')
- getCapabilitiesUrl.searchParams.set('REQUEST', 'GetCapabilities')
- return from(
- fetch(getCapabilitiesUrl.toString())
- .then(async function (response) {
- if (!response.ok) {
- throw new Error(`WMTS GetCapabilities HTTP request failed with code ${
- response.status
- } and body:
-${await response.text()}`)
- }
- return response.text()
- })
- .then(function (text) {
- try {
- const result = new WMTSCapabilities().read(text)
- const options = optionsFromCapabilities(result, {
- layer: link.name,
- matrixSet: 'EPSG:3857',
- })
- const layerCap = result?.Contents?.Layer.find(
- (layer) => layer.Identifier === link.name
- )
- return {
- options,
- type: MapContextLayerTypeEnum.WMTS as 'wmts',
- ...(layerCap?.WGS84BoundingBox
- ? { extent: layerCap.WGS84BoundingBox }
- : {}),
- }
- } catch (e: any) {
- throw new Error(`WMTS GetCapabilities parsing failed:
-${e.stack || e.message || e}`)
- }
- })
- )
- }
-
prioritizePageScroll(interactions: Collection) {
interactions.clear()
interactions.extend(
diff --git a/libs/feature/record/src/lib/map-view/map-view.component.spec.ts b/libs/feature/record/src/lib/map-view/map-view.component.spec.ts
index 89288877dc..90167937f7 100644
--- a/libs/feature/record/src/lib/map-view/map-view.component.spec.ts
+++ b/libs/feature/record/src/lib/map-view/map-view.component.spec.ts
@@ -451,8 +451,9 @@ describe('MapViewComponent', () => {
expect(mapComponent.context).toEqual({
layers: [
{
+ name: 'orthophoto',
type: 'wmts',
- options: expect.any(Object),
+ url: 'http://abcd.com/wmts',
},
],
view: expect.any(Object),
diff --git a/libs/feature/record/src/lib/map-view/map-view.component.ts b/libs/feature/record/src/lib/map-view/map-view.component.ts
index 4bd4df379f..5cc2a7f295 100644
--- a/libs/feature/record/src/lib/map-view/map-view.component.ts
+++ b/libs/feature/record/src/lib/map-view/map-view.component.ts
@@ -188,7 +188,11 @@ export class MapViewComponent implements OnInit, OnDestroy {
link.type === 'service' &&
link.accessServiceProtocol === 'wmts'
) {
- return this.mapUtils.getWmtsLayerFromCapabilities(link)
+ return of({
+ url: link.url.toString(),
+ type: MapContextLayerTypeEnum.WMTS,
+ name: link.name,
+ })
} else if (
(link.type === 'service' &&
(link.accessServiceProtocol === 'wfs' ||
diff --git a/libs/util/data-fetcher/src/lib/readers/csv.spec.ts b/libs/util/data-fetcher/src/lib/readers/csv.spec.ts
index d182b0bb07..c8f74272f1 100644
--- a/libs/util/data-fetcher/src/lib/readers/csv.spec.ts
+++ b/libs/util/data-fetcher/src/lib/readers/csv.spec.ts
@@ -7,6 +7,14 @@ afterEach(() => {
jest.clearAllMocks()
})
+//todo: fix this test, to run without mocking useCache
+jest.mock('@camptocamp/ogc-client', () => ({
+ useCache: jest.fn(async (factory) =>
+ JSON.parse(JSON.stringify(await factory()))
+ ),
+ sharedFetch: jest.fn((url) => global.fetch(url)),
+}))
+
describe('CSV parsing', () => {
describe('parseCsv', () => {
describe('valid CSV with id', () => {
diff --git a/libs/util/data-fetcher/src/lib/readers/excel.spec.ts b/libs/util/data-fetcher/src/lib/readers/excel.spec.ts
index f2649022ae..b2830bdd56 100644
--- a/libs/util/data-fetcher/src/lib/readers/excel.spec.ts
+++ b/libs/util/data-fetcher/src/lib/readers/excel.spec.ts
@@ -12,6 +12,14 @@ const sampleXls = fs.readFileSync(
null
)
+//todo: fix this test, to run without mocking useCache
+jest.mock('@camptocamp/ogc-client', () => ({
+ useCache: jest.fn(async (factory) =>
+ JSON.parse(JSON.stringify(await factory()))
+ ),
+ sharedFetch: jest.fn((url) => global.fetch(url)),
+}))
+
describe('Excel parsing', () => {
describe('parseExcel', () => {
describe('.xslx file', () => {
diff --git a/libs/util/data-fetcher/src/lib/readers/geojson.spec.ts b/libs/util/data-fetcher/src/lib/readers/geojson.spec.ts
index 4122dd1b9b..63287e7be7 100644
--- a/libs/util/data-fetcher/src/lib/readers/geojson.spec.ts
+++ b/libs/util/data-fetcher/src/lib/readers/geojson.spec.ts
@@ -3,6 +3,14 @@ import fetchMock from 'fetch-mock-jest'
import path from 'path'
import fs from 'fs/promises'
+//todo: fix this test, to run without mocking useCache
+jest.mock('@camptocamp/ogc-client', () => ({
+ useCache: jest.fn(async (factory) =>
+ JSON.parse(JSON.stringify(await factory()))
+ ),
+ sharedFetch: jest.fn((url) => global.fetch(url)),
+}))
+
describe('geojson parsing', () => {
describe('parseGeojson', () => {
describe('Valid Geojson (array of features)', () => {
diff --git a/libs/util/data-fetcher/src/lib/readers/gml.spec.ts b/libs/util/data-fetcher/src/lib/readers/gml.spec.ts
index e8d0f09948..ed5076c44e 100644
--- a/libs/util/data-fetcher/src/lib/readers/gml.spec.ts
+++ b/libs/util/data-fetcher/src/lib/readers/gml.spec.ts
@@ -6,6 +6,14 @@ import fetchMock from 'fetch-mock-jest'
import path from 'path'
import fs from 'fs/promises'
+//todo: fix this test, to run without mocking useCache
+jest.mock('@camptocamp/ogc-client', () => ({
+ useCache: jest.fn(async (factory) =>
+ JSON.parse(JSON.stringify(await factory()))
+ ),
+ sharedFetch: jest.fn((url) => global.fetch(url)),
+}))
+
const singleFeatureValidGml = `
({
+ useCache: jest.fn(async (factory) =>
+ JSON.parse(JSON.stringify(await factory()))
+ ),
+ sharedFetch: jest.fn((url) => global.fetch(url)),
+}))
+
describe('json parsing', () => {
describe('parseJson', () => {
describe('valid JSON with id', () => {
diff --git a/package-lock.json b/package-lock.json
index 9e4aca1a0e..195668fdca 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -23,7 +23,7 @@
"@angular/router": "16.1.7",
"@bartholomej/ngx-translate-extract": "^8.0.2",
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
- "@camptocamp/ogc-client": "^0.4.0",
+ "@camptocamp/ogc-client": "^1.1.0-RC.3",
"@geospatial-sdk/geocoding": "^0.0.5-alpha.2",
"@ltd/j-toml": "~1.35.2",
"@messageformat/core": "^3.0.1",
@@ -3651,11 +3651,31 @@
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/@camptocamp/ogc-client": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/@camptocamp/ogc-client/-/ogc-client-0.4.0.tgz",
- "integrity": "sha512-fGLkg4xyZQg4xbZx8E8HqACfZJZ4ijcpBDgwYnDzCAX+AjnAhqUqs/jwtR7i9xgoOLcjAftPsQVZWVcDLufytw==",
+ "version": "1.1.0-RC.3",
+ "resolved": "https://registry.npmjs.org/@camptocamp/ogc-client/-/ogc-client-1.1.0-RC.3.tgz",
+ "integrity": "sha512-XZJwp0vxTQGtJD3t4GdTHJDLTidlPmv0sBvXskEt0A0cmrdaGUgBqr8KPeDfhjZfq99WFcXv/Gb3+hQXA0+LmQ==",
"dependencies": {
- "@rgrove/parse-xml": "^4.0.1"
+ "@rgrove/parse-xml": "^4.1.0"
+ },
+ "peerDependencies": {
+ "ol": ">5.x",
+ "proj4": ">2.8"
+ },
+ "peerDependenciesMeta": {
+ "ol": {
+ "optional": true
+ },
+ "proj4": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@camptocamp/ogc-client/node_modules/@rgrove/parse-xml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@rgrove/parse-xml/-/parse-xml-4.1.0.tgz",
+ "integrity": "sha512-pBiltENdy8SfI0AeR1e5TRpS9/9Gl0eiOEt6ful2jQfzsgvZYWqsKiBWaOCLdocQuk0wS7KOHI37n0C1pnKqTw==",
+ "engines": {
+ "node": ">=14.0.0"
}
},
"node_modules/@colors/colors": {
diff --git a/package.json b/package.json
index d516bf2623..bf37f4ae1b 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"@angular/router": "16.1.7",
"@bartholomej/ngx-translate-extract": "^8.0.2",
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
- "@camptocamp/ogc-client": "^0.4.0",
+ "@camptocamp/ogc-client": "^1.1.0-RC.3",
"@geospatial-sdk/geocoding": "^0.0.5-alpha.2",
"@ltd/j-toml": "~1.35.2",
"@messageformat/core": "^3.0.1",
diff --git a/package/package.json b/package/package.json
index cf48675b41..40675b1994 100644
--- a/package/package.json
+++ b/package/package.json
@@ -38,7 +38,7 @@
},
"dependencies": {
"@biesbjerg/ngx-translate-extract-marker": "^1.0.0",
- "@camptocamp/ogc-client": "^0.4.0",
+ "@camptocamp/ogc-client": "^1.1.0-RC.3",
"@geospatial-sdk/geocoding": "^0.0.5-alpha.2",
"@ltd/j-toml": "~1.35.2",
"@messageformat/core": "^3.0.1",
diff --git a/translations/de.json b/translations/de.json
index f8324d3d2e..a1fbcf03bc 100644
--- a/translations/de.json
+++ b/translations/de.json
@@ -177,6 +177,7 @@
"map.add.layer": "Eine Ebene hinzufügen",
"map.add.layer.catalog": "Aus dem Katalog",
"map.add.layer.file": "Aus einer Datei",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "Aus WFS",
"map.add.layer.wms": "Aus WMS",
"map.addFromFile.placeholder": "Klicke hier oder ziehe eine Datei herein",
@@ -188,6 +189,7 @@
"map.loading.data": "Kartendaten werden geladen...",
"map.loading.service": "Dienst wird geladen...",
"map.navigation.message": "Bitte verwenden Sie STRG + Maus (oder zwei Finger auf einem Mobilgerät), um die Karte zu navigieren",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "Datenquelle",
"map.wfs.urlInput.hint": "Geben Sie die WFS URL ein",
"map.wms.urlInput.hint": "Geben Sie die WMS URL ein",
diff --git a/translations/en.json b/translations/en.json
index dd45df888c..c43d66ee41 100644
--- a/translations/en.json
+++ b/translations/en.json
@@ -177,6 +177,7 @@
"map.add.layer": "Add a layer",
"map.add.layer.catalog": "From the catalog",
"map.add.layer.file": "From a file",
+ "map.add.layer.ogc.api": "From OGC API",
"map.add.layer.wfs": "From WFS",
"map.add.layer.wms": "From WMS",
"map.addFromFile.placeholder": "Click or drop a file here",
@@ -188,6 +189,7 @@
"map.loading.data": "Loading map data...",
"map.loading.service": "Loading service...",
"map.navigation.message": "Please use CTRL + mouse (or two fingers on mobile) to navigate the map",
+ "map.ogc.urlInput.hint": "Enter OGC API service URL",
"map.select.layer": "Data source",
"map.wfs.urlInput.hint": "Enter WFS service URL",
"map.wms.urlInput.hint": "Enter WMS service URL",
diff --git a/translations/es.json b/translations/es.json
index 9f82e0ab23..8552c95c54 100644
--- a/translations/es.json
+++ b/translations/es.json
@@ -177,6 +177,7 @@
"map.add.layer": "",
"map.add.layer.catalog": "",
"map.add.layer.file": "",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "",
"map.add.layer.wms": "",
"map.addFromFile.placeholder": "",
@@ -188,6 +189,7 @@
"map.loading.data": "",
"map.loading.service": "",
"map.navigation.message": "",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "",
"map.wfs.urlInput.hint": "",
"map.wms.urlInput.hint": "",
diff --git a/translations/fr.json b/translations/fr.json
index 799605a027..a0e7906c03 100644
--- a/translations/fr.json
+++ b/translations/fr.json
@@ -177,6 +177,7 @@
"map.add.layer": "Ajouter une couche",
"map.add.layer.catalog": "Du catalogue",
"map.add.layer.file": "À partir d'un fichier",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "Depuis un service WFS",
"map.add.layer.wms": "Depuis un service WMS",
"map.addFromFile.placeholder": "Cliquez ou déposez un fichier ici",
@@ -188,6 +189,7 @@
"map.loading.data": "Chargement des données...",
"map.loading.service": "Chargement du service...",
"map.navigation.message": "Veuillez utiliser CTRL + souris (ou deux doigts sur mobile) pour naviguer sur la carte",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "Source de données",
"map.wfs.urlInput.hint": "Entrez l'URL du service WFS",
"map.wms.urlInput.hint": "Entrez l'URL du service WMS",
diff --git a/translations/it.json b/translations/it.json
index 9b03fabaca..fd48ddb71a 100644
--- a/translations/it.json
+++ b/translations/it.json
@@ -177,6 +177,7 @@
"map.add.layer": "Aggiungere un layer",
"map.add.layer.catalog": "Dal catalogo",
"map.add.layer.file": "Da un file",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "Da un WFS",
"map.add.layer.wms": "Da un WMS",
"map.addFromFile.placeholder": "Clicca o trascina un file qui",
@@ -188,6 +189,7 @@
"map.loading.data": "Caricamento dati...",
"map.loading.service": "Caricamento del servizio...",
"map.navigation.message": "Si prega di utilizzare CTRL + mouse (o due dita su mobile) per navigare sulla mappa",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "Sorgente dati",
"map.wfs.urlInput.hint": "Inserisci URL del servizio WFS",
"map.wms.urlInput.hint": "Inserisci URL del servizio WMS",
diff --git a/translations/nl.json b/translations/nl.json
index 64ee837518..449bb5d88e 100644
--- a/translations/nl.json
+++ b/translations/nl.json
@@ -177,6 +177,7 @@
"map.add.layer": "",
"map.add.layer.catalog": "",
"map.add.layer.file": "",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "",
"map.add.layer.wms": "",
"map.addFromFile.placeholder": "",
@@ -188,6 +189,7 @@
"map.loading.data": "",
"map.loading.service": "",
"map.navigation.message": "",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "",
"map.wfs.urlInput.hint": "",
"map.wms.urlInput.hint": "",
diff --git a/translations/pt.json b/translations/pt.json
index 86fe64024b..f0c130712c 100644
--- a/translations/pt.json
+++ b/translations/pt.json
@@ -177,6 +177,7 @@
"map.add.layer": "",
"map.add.layer.catalog": "",
"map.add.layer.file": "",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "",
"map.add.layer.wms": "",
"map.addFromFile.placeholder": "",
@@ -188,6 +189,7 @@
"map.loading.data": "",
"map.loading.service": "",
"map.navigation.message": "",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "",
"map.wfs.urlInput.hint": "",
"map.wms.urlInput.hint": "",
diff --git a/translations/sk.json b/translations/sk.json
index db63a71d01..a5c07120a2 100644
--- a/translations/sk.json
+++ b/translations/sk.json
@@ -177,6 +177,7 @@
"map.add.layer": "Pridať vrstvu",
"map.add.layer.catalog": "Z katalógu",
"map.add.layer.file": "Zo súboru",
+ "map.add.layer.ogc.api": "",
"map.add.layer.wfs": "Z WFS",
"map.add.layer.wms": "Z WMS",
"map.addFromFile.placeholder": "Kliknite na tlačidlo alebo sem vložte súbor",
@@ -188,6 +189,7 @@
"map.loading.data": "Načítavanie dát mapy...",
"map.loading.service": "Načítavanie služieb...",
"map.navigation.message": "Použite prosím CTRL + myš (alebo dva prsty na mobilnom zariadení) na navigáciu po mape",
+ "map.ogc.urlInput.hint": "",
"map.select.layer": "Zdroj dát",
"map.wfs.urlInput.hint": "Zadajte URL adresu služby WFS",
"map.wms.urlInput.hint": "Zadajte URL adresu služby WMS",