Skip to content

Commit

Permalink
Merge branch 'Api_telechargement' into passeplat
Browse files Browse the repository at this point in the history
  • Loading branch information
mmohadIGN authored Jun 6, 2024
2 parents aef4372 + 99b29e6 commit f4e522e
Show file tree
Hide file tree
Showing 18 changed files with 539 additions and 6 deletions.
2 changes: 2 additions & 0 deletions apps/datahub/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ import {
UiLayoutModule,
} from '@geonetwork-ui/ui/layout'
import { UiSearchModule } from '@geonetwork-ui/ui/search'
import { IgnApiDlComponent } from '@geonetwork-ui/feature/record'

import {
getGlobalConfig,
getOptionalSearchConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,13 @@
</mat-icon>
</button>
</div>

<gn-ui-ign-api-dl
*ngIf="displayApiIgnForm"
[apiLink]="selectedApiLink"
></gn-ui-ign-api-dl>
<gn-ui-record-api-form
*ngIf="!displayApiIgnForm"
[apiLink]="selectedApiLink"
></gn-ui-record-api-form>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export class RecordApisComponent implements OnInit {

maxHeight = '0px'
opacity = 0
displayApiIgnForm: boolean
selectedApiLink: DatasetServiceDistribution

apiLinks$ = this.facade.apiLinks$
Expand Down Expand Up @@ -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)
}
Expand All @@ -61,7 +64,7 @@ export class RecordApisComponent implements OnInit {
}

setStyle(link: DatasetServiceDistribution) {
this.maxHeight = link === undefined ? '0px' : '500px'
this.maxHeight = link === undefined ? '0px' : '600px'
this.opacity = link === undefined ? 0 : 1
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}

Expand Down
5 changes: 3 additions & 2 deletions libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,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'
}
Expand Down Expand Up @@ -440,11 +441,11 @@ export class Gn4FieldMapper {
const mimeTypeMatches =
protocol && protocol.match(/^WWW:DOWNLOAD:(.+\/.+)$/)
const mimeType = mimeTypeMatches && mimeTypeMatches[1]

const distribution = {
...(name && { name }),
...(description && { description }),
}

switch (type) {
case 'service':
return {
Expand Down
1 change: 1 addition & 0 deletions libs/common/domain/src/lib/model/record/metadata.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ export type ServiceProtocol =
| 'wmts'
| 'esriRest'
| 'ogcFeatures'
| 'GPFDL'
| 'other'

export type DatasetDistributionType = 'service' | 'download' | 'link'
Expand Down
1 change: 1 addition & 0 deletions libs/feature/record/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'
5 changes: 5 additions & 0 deletions libs/feature/record/src/lib/feature-record.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 { UiWidgetsModule } from '@geonetwork-ui/ui/widgets'
Expand All @@ -35,6 +37,8 @@ import { DataViewShareComponent } from './data-view-share/data-view-share.compon
DataViewPermalinkComponent,
DataViewWebComponentComponent,
DataViewShareComponent,
IgnApiDlComponent,
IgnApiProduitComponent,
],
imports: [
CommonModule,
Expand All @@ -60,6 +64,7 @@ import { DataViewShareComponent } from './data-view-share/data-view-share.compon
DataViewPermalinkComponent,
DataViewWebComponentComponent,
DataViewShareComponent,
IgnApiDlComponent,
],
})
export class FeatureRecordModule {}
22 changes: 22 additions & 0 deletions libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.css
Original file line number Diff line number Diff line change
@@ -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;
}
97 changes: 97 additions & 0 deletions libs/feature/record/src/lib/ign-api-dl/ign-api-dl.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<div class="flex flex-col gap-8">
<div class="flex flex-col bg-white p-8 ng-star-inserted shadow-xl gap-8">
<div class="flex flex-row">
<div class="text-[16px] text-black truncate font-title w-11/12" translate>
record.metadata.api.form.create
</div>
<button
(click)="resetUrl()"
class="bg-primary-opacity-50 inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded capitalize text-primary-lightest hover:bg-primary transition-colors"
>
<p class="text-[13px] uppercase" translate>
record.metadata.api.form.reset
</p>
</button>
</div>
<div class="flex flex-row flex-wrap justify-between flex-grow gap-5">
<div class="flex flex-col gap-3">
<!--<p class="text-sm" translate>record.metadata.api.form.type</p>-->
<gn-ui-dropdown-selector
#zone
[title]="''"
extraBtnClass="secondary min-w-full !w-40 !text-black"
[showTitle]="false"
class="text-black"
[choices]="bucketPromisesZone"
(selectValue)="setZone($event)"
[selected]="zone$ | async"
>
</gn-ui-dropdown-selector>
</div>
<div class="flex flex-col gap-3">
<!--<p class="text-sm" translate>record.metadata.api.form.type</p>-->
<gn-ui-dropdown-selector
#format
[title]="''"
extraBtnClass="secondary min-w-full !w-40 !text-black"
[showTitle]="false"
class="text-black"
[choices]="bucketPromisesFormat"
(selectValue)="setFormat($event)"
[selected]="format$ | async"
>
</gn-ui-dropdown-selector>
</div>
<div class="flex flex-col gap-3">
<!--<p class="text-sm" translate>record.metadata.api.form.type</p>-->
<gn-ui-dropdown-selector
#format
[title]="'CRS'"
[choices]="bucketPromisesCrs"
(selectValue)="setCrs($event)"
[selected]="crs$ | async"
>
</gn-ui-dropdown-selector>
</div>
</div>
<div class="bg-white rounded-lg h-min">
<div class="overflow-auto h-60 w-65 bg-white-300 m-2">
<table class="w-full text-left border-collapse">
<thead>
<tr
class="sticky z-10 top-0 text-sm leading-6 font-semibold text-slate-700 bg-white p-0 dark:bg-slate-900 dark:text-slate-300"
>
<div
class="py-2 pr-2 text-xl border-b border-slate-200 dark:border-slate-400/20"
>
Produits ({{ numberFilteredProduct$ | async }}):
</div>
</tr>
</thead>
<tbody class="align-baseline">
<tr>
<div *ngFor="let link of listFilteredProduct$ | async">
<div class="mb-2 sm:mb-3">
<gn-ui-ign-api-produit
[link]="link"
color="rgb(124 45 18)"
[format]="getLinkFormat(link)"
[isFromWfs]="true"
></gn-ui-ign-api-produit>
</div>
</div>
</tr>
<tr>
<button
(click)="moreResult()"
class="bg-primary-opacity-50 inline-flex items-center justify-center px-2 py-1 text-13 font-medium leading-none text-white rounded capitalize text-primary-lightest hover:bg-primary transition-colors"
>
<p class="text-[13px] uppercase" translate>Plus de résultats</p>
</button>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { TestBed, ComponentFixture } from '@angular/core/testing'
import { RecordApiFormComponent } from './record-api-form.component'
import { DatasetServiceDistribution } from '@geonetwork-ui/common/domain/model/record'
import { firstValueFrom } from 'rxjs'
import { UiInputsModule } from '@geonetwork-ui/ui/inputs'
import { TranslateModule } from '@ngx-translate/core'

