From 37290df24069970f51768bb557f48694ec1d48c6 Mon Sep 17 00:00:00 2001 From: Olivia Guyot Date: Fri, 31 Jan 2025 10:30:37 +0100 Subject: [PATCH] feat(ui): use OGCAPI collection name if available If multiple collections are available in an endpoint then use the name in the online resource instead of the first collection --- .../record-api-form.component.spec.ts | 43 ++++++++++++++++--- .../record-api-form.component.ts | 12 ++++-- 2 files changed, 45 insertions(+), 10 deletions(-) diff --git a/libs/ui/elements/src/lib/record-api-form/record-api-form.component.spec.ts b/libs/ui/elements/src/lib/record-api-form/record-api-form.component.spec.ts index 36f54ea413..d3f19a7132 100644 --- a/libs/ui/elements/src/lib/record-api-form/record-api-form.component.spec.ts +++ b/libs/ui/elements/src/lib/record-api-form/record-api-form.component.spec.ts @@ -13,9 +13,16 @@ const mockDatasetServiceDistribution: DatasetServiceDistribution = { jest.mock('@camptocamp/ogc-client', () => ({ OgcApiEndpoint: class { + collections_ = [{ name: 'uniqueCollection' }] constructor(private url) {} get allCollections() { - return Promise.resolve([{ name: 'feature1' }]) + if (this.url.toString().includes('multiple')) { + return Promise.resolve([ + { name: 'firstCollection' }, + { name: 'otherCollection' }, + ]) + } + return Promise.resolve(this.collections_) } getCollectionInfo(collectionId) { return Promise.resolve({ @@ -91,7 +98,7 @@ describe('RecordApiFormComponent', () => { expect(component.format$.getValue()).toBe('application/json') const url = await firstValueFrom(component.apiQueryUrl$) expect(url).toBe( - 'https://api.example.com/data/collections/feature1/items?limit=-1&f=application%2Fjson' + 'https://api.example.com/data/collections/uniqueCollection/items?limit=-1&f=application%2Fjson' ) }) }) @@ -105,7 +112,7 @@ describe('RecordApiFormComponent', () => { component.setFormat(mockFormat) const url = await firstValueFrom(component.apiQueryUrl$) expect(url).toBe( - `https://api.example.com/data/collections/feature1/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}` + `https://api.example.com/data/collections/uniqueCollection/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}` ) }) it('should remove the param in url if value is null', async () => { @@ -117,7 +124,7 @@ describe('RecordApiFormComponent', () => { component.setFormat(mockFormat) const url = await firstValueFrom(component.apiQueryUrl$) expect(url).toBe( - `https://api.example.com/data/collections/feature1/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}` + `https://api.example.com/data/collections/uniqueCollection/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}` ) }) it('should remove the param in url if value is zero', async () => { @@ -129,9 +136,24 @@ describe('RecordApiFormComponent', () => { component.setFormat(mockFormat) const url = await firstValueFrom(component.apiQueryUrl$) expect(url).toBe( - `https://api.example.com/data/collections/feature1/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}` + `https://api.example.com/data/collections/uniqueCollection/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}` ) }) + + describe('when multiple collections available', () => { + it('uses the link name', async () => { + component.apiLink = { + ...mockDatasetServiceDistribution, + url: new URL('https://api.example.com/multiple'), + name: 'myCollection', + } + fixture.detectChanges() + const url = await firstValueFrom(component.apiQueryUrl$) + expect(url).toBe( + `https://api.example.com/multiple/collections/myCollection/items?limit=-1&f=application%2Fjson` + ) + }) + }) }) describe('#resetUrl', () => { @@ -175,7 +197,16 @@ describe('RecordApiFormComponent', () => { expect(component.format$.getValue()).toBe('application/json') const url = await firstValueFrom(component.apiQueryUrl$) expect(url).toBe( - `https://api.example.com/data?type=mockFeatureType&options={"outputFormat":"application/json","limit":-1}` + `https://api.example.com/data?type=mockFeatureType&options={"outputFormat":"application/json"}` + ) + }) + + it('sets maxFeatures if a limit is set', async () => { + component.setLimit('12') + expect(component.limit$.getValue()).toBe('12') + const url = await firstValueFrom(component.apiQueryUrl$) + expect(url).toBe( + `https://api.example.com/data?type=mockFeatureType&options={"outputFormat":"application/json","maxFeatures":12}` ) }) }) diff --git a/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts b/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts index 11e4e77b17..d84f96c697 100644 --- a/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts +++ b/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts @@ -61,7 +61,6 @@ export class RecordApiFormComponent { { value: 'application/json', label: 'JSON' }, ] endpoint: WfsEndpoint | OgcApiEndpoint | undefined - firstCollection: string | undefined apiQueryUrl$ = combineLatest([ this.offset$, @@ -128,7 +127,7 @@ export class RecordApiFormComponent { this.supportOffset = this.endpoint.supportsStartIndex() return this.endpoint.getServiceInfo().outputFormats } else { - return (await this.endpoint.getCollectionInfo(this.firstCollection)) + return (await this.endpoint.getCollectionInfo(this.apiFeatureType)) .itemFormats } } @@ -140,7 +139,11 @@ export class RecordApiFormComponent { await (this.endpoint as WfsEndpoint).isReady() } else { this.endpoint = new OgcApiEndpoint(this.apiBaseUrl) - this.firstCollection = (await this.endpoint.allCollections)[0].name + const collections = await this.endpoint.allCollections + // if there's only one collection, use this instead of the name given in the link. + if (collections.length === 1) { + this.apiFeatureType = collections[0].name + } } this.endpoint$.next(this.endpoint) } @@ -161,11 +164,12 @@ export class RecordApiFormComponent { } if (this.endpoint instanceof WfsEndpoint) { + delete options.limit options.maxFeatures = limit !== '-1' ? Number(limit) : undefined return this.endpoint.getFeatureUrl(this.apiFeatureType, options) } else { return await this.endpoint.getCollectionItemsUrl( - this.firstCollection, + this.apiFeatureType, options ) }