Skip to content

Commit

Permalink
feat(ui): use mimeTypes in API form query url generation
Browse files Browse the repository at this point in the history
  • Loading branch information
jahow committed Jan 31, 2025
1 parent 070a455 commit 272c2f7
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 47 deletions.
2 changes: 1 addition & 1 deletion apps/datahub-e2e/src/e2e/datasetDetailPage.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,7 @@ describe('api form', () => {
cy.get('@secondInput').type('87')

cy.get('@apiForm').find('gn-ui-dropdown-selector').as('dropdown')
cy.get('@dropdown').eq(0).selectDropdownOption('geojson')
cy.get('@dropdown').eq(0).selectDropdownOption('application/geo+json')

cy.get('@apiForm')
.find('gn-ui-copy-text-button')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,48 +88,48 @@ describe('RecordApiFormComponent', () => {
expect(component.apiBaseUrl).toBe('https://api.example.com/data')
expect(component.offset$.getValue()).toBe('')
expect(component.limit$.getValue()).toBe('-1')
expect(component.format$.getValue()).toBe('json')
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=json'
'https://api.example.com/data/collections/feature1/items?limit=-1&f=application%2Fjson'
)
})
})
describe('When URL params are changed', () => {
it('should update query URL correctly when setting offset, limit, and format', async () => {
const mockOffset = '10'
const mockLimit = '20'
const mockFormat = 'json'
const mockFormat = 'text/csv'
component.setOffset(mockOffset)
component.setLimit(mockLimit)
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=${mockFormat}`
`https://api.example.com/data/collections/feature1/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}`
)
})
it('should remove the param in url if value is null', async () => {
const mockOffset = '0'
const mockLimit = '20'
const mockFormat = 'json'
const mockFormat = 'application/json'
component.setOffset(mockOffset)
component.setLimit(mockLimit)
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=${mockFormat}`
`https://api.example.com/data/collections/feature1/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}`
)
})
it('should remove the param in url if value is zero', async () => {
const mockOffset = '10'
const mockLimit = '0'
const mockFormat = 'json'
const mockFormat = 'application/json'
component.setOffset(mockOffset)
component.setLimit(mockLimit)
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=${mockFormat}`
`https://api.example.com/data/collections/feature1/items?limit=${mockLimit}&offset=${mockOffset}&f=${encodeURIComponent(mockFormat)}`
)
})
})
Expand All @@ -139,7 +139,7 @@ describe('RecordApiFormComponent', () => {
component.resetUrl()
expect(component.offset$.getValue()).toBe('')
expect(component.limit$.getValue()).toBe('-1')
expect(component.format$.getValue()).toBe('json')
expect(component.format$.getValue()).toBe('application/json')
})
})