const mockDatasetServiceDistribution: DatasetServiceDistribution = {
url: new URL('https://api.example.com/data'),
type: 'service',
accessServiceProtocol: 'ogcFeatures',
}

describe('RecordApFormComponent', () => {
let component: RecordApiFormComponent
let fixture: ComponentFixture<RecordApiFormComponent>

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [RecordApiFormComponent],
imports: [UiInputsModule, TranslateModule.forRoot()],
}).compileComponents()

fixture = TestBed.createComponent(RecordApiFormComponent)
component = fixture.componentInstance
component.apiLink = mockDatasetServiceDistribution
fixture.detectChanges()
})

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.offset$.getValue()).toBe('')
expect(component.limit$.getValue()).toBe('')
expect(component.format$.getValue()).toBe('json')
const url = await firstValueFrom(component.apiQueryUrl$)
expect(url).toBe('https://api.example.com/data?f=json')
})
})
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'
component.setOffset(mockOffset)
component.setLimit(mockLimit)
component.setFormat(mockFormat)
const url = await firstValueFrom(component.apiQueryUrl$)
expect(url).toBe(
`https://api.example.com/data?offset=${mockOffset}&limit=${mockLimit}&f=${mockFormat}`
)
})
it('should remove the param in url if value is null', async () => {
const mockOffset = null
const mockLimit = '20'
const mockFormat = 'json'
component.setOffset(mockOffset)
component.setLimit(mockLimit)
component.setFormat(mockFormat)
const url = await firstValueFrom(component.apiQueryUrl$)
expect(url).toBe(
`https://api.example.com/data?limit=${mockLimit}&f=${mockFormat}`
)
})
it('should remove the param in url if value is zero', async () => {
const mockOffset = '10'
const mockLimit = '0'
const mockFormat = 'json'
component.setOffset(mockOffset)
component.setLimit(mockLimit)
component.setFormat(mockFormat)
const url = await firstValueFrom(component.apiQueryUrl$)
expect(url).toBe(
`https://api.example.com/data?offset=${mockOffset}&f=${mockFormat}`
)
})
})

describe('#resetUrl', () => {
it('should reset URL to default parameters', () => {
component.resetUrl()
expect(component.offset$.getValue()).toBe('')
expect(component.limit$.getValue()).toBe('')
expect(component.format$.getValue()).toBe('json')
})
})
})
Loading

0 comments on commit f4e522e

Please sign in to comment.