Skip to content

Commit

Permalink
rebase lastest main
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume Keime committed Aug 21, 2023
1 parent 616ce22 commit d7ebdcd
Show file tree
Hide file tree
Showing 38 changed files with 672 additions and 43 deletions.
3 changes: 3 additions & 0 deletions apps/datahub/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ body {
margin: 0;
}

.container-xs {
max-width: calc(100% - 170px);
}
.container-sm {
max-width: 640px;
}
Expand Down
2 changes: 1 addition & 1 deletion apps/search/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@
"search.field.any.placeholder": "Search datasets, services and maps ...",
"search.field.sortBy": "Sort by",
"search.loading": "Loading ..."
}
}
1 change: 1 addition & 0 deletions apps/webcomponents/src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"results.sortBy.dateStamp": "Most recent",
"results.sortBy.popularity": "Popularity",
"results.sortBy.relevancy": "Relevancy",
"results.sortBy.qualityScore": "Quality score",
"search.field.any.placeholder": "Search datasets, services and maps ...",
"search.field.sortBy": "Sort by",
"search.loading": "Loading ..."
Expand Down
31 changes: 31 additions & 0 deletions conf/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ background_color = "#fdfbff"
# title_font = "'My Custom Title Font', fallback-font-title"
# fonts_stylesheet_url = "https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&family=Permanent+Marker&display=swap"

# This optional parameter allow you to change the default class on progress bar, by default is font-bold
# progress_bar_text_class = 'font-normal'

### SEARCH SETTINGS

# This section contains settings used for fine-tuning the search experience
Expand Down Expand Up @@ -95,6 +98,34 @@ background_color = "#fdfbff"

# Search presets will be advertised to the user along the main search field.


### METADATA QUALITY SETTINGS

# This section contains settings used for fine-tuning the metadata quality experience
[metadata-quality]
# By default the widget is not activated to enable it, just add this parameter.
# enabled = true
# If u want to use metadata quality widget this configuration is required

# if you add an indexed field to calculate the qualityScore, the datahub search allow you to sort on this field with this parameter
# sortable = true

# by default the wudget appear in 2 location in search list and in detail page
# display_widget_in_detail = false // allow you to hide the widget in detail
# display_widget_in_search = false // allow you to hide the widget in search list
# If you want see the widget in the two location, don't fill theses configurations

# By default the window popup all fields to view if they are filled or not but you can hide some
# display_title = false
# display_description = false
# display_topic = false
# display_keywords = false
# display_legal_constraints = false
# display_contact = false
# display_update_frequency = false
# display_organisation = false
# If you want see all fields, don't fill theses configurations

### MAP SETTINGS

# The map section allows to customize how maps are configured.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
</gn-ui-metadata-info>
</div>
<div>
<gn-ui-metadata-quality *ngIf="hasMetadataQualityWidget" [metadata]="facade.metadata$ | async"></gn-ui-metadata-quality>
<gn-ui-metadata-contact
(contact)="onContactClick($event)"
[metadata]="facade.metadata$ | async"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { ErrorType } from '@geonetwork-ui/ui/elements'
import { BehaviorSubject, combineLatest } from 'rxjs'
import { filter, map, mergeMap, pluck } from 'rxjs/operators'
import { MdViewFacade } from '../state/mdview.facade'
import { MetadataContact, Organisation } from '@geonetwork-ui/util/shared'
import { MetadataContact } from '@geonetwork-ui/util/shared'
import { MetadataQualityConfig, getMetadataQualityConfig } from '@geonetwork-ui/util/app-config'