Expand All @@ -151,9 +151,9 @@ describe('RecordApiFormComponent', () => {
it('should parse the returned formats', () => {
component.parseOutputFormats()
expect(component.outputFormats).toEqual([
{ value: 'csv', label: 'CSV' },
{ value: 'geojson', label: 'GEOJSON' },
{ value: 'json', label: 'JSON' },
{ value: 'text/csv', label: 'CSV' },
{ value: 'application/geo+json', label: 'GEOJSON' },
{ value: 'application/json', label: 'JSON' },
])
})
})
Expand All @@ -172,10 +172,10 @@ describe('RecordApiFormComponent', () => {
expect(component.accessServiceProtocol).toBe('wfs')
expect(component.offset$.getValue()).toBe('')
expect(component.limit$.getValue()).toBe('-1')
expect(component.format$.getValue()).toBe('json')
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":"json","limit":-1}`
`https://api.example.com/data?type=mockFeatureType&options={"outputFormat":"application/json","limit":-1}`
)
})
})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { OgcApiEndpoint, WfsEndpoint } from '@camptocamp/ogc-client'
import { MimeType, OgcApiEndpoint, WfsEndpoint } from '@camptocamp/ogc-client'
import {
DatasetServiceDistribution,
ServiceProtocol,
Expand All @@ -8,6 +8,7 @@ import { mimeTypeToFormat } from '@geonetwork-ui/util/shared'
import { BehaviorSubject, combineLatest, filter, map, switchMap } from 'rxjs'
import {
CopyTextButtonComponent,
DropdownChoice,
DropdownSelectorComponent,
TextInputComponent,
} from '@geonetwork-ui/ui/inputs'
Expand All @@ -17,12 +18,7 @@ import { TranslateModule } from '@ngx-translate/core'
const DEFAULT_PARAMS = {
OFFSET: '',
LIMIT: '-1',
FORMAT: 'json',
}

interface OutputFormats {
itemFormats?: any[]
outputFormats?: any[]
FORMAT: 'application/json',
}

@Component({
Expand All @@ -41,7 +37,7 @@ interface OutputFormats {
})
export class RecordApiFormComponent {
@Input() set apiLink(value: DatasetServiceDistribution) {
this.outputFormats = [{ value: 'json', label: 'JSON' }]
this.outputFormats = [{ value: 'application/json', label: 'JSON' }]
this.accessServiceProtocol = value ? value.accessServiceProtocol : undefined
this.apiFeatureType = value ? value.name : undefined
if (value) {
Expand All @@ -61,7 +57,9 @@ export class RecordApiFormComponent {
apiFeatureType: string
supportOffset = true
accessServiceProtocol: ServiceProtocol | undefined
outputFormats = [{ value: 'json', label: 'JSON' }]
outputFormats: DropdownChoice[] = [
{ value: 'application/json', label: 'JSON' },
]
endpoint: WfsEndpoint | OgcApiEndpoint | undefined
firstCollection: string | undefined

Expand Down Expand Up @@ -104,42 +102,34 @@ export class RecordApiFormComponent {

async parseOutputFormats() {
if (!this.endpoint) return
const apiUrl = this.apiBaseUrl.endsWith('?')
? this.apiBaseUrl.slice(0, -1)
: this.apiBaseUrl
const outputFormats = await this.getOutputFormats(apiUrl)

const formatsList = outputFormats.itemFormats
? this.mapFormats(outputFormats.itemFormats)
: this.mapFormats(outputFormats.outputFormats || [])
const outputFormats = (await this.getOutputFormats()).map(
this.mimeTypeToFormatName
)

this.outputFormats = this.outputFormats
.concat(formatsList.filter(Boolean))
.concat(outputFormats.filter(Boolean))
.filter(
(format, index, self) =>
index === self.findIndex((t) => t.value === format.value)
)
.sort((a, b) => a.label.localeCompare(b.label))
}

mapFormats(formats: any[]) {
return formats.map((format) => {
const normalizedFormat = mimeTypeToFormat(format)
return normalizedFormat
? { label: normalizedFormat.toUpperCase(), value: normalizedFormat }
: null
})
mimeTypeToFormatName(mimeType: MimeType): DropdownChoice | null {
const formatName = mimeTypeToFormat(mimeType)
return formatName
? { label: formatName.toUpperCase(), value: mimeType }
: null
}

async getOutputFormats(url: string): Promise<OutputFormats> {
if (!this.endpoint) return {}
async getOutputFormats(): Promise<MimeType[]> {
if (!this.endpoint) return []
if (this.endpoint instanceof WfsEndpoint) {
this.supportOffset = this.endpoint.supportsStartIndex()
return this.endpoint.getServiceInfo() as OutputFormats
return this.endpoint.getServiceInfo().outputFormats
} else {
return (await this.endpoint.getCollectionInfo(
this.firstCollection
)) as OutputFormats
return (await this.endpoint.getCollectionInfo(this.firstCollection))
.itemFormats
}
}

Expand All @@ -166,7 +156,7 @@ export class RecordApiFormComponent {
outputFormat: format,
startIndex: offset ? Number(offset) : undefined,
maxFeatures: limit !== '-1' ? Number(limit) : undefined,
limit: limit !== '-1' ? Number(limit) : limit === '-1' ? -1 : undefined,
limit: limit !== '-1' ? Number(limit) : -1,
offset: offset !== '' ? Number(offset) : undefined,
}

Expand Down

0 comments on commit 272c2f7

Please sign in to comment.