diff --git a/apps/datahub/src/app/app.module.ts b/apps/datahub/src/app/app.module.ts
index 0c69562559..ec34f60ce3 100644
--- a/apps/datahub/src/app/app.module.ts
+++ b/apps/datahub/src/app/app.module.ts
@@ -41,6 +41,7 @@ import {
UiLayoutModule,
} from '@geonetwork-ui/ui/layout'
import { UiSearchModule } from '@geonetwork-ui/ui/search'
+import { IgnApiDlComponent } from '@geonetwork-ui/feature/record'
import {
getGlobalConfig,
getOptionalSearchConfig,
@@ -95,6 +96,7 @@ import { UiWidgetsModule } from '@geonetwork-ui/ui/widgets'
import { RecordUserFeedbacksComponent } from './record/record-user-feedbacks/record-user-feedbacks.component'
import { LetDirective } from '@ngrx/component'
import { OrganizationPageComponent } from './organization/organization-page/organization-page.component'
+import { MatButtonToggleModule } from '@angular/material/button-toggle'
export const metaReducers: MetaReducer[] = !environment.production ? [] : []
@@ -168,6 +170,7 @@ export const metaReducers: MetaReducer[] = !environment.production ? [] : []
BlockListComponent,
PreviousNextButtonsComponent,
LetDirective,
+ MatButtonToggleModule,
],
providers: [
importProvidersFrom(FeatureAuthModule),
diff --git a/apps/datahub/src/app/record/record-apis/record-apis.component.html b/apps/datahub/src/app/record/record-apis/record-apis.component.html
index a4bf38449f..30cdc4d61d 100644
--- a/apps/datahub/src/app/record/record-apis/record-apis.component.html
+++ b/apps/datahub/src/app/record/record-apis/record-apis.component.html
@@ -36,9 +36,20 @@
-
+
record.metadata.api.form.title
+
+ record.metadata.api.form.title.gpf
+
+
+
diff --git a/apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts b/apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts
index 699b7e7b08..994c4ceb0e 100644
--- a/apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts
+++ b/apps/datahub/src/app/record/record-apis/record-apis.component.spec.ts
@@ -50,7 +50,7 @@ describe('RecordApisComponent', () => {
expect(component.selectedApiLink).toEqual(serviceDistributionMock)
})
it('should update maxHeight for transition', () => {
- expect(component.maxHeight).toEqual('500px')
+ expect(component.maxHeight).toEqual('700px')
})
it('should update opacity for transition', () => {
expect(component.opacity).toEqual(1)
diff --git a/apps/datahub/src/app/record/record-apis/record-apis.component.ts b/apps/datahub/src/app/record/record-apis/record-apis.component.ts
index c89732aff9..72c1970d3e 100644
--- a/apps/datahub/src/app/record/record-apis/record-apis.component.ts
+++ b/apps/datahub/src/app/record/record-apis/record-apis.component.ts
@@ -20,6 +20,7 @@ export class RecordApisComponent implements OnInit {
maxHeight = '0px'
opacity = 0
+ displayApiIgnForm: boolean
selectedApiLink: DatasetServiceDistribution
apiLinks$ = this.facade.apiLinks$
@@ -51,6 +52,8 @@ export class RecordApisComponent implements OnInit {
}
openRecordApiForm(link: DatasetServiceDistribution) {
+ this.displayApiIgnForm =
+ link.accessServiceProtocol === 'GPFDL' ? true : false
this.selectedApiLink = link
this.setStyle(link)
}
@@ -61,7 +64,7 @@ export class RecordApisComponent implements OnInit {
}
setStyle(link: DatasetServiceDistribution) {
- this.maxHeight = link === undefined ? '0px' : '500px'
+ this.maxHeight = link === undefined ? '0px' : '700px'
this.opacity = link === undefined ? 0 : 1
}
diff --git a/libs/api/metadata-converter/src/lib/common/distribution.mapper.ts b/libs/api/metadata-converter/src/lib/common/distribution.mapper.ts
index e5d66e3b66..172fc2190c 100644
--- a/libs/api/metadata-converter/src/lib/common/distribution.mapper.ts
+++ b/libs/api/metadata-converter/src/lib/common/distribution.mapper.ts
@@ -7,6 +7,7 @@ export function matchProtocol(protocol: string): ServiceProtocol {
if (/wps/i.test(protocol)) return 'wps'
if (/ogc\W*api\W*features/i.test(protocol)) return 'ogcFeatures'
if (/esri/i.test(protocol)) return 'esriRest'
+ if (/DOWNLOAD-1/i.test(protocol)) return 'GPFDL'
return 'other'
}
diff --git a/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts b/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts
index cdf02b3482..656ee891c3 100644
--- a/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts
+++ b/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts
@@ -393,7 +393,8 @@ export class Gn4FieldMapper {
/^OGC:WMS/.test(protocol) ||
/^OGC:WFS/.test(protocol) ||
/^OGC:WMTS/.test(protocol) ||
- /ogc\W*api\W*features/i.test(protocol)
+ /ogc\W*api\W*features/i.test(protocol) ||
+ /^WWW:DOWNLOAD-/.test(protocol)
) {
return 'service'
}
diff --git a/libs/common/domain/src/lib/model/record/metadata.model.ts b/libs/common/domain/src/lib/model/record/metadata.model.ts
index 0589e96b7c..7952d917a0 100644
--- a/libs/common/domain/src/lib/model/record/metadata.model.ts
+++ b/libs/common/domain/src/lib/model/record/metadata.model.ts
@@ -113,6 +113,7 @@ export type ServiceProtocol =
| 'wmts'
| 'esriRest'
| 'ogcFeatures'
+ | 'GPFDL'
| 'other'
export type OnlineResourceType = 'service' | 'download' | 'link' | 'endpoint'
diff --git a/libs/feature/record/src/index.ts b/libs/feature/record/src/index.ts
index 5cd2bfe857..e9f1785563 100644
--- a/libs/feature/record/src/index.ts
+++ b/libs/feature/record/src/index.ts
@@ -7,3 +7,4 @@ export * from './lib/data-view-share/data-view-share.component'
export * from './lib/data-view-web-component/data-view-web-component.component'
export * from './lib/external-viewer-button/external-viewer-button.component'
export * from './lib/map-view/map-view.component'
+export * from './lib/ign-api-dl/ign-api-dl.component'
diff --git a/libs/feature/record/src/lib/feature-record.module.ts b/libs/feature/record/src/lib/feature-record.module.ts
index e0488ff889..be19442097 100644
--- a/libs/feature/record/src/lib/feature-record.module.ts
+++ b/libs/feature/record/src/lib/feature-record.module.ts
@@ -15,6 +15,8 @@ import {
METADATA_VIEW_FEATURE_STATE_KEY,
reducer,
} from './state/mdview.reducer'
+import { IgnApiDlComponent } from './ign-api-dl/ign-api-dl.component'
+import { IgnApiProduitComponent } from './ign-api-produit/ign-api-produit.component'
import { MatTabsModule } from '@angular/material/tabs'
import { MatIconModule } from '@angular/material/icon'
import { PopupAlertComponent, UiWidgetsModule } from '@geonetwork-ui/ui/widgets'
@@ -35,6 +37,8 @@ import { DataViewShareComponent } from './data-view-share/data-view-share.compon
DataViewPermalinkComponent,
DataViewWebComponentComponent,
DataViewShareComponent,
+ IgnApiDlComponent,
+ IgnApiProduitComponent,
],
imports: [
CommonModule,
@@ -61,6 +65,7 @@ import { DataViewShareComponent } from './data-view-share/data-view-share.compon
DataViewPermalinkComponent,
DataViewWebComponentComponent,
DataViewShareComponent,
+ IgnApiDlComponent,
],
})
export class FeatureRecordModule {}
diff --git a/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.css b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.css
new file mode 100644
index 0000000000..0aa4ba7d0b
--- /dev/null
+++ b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.css
@@ -0,0 +1,22 @@
+:host ::ng-deep input {
+ color: black;
+ opacity: 1;
+}
+
+:host ::ng-deep gn-ui-copy-text-button input[type='text'] {
+ color: black;
+ background-color: white;
+}
+
+:host ::ng-deep gn-ui-copy-text-button button,
+host ::ng-deep gn-ui-copy-text-button button:hover {
+ background-color: var(--color-secondary) !important;
+}
+
+:host ::ng-deep gn-ui-copy-text-button button mat-icon {
+ color: white !important;
+ opacity: 1 !important;
+}
+:host ::ng-deep gn-ui-copy-text-button button:hover mat-icon {
+ color: lightgrey !important;
+}
diff --git a/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.html b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.html
new file mode 100644
index 0000000000..3dc41b5f21
--- /dev/null
+++ b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.html
@@ -0,0 +1,108 @@
+
+
+
+
+ record.metadata.api.form.create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ page$.value }}/{{ pageMax$ | async }}
+
+
+
+
+
= (pageMax$ | async)">
+
+
+
+
+
+
+
+
diff --git a/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.spec.ts b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.spec.ts
new file mode 100644
index 0000000000..78d9cb64a6
--- /dev/null
+++ b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.spec.ts
@@ -0,0 +1,150 @@
+import { TestBed, ComponentFixture } from '@angular/core/testing'
+
+import { DatasetServiceDistribution } from '@geonetwork-ui/common/domain/model/record'
+import { firstValueFrom } from 'rxjs'
+import { Choice, UiInputsModule } from '@geonetwork-ui/ui/inputs'
+import { TranslateModule } from '@ngx-translate/core'
+import { IgnApiDlComponent } from './ign-api-dl.component'
+import { HttpClientTestingModule } from '@angular/common/http/testing'
+import exp from 'constants'
+
+const mockDatasetServiceDistribution: DatasetServiceDistribution = {
+ url: new URL('https://api.example.com/data'),
+ type: 'service',
+ accessServiceProtocol: 'GPFDL',
+}
+
+describe('IgnApiDlComponent', () => {
+ let component: IgnApiDlComponent
+ let fixture: ComponentFixture
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ declarations: [IgnApiDlComponent],
+ imports: [
+ UiInputsModule,
+ HttpClientTestingModule,
+ TranslateModule.forRoot(),
+ ],
+ }).compileComponents()
+
+ fixture = TestBed.createComponent(IgnApiDlComponent)
+ component = fixture.componentInstance
+ component.apiLink = mockDatasetServiceDistribution
+ })
+
+ it('should create', () => {
+ expect(component).toBeTruthy()
+ })
+ describe('When panel is opened', () => {
+ it('should set the links and initial values correctly', async () => {
+ expect(component.apiBaseUrl).toBe('https://api.example.com/data')
+ expect(component.format$.getValue()).toBe('')
+ expect(component.zone$.getValue()).toBe('')
+ expect(component.crs$.getValue()).toBe('')
+ const url = await firstValueFrom(component.apiQueryUrl$)
+ expect(url).toBe('https://api.example.com/data?pageSize=200&page=0')
+ //expect(component.apiLink.accessServiceProtocol).toBe('GPFDL')
+ })
+ })
+ describe('When URL params are changed', () => {
+ describe('When Format changed', () => {
+ const bucketFormat: Choice[] = [
+ { value: 'SHP', label: 'SHP' },
+ { value: 'json', label: 'json' },
+ { value: 'SQL', label: 'SQL' },
+ ]
+ const mockFormat = 'SHP'
+ const mockBadFormat = 'notAFormat'
+ it('should be a correct format', async () => {
+ jest.spyOn(component, 'resetPage')
+ component.bucketPromisesFormat = bucketFormat
+ component.setFormat(mockFormat)
+ expect(component.format$.getValue()).toBe(mockFormat)
+ expect(component.resetPage).toHaveBeenCalled()
+ })
+
+ it('should not be a correct format', async () => {
+ component.bucketPromisesFormat = bucketFormat
+ component.setFormat(mockBadFormat)
+ expect(component.format$.getValue()).toBe('')
+ })
+ })
+ describe('When CRS changed', () => {
+ const bucketCRS: Choice[] = [
+ { value: 'CRS12', label: 'CRS1' },
+ { value: 'CRS2', label: 'CRS2' },
+ { value: 'CRS3', label: 'CRS3' },
+ ]
+ const mockCRS = 'CRS12'
+ const mockBadCRS = 'notACRS'
+ it('should be a correct CRS', async () => {
+ jest.spyOn(component, 'resetPage')
+ component.bucketPromisesCrs = bucketCRS
+ component.setCrs(mockCRS)
+ expect(component.crs$.getValue()).toBe(mockCRS)
+ expect(component.resetPage).toHaveBeenCalled()
+ })
+
+ it('should not be a correct CRS', async () => {
+ component.bucketPromisesCrs = bucketCRS
+ component.setCrs(mockBadCRS)
+ expect(component.crs$.getValue()).toBe('')
+ })
+ })
+ describe('When Zone changed', () => {
+ const bucketZone: Choice[] = [
+ { value: 'D01', label: 'D01' },
+ { value: 'D02', label: 'D02' },
+ { value: 'D03', label: 'D03' },
+ ]
+ const mockZone = 'D03'
+ const mockBadZone = 'notAZone'
+ it('should be a correct Zone', async () => {
+ jest.spyOn(component, 'resetPage')
+ component.bucketPromisesZone = bucketZone
+ component.setZone(mockZone)
+ expect(component.zone$.getValue()).toBe(mockZone)
+ expect(component.resetPage).toHaveBeenCalled()
+ })
+
+ it('should not be a correct Zone', async () => {
+ component.bucketPromisesZone = bucketZone
+ component.setZone(mockBadZone)
+ expect(component.zone$.getValue()).toBe('')
+ })
+ })
+
+ describe('When EditionDate changed', () => {
+ const mockEditionDate = '2022-04-30'
+ const mockBadEditionDate = '88-88-88'
+ it('hould be a correct edition date', () => {
+ jest.spyOn(component, 'resetPage')
+ component.setEditionDate(mockEditionDate)
+ expect(component.editionDate$.getValue()).toBe(mockEditionDate)
+ expect(component.resetPage).toHaveBeenCalled()
+ })
+ it('should not be a correct edition date', () => {
+ component.setEditionDate(mockBadEditionDate)
+ expect(component.editionDate$.getValue()).toBe('')
+ })
+ })
+
+ describe('When Url is reset', () => {
+ it('Should reset zone, format, crs, page and size value', () => {
+ component.resetUrl()
+ expect(component.zone$.getValue()).toBe('null')
+ expect(component.format$.getValue()).toBe('null')
+ expect(component.crs$.getValue()).toBe('null')
+ expect(component.page$.getValue()).toBe('0')
+ })
+ })
+
+ describe('When page is reset', () => {
+ it('Should reset page value', () => {
+ component.resetPage()
+ expect(component.page$.getValue()).toBe('0')
+ })
+ })
+ })
+})
diff --git a/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.ts b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.ts
new file mode 100644
index 0000000000..a741abd5ec
--- /dev/null
+++ b/libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.ts
@@ -0,0 +1,249 @@
+import {
+ ChangeDetectionStrategy,
+ Component,
+ Input,
+ OnInit,
+} from '@angular/core'
+import { DatasetServiceDistribution } from '@geonetwork-ui/common/domain/model/record'
+import { BehaviorSubject, Observable, combineLatest, map, mergeMap } from 'rxjs'
+import { HttpClient } from '@angular/common/http'
+import { Choice } from '@geonetwork-ui/ui/inputs'
+import axios from 'axios'
+
+export interface Label {
+ label: string
+}
+
+export interface FormatProduit {
+ title: string
+ update: string
+ format: Array
+ zone: Array
+}
+
+export interface FormatSortieProduit {
+ label: string
+ value: string | number
+}
+export interface ListUrl {
+ url: string
+}
+
+export interface listChoice {
+ zone: Choice[]
+ format: Choice[]
+ editionDate: Choice[]
+ crs: Choice[]
+}
+
+export interface TermBucket {
+ term: string
+ label: string | number
+}
+
+export interface Field {
+ entry: Array
+ link: any
+}
+
+@Component({
+ selector: 'gn-ui-ign-api-dl',
+ templateUrl: './ign-api-dl.component.html',
+ styleUrls: ['./ign-api-dl.component.css'],
+ changeDetection: ChangeDetectionStrategy.OnPush,
+})
+export class IgnApiDlComponent implements OnInit {
+ isOpen = false
+ collapsed = false
+ initialLimit = 50
+ apiBaseUrl: string
+ editionDate$ = new BehaviorSubject('')
+ zone$ = new BehaviorSubject('')
+ format$ = new BehaviorSubject('')
+ crs$ = new BehaviorSubject('')
+ page$ = new BehaviorSubject(1)
+ // a passer en config
+ url =
+ 'https://data.geopf.fr/telechargement/capabilities?outputFormat=application/json'
+ choices: any
+ bucketPromisesZone: Choice[]
+ bucketPromisesFormat: Choice[]
+ bucketPromisesCrs: Choice[]
+
+ constructor(protected http: HttpClient) {}
+
+ @Input() set apiLink(value: DatasetServiceDistribution) {
+ this.apiBaseUrl = value ? value.url.href : undefined
+ }
+
+ ngOnInit(): void {
+ this.bucketPromisesZone = [{ value: '', label: 'ZONE' }]
+ this.bucketPromisesFormat = [{ value: '', label: 'FORMAT' }]
+ this.bucketPromisesCrs = [{ value: '', label: 'CRS' }]
+ this.getFields()
+ }
+
+ apiQueryUrl$ = combineLatest([
+ this.zone$,
+ this.format$,
+ this.editionDate$,
+ this.crs$,
+ this.page$,
+ ]).pipe(
+ map(([zone, format, editionDate, crs, page]) => {
+ let outputUrl
+ if (this.apiBaseUrl) {
+ const url = new URL(this.apiBaseUrl) // initialisation de l'url avec l'url de base
+ const params = {
+ zone: zone,
+ format: format,
+ editionDate: editionDate,
+ crs: crs,
+ page: page,
+ } // initialisation des paramètres de filtres
+ for (const [key, value] of Object.entries(params)) {
+ if (value && value !== 'null') {
+ url.searchParams.set(key, String(value))
+ } else {
+ url.searchParams.delete(key)
+ }
+ }
+ outputUrl = url.toString()
+ } else {
+ console.error('erreur apibaseUrl null')
+ }
+ return outputUrl
+ })
+ // startWith(() => this.apiBaseUrl)
+ )
+
+ listFilteredProduct$ = this.apiQueryUrl$.pipe(
+ mergeMap((url) => {
+ console.log(url)
+
+ return this.getFilteredProduct$(url).pipe(
+ map((response) => response['entry'])
+ // startWith([])
+ )
+ })
+ )
+
+ pageMax$ = this.apiQueryUrl$.pipe(
+ mergeMap((url) => {
+ return this.getFilteredProduct$(url).pipe(
+ map((response) =>
+ Math.ceil(response['totalentries'] / Number(this.initialLimit))
+ )
+ )
+ })
+ )
+
+ getFilteredProduct$(url): Observable {
+ return this.http.get(url)
+ }
+
+ getLinkFormat(produit): string {
+ return produit['format'][0]['label']
+ }
+
+ setEditionDate(value: string) {
+ if (value.match(/[0-9]{4}-[0-1][0-9]-[0-3][0-9]/)) {
+ this.editionDate$.next(value)
+ this.resetPage()
+ }
+ }
+
+ setZone(value: string) {
+ if (this.bucketPromisesZone.map((choice) => choice.value).includes(value)) {
+ this.zone$.next(value)
+ this.resetPage()
+ }
+ }
+
+ setCrs(value: string) {
+ if (this.bucketPromisesCrs.map((choice) => choice.value).includes(value)) {
+ this.crs$.next(value)
+ this.resetPage()
+ }
+ }
+
+ setFormat(value: string) {
+ if (
+ this.bucketPromisesFormat.map((choice) => choice.value).includes(value)
+ ) {
+ this.format$.next(value)
+ this.resetPage()
+ }
+ }
+
+ resetUrl() {
+ // this.offset$.next(DEFAULT_PARAMS.OFFSET)
+ this.zone$.next('null')
+ this.format$.next('null')
+ this.crs$.next('null')
+ this.page$.next(1)
+ }
+ moreResult(): void {
+ this.page$.next(this.page$.value + 1)
+ }
+
+ lessResult(): void {
+ this.page$.next(this.page$.value - 1)
+ }
+
+ resetPage(): void {
+ this.page$.next(1)
+ }
+
+ async getCapabilities() {
+ let page = 0
+ let choicesTest = undefined
+ let pageCount = 1
+
+ while (choicesTest === undefined && pageCount > page) {
+ const response = await axios.get(
+ this.url.concat(`&limit=200&page=${page}`)
+ )
+
+ choicesTest = response.data.entry.filter(
+ (element) => element['id'] == this.apiBaseUrl
+ )[0]
+ page += 1
+ pageCount = response.data.pagecount
+ }
+
+ return choicesTest
+ }
+ async getFields() {
+ this.choices = await this.getCapabilities()
+
+ const tempZone = this.choices.zone.map((bucket) => ({
+ value: bucket.label,
+ label: bucket.term,
+ }))
+ tempZone.sort((a, b) => (a.label > b.label ? 1 : -1))
+ tempZone.unshift({ value: 'null', label: 'ZONE' })
+
+ this.bucketPromisesZone = tempZone
+
+ const tempFormat = this.choices.format.map((bucket) => ({
+ value: bucket.label,
+ label: bucket.term,
+ }))
+ tempFormat.sort((a, b) => (a.label > b.label ? 1 : -1))
+ tempFormat.unshift({ value: 'null', label: 'FORMAT' })
+
+ this.bucketPromisesFormat = tempFormat
+
+ const tempCrs = this.choices.category.map((bucket) => ({
+ value: bucket.label,
+ label: bucket.label,
+ }))
+ tempCrs.sort((a, b) => (a.label > b.label ? 1 : -1))
+ tempCrs.unshift({ value: 'null', label: 'CRS' })
+
+ this.bucketPromisesCrs = tempCrs
+
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ }
+}
diff --git a/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.css b/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.css
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.html b/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.html
new file mode 100644
index 0000000000..c413764ffa
--- /dev/null
+++ b/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.html
@@ -0,0 +1,37 @@
+
+
+
+ {{ link['title'] || link.name }}
+
+
+ {{ format || ('downloads.format.unknown' | translate) }}
+ datahub.search.filter.generatedByWfs
+
+
+
+
diff --git a/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.ts b/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.ts
new file mode 100644
index 0000000000..e3ecbfc07f
--- /dev/null
+++ b/libs/feature/record/src/lib/ign-api-produit/ign-api-produit.component.ts
@@ -0,0 +1,45 @@
+import { HttpClient, HttpErrorResponse } from '@angular/common/http'
+import {
+ ChangeDetectionStrategy,
+ Component,
+ EventEmitter,
+ Input,
+ OnInit,
+ Output,
+} from '@angular/core'
+import { Observable, catchError, map, mergeMap, tap, throwError } from 'rxjs'
+
+@Component({
+ selector: 'gn-ui-ign-api-produit',
+ templateUrl: './ign-api-produit.component.html',
+ styleUrls: ['./ign-api-produit.component.css'],
+})
+export class IgnApiProduitComponent implements OnInit {
+ @Input() link
+ @Input() color: string
+ @Input() format: string
+ @Input() isFromWfs: boolean
+
+ constructor(protected http: HttpClient) {}
+ liste$: Observable
+
+ ngOnInit(): void {
+ this.liste$ = this.http
+ .get(this.link['id'])
+ .pipe(map((response) => response['entry']))
+ }
+
+ downloadListe(): void {
+ this.http
+ .get(this.link['id'])
+ .pipe(
+ map((response) => response['entry']),
+ mergeMap((response) => response)
+ )
+ .subscribe((reponse) => this.download(reponse['id']))
+ }
+
+ download(url): void {
+ this.http.get(url).subscribe()
+ }
+}
diff --git a/libs/feature/record/src/lib/state/mdview.facade.ts b/libs/feature/record/src/lib/state/mdview.facade.ts
index 02c869e5d5..faed694ccf 100644
--- a/libs/feature/record/src/lib/state/mdview.facade.ts
+++ b/libs/feature/record/src/lib/state/mdview.facade.ts
@@ -15,6 +15,7 @@ import { LinkClassifierService, LinkUsage } from '@geonetwork-ui/util/shared'
import { DatavizConfigurationModel } from '@geonetwork-ui/common/domain/model/dataviz/dataviz-configuration.model'
import {
CatalogRecord,
+ DatasetServiceDistribution,
UserFeedback,
} from '@geonetwork-ui/common/domain/model/record'
import { AvatarServiceInterface } from '@geonetwork-ui/api/repository'
@@ -72,7 +73,14 @@ export class MdViewFacade {
apiLinks$ = this.allLinks$.pipe(
map((links) =>
- links.filter((link) => this.linkClassifier.hasUsage(link, LinkUsage.API))
+ links
+ .filter((link) => this.linkClassifier.hasUsage(link, LinkUsage.API))
+ .sort((dd1, dd2) => {
+ return (dd2 as DatasetServiceDistribution).accessServiceProtocol ===
+ 'GPFDL'
+ ? 1
+ : -1
+ })
)
)
diff --git a/libs/ui/elements/src/lib/api-card/api-card.component.html b/libs/ui/elements/src/lib/api-card/api-card.component.html
index c381e4fbf5..bc72720b1d 100644
--- a/libs/ui/elements/src/lib/api-card/api-card.component.html
+++ b/libs/ui/elements/src/lib/api-card/api-card.component.html
@@ -9,12 +9,23 @@
{{ link.accessServiceProtocol }}
+
+ record.metadata.api.gpfdl