@Component({
selector: 'gn-ui-record-metadata',
Expand All @@ -17,6 +18,7 @@ import { MetadataContact, Organisation } from '@geonetwork-ui/util/shared'
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RecordMetadataComponent {
metadataQualityConfig: MetadataQualityConfig = getMetadataQualityConfig();
displayMap$ = combineLatest([
this.facade.mapApiLinks$,
this.facade.geoDataLinks$,
Expand Down Expand Up @@ -60,7 +62,11 @@ export class RecordMetadataComponent {
private searchService: SearchService,
private sourceService: SourcesService,
private orgsService: OrganisationsServiceInterface
) {}
) { }

get hasMetadataQualityWidget() {
return this.metadataQualityConfig.ENABLED && this.metadataQualityConfig.DISPLAY_WIDGET_IN_RECORD_METADATA !== false
}

onTabIndexChange(index: number): void {
this.selectedTabIndex$.next(index)
Expand Down
12 changes: 11 additions & 1 deletion libs/feature/search/src/lib/sort-by/sort-by.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { marker } from '@biesbjerg/ngx-translate-extract-marker'
import { SortByEnum } from '@geonetwork-ui/util/shared'
import { SearchFacade } from '../state/search.facade'
import { SearchService } from '../utils/service/search.service'
import { getMetadataQualityConfig } from '@geonetwork-ui/util/app-config'

marker('results.sortBy.relevancy')
marker('results.sortBy.dateStamp')
marker('results.sortBy.popularity')
marker('results.sortBy.qualityScore')

@Component({
selector: 'gn-ui-sort-by',
Expand All @@ -27,12 +29,20 @@ export class SortByComponent {
value: SortByEnum.POPULARITY,
},
]
metadataQualityConfig = getMetadataQualityConfig();
currentSortBy$ = this.facade.sortBy$

constructor(
private facade: SearchFacade,
private searchService: SearchService
) {}
) {
if (this.metadataQualityConfig.ENABLED && this.metadataQualityConfig.SORTABLE) {
this.choices.push({
label: 'results.sortBy.qualityScore',
value: SortByEnum.QUALITY_SCORE,
});
}
}

changeSortBy(criteria: any) {
if (typeof criteria === 'string') {
Expand Down
112 changes: 96 additions & 16 deletions libs/feature/search/src/lib/utils/mapper/elasticsearch.field.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getFirstValue,
LinkClassifierService,
LinkUsage,
mapContact,
MetadataLink,
MetadataLinkType,
MetadataRecord,
Expand All @@ -17,6 +18,7 @@ import {
toDate,
} from '@geonetwork-ui/util/shared'
import { MetadataUrlService } from '../service/metadata-url.service'
import { MetadataQualityConfig, getMetadataQualityConfig } from '@geonetwork-ui/util/app-config'

type ESResponseSource = SourceWithUnknownProps

Expand All @@ -32,7 +34,7 @@ export class ElasticsearchFieldMapper {
constructor(
private metadataUrlService: MetadataUrlService,
private linkClassifier: LinkClassifierService
) {}
) { }

protected fields: Record<string, EsFieldMapperFn> = {
id: (output, source) => ({
Expand All @@ -42,7 +44,8 @@ export class ElasticsearchFieldMapper {
uuid: (output, source) => {
const uuid = selectField<string>(source, 'uuid')
const metadataUrl = this.metadataUrlService.getUrl(uuid)
return { ...output, uuid, metadataUrl }
const qualityScore = this.calculateQualityScore(source)
return { ...output, uuid, metadataUrl, qualityScore }
},
resourceTitleObject: (output, source) => ({
...output,
Expand Down Expand Up @@ -71,6 +74,12 @@ export class ElasticsearchFieldMapper {
)
),
}),
cl_topic: (output, source) => ({
...output,
topic: getAsArray(
selectField<SourceWithUnknownProps[]>(source, 'cl_topic')
).map((cl_topic) => selectTranslatedValue<string>(cl_topic)),
}),
cl_status: (output, source) => ({
...output,
updateStatus: selectTranslatedValue(
Expand Down Expand Up @@ -130,12 +139,21 @@ export class ElasticsearchFieldMapper {
}),
MD_ConstraintsUseLimitationObject: (output, source) =>
this.constraintField('MD_ConstraintsUseLimitationObject', output, source),
MD_LegalConstraintsUseLimitationObject: (output, source) =>
this.constraintField(
'MD_LegalConstraintsUseLimitationObject',
output,
source
),
MD_LegalConstraintsUseLimitationObject: (output, source) => {
const legalConstraints = getAsArray(
selectField<SourceWithUnknownProps[]>(source, 'MD_LegalConstraintsUseLimitationObject')
).map((MD_LegalConstraintsUseLimitationObject) => selectTranslatedValue<string>(MD_LegalConstraintsUseLimitationObject));
let prevConstraints = output.constraints || [];
const constraints = {
...prevConstraints,
...legalConstraints
};
return {
...output,
legalConstraints,
constraints
}
},
MD_LegalConstraintsOtherConstraintsObject: (output, source) =>
this.constraintField(
'MD_LegalConstraintsOtherConstraintsObject',
Expand Down Expand Up @@ -171,16 +189,78 @@ export class ElasticsearchFieldMapper {
}),
}

private genericField = (output) => output
private calculateQualityScore = (source) => {
const qualityScore: number = selectField(source, 'qualityScore');
if (qualityScore != null) {
return qualityScore;
}
const metadataQualityConfig: MetadataQualityConfig = getMetadataQualityConfig();
let total = 0;
let success = 0;
const check = (name: string) => {
const display = metadataQualityConfig[`DISPLAY_${name}`] !== false;
if (display) total++;
return display;
}
if (check('TITLE')) {
if (selectField(source, 'resourceTitleObject')) {
success++;
}
}
if (check('DESCRIPTION')) {
if (selectFallback(selectTranslatedField(source, 'resourceAbstractObject'), 'no title')) {
success++;
}
}
const contact = mapContact(
getFirstValue(selectField(source, 'contact')),
source
);
if (check('ORGANISATION')) {
if (contact?.organisation) {
success++;
}
}
if (check('CONTACT')) {
if (contact?.email) {
success++;
}
}
if (check('TOPIC')) {
if (selectField<SourceWithUnknownProps[]>(source, 'cl_topic')?.length > 0) {
success++;
}
}
if (check('KEYWORDS')) {
if (selectField<SourceWithUnknownProps[]>(source, 'tag')?.length > 0) {
success++;
}
}
if (check('UPDATE_FREQUENCY')) {
if (getFirstValue(selectField(source, 'cl_maintenanceAndUpdateFrequency'))) {
success++;
}
}
if (check("LEGAL_CONSTRAINTS")) {
if (selectField<unknown[]>(source, 'MD_LegalConstraintsUseLimitationObject')?.length > 0) {
success++;
}
}
return Math.round(success * 100 / total);
}

private constraintField = (fieldName: string, output, source) => ({
...output,
constraints: [
...(output.constraints || []),
...selectField<unknown[]>(source, fieldName).map(selectTranslatedValue),
],
})
private genericField = (output) => output

private constraintField = (fieldName: string, output, source) => {
const constraints = Array.isArray(output.constraints) ? output.constraints : [];
const fieldValues = selectField<unknown[]>(source, fieldName);
const translatedValues = fieldValues.map(selectTranslatedValue);
const updatedConstraints = [...constraints, ...translatedValues];
return {
...output,
constraints: updatedConstraints,
};
}
getMappingFn(fieldName: string) {
return fieldName in this.fields ? this.fields[fieldName] : this.genericField
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ class OrganisationsServiceMock {
of(
'contact' in source
? {
...record,
contact: {
name: 'Main Contact',
...record,
contact: {
name: 'Main Contact',
email: '[email protected]',
organisation: source.contact[0].organisation,
},
resourceContacts: [
{
name: 'Resource Contact 1',
email: '[email protected]',
organisation: source.contact[0].organisation,
},
resourceContacts: [
{
name: 'Resource Contact 1',
email: '[email protected]',
},
{
name: 'Resource Contact 2',
email: '[email protected]',
},
],
}
{
name: 'Resource Contact 2',
email: '[email protected]',
},
],
}
: record
)
)
Expand Down Expand Up @@ -78,8 +78,13 @@ describe('ElasticsearchMapper', () => {
abstract: 'The grid is based on proposal ',
id: '12456',
metadataUrl: 'url',
<<<<<<< HEAD
thumbnailUrl:
'https://sdi.eea.europa.eu/public/catalogue-graphic-overview/20e9e1a1-83c1-4f13-89ef-c19767d6ee18f.png',
=======
qualityScore: 25,
thumbnailUrl: 'data:image/png;base64,',
>>>>>>> 00e9c4b0 (fix asked by camp2camp)
title: 'EEA reference grid for Germany (10km), May 2013',
uuid: '20e9e1a1-83c1-4f13-89ef-c19767d6ee18f',
catalogUuid: '6731be1e-6533-44e0-9b8a-580b45e36e80',
Expand All @@ -101,6 +106,7 @@ describe('ElasticsearchMapper', () => {
hasDownloads: false,
hasMaps: false,
links: [],
qualityScore: 25
},
])
})
Expand Down Expand Up @@ -432,9 +438,13 @@ describe('ElasticsearchMapper', () => {
],
metadataUrl: 'url',
ownerInfo: 'testadmin|ADMIN|Test|Administrator',
qualityScore: 100,
thumbnailUrl:
'https://sextant.ifremer.fr/geonetwork/srv/api/records/cf5048f6-5bbf-4e44-ba74-e6f429af51ea/attachments/parametres.gif',
title: 'Surval - Données par paramètre',
topic: [
'Océans',
],
uuid: 'cf5048f6-5bbf-4e44-ba74-e6f429af51ea',
contact: {
name: 'Main Contact',
Expand Down Expand Up @@ -516,11 +526,12 @@ describe('ElasticsearchMapper', () => {
'Sète',
'La Rochelle',
],
legalConstraints: [
"Restriction légale d'utilisation à préciser",
],
lineage:
'Les données sont bancarisées dans la base de données Quadrige.',
constraints: [
'Restriction lié à l’exercice du droit moral',
"Restriction légale d'utilisation à préciser",
'Pas de restriction d’accès public',
'Licence Ouverte version 2.0 https://www.etalab.gouv.fr/wp-content/uploads/2017/04/ETALAB-Licence-Ouverte-v2.0.pdf',
],
Expand Down
Loading

0 comments on commit d7ebdcd

Please sign in to comment.