Skip to content

Commit

Permalink
Merge pull request #497 from gkeimeHDF/main
Browse files Browse the repository at this point in the history
[Sponsor by MEL] Add feature Metadata Quality Widget
  • Loading branch information
jahow committed Oct 25, 2023
2 parents 279fe11 + dddbe48 commit 2901ae6
Show file tree
Hide file tree
Showing 48 changed files with 808 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ <h2 class="text-xl mr-4 font-title" translate>
</button>
<gn-ui-sort-by
[ngClass]="isOpen ? 'block text-white mb-1' : 'hidden sm:block'"
[isQualitySortable]="isQualitySortable"
></gn-ui-sort-by>
</div>
<div class="text-right">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@ import { SearchFiltersComponent } from './search-filters.component'
import { TranslateModule } from '@ngx-translate/core'
import { By } from '@angular/platform-browser'
import { FormsModule } from '@angular/forms'
import {
AggregationsTypes,
FieldFilters,
} from '@geonetwork-ui/common/domain/search'
import { FieldFilters } from '@geonetwork-ui/common/domain/search'

jest.mock('@geonetwork-ui/util/app-config', () => ({
getOptionalSearchConfig: () => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ChangeDetectionStrategy,
Component,
Input,
OnInit,
QueryList,
ViewChildren,
Expand All @@ -24,6 +25,7 @@ export class SearchFiltersComponent implements OnInit {
filters: QueryList<FilterDropdownComponent>
searchConfig: { fieldName: string; title: string }[]
isOpen = false
@Input() isQualitySortable = false

constructor(
public searchFacade: SearchFacade,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<div class="container-lg mx-auto mt-8">
<datahub-search-filters></datahub-search-filters>
<datahub-search-filters
[isQualitySortable]="isQualitySortable"
></datahub-search-filters>
<div class="mt-6 rounded-lg text-gray-800 p-4 bg-slate-100">
<gn-ui-results-hits></gn-ui-results-hits>
</div>
<div class="mt-8">
<gn-ui-results-list-container
[metadataQualityDisplay]="metadataQualityDisplay"
(mdSelect)="onMetadataSelection($event)"
showMore="button"
></gn-ui-results-list-container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'
import { RouterFacade } from '@geonetwork-ui/feature/router'
import { SearchFacade } from '@geonetwork-ui/feature/search'
import { CatalogRecord } from '@geonetwork-ui/common/domain/record'
import { MetadataQualityDisplay } from '@geonetwork-ui/ui/elements'
import {
MetadataQualityConfig,
getMetadataQualityConfig,
} from '@geonetwork-ui/util/app-config'

@Component({
selector: 'datahub-search-page',
Expand All @@ -10,13 +15,31 @@ import { CatalogRecord } from '@geonetwork-ui/common/domain/record'
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class SearchPageComponent implements OnInit {
isQualitySortable = false
metadataQualityDisplay = {} as MetadataQualityDisplay

constructor(
private searchRouter: RouterFacade,
private searchFacade: SearchFacade
) {}

ngOnInit() {
this.searchFacade.setResultsLayout('ROW')

const cfg: MetadataQualityConfig =
getMetadataQualityConfig() || ({} as MetadataQualityConfig)
this.isQualitySortable = cfg.SORTABLE === true
this.metadataQualityDisplay = {
widget: cfg.ENABLED && cfg.DISPLAY_WIDGET_IN_SEARCH !== false,
title: cfg.DISPLAY_TITLE,
description: cfg.DISPLAY_DESCRIPTION,
contact: cfg.DISPLAY_CONTACT,
keywords: cfg.DISPLAY_KEYWORDS,
legalConstraints: cfg.DISPLAY_LEGAL_CONSTRAINTS,
topic: cfg.DISPLAY_TOPIC,
updateFrequency: cfg.DISPLAY_UPDATE_FREQUENCY,
organisation: cfg.DISPLAY_ORGANISATION,
}
}

onMetadataSelection(metadata: CatalogRecord): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
<datahub-header-record
[metadata]="mdViewFacade.metadata$ | async"
></datahub-header-record>
<gn-ui-record-metadata></gn-ui-record-metadata>
<gn-ui-record-metadata
[metadataQualityDisplay]="metadataQualityDisplay"
></gn-ui-record-metadata>
</div>
20 changes: 20 additions & 0 deletions apps/datahub/src/app/record/record-page/record-page.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core'
import { MdViewFacade } from '@geonetwork-ui/feature/record'
import { MetadataQualityDisplay } from '@geonetwork-ui/ui/elements'
import {
MetadataQualityConfig,
getMetadataQualityConfig,
} from '@geonetwork-ui/util/app-config'

@Component({
selector: 'datahub-record-page',
Expand All @@ -8,8 +13,23 @@ import { MdViewFacade } from '@geonetwork-ui/feature/record'
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RecordPageComponent implements OnDestroy {
metadataQualityDisplay: MetadataQualityDisplay = {} as MetadataQualityDisplay

constructor(public mdViewFacade: MdViewFacade) {
document.documentElement.classList.add('record-page-active')
const cfg: MetadataQualityConfig =
getMetadataQualityConfig() || ({} as MetadataQualityConfig)
this.metadataQualityDisplay = {
widget: cfg.ENABLED && cfg.DISPLAY_WIDGET_IN_DETAIL !== false,
title: cfg.DISPLAY_TITLE,
description: cfg.DISPLAY_DESCRIPTION,
contact: cfg.DISPLAY_CONTACT,
keywords: cfg.DISPLAY_KEYWORDS,
legalConstraints: cfg.DISPLAY_LEGAL_CONSTRAINTS,
topic: cfg.DISPLAY_TOPIC,
updateFrequency: cfg.DISPLAY_UPDATE_FREQUENCY,
organisation: cfg.DISPLAY_ORGANISATION,
}
}
ngOnDestroy() {
document.documentElement.classList.remove('record-page-active')
Expand Down
30 changes: 30 additions & 0 deletions conf/default.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,36 @@ 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 widget appears in 2 locations in the search list and in the detail page
# allow you to hide the widget in detail
# display_widget_in_detail = false
# allow you to hide the widget in search list
# display_widget_in_search = false
# If you want see the widget in the two locations, 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
31 changes: 30 additions & 1 deletion libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ export class Gn4FieldMapper {
const landingPage = getAsUrl(this.metadataUrlService.getUrl(uuid))
return { ...output, uniqueIdentifier: uuid, landingPage }
},
qualityScore: (output, source) =>
this.addExtra(
{ qualityScore: selectField(source, 'qualityScore') },
output
),
resourceTitleObject: (output, source) => ({
...output,
title: selectFallback(
Expand Down Expand Up @@ -83,6 +88,15 @@ export class Gn4FieldMapper {
],
}
},
cl_topic: (output, source) => ({
...output,
themes: [
...(output.themes || []),
...getAsArray(
selectField<SourceWithUnknownProps[]>(source, 'cl_topic')
).map((topic) => selectTranslatedValue<string>(topic, this.lang3)),
],
}),
cl_status: (output, source) => ({
...output,
status: getStatusFromStatusCode(
Expand Down Expand Up @@ -163,7 +177,10 @@ export class Gn4FieldMapper {
}),
inspireTheme: (output, source) => ({
...output,
themes: getAsArray(selectField(source, 'inspireTheme_syn')),
themes: [
...(output.themes || []),
...getAsArray(selectField(source, 'inspireTheme_syn')),
],
}),
MD_ConstraintsUseLimitationObject: (output, source) =>
this.constraintField('MD_ConstraintsUseLimitationObject', output, source),
Expand Down Expand Up @@ -249,6 +266,18 @@ export class Gn4FieldMapper {
...output,
...(fieldName.endsWith('UseLimitationObject')
? {
legalConstraints:
fieldName === 'MD_LegalConstraintsUseLimitationObject'
? [
...(output.legalConstraints || []),
...selectField<SourceWithUnknownProps[]>(
source,
fieldName
).map((source: SourceWithUnknownProps) =>
selectTranslatedValue(source, this.lang3)
),
]
: output.legalConstraints || [],
useLimitations: [
...(output.useLimitations || []),
...selectField<SourceWithUnknownProps[]>(source, fieldName).map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ describe('Gn4MetadataMapper', () => {
landingPage: new URL(
'http://my.catalog.org/metadata/cf5048f6-5bbf-4e44-ba74-e6f429af51ea'
),
legalConstraints: ["Restriction légale d'utilisation à préciser"],
licenses: [
{
link: new URL(
Expand All @@ -635,7 +636,7 @@ describe('Gn4MetadataMapper', () => {
recordCreated: new Date('2021-10-05T12:48:57.678Z'),
recordUpdated: new Date('2021-10-05T12:48:57.678Z'),
status: 'under_development',
themes: ['Installations de suivi environnemental'],
themes: ['Installations de suivi environnemental', 'Océans'],
title: 'Surval - Données par paramètre',
uniqueIdentifier: 'cf5048f6-5bbf-4e44-ba74-e6f429af51ea',
updateFrequency: {
Expand Down
7 changes: 7 additions & 0 deletions libs/api/repository/src/lib/gn4/elasticsearch/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ export const ES_SOURCE_SUMMARY = [
'linkProtocol',
'contactForResource.organisation',
'contact.organisation',
'contact.email',
'userSavedCount',
'updateFrequency',
'cl_topic',
'cl_maintenanceAndUpdateFrequency',
'tag',
'MD_LegalConstraintsUseLimitationObject',
'qualityScore',
]

export const ES_QUERY_STRING_FIELDS = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,14 @@ describe('ElasticsearchService', () => {
'linkProtocol',
'contactForResource.organisation',
'contact.organisation',
'contact.email',
'userSavedCount',
'updateFrequency',
'cl_topic',
'cl_maintenanceAndUpdateFrequency',
'tag',
'MD_LegalConstraintsUseLimitationObject',
'qualityScore',
],
query: {
bool: {
Expand Down
3 changes: 2 additions & 1 deletion libs/common/domain/src/lib/record/metadata.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ export interface BaseRecord {
keywords: Array<string> // TODO: handle thesaurus and id
accessConstraints: Array<AccessConstraint>
useLimitations: Array<string>
legalConstraints?: Array<string>
licenses: Array<License>
overviews: Array<GraphicOverview>
extras?: Record<string, unknown>
landingPage?: URL
updateFrequency?: UpdateFrequency

// to add: iso19139.topicCategory
// to add: canonical url
Expand Down Expand Up @@ -156,7 +158,6 @@ export interface DatasetRecord extends BaseRecord {
kind: 'dataset'
contactsForResource: Array<Individual>
status: RecordStatus
updateFrequency: UpdateFrequency
datasetCreated?: Date
datasetUpdated?: Date
lineage: string // Explanation of the origin of this record (e.g: how, why)"
Expand Down
1 change: 1 addition & 0 deletions libs/common/domain/src/lib/search/sort-by.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export const SortByEnum: Record<string, SortByField> = {
CREATE_DATE: ['desc', 'createDate'],
POPULARITY: ['desc', 'userSavedCount'],
RELEVANCY: ['desc', '_score'],
QUALITY_SCORE: ['desc', 'qualityScore'],
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,15 @@
</gn-ui-metadata-info>
</div>
<div>
<div *ngIf="hasMetadataQualityWidget">
<p class="text text-gray-700 text-xs mb-3 uppercase" translate>
record.metadata.quality
</p>
<gn-ui-metadata-quality
[metadata]="facade.metadata$ | async"
[metadataQualityDisplay]="metadataQualityDisplay"
></gn-ui-metadata-quality>
</div>
<gn-ui-metadata-contact
(organizationClick)="onOrganizationClick($event)"
[metadata]="facade.metadata$ | async"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'
import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { SourcesService } from '@geonetwork-ui/feature/catalog'
import { SearchService } from '@geonetwork-ui/feature/search'
import { ErrorType } from '@geonetwork-ui/ui/elements'
import { ErrorType, MetadataQualityDisplay } from '@geonetwork-ui/ui/elements'
import { BehaviorSubject, combineLatest } from 'rxjs'
import { filter, map, mergeMap, pluck } from 'rxjs/operators'
import { filter, map, mergeMap } from 'rxjs/operators'
import { MdViewFacade } from '../state/mdview.facade'
import { OrganizationsServiceInterface } from '@geonetwork-ui/common/domain/organizations.service.interface'
import { Individual, Organization } from '@geonetwork-ui/common/domain/record'
import { Organization } from '@geonetwork-ui/common/domain/record'

@Component({
selector: 'gn-ui-record-metadata',
Expand All @@ -15,6 +15,8 @@ import { Individual, Organization } from '@geonetwork-ui/common/domain/record'
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RecordMetadataComponent {
@Input() metadataQualityDisplay: MetadataQualityDisplay

displayMap$ = combineLatest([
this.facade.mapApiLinks$,
this.facade.geoDataLinks$,
Expand Down Expand Up @@ -75,4 +77,8 @@ export class RecordMetadataComponent {
.getFiltersForOrgs([org])
.subscribe((filters) => this.searchService.updateFilters(filters))
}

get hasMetadataQualityWidget() {
return this.metadataQualityDisplay?.widget === true
}
}
6 changes: 6 additions & 0 deletions libs/feature/search/src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,13 @@ export const FIELDS_SUMMARY: FieldName[] = [
'linkProtocol',
'contactForResource*.organisation*',
'contact*.organisation*',
'contact*.email',
'userSavedCount',
'cl_topic',
'cl_maintenanceAndUpdateFrequency',
'tag',
'MD_LegalConstraintsUseLimitationObject',
'qualityScore',
]

export const FIELDS_BRIEF: FieldName[] = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<gn-ui-results-list
[records]="facade.results$ | async"
[layoutConfig]="layoutConfig$ | async"
[metadataQualityDisplay]="metadataQualityDisplay"
[favoriteTemplate]="favoriteToggle"
[recordUrlGetter]="recordUrlGetter"
(mdSelect)="onMetadataSelection($event)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Observable } from 'rxjs'
import { filter, map } from 'rxjs/operators'
import { SearchFacade } from '../state/search.facade'
import { SearchError } from '../state/reducer'
import { ErrorType } from '@geonetwork-ui/ui/elements'
import { ErrorType, MetadataQualityDisplay } from '@geonetwork-ui/ui/elements'
import {
RESULTS_LAYOUT_CONFIG,
ResultsLayoutConfigItem,
Expand All @@ -28,6 +28,7 @@ export type ResultsListShowMoreStrategy = 'auto' | 'button' | 'none'
styleUrls: ['./results-list.container.component.css'],
})
export class ResultsListContainerComponent implements OnInit {
@Input() metadataQualityDisplay: MetadataQualityDisplay
@Input() layout: string
@Input() showMore: ResultsListShowMoreStrategy = 'auto'
@Output() mdSelect = new EventEmitter<CatalogRecord>()
Expand Down
Loading

0 comments on commit 2901ae6

Please sign in to comment.