Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP : Advanced filters #702

Closed
wants to merge 10 commits into from
103 changes: 100 additions & 3 deletions libs/data-access/gn4/src/openapi/api/tools.api.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,31 @@
import { Inject, Injectable, Optional } from '@angular/core'
import {
HttpClient,
HttpEvent,
HttpHeaders,
HttpParameterCodec,
HttpParams,
HttpResponse,
HttpEvent,
HttpParameterCodec,
} from '@angular/common/http'
import { CustomHttpParameterCodec } from '../encoder'
import { Observable } from 'rxjs'

import { BASE_PATH, COLLECTION_FORMATS } from '../variables'
import { BASE_PATH } from '../variables'
import { Configuration } from '../configuration'

interface thesaurusResponse {
values: string[]
definitions: string[]
coordEast: string
coordWest: string
coordSouth: string
coordNorth: string
thesaurusKey: string
value: string
uri: string
definition: string
}

@Injectable({
providedIn: 'root',
})
Expand Down Expand Up @@ -913,4 +926,88 @@ export class ToolsApiService {
}
)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never write open API client by hand.
BTW, the registries client already exists in RegistriesApiService

/**
* List database translations (used to overrides client application translations).
* @param esFieldName set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param iso3 set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
* @param reportProgress flag to report request and response progress.
*/
public getTranslationsFromThesaurus(
thesaurusName: string,
langIso3: string,
observe?: 'body',
reportProgress?: boolean,
options?: { httpHeaderAccept?: 'application/json' }
): Observable<any>
public getTranslationsFromThesaurus(
thesaurusName: string,
langIso3: string,
observe?: 'response',
reportProgress?: boolean,
options?: { httpHeaderAccept?: 'application/json' }
): Observable<thesaurusResponse[]>
public getTranslationsFromThesaurus(
thesaurusName: string,
langIso3: string,
observe?: 'events',
reportProgress?: boolean,
options?: { httpHeaderAccept?: 'application/json' }
): Observable<thesaurusResponse[]>
public getTranslationsFromThesaurus(
thesaurusName: string,
langIso3: string,
observe: any = 'body',
reportProgress: boolean = false,
options?: { httpHeaderAccept?: 'application/json' }
): Observable<any> {
if (
thesaurusName === null ||
thesaurusName === undefined ||
langIso3 === null ||
langIso3 === undefined
) {
throw new Error(
'Required parameter pack was null or undefined when calling getTranslationsFromThesaurus.'
)
}

let headers = this.defaultHeaders

let httpHeaderAcceptSelected: string | undefined =
options && options.httpHeaderAccept
if (httpHeaderAcceptSelected === undefined) {
// to determine the Accept header
const httpHeaderAccepts: string[] = ['application/json']
httpHeaderAcceptSelected =
this.configuration.selectHeaderAccept(httpHeaderAccepts)
}
if (httpHeaderAcceptSelected !== undefined) {
headers = headers.set('Accept', httpHeaderAcceptSelected)
}

let responseType_: 'text' | 'json' = 'json'
if (
httpHeaderAcceptSelected &&
httpHeaderAcceptSelected.startsWith('text')
) {
responseType_ = 'text'
}

return this.httpClient.get<thesaurusResponse[]>(
`${
this.configuration.basePath
}/registries/vocabularies/search?rows=1000&type=CONTAINS&sort=DESC&thesaurus=${encodeURIComponent(
String(thesaurusName)
)}&lang=${encodeURIComponent(langIso3)}`,
{
responseType: <any>responseType_,
withCredentials: this.configuration.withCredentials,
headers: headers,
observe: observe,
reportProgress: reportProgress,
}
)
}
}
8 changes: 5 additions & 3 deletions libs/feature/search/src/lib/utils/service/fields.service.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Injectable, Injector } from '@angular/core'
import {
AbstractSearchField,
GnUiTranslationSearchField,
FieldValue,
FullTextSearchField,
GnUiTranslationSearchField,
IsSpatialSearchField,
LicenseSearchField,
OrganizationSearchField,
OwnerSearchField,
SimpleSearchField,
ThesaurusTranslationSearchField,
} from './fields'
import { forkJoin, Observable, of } from 'rxjs'
import { map } from 'rxjs/operators'
Expand Down Expand Up @@ -52,8 +53,9 @@ export class FieldsService {
this.injector
),
topic: new GnUiTranslationSearchField('cl_topic.key', 'asc', this.injector),
inspireKeyword: new SimpleSearchField(
'th_httpinspireeceuropaeutheme-theme_tree.default',
inspireKeyword: new ThesaurusTranslationSearchField(
'th_httpinspireeceuropaeutheme-theme.link',
'external.theme.httpinspireeceuropaeutheme-theme',
'asc',
this.injector
),
Expand Down
52 changes: 52 additions & 0 deletions libs/feature/search/src/lib/utils/service/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from '@geonetwork-ui/common/domain/model/search'
import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/repository/records-repository.interface'
import { ElasticsearchService } from '@geonetwork-ui/api/repository/gn4'
import { LangService } from '@geonetwork-ui/util/i18n'

export type FieldValue = string | number
export interface FieldAvailableValue {
Expand Down Expand Up @@ -127,6 +128,57 @@ export class GnUiTranslationSearchField extends SimpleSearchField {
}
}

export class ThesaurusTranslationSearchField extends SimpleSearchField {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could have extended the GnuiTranslationField, which is almost the same, instead.

private toolsApiService = this.injector.get(ToolsApiService)
private langService = this.injector.get(LangService)
allTranslations = this.toolsApiService
.getTranslationsFromThesaurus(this.thesaurusName, this.langService.iso3)
.pipe(
map((thesaurus) => {
const alltranslations = {}
thesaurus.map((val) => {
alltranslations[val.uri] = val.value
})
return alltranslations
}),
catchError(() => {
console.warn('Error while loading thesaurus language package')
return of({})
}),
shareReplay(1)
)

constructor(
esFieldName: string,
protected thesaurusName: string,
order: 'asc' | 'desc' = 'asc',
injector: Injector
) {
super(esFieldName, order, injector)
}

private async getTranslation(topicKey: string) {
return firstValueFrom(
this.allTranslations.pipe(map((translations) => translations[topicKey]))
)
}

protected async getBucketLabel(bucket: TermBucket) {
return (await this.getTranslation(bucket.term)) || bucket.term
}

getAvailableValues(): Observable<FieldAvailableValue[]> {
// sort values by alphabetical order
return super
.getAvailableValues()
.pipe(
map((values) =>
values.sort((a, b) => new Intl.Collator().compare(a.label, b.label))
)
)
}
}

export class FullTextSearchField implements AbstractSearchField {
getAvailableValues(): Observable<FieldAvailableValue[]> {
return of([])
Expand Down