Skip to content

Commit

Permalink
Merge pull request geonetwork#889 from geonetwork/handle-non-geospati…
Browse files Browse the repository at this point in the history
…al-ogc-services

[Fix] : Handle non geospatial ogc services
  • Loading branch information
cmoinier authored Jun 6, 2024
2 parents cd1164a + d89a1b0 commit aef4372
Show file tree
Hide file tree
Showing 11 changed files with 243 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class MdViewFacadeMock {
mapApiLinks$ = new BehaviorSubject([])
dataLinks$ = new BehaviorSubject([])
geoDataLinks$ = new BehaviorSubject([])
geoDataLinksWithGeometry$ = new BehaviorSubject([])
downloadLinks$ = new BehaviorSubject([])
apiLinks$ = new BehaviorSubject([])
otherLinks$ = new BehaviorSubject([])
Expand Down Expand Up @@ -377,6 +378,7 @@ describe('RecordMetadataComponent', () => {
})
describe('when a GEODATA link present', () => {
beforeEach(() => {
facade.geoDataLinksWithGeometry$.next(['link'])
facade.geoDataLinks$.next(['link'])
fixture.detectChanges()
mapTab = fixture.debugElement.queryAll(By.css('mat-tab'))[0]
Expand All @@ -399,7 +401,7 @@ describe('RecordMetadataComponent', () => {
beforeEach(() => {
facade.mapApiLinks$.next(['link'])
facade.dataLinks$.next(null)
facade.geoDataLinks$.next(null)
facade.geoDataLinksWithGeometry$.next(null)
fixture.detectChanges()
tableTab = fixture.debugElement.queryAll(By.css('mat-tab'))[1]
chartTab = fixture.debugElement.queryAll(By.css('mat-tab'))[2]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { SourcesService } from '@geonetwork-ui/feature/catalog'
import { SearchService } from '@geonetwork-ui/feature/search'
import { ErrorType } from '@geonetwork-ui/ui/elements'
import { BehaviorSubject, combineLatest } from 'rxjs'
import { filter, map, mergeMap } from 'rxjs/operators'
import { filter, map, mergeMap, startWith } from 'rxjs/operators'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
import {
Keyword,
Expand All @@ -22,12 +22,12 @@ export class RecordMetadataComponent {

displayMap$ = combineLatest([
this.metadataViewFacade.mapApiLinks$,
this.metadataViewFacade.geoDataLinks$,
this.metadataViewFacade.geoDataLinksWithGeometry$,
]).pipe(
map(
([mapLinks, geoDataLinks]) =>
mapLinks?.length > 0 || geoDataLinks?.length > 0
)
map(([mapApiLinks, geoDataLinksWithGeometry]) => {
return mapApiLinks?.length > 0 || geoDataLinksWithGeometry?.length > 0
}),
startWith(false)
)

displayData$ = combineLatest([
Expand Down
8 changes: 8 additions & 0 deletions libs/common/fixtures/src/lib/records.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ Cette section contient des *caractères internationaux* (ainsi que des "caractè
description: 'This WFS service offers direct download capability',
identifierInService: 'my:featuretype',
},
{
type: 'service',
url: new URL('https://my-org.net/ogc'),
accessServiceProtocol: 'ogcFeatures',
name: 'my:featuretype',
description: 'This OGC service offers direct download capability',
identifierInService: 'my:featuretype',
},
],
lineage: `This record was edited manually to test the conversion processes
Expand Down
27 changes: 27 additions & 0 deletions libs/feature/dataviz/src/lib/service/data.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ jest.mock('@camptocamp/ogc-client', () => ({
})
}
allCollections = Promise.resolve([{ name: 'collection1' }])
featureCollections =
this.url.indexOf('error.http') > -1
? Promise.reject(new Error())
: Promise.resolve(['collection1', 'collection2'])
getCollectionItem(collection, id) {
return Promise.resolve('item1')
}
},
}))

Expand Down Expand Up @@ -700,5 +707,25 @@ describe('DataService', () => {
)
})
})
describe('#getItemsFromOgcApi', () => {
describe('calling getItemsFromOgcApi() with a valid URL', () => {
it('returns the first collection item when collections array is not empty', async () => {
const item = await service.getItemsFromOgcApi(
'https://my.ogc.api/features'
)
expect(item).toBe('item1')
})
})

describe('calling getItemsFromOgcApi() with an erroneous URL', () => {
it('throws an error', async () => {
try {
await service.getItemsFromOgcApi('http://error.http/ogcapi')
} catch (e) {
expect(e.message).toBe('ogc.unreachable.unknown')
}
})
})
})
})
})
14 changes: 14 additions & 0 deletions libs/feature/dataviz/src/lib/service/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { marker } from '@biesbjerg/ngx-translate-extract-marker'
import {
OgcApiCollectionInfo,
OgcApiEndpoint,
OgcApiRecord,
WfsEndpoint,
WfsVersion,
} from '@camptocamp/ogc-client'
Expand Down Expand Up @@ -183,6 +184,19 @@ export class DataService {
})
}

async getItemsFromOgcApi(url: string): Promise<OgcApiRecord> {
const endpoint = new OgcApiEndpoint(this.proxy.getProxiedUrl(url))
return await endpoint.featureCollections
.then((collections) => {
return collections.length
? endpoint.getCollectionItem(collections[0], '1')
: null
})
.catch((error) => {
throw new Error(`ogc.unreachable.unknown`)
})
}

getDownloadLinksFromEsriRest(
esriRestLink: DatasetServiceDistribution
): DatasetDistribution[] {
Expand Down
10 changes: 10 additions & 0 deletions libs/feature/map/src/lib/utils/map-utils.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,16 @@ describe('MapUtilsService', () => {
})
})

describe('getRecordExtent', () => {
it('should return null if spatialExtents is not present or is an empty array', () => {
const record1: Partial<CatalogRecord> = {}
const record2: Partial<CatalogRecord> = { spatialExtents: [] }

expect(service.getRecordExtent(record1)).toBeNull()
expect(service.getRecordExtent(record2)).toBeNull()
})
})

describe('#prioritizePageScroll', () => {
const interactions = defaults()
let dragRotate
Expand Down
2 changes: 1 addition & 1 deletion libs/feature/map/src/lib/utils/map-utils.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ export class MapUtilsService {
}

getRecordExtent(record: Partial<CatalogRecord>): Extent {
if (!('spatialExtents' in record)) {
if (!('spatialExtents' in record) || record.spatialExtents.length === 0) {
return null
}
// transform an array of geojson geometries into a bbox
Expand Down
30 changes: 15 additions & 15 deletions libs/feature/record/src/lib/map-view/map-view.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ jest.mock('@geonetwork-ui/util/app-config', () => ({

class MdViewFacadeMock {
mapApiLinks$ = new Subject()
geoDataLinks$ = new Subject()
geoDataLinksWithGeometry$ = new Subject()
metadata$ = of({ title: 'abcd' })
}

Expand Down Expand Up @@ -272,7 +272,7 @@ describe('MapViewComponent', () => {
describe('with no link compatible with MAP_API or GEODATA usage', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([])
mdViewFacade.geoDataLinksWithGeometry$.next([])
tick()
fixture.detectChanges()
}))
Expand Down Expand Up @@ -317,7 +317,7 @@ describe('MapViewComponent', () => {
accessServiceProtocol: 'wms',
},
])
mdViewFacade.geoDataLinks$.next([])
mdViewFacade.geoDataLinksWithGeometry$.next([])
tick()
fixture.detectChanges()
}))
Expand Down Expand Up @@ -365,7 +365,7 @@ describe('MapViewComponent', () => {
accessServiceProtocol: 'wms',
},
])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
url: new URL('http://abcd.com/wfs'),
name: 'featuretype',
Expand Down Expand Up @@ -419,7 +419,7 @@ describe('MapViewComponent', () => {
describe('with a link using WFS protocol', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
url: new URL('http://abcd.com/wfs'),
name: 'featuretype',
Expand Down Expand Up @@ -453,7 +453,7 @@ describe('MapViewComponent', () => {
accessServiceProtocol: 'wmts',
},
])
mdViewFacade.geoDataLinks$.next([])
mdViewFacade.geoDataLinksWithGeometry$.next([])
tick(200)
fixture.detectChanges()
}))
Expand All @@ -474,7 +474,7 @@ describe('MapViewComponent', () => {
describe('with a link using ESRI:REST protocol', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
name: 'mes_hdf',
url: new URL(
Expand Down Expand Up @@ -503,7 +503,7 @@ describe('MapViewComponent', () => {
describe('with a link using OGC API protocol', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
name: 'ogc layer',
url: new URL('http://abcd.com/data/ogcapi'),
Expand All @@ -530,7 +530,7 @@ describe('MapViewComponent', () => {
describe('with a link using WFS which returns an error', () => {
beforeEach(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
url: new URL('http://abcd.com/wfs/error'),
name: 'featuretype',
Expand All @@ -548,7 +548,7 @@ describe('MapViewComponent', () => {
describe('during download', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
url: new URL('http://abcd.com/data.geojson'),
name: 'data.geojson',
Expand All @@ -571,7 +571,7 @@ describe('MapViewComponent', () => {
describe('after download', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
url: new URL('http://abcd.com/data.geojson'),
name: 'data.geojson',
Expand Down Expand Up @@ -605,7 +605,7 @@ describe('MapViewComponent', () => {
describe('when receiving several metadata records', () => {
beforeEach(fakeAsync(() => {
mdViewFacade.mapApiLinks$.next([])
mdViewFacade.geoDataLinks$.next([
mdViewFacade.geoDataLinksWithGeometry$.next([
{
url: new URL('http://abcd.com/data.geojson'),
name: 'data.geojson',
Expand All @@ -620,7 +620,7 @@ describe('MapViewComponent', () => {
accessServiceProtocol: 'wms',
},
])
mdViewFacade.geoDataLinks$.next([])
mdViewFacade.geoDataLinksWithGeometry$.next([])
tick()
fixture.detectChanges()
}))
Expand Down Expand Up @@ -671,7 +671,7 @@ describe('MapViewComponent', () => {
accessServiceProtocol: 'wms',
},
])
mdViewFacade.geoDataLinks$.next([])
mdViewFacade.geoDataLinksWithGeometry$.next([])
dropdownComponent.selectValue.emit(1)
tick()
fixture.detectChanges()
Expand Down Expand Up @@ -856,7 +856,7 @@ describe('MapViewComponent', () => {
describe('changing the map context', () => {
beforeEach(() => {
jest.spyOn(component, 'resetSelection')
mdViewFacade.geoDataLinks$.next([])
mdViewFacade.geoDataLinksWithGeometry$.next([])
mdViewFacade.mapApiLinks$.next([])
})
it('resets selection', () => {
Expand Down
10 changes: 6 additions & 4 deletions libs/feature/record/src/lib/map-view/map-view.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ export class MapViewComponent implements OnInit, OnDestroy {

compatibleMapLinks$ = combineLatest([
this.mdViewFacade.mapApiLinks$,
this.mdViewFacade.geoDataLinks$,
this.mdViewFacade.geoDataLinksWithGeometry$,
]).pipe(
map(([mapApiLinks, geoDataLinks]) => [...mapApiLinks, ...geoDataLinks])
map(([mapApiLinks, geoDataLinksWithGeometry]) => {
return [...mapApiLinks, ...geoDataLinksWithGeometry]
})
)

dropdownChoices$ = this.compatibleMapLinks$.pipe(
Expand Down Expand Up @@ -102,8 +104,8 @@ export class MapViewComponent implements OnInit, OnDestroy {
mapContext$ = this.currentLayers$.pipe(
switchMap((layers) =>
from(this.mapUtils.getLayerExtent(layers[0])).pipe(
catchError((error) => {
console.warn(error) // FIXME: report this to the user somehow
catchError(() => {
this.error = 'The layer has no extent'
return of(undefined)
}),
map(
Expand Down
Loading

0 comments on commit aef4372

Please sign in to comment.