Skip to content

Commit

Permalink
GSIGNGPF-39-load attribute descriptions embedded ( feature catalog)
Browse files Browse the repository at this point in the history
  • Loading branch information
Guillaume-d-o committed Feb 26, 2025
1 parent 6410b21 commit 4279231
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 4 deletions.
73 changes: 72 additions & 1 deletion libs/api/repository/src/lib/gn4/gn4-repository.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import {
simpleDatasetRecordFixture,
duplicateDatasetRecordAsXmlFixture,
} from '@geonetwork-ui/common/fixtures'
import { CatalogRecord } from '@geonetwork-ui/common/domain/model/record'
import {
CatalogRecord,
DatasetFeatureCatalog,
} from '@geonetwork-ui/common/domain/model/record'
import { map } from 'rxjs/operators'
import { HttpErrorResponse } from '@angular/common/http'
import {
Expand Down Expand Up @@ -92,6 +95,7 @@ class RecordsApiServiceMock {
)
deleteRecord = jest.fn(() => of({}))
create = jest.fn(() => of('1234-5678'))
getFeatureCatalog = jest.fn(() => of({}))
}

class PlatformServiceInterfaceMock {
Expand Down Expand Up @@ -253,6 +257,73 @@ describe('Gn4Repository', () => {
})
})
})

describe('getFeatureCatalog', () => {
let catalog: DatasetFeatureCatalog
const mockFeatureCatalogResponse = {
decodeMap: {
feature1: ['memberName', 'definition'],
feature2: ['name2', 'title2'],
feature3: ['name3', 'title3'],
},
}

describe('when feature catalog exists', () => {
beforeEach(async () => {
;(gn4RecordsApi.getFeatureCatalog as jest.Mock).mockReturnValue(
of(mockFeatureCatalogResponse)
)
catalog = await lastValueFrom(repository.getFeatureCatalog('1234-5678'))
})

it('calls the API with correct parameters', () => {
expect(gn4RecordsApi.getFeatureCatalog).toHaveBeenCalledWith(
'1234-5678',
undefined
)
})

it('returns the feature catalog with mapped features', () => {
expect(catalog).toEqual({
features: [
{ name: 'memberName', title: 'definition' },
{ name: 'name2', title: 'title2' },
{ name: 'name3', title: 'title3' },
],
})
})
})

describe('when feature catalog does not exist', () => {
beforeEach(async () => {
;(gn4RecordsApi.getFeatureCatalog as jest.Mock).mockReturnValue(of({}))
catalog = await lastValueFrom(repository.getFeatureCatalog('1234-5678'))
})

it('returns null when no decode map is present', () => {
expect(catalog).toBe(null)
})
})

describe('with approved version parameter', () => {
beforeEach(async () => {
;(gn4RecordsApi.getFeatureCatalog as jest.Mock).mockReturnValue(
of(mockFeatureCatalogResponse)
)
catalog = await lastValueFrom(
repository.getFeatureCatalog('1234-5678', true)
)
})

it('calls the API with approved parameter', () => {
expect(gn4RecordsApi.getFeatureCatalog).toHaveBeenCalledWith(
'1234-5678',
true
)
})
})
})

describe('getSimilarRecords', () => {
let results: CatalogRecord[]
beforeEach(async () => {
Expand Down
27 changes: 26 additions & 1 deletion libs/api/repository/src/lib/gn4/gn4-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@ import {
Iso19139Converter,
} from '@geonetwork-ui/api/metadata-converter'
import { PublicationVersionError } from '@geonetwork-ui/common/domain/model/error'
import { CatalogRecord } from '@geonetwork-ui/common/domain/model/record'
import {
CatalogRecord,
DatasetFeatureCatalog,
} from '@geonetwork-ui/common/domain/model/record'
import {
Aggregations,
AggregationsParams,
Expand All @@ -27,6 +30,7 @@ import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/reposit
import {
RecordsApiService,
SearchApiService,
FeatureResponseApiModel,
} from '@geonetwork-ui/data-access/gn4'
import {
combineLatest,
Expand Down Expand Up @@ -137,6 +141,27 @@ export class Gn4Repository implements RecordsRepositoryInterface {
)
}

getFeatureCatalog(
metadataUuid: string,
approvedVersion?: boolean
): Observable<DatasetFeatureCatalog | null> {
return this.gn4RecordsApi
.getFeatureCatalog(metadataUuid, approvedVersion)
.pipe(
map((results: FeatureResponseApiModel) => {
if (results.decodeMap) {
const features = Object.keys(results.decodeMap).map((key) => {
const feature = results.decodeMap[key]
return { name: feature[0], title: feature[1] }
})
return { features } as DatasetFeatureCatalog
}
return null
}),
switchMap((record) => (record ? of(record) : of(null)))
)
}

getSimilarRecords(similarTo: CatalogRecord): Observable<CatalogRecord[]> {
return this.gn4SearchApi
.search(
Expand Down
3 changes: 3 additions & 0 deletions libs/common/domain/src/lib/model/record/metadata.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ export interface DatasetRecord extends BaseRecord {
temporalExtents: Array<DatasetTemporalExtent>
spatialRepresentation?: SpatialRepresentationType
}
export type DatasetFeatureCatalog = {
features: Array<{ name: string; title: string }>
}

export interface ServiceEndpoint {
endpointUrl: URL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@ import {
SearchParams,
SearchResults,
} from '../model/search'
import { CatalogRecord } from '../model/record'
import { CatalogRecord, DatasetFeatureCatalog } from '../model/record'

export abstract class RecordsRepositoryInterface {
abstract search(params: SearchParams): Observable<SearchResults>
abstract getMatchesCount(filters: FieldFilters): Observable<number>
abstract getRecord(uniqueIdentifier: string): Observable<CatalogRecord | null>
abstract getFeatureCatalog(
metadataUuid: string,
approvedVersion?: boolean
): Observable<DatasetFeatureCatalog | null>
abstract aggregate(params: AggregationsParams): Observable<Aggregations>
abstract getSimilarRecords(
similarTo: CatalogRecord
Expand Down
16 changes: 16 additions & 0 deletions libs/feature/record/src/lib/state/mdview.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { DatavizConfigurationModel } from '@geonetwork-ui/common/domain/model/da
import { createAction, props } from '@ngrx/store'
import {
CatalogRecord,
DatasetFeatureCatalog,
UserFeedback,
} from '@geonetwork-ui/common/domain/model/record'

Expand All @@ -28,6 +29,21 @@ export const loadFullMetadataFailure = createAction(
props<{ otherError?: string; notFound?: boolean }>()
)

export const loadFeatureCatalogAttributes = createAction(
'[Metadata view] Load catalog attributes of the metadata',
props<{ metadataUuid: string; approvedVersion?: boolean }>()
)

export const loadFeatureCatalogAttributesSuccess = createAction(
'[Metadata view] Load full metadata success',
props<{ datasetCatalog: DatasetFeatureCatalog }>()
)

export const loadFeatureCatalogAttributesFailure = createAction(
'[Metadata view] Load full metadata failure',
props<{ otherError?: string; notFound?: boolean }>()
)

export const closeMetadata = createAction('[Metadata view] close')

/*
Expand Down
30 changes: 29 additions & 1 deletion libs/feature/record/src/lib/state/mdview.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { catchError, map, switchMap } from 'rxjs/operators'
import * as MdViewActions from './mdview.actions'
import { RecordsRepositoryInterface } from '@geonetwork-ui/common/domain/repository/records-repository.interface'
import { PlatformServiceInterface } from '@geonetwork-ui/common/domain/platform.service.interface'

@Injectable()
export class MdViewEffects {
constructor(
Expand All @@ -32,6 +31,35 @@ export class MdViewEffects {
)
)
)
/*
Feature Catalog effects
*/
loadCatalogAttributes = createEffect(() =>
this.actions$.pipe(
ofType(MdViewActions.loadFeatureCatalogAttributes),
switchMap(({ metadataUuid, approvedVersion }) =>
this.recordsRepository.getFeatureCatalog(metadataUuid, approvedVersion)
),
map((record) => {
if (record === null) {
return MdViewActions.loadFeatureCatalogAttributesFailure({
notFound: true,
})
}

return MdViewActions.loadFeatureCatalogAttributesSuccess({
datasetCatalog: record,
})
}),
catchError((error) =>
of(
MdViewActions.loadFeatureCatalogAttributesFailure({
otherError: error.message,
})
)
)
)
)

/*
Related effects
Expand Down
18 changes: 18 additions & 0 deletions libs/feature/record/src/lib/state/mdview.facade.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export class MdViewFacade {
filter((md) => !!md)
)

featureCatalog$ = this.store.pipe(
select(MdViewSelectors.getFeatureCatalog),
filter((fc) => !!fc)
)

isIncomplete$ = this.store.pipe(
select(MdViewSelectors.getMetadataIsIncomplete),
filter((incomplete) => incomplete !== null)
Expand Down Expand Up @@ -204,4 +209,17 @@ export class MdViewFacade {
loadUserFeedbacks(datasetUuid: string) {
this.store.dispatch(MdViewActions.loadUserFeedbacks({ datasetUuid }))
}

/**
* FeatureCatalog
*/

loadFeatureCatalog(metadataUuid: string, approvedVersion = false) {
this.store.dispatch(
MdViewActions.loadFeatureCatalogAttributes({
metadataUuid,
approvedVersion,
})
)
}
}
29 changes: 29 additions & 0 deletions libs/feature/record/src/lib/state/mdview.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as MetadataViewActions from './mdview.actions'
import { DatavizConfigurationModel } from '@geonetwork-ui/common/domain/model/dataviz/dataviz-configuration.model'
import {
CatalogRecord,
DatasetFeatureCatalog,
UserFeedback,
} from '@geonetwork-ui/common/domain/model/record'

Expand All @@ -17,13 +18,16 @@ export interface MetadataViewState {
allUserFeedbacksLoading: boolean
addUserFeedbackLoading: boolean
chartConfig?: DatavizConfigurationModel
featureCatalog?: DatasetFeatureCatalog
featureCatalogLoading: boolean
}

export const initialMetadataViewState: MetadataViewState = {
error: null,
loadingFull: false,
allUserFeedbacksLoading: false,
addUserFeedbackLoading: false,
featureCatalogLoading: false,
}

const metadataViewReducer = createReducer(
Expand Down Expand Up @@ -105,6 +109,31 @@ const metadataViewReducer = createReducer(
addUserFeedbackLoading: false,
allUserFeedbacksLoading: false,
})
),

/**
* FeatureCatalog reducers
*/

on(MetadataViewActions.loadFeatureCatalogAttributes, (state) => ({
...state,
featureCatalogLoading: true,
})),
on(
MetadataViewActions.loadFeatureCatalogAttributesSuccess,
(state, { datasetCatalog }) => ({
...state,
featureCatalog: datasetCatalog,
featureCatalogLoading: false,
})
),
on(
MetadataViewActions.loadFeatureCatalogAttributesFailure,
(state, { otherError, notFound }) => ({
...state,
error: { otherError, notFound },
featureCatalogLoading: false,
})
)
)

Expand Down
3 changes: 3 additions & 0 deletions libs/feature/record/src/lib/state/mdview.selectors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe('MdView Selectors', () => {
error: null,
allUserFeedbacksLoading: false,
addUserFeedbackLoading: false,
featureCatalogLoading: false,
})
expect(results).toBe(null)
})
Expand Down Expand Up @@ -73,6 +74,7 @@ describe('MdView Selectors', () => {
error: null,
allUserFeedbacksLoading: false,
addUserFeedbackLoading: false,
featureCatalogLoading: false,
})
expect(results).toBe(null)
})
Expand Down Expand Up @@ -108,6 +110,7 @@ describe('MdView Selectors', () => {
error: null,
allUserFeedbacksLoading: false,
addUserFeedbackLoading: false,
featureCatalogLoading: false,
})
expect(results).toBe(null)
})
Expand Down
8 changes: 8 additions & 0 deletions libs/feature/record/src/lib/state/mdview.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,11 @@ export const getAddUserFeedbacksLoading = createSelector(
getMdViewState,
(state: MetadataViewState) => state.addUserFeedbackLoading
)

/*
Feature Catalog Selectors
*/
export const getFeatureCatalog = createSelector(
getMdViewState,
(state: MetadataViewState) => state.featureCatalog
)

0 comments on commit 4279231

Please sign in to comment.