Skip to content

Commit

Permalink
Merge pull request #719 from geonetwork/rework-filters
Browse files Browse the repository at this point in the history
Datahub: support thesaurus based advanced fields
  • Loading branch information
fgravin authored Dec 11, 2023
2 parents 7cd87cb + 7d3e1e1 commit 2f085bb
Show file tree
Hide file tree
Showing 23 changed files with 536 additions and 203 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
class="py-[37px] pl-[47px] rounded-lg border bg-white mb-5 card-shadow cursor-pointer"
[figure]="recordsCount$ | async"
[icon]="'folder_open'"
[title]="'catalog.figures.datasets'"
title="catalog.figures.datasets"
[color]="'secondary'"
></gn-ui-figure>
</a>
Expand All @@ -13,7 +13,7 @@
class="py-[37px] pl-[47px] rounded-lg bg-white border card-shadow cursor-pointer"
[figure]="orgsCount$ | async"
[icon]="'corporate_fare'"
[title]="'catalog.figures.organisations'"
title="catalog.figures.organisations"
[color]="'secondary'"
></gn-ui-figure>
</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { RecordsService } from '@geonetwork-ui/feature/catalog'
import { ROUTER_ROUTE_SEARCH } from '@geonetwork-ui/feature/router'
import { ROUTER_ROUTE_ORGANISATIONS } from '../../../router/constants'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
import { marker } from '@biesbjerg/ngx-translate-extract-marker'

marker('catalog.figures.datasets')
marker('catalog.figures.organisations')

@Component({
selector: 'datahub-key-figures',
Expand Down
11 changes: 11 additions & 0 deletions libs/api/repository/src/lib/gn4/platform/gn4-platform.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Injectable } from '@angular/core'
import { AvatarServiceInterface } from '../auth/avatar.service.interface'
import { map } from 'rxjs/operators'
import { Observable, of } from 'rxjs'
import { ThesaurusModel } from '@geonetwork-ui/common/domain/model/thesaurus/thesaurus.model'

@Injectable()
export class Gn4PlatformMapper {
Expand Down Expand Up @@ -43,4 +44,14 @@ export class Gn4PlatformMapper {
} = apiUser
return { ...apiUser, id: id + '' } as UserModel
}

thesaurusFromApi(thesaurus: any[]): ThesaurusModel {
return thesaurus.map((keyword) => {
const { uri, value } = keyword
return {
key: uri,
label: value,
}
})
}
}
100 changes: 100 additions & 0 deletions libs/api/repository/src/lib/gn4/platform/gn4-platform.service.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import {
MeApiService,
RegistriesApiService,
SiteApiService,
ToolsApiService,
UsersApiService,
} from '@geonetwork-ui/data-access/gn4'
import { TestBed } from '@angular/core/testing'
Expand Down Expand Up @@ -63,9 +65,62 @@ class UsersApiServiceMock {
}
}

class ToolsApiServiceMock {
getTranslationsPackage1 = jest.fn(() =>
of({
'First value': 'Translated first value',
'Second value': 'Hello',
'Third value': 'Bla',
})
)
}

class RegistriesApiServiceMock {
searchKeywords = jest.fn(() =>
of([
{
values: {
fre: 'Adresses',
},
definitions: {
fre: 'Localisation des propriétés fondée sur les identifiants des adresses, habituellement le nom de la rue, le numéro de la maison et le code postal.',
},
coordEast: '',
coordWest: '',
coordSouth: '',
coordNorth: '',
thesaurusKey: 'external.theme.httpinspireeceuropaeutheme-theme',
uri: 'http://inspire.ec.europa.eu/theme/ad',
definition:
'Localisation des propriétés fondée sur les identifiants des adresses, habituellement le nom de la rue, le numéro de la maison et le code postal.',
value: 'Adresses',
},
{
values: {
fre: 'Altitude',
},
definitions: {
fre: "Modèles numériques pour l'altitude des surfaces terrestres, glaciaires et océaniques. Comprend l'altitude terrestre, la bathymétrie et la ligne de rivage.",
},
coordEast: '',
coordWest: '',
coordSouth: '',
coordNorth: '',
thesaurusKey: 'external.theme.httpinspireeceuropaeutheme-theme',
uri: 'http://inspire.ec.europa.eu/theme/el',
definition:
"Modèles numériques pour l'altitude des surfaces terrestres, glaciaires et océaniques. Comprend l'altitude terrestre, la bathymétrie et la ligne de rivage.",
value: 'Altitude',
},
])
)
}

describe('Gn4PlatformService', () => {
let service: Gn4PlatformService
let meApiService: MeApiService
let toolsApiService: ToolsApiService
let registriesApiService: RegistriesApiService

beforeEach(() => {
TestBed.configureTestingModule({
Expand All @@ -88,10 +143,20 @@ describe('Gn4PlatformService', () => {
provide: AvatarServiceInterface,
useClass: AvatarServiceInterfaceMock,
},
{
provide: ToolsApiService,
useClass: ToolsApiServiceMock,
},
{
provide: RegistriesApiService,
useClass: RegistriesApiServiceMock,
},
],
})
service = TestBed.inject(Gn4PlatformService)
meApiService = TestBed.inject(MeApiService)
toolsApiService = TestBed.inject(ToolsApiService)
registriesApiService = TestBed.inject(RegistriesApiService)
})

it('creates', () => {
Expand Down Expand Up @@ -161,4 +226,39 @@ describe('Gn4PlatformService', () => {
})
})
})
describe('#translateKey', () => {
it('returns translation ', async () => {
const translation = await lastValueFrom(
service.translateKey('First value')
)
expect(translation).toEqual('Translated first value')
})
it('fetch api translations once ', async () => {
await lastValueFrom(service.translateKey('First value'))
await lastValueFrom(service.translateKey('Second value'))
expect(toolsApiService.getTranslationsPackage1).toHaveBeenCalledTimes(1)
})
})
describe('#getThesaurusByLang', () => {
it('calls api service ', async () => {
service.getThesaurusByLang('inspire', 'fre')
expect(registriesApiService.searchKeywords).toHaveBeenCalledWith(
null,
'fre',
1000,
0,
null,
['inspire']
)
})
it('returns mapped thesaurus ', async () => {
const thesaurusDomain = await lastValueFrom(
service.getThesaurusByLang('inspire', 'fre')
)
expect(thesaurusDomain).toEqual([
{ key: 'http://inspire.ec.europa.eu/theme/ad', label: 'Adresses' },
{ key: 'http://inspire.ec.europa.eu/theme/el', label: 'Altitude' },
])
})
})
})
36 changes: 33 additions & 3 deletions libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import { Injectable } from '@angular/core'
import { Observable, of, switchMap } from 'rxjs'
import { map, shareReplay, tap } from 'rxjs/operators'
import { catchError, map, shareReplay, tap } from 'rxjs/operators'
import {
MeApiService,
RegistriesApiService,
SiteApiService,
ToolsApiService,
UsersApiService,
} from '@geonetwork-ui/data-access/gn4'
import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'
import { UserModel } from '@geonetwork-ui/common/domain/model/user/user.model'
import { Organization } from '@geonetwork-ui/common/domain/model/record'
import { Gn4PlatformMapper } from './gn4-platform.mapper'
import { ThesaurusModel } from '@geonetwork-ui/common/domain/model/thesaurus/thesaurus.model'

const minApiVersion = '4.2.0'
@Injectable()
export class Gn4PlatformService implements PlatformServiceInterface {
private readonly type = 'GeoNetwork'
private me$: Observable<UserModel>
private users$: Observable<UserModel[]>
isAnonymous$: Observable<boolean>
private isAnonymous$: Observable<boolean>

private keyTranslations$ = this.toolsApiService
.getTranslationsPackage1('gnui')
.pipe(
catchError(() => {
console.warn('Error while loading gnui language package')
return of({})
}),
shareReplay(1)
)

private settings$ = of(true).pipe(
switchMap(() => this.siteApiService.getSiteOrPortalDescription()),
Expand All @@ -42,7 +55,9 @@ export class Gn4PlatformService implements PlatformServiceInterface {
private siteApiService: SiteApiService,
private meApi: MeApiService,
private usersApi: UsersApiService,
private mapper: Gn4PlatformMapper
private mapper: Gn4PlatformMapper,
private toolsApiService: ToolsApiService,
private registriesApiService: RegistriesApiService
) {
this.me$ = this.meApi.getMe().pipe(
switchMap((apiUser) => this.mapper.userFromMeApi(apiUser)),
Expand Down Expand Up @@ -85,4 +100,19 @@ export class Gn4PlatformService implements PlatformServiceInterface {
getUsers(): Observable<UserModel[]> {
return this.users$
}

translateKey(key: string): Observable<string> {
return this.keyTranslations$.pipe(map((translations) => translations[key]))
}

getThesaurusByLang(
thesaurusName: string,
lang: string
): Observable<ThesaurusModel> {
return this.registriesApiService
.searchKeywords(null, lang, 1000, 0, null, [thesaurusName])
.pipe(
map((thesaurus) => this.mapper.thesaurusFromApi(thesaurus as any[]))
)
}
}
1 change: 1 addition & 0 deletions libs/common/domain/src/lib/model/thesaurus/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './thesaurus.model'
6 changes: 6 additions & 0 deletions libs/common/domain/src/lib/model/thesaurus/thesaurus.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface ThesaurusItemModel {
key: string
label: string
}

export type ThesaurusModel = ThesaurusItemModel[]
12 changes: 9 additions & 3 deletions libs/common/domain/src/lib/platform.service.interface.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Observable } from 'rxjs'
import { UserModel } from './model/user/user.model'
import { Organization } from './model/record/organization.model'
import type { Observable } from 'rxjs'
import type { UserModel } from './model/user/user.model'
import type { Organization } from './model/record/organization.model'
import type { ThesaurusModel } from './model/thesaurus/'

export abstract class PlatformServiceInterface {
abstract getType(): string
Expand All @@ -14,4 +15,9 @@ export abstract class PlatformServiceInterface {
organisation: Organization
): Observable<UserModel[]>
abstract getOrganizations(): Observable<Organization[]>
abstract translateKey(key: string): Observable<string>
abstract getThesaurusByLang(
thesaurusName: string,
lang: string
): Observable<ThesaurusModel>
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { Observable } from 'rxjs'
import { LangService } from '@geonetwork-ui/util/i18n'

class SourcesApiServiceMock {
getSourcesByType = jest.fn(function () {
getSubPortals1 = jest.fn(function () {
return new Observable((observer) => {
observer.next(SOURCES_FIXTURE)
})
Expand Down
4 changes: 1 addition & 3 deletions libs/feature/catalog/src/lib/sources/sources.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ import { CatalogSource } from './sources.model'
})
export class SourcesService {
sources$: Observable<CatalogSource[]> = (
this.sourcesApiService.getSourcesByType('harvester') as Observable<
CatalogSource[]
>
this.sourcesApiService.getSubPortals1() as Observable<CatalogSource[]>
).pipe(shareReplay())

constructor(
Expand Down
27 changes: 27 additions & 0 deletions libs/feature/search/src/lib/utils/service/fields.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TranslateModule } from '@ngx-translate/core'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/repository/records-repository.interface'
import { ElasticsearchService } from '@geonetwork-ui/api/repository/gn4'
import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'

class RecordsRepositoryMock {
aggregate = jest.fn(() => EMPTY)
Expand All @@ -27,6 +28,28 @@ class OrganisationsServiceMock {
)
}

class PlatformServiceInterfaceMock {
translateKey = jest.fn((key) => {
switch (key) {
case 'First value':
return of('Translated first value')
case 'Second value':
return of('Hello')
case 'Third value':
return of('Bla')
default:
return of(null)
}
})
getThesaurusByLang = jest.fn((thesaurusName: string, lang: string) =>
of([
{ key: 'First value', label: 'Rivière' },
{ key: 'Second value', label: 'Forêt' },
{ key: 'Third value', label: 'Planète' },
])
)
}

describe('FieldsService', () => {
let service: FieldsService

Expand All @@ -50,6 +73,10 @@ describe('FieldsService', () => {
provide: OrganizationsServiceInterface,
useClass: OrganisationsServiceMock,
},
{
provide: PlatformServiceInterface,
useClass: PlatformServiceInterfaceMock,
},
],
})
})
Expand Down
Loading

0 comments on commit 2f085bb

Please sign in to comment.