geonetwork-ui 2.10.0-dev.88fb568d7 → 2.10.0-dev.89f0dfe6f
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/geonetwork-ui.mjs +520 -127
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +107 -29
- package/index.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.ts +9 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/eu.dcat-ap.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+ongules.ts +7 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+roilaye.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/georhena.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/metadata-for-i18n.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/opendataswiss.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/sextant.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/vlaanderen.dcat-ap.records.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.reuse.ts +8 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.converter.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.ts +7 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +8 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +8 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +11 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +33 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +33 -0
- package/src/libs/api/repository/src/lib/gn4/auth/auth.service.ts +4 -0
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +14 -2
- package/src/libs/api/repository/src/lib/gn4/gn4.provider.ts +6 -1
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +11 -0
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +7 -0
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +6 -0
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +0 -1
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +10 -1
- package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.css +0 -0
- package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.html +67 -0
- package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.ts +39 -0
- package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.html +18 -3
- package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.ts +33 -40
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/field-focus.directive.ts +38 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-constraints-shortcuts/form-field-constraints-shortcuts.component.ts +33 -34
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html +13 -13
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.ts +18 -4
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html +8 -7
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.ts +6 -6
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-single-link-resource/form-field-online-single-link-resource.component.css +0 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-single-link-resource/form-field-online-single-link-resource.component.html +5 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-single-link-resource/form-field-online-single-link-resource.component.ts +89 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.css +37 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +1 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +5 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/index.ts +1 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +59 -3
- package/src/libs/feature/editor/src/lib/models/editor-config.model.ts +4 -0
- package/src/libs/feature/notify-reuse/src/index.ts +1 -0
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.css +0 -0
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.html +1 -0
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.ts +21 -0
- package/src/libs/ui/elements/src/index.ts +2 -0
- package/src/libs/ui/elements/src/lib/contact-details/contact-details.component.html +96 -0
- package/src/libs/ui/elements/src/lib/contact-details/contact-details.component.ts +45 -0
- package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.html +37 -0
- package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.ts +70 -0
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +1 -1
- package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +0 -1
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.ts +2 -5
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.css +0 -4
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +28 -67
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +30 -10
- package/src/libs/ui/inputs/src/lib/button/button.component.ts +4 -0
- package/src/libs/ui/inputs/src/lib/url-input/url-input.component.html +2 -2
- package/src/libs/ui/inputs/src/lib/url-input/url-input.component.ts +2 -1
- package/src/libs/ui/map/src/lib/components/map-container/map-container.component.ts +2 -1
- package/src/libs/ui/map/src/lib/components/spatial-extent/spatial-extent.component.ts +11 -10
- package/src/libs/ui/search/src/lib/record-preview-row/record-preview-row.component.html +0 -1
- package/src/libs/util/app-config/src/lib/app-config.ts +36 -0
- package/src/libs/util/app-config/src/lib/model.ts +4 -0
- package/src/libs/util/app-config/src/lib/parse-utils.ts +23 -1
- package/src/libs/util/shared/src/lib/record/quality-score.util.ts +33 -18
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/src/libs/util/shared/src/lib/utils/user-display.ts +32 -0
- package/tailwind.base.css +11 -2
- package/translations/de.json +10 -1
- package/translations/en.json +10 -1
- package/translations/es.json +10 -1
- package/translations/fr.json +10 -1
- package/translations/it.json +10 -1
- package/translations/nl.json +10 -1
- package/translations/pt.json +10 -1
- package/translations/sk.json +10 -1
|
@@ -82,6 +82,7 @@ export const SEXTANT_BATHYMETRY_DATASET_RECORD: DatasetRecord = {
|
|
|
82
82
|
Le pas de la grille est de 25m.
|
|
83
83
|
Produit interne Ifremer.`,
|
|
84
84
|
lineage: '',
|
|
85
|
+
sourceRecords: [],
|
|
85
86
|
ownerOrganization: null,
|
|
86
87
|
recordUpdated: new Date('2020-06-03T22:34:05.000Z'),
|
|
87
88
|
resourceUpdated: new Date('2020-06-03T22:34:05.000Z'),
|
|
@@ -322,6 +323,7 @@ export const SEXTANT_CURRENTS_DATASET_RECORD: CatalogRecord = {
|
|
|
322
323
|
],
|
|
323
324
|
lineage:
|
|
324
325
|
'Sallée, J.B.; Speer, K and Morrow, R. Southern Ocean fronts and their variability to climate modes, Journ. of Climate, 2008, Vol. 21(12), pp. 3020-3039',
|
|
326
|
+
sourceRecords: [],
|
|
325
327
|
onlineResources: [
|
|
326
328
|
{
|
|
327
329
|
name: 'Digital Object Identifier (DOI)',
|
|
@@ -68,6 +68,7 @@ export const VLAANDEREN_DATASET_RECORD: DatasetRecord = {
|
|
|
68
68
|
temporalExtents: [],
|
|
69
69
|
topics: ['biodiversity'],
|
|
70
70
|
lineage: '',
|
|
71
|
+
sourceRecords: [],
|
|
71
72
|
recordUpdated: new Date('2024-09-19T01:15:09.732Z'),
|
|
72
73
|
resourceUpdated: new Date('2021-04-14T11:15+02:00'),
|
|
73
74
|
status: 'completed',
|
|
@@ -447,5 +447,13 @@ export const WALLONIE_REUSE_SPW_RECORD: ReuseRecord = {
|
|
|
447
447
|
'https://metawal.wallonie.be/geonetwork/srv/api/records/83809bcd-1763-4d28-b820-2b9828083ba5'
|
|
448
448
|
),
|
|
449
449
|
lineage: "L'application a été développée sur base de l'API GeoViewer",
|
|
450
|
+
sourceRecords: [
|
|
451
|
+
{
|
|
452
|
+
uuid: 'ee965118-2416-4d48-b07e-bbc696f002c2',
|
|
453
|
+
title:
|
|
454
|
+
'SCoT (Schéma de cohérence territoriale) en région Hauts-de-France',
|
|
455
|
+
href: 'https://metawal.wallonie.be/geonetwork/srv/api/records/ee965118-2416-4d48-b07e-bbc696f002c2',
|
|
456
|
+
},
|
|
457
|
+
],
|
|
450
458
|
temporalExtents: [],
|
|
451
459
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
readKind,
|
|
10
10
|
readLandingPage,
|
|
11
11
|
readLineage,
|
|
12
|
+
readSourceRecords,
|
|
12
13
|
readOnlineResources,
|
|
13
14
|
readOtherLanguages,
|
|
14
15
|
readOwnerOrganization,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
writeKind,
|
|
26
27
|
writeLandingPage,
|
|
27
28
|
writeLineage,
|
|
29
|
+
writeSourceRecords,
|
|
28
30
|
writeOnlineResources,
|
|
29
31
|
writeOtherLanguages,
|
|
30
32
|
writeRecordCreated,
|
|
@@ -53,6 +55,7 @@ export class Iso191153Converter extends Iso19139Converter {
|
|
|
53
55
|
this.readers['ownerOrganization'] = readOwnerOrganization
|
|
54
56
|
this.readers['landingPage'] = readLandingPage
|
|
55
57
|
this.readers['lineage'] = readLineage
|
|
58
|
+
this.readers['sourceRecords'] = readSourceRecords
|
|
56
59
|
this.readers['onlineResources'] = readOnlineResources
|
|
57
60
|
this.readers['defaultLanguage'] = readDefaultLanguage
|
|
58
61
|
this.readers['otherLanguages'] = readOtherLanguages
|
|
@@ -72,6 +75,7 @@ export class Iso191153Converter extends Iso19139Converter {
|
|
|
72
75
|
this.writers['ownerOrganization'] = () => undefined // fixme: find a way to store this value properly
|
|
73
76
|
this.writers['landingPage'] = writeLandingPage
|
|
74
77
|
this.writers['lineage'] = writeLineage
|
|
78
|
+
this.writers['sourceRecords'] = writeSourceRecords
|
|
75
79
|
this.writers['onlineResources'] = writeOnlineResources
|
|
76
80
|
this.writers['status'] = writeStatus
|
|
77
81
|
this.writers['spatialRepresentation'] = writeSpatialRepresentation
|
|
@@ -167,6 +171,9 @@ export class Iso191153Converter extends Iso19139Converter {
|
|
|
167
171
|
'gmd:fileName': 'mcc:fileName',
|
|
168
172
|
'gmd:fileDescription': 'mcc:fileDescription',
|
|
169
173
|
|
|
174
|
+
// lineage sources
|
|
175
|
+
'gmd:source': 'mrl:source',
|
|
176
|
+
|
|
170
177
|
// no more URL elements
|
|
171
178
|
'gmd:URL': 'gco:CharacterString',
|
|
172
179
|
})
|
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
extractCharacterString,
|
|
22
22
|
extractDatasetOnlineResources,
|
|
23
23
|
extractDateTime,
|
|
24
|
+
extractSourceRecords,
|
|
24
25
|
extractLocalizedCharacterString,
|
|
25
26
|
extractReuseOnlineResources,
|
|
26
27
|
extractRole,
|
|
@@ -31,6 +32,7 @@ import {
|
|
|
31
32
|
import {
|
|
32
33
|
Individual,
|
|
33
34
|
LanguageCode,
|
|
35
|
+
SourceRecord,
|
|
34
36
|
OnlineResource,
|
|
35
37
|
Organization,
|
|
36
38
|
OrganizationTranslations,
|
|
@@ -291,6 +293,12 @@ export function readLineage(
|
|
|
291
293
|
)(rootEl)
|
|
292
294
|
}
|
|
293
295
|
|
|
296
|
+
export function readSourceRecords(rootEl: XmlElement): SourceRecord[] {
|
|
297
|
+
return extractSourceRecords(
|
|
298
|
+
pipe(findNestedElement('mdb:resourceLineage', 'mrl:LI_Lineage'))(rootEl)
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
|
|
294
302
|
function extractDateInfo(
|
|
295
303
|
type: 'creation' | 'revision' | 'publication'
|
|
296
304
|
): ChainableFunction<XmlElement, Date> {
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
} from '../function-utils'
|
|
35
35
|
import {
|
|
36
36
|
appendKeywords,
|
|
37
|
+
appendSourceRecords,
|
|
37
38
|
appendOnlineResource,
|
|
38
39
|
appendServiceOnlineResources,
|
|
39
40
|
createDistributionInfo,
|
|
@@ -564,3 +565,10 @@ export function writeOtherLanguages(record: DatasetRecord, rootEl: XmlElement) {
|
|
|
564
565
|
)
|
|
565
566
|
)(rootEl)
|
|
566
567
|
}
|
|
568
|
+
|
|
569
|
+
export function writeSourceRecords(record: DatasetRecord, rootEl: XmlElement) {
|
|
570
|
+
pipe(
|
|
571
|
+
findNestedChildOrCreate('mdb:resourceLineage', 'mrl:LI_Lineage'),
|
|
572
|
+
appendSourceRecords(record.sourceRecords)
|
|
573
|
+
)(rootEl)
|
|
574
|
+
}
|
|
@@ -30,6 +30,7 @@ import {
|
|
|
30
30
|
readLegalConstraints,
|
|
31
31
|
readLicenses,
|
|
32
32
|
readLineage,
|
|
33
|
+
readSourceRecords,
|
|
33
34
|
readOnlineResources,
|
|
34
35
|
readOtherConstraints,
|
|
35
36
|
readOtherLanguages,
|
|
@@ -62,6 +63,7 @@ import {
|
|
|
62
63
|
writeLegalConstraints,
|
|
63
64
|
writeLicenses,
|
|
64
65
|
writeLineage,
|
|
66
|
+
writeSourceRecords,
|
|
65
67
|
writeOnlineResources,
|
|
66
68
|
writeOtherConstraints,
|
|
67
69
|
writeRecordUpdated,
|
|
@@ -112,6 +114,7 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
112
114
|
spatialRepresentation: readSpatialRepresentation,
|
|
113
115
|
overviews: readOverviews,
|
|
114
116
|
lineage: readLineage,
|
|
117
|
+
sourceRecords: readSourceRecords,
|
|
115
118
|
onlineResources: readOnlineResources,
|
|
116
119
|
temporalExtents: readTemporalExtents,
|
|
117
120
|
spatialExtents: readSpatialExtents,
|
|
@@ -153,6 +156,7 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
153
156
|
spatialRepresentation: writeSpatialRepresentation,
|
|
154
157
|
overviews: writeGraphicOverviews,
|
|
155
158
|
lineage: writeLineage,
|
|
159
|
+
sourceRecords: writeSourceRecords,
|
|
156
160
|
onlineResources: writeOnlineResources,
|
|
157
161
|
temporalExtents: writeTemporalExtents,
|
|
158
162
|
spatialExtents: writeSpatialExtents,
|
|
@@ -295,6 +299,7 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
295
299
|
)
|
|
296
300
|
const temporalExtents = this.readers['temporalExtents'](rootEl, tr)
|
|
297
301
|
const lineage = this.readers['lineage'](rootEl, tr)
|
|
302
|
+
const sourceRecords = this.readers['sourceRecords'](rootEl, tr)
|
|
298
303
|
const updateFrequency = this.readers['updateFrequency'](rootEl, tr)
|
|
299
304
|
|
|
300
305
|
return this.afterRecordRead({
|
|
@@ -302,6 +307,7 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
302
307
|
kind,
|
|
303
308
|
status,
|
|
304
309
|
lineage,
|
|
310
|
+
...(sourceRecords && { sourceRecords }),
|
|
305
311
|
...(spatialRepresentation && { spatialRepresentation }),
|
|
306
312
|
temporalExtents,
|
|
307
313
|
updateFrequency,
|
|
@@ -309,6 +315,7 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
309
315
|
} as DatasetRecord)
|
|
310
316
|
} else if (kind === 'reuse') {
|
|
311
317
|
const lineage = this.readers['lineage'](rootEl, tr)
|
|
318
|
+
const sourceRecords = this.readers['sourceRecords'](rootEl, tr)
|
|
312
319
|
const temporalExtents = this.readers['temporalExtents'](rootEl, tr)
|
|
313
320
|
const reuseType = this.readers['reuseType'](rootEl, tr)
|
|
314
321
|
|
|
@@ -316,6 +323,7 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
316
323
|
...this.readBaseRecord(rootEl, tr),
|
|
317
324
|
kind,
|
|
318
325
|
lineage,
|
|
326
|
+
...(sourceRecords && { sourceRecords }),
|
|
319
327
|
temporalExtents,
|
|
320
328
|
reuseType,
|
|
321
329
|
} as ReuseRecord)
|
|
@@ -411,7 +419,10 @@ export class Iso19139Converter extends BaseConverter<string> {
|
|
|
411
419
|
this.writers['spatialExtents'](record, rootEl)
|
|
412
420
|
;(fieldChanged('lineage') || fieldChanged('translations')) &&
|
|
413
421
|
this.writers['lineage'](record, rootEl)
|
|
422
|
+
fieldChanged('sourceRecords') &&
|
|
423
|
+
this.writers['sourceRecords'](record, rootEl)
|
|
414
424
|
}
|
|
425
|
+
|
|
415
426
|
fieldChanged('otherLanguages') &&
|
|
416
427
|
this.writers['otherLanguages'](record, rootEl)
|
|
417
428
|
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Keyword,
|
|
9
9
|
KeywordTranslations,
|
|
10
10
|
LanguageCode,
|
|
11
|
+
SourceRecord,
|
|
11
12
|
ModelTranslations,
|
|
12
13
|
OnlineLinkResource,
|
|
13
14
|
OnlineResource,
|
|
@@ -894,6 +895,38 @@ export function readLineage(
|
|
|
894
895
|
)(rootEl)
|
|
895
896
|
}
|
|
896
897
|
|
|
898
|
+
export function extractSourceRecords(liLineageEl: XmlElement): SourceRecord[] {
|
|
899
|
+
if (!liLineageEl) return []
|
|
900
|
+
return pipe(
|
|
901
|
+
findChildrenElement('gmd:source', false),
|
|
902
|
+
mapArray((el) => {
|
|
903
|
+
const uuid = readAttribute('uuidref')(el)
|
|
904
|
+
const title = readAttribute('xlink:title')(el)
|
|
905
|
+
const href = readAttribute('xlink:href')(el)
|
|
906
|
+
if (!uuid && !title && !href) return null
|
|
907
|
+
return {
|
|
908
|
+
...(uuid ? { uuid } : {}),
|
|
909
|
+
...(title ? { title } : {}),
|
|
910
|
+
...(href ? { href } : {}),
|
|
911
|
+
} as SourceRecord
|
|
912
|
+
}),
|
|
913
|
+
filterArray((s): s is SourceRecord => s !== null)
|
|
914
|
+
)(liLineageEl)
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
export function readSourceRecords(rootEl: XmlElement): SourceRecord[] {
|
|
918
|
+
return extractSourceRecords(
|
|
919
|
+
pipe(
|
|
920
|
+
findNestedElement(
|
|
921
|
+
'gmd:dataQualityInfo',
|
|
922
|
+
'gmd:DQ_DataQuality',
|
|
923
|
+
'gmd:lineage',
|
|
924
|
+
'gmd:LI_Lineage'
|
|
925
|
+
)
|
|
926
|
+
)(rootEl)
|
|
927
|
+
)
|
|
928
|
+
}
|
|
929
|
+
|
|
897
930
|
export function readUpdateFrequency(rootEl: XmlElement): UpdateFrequency {
|
|
898
931
|
return pipe(
|
|
899
932
|
findIdentification(),
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
Individual,
|
|
9
9
|
Keyword,
|
|
10
10
|
LanguageCode,
|
|
11
|
+
SourceRecord,
|
|
11
12
|
RecordStatus,
|
|
12
13
|
RecordTranslations,
|
|
13
14
|
ReuseRecord,
|
|
@@ -1231,6 +1232,38 @@ export function writeLineage(record: DatasetRecord, rootEl: XmlElement) {
|
|
|
1231
1232
|
)(rootEl)
|
|
1232
1233
|
}
|
|
1233
1234
|
|
|
1235
|
+
export function appendSourceRecords(
|
|
1236
|
+
sources: SourceRecord[]
|
|
1237
|
+
): ChainableFunction<XmlElement, XmlElement> {
|
|
1238
|
+
return pipe(
|
|
1239
|
+
removeChildrenByName('gmd:source'),
|
|
1240
|
+
appendChildren(
|
|
1241
|
+
...sources
|
|
1242
|
+
.filter((source) => source.uuid || source.title || source.href)
|
|
1243
|
+
.map((source) =>
|
|
1244
|
+
pipe(
|
|
1245
|
+
createElement('gmd:source'),
|
|
1246
|
+
source.uuid ? writeAttribute('uuidref', source.uuid) : noop,
|
|
1247
|
+
source.title ? writeAttribute('xlink:title', source.title) : noop,
|
|
1248
|
+
source.href ? writeAttribute('xlink:href', source.href) : noop
|
|
1249
|
+
)
|
|
1250
|
+
)
|
|
1251
|
+
)
|
|
1252
|
+
)
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
export function writeSourceRecords(record: DatasetRecord, rootEl: XmlElement) {
|
|
1256
|
+
pipe(
|
|
1257
|
+
findNestedChildOrCreate(
|
|
1258
|
+
'gmd:dataQualityInfo',
|
|
1259
|
+
'gmd:DQ_DataQuality',
|
|
1260
|
+
'gmd:lineage',
|
|
1261
|
+
'gmd:LI_Lineage'
|
|
1262
|
+
),
|
|
1263
|
+
appendSourceRecords(record.sourceRecords)
|
|
1264
|
+
)(rootEl)
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1234
1267
|
export function getServiceEndpointProtocol(endpoint: ServiceEndpoint): string {
|
|
1235
1268
|
switch (endpoint.accessServiceProtocol.toLowerCase()) {
|
|
1236
1269
|
case 'wfs':
|
|
@@ -44,6 +44,10 @@ export class AuthService {
|
|
|
44
44
|
window.location.href
|
|
45
45
|
).toString()
|
|
46
46
|
)
|
|
47
|
+
.replace(
|
|
48
|
+
'${current_path}',
|
|
49
|
+
this.location.prepareExternalUrl(this.location.path())
|
|
50
|
+
)
|
|
47
51
|
.replace('${lang2}', toLang2(this.translateService.currentLang))
|
|
48
52
|
.replace('${lang3}', toLang3(this.translateService.currentLang))
|
|
49
53
|
}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
HttpErrorResponse,
|
|
4
4
|
HttpHeaders,
|
|
5
5
|
} from '@angular/common/http'
|
|
6
|
-
import { Injectable, inject } from '@angular/core'
|
|
6
|
+
import { Injectable, InjectionToken, inject } from '@angular/core'
|
|
7
7
|
import {
|
|
8
8
|
assertValidXml,
|
|
9
9
|
findConverterForDocument,
|
|
@@ -57,6 +57,10 @@ const TEMPORARY_ID_PREFIX = 'TEMP-ID-'
|
|
|
57
57
|
|
|
58
58
|
export type RecordAsXml = string
|
|
59
59
|
|
|
60
|
+
export const DISABLE_DRAFT = new InjectionToken<boolean>('gnDisableDraft', {
|
|
61
|
+
factory: () => false,
|
|
62
|
+
})
|
|
63
|
+
|
|
60
64
|
@Injectable()
|
|
61
65
|
export class Gn4Repository implements RecordsRepositoryInterface {
|
|
62
66
|
private httpClient = inject(HttpClient)
|
|
@@ -67,6 +71,7 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
67
71
|
private platformService = inject(PlatformServiceInterface)
|
|
68
72
|
private gn4LanguagesApi = inject(LanguagesApiService)
|
|
69
73
|
private settingsService = inject(Gn4SettingsService)
|
|
74
|
+
private disableDraft = inject(DISABLE_DRAFT, { optional: true }) ?? false
|
|
70
75
|
|
|
71
76
|
_draftsChanged = new Subject<void>()
|
|
72
77
|
draftsChanged$ = this._draftsChanged.asObservable()
|
|
@@ -350,7 +355,9 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
350
355
|
openRecordForEdition(
|
|
351
356
|
uniqueIdentifier: string
|
|
352
357
|
): Observable<[CatalogRecord, string, boolean] | null> {
|
|
353
|
-
const draft$ =
|
|
358
|
+
const draft$ = this.disableDraft
|
|
359
|
+
? of(null)
|
|
360
|
+
: of(this.getRecordFromLocalStorage(uniqueIdentifier))
|
|
354
361
|
const recordAsXml$ = this.getRecordAsXml(uniqueIdentifier)
|
|
355
362
|
|
|
356
363
|
return combineLatest([draft$, recordAsXml$]).pipe(
|
|
@@ -475,6 +482,7 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
475
482
|
record: CatalogRecord,
|
|
476
483
|
referenceRecordSource?: string
|
|
477
484
|
): Observable<string> {
|
|
485
|
+
if (this.disableDraft) return of('')
|
|
478
486
|
return this.serializeRecordToXml(record, referenceRecordSource).pipe(
|
|
479
487
|
tap((recordXml) => {
|
|
480
488
|
this.saveRecordToLocalStorage(recordXml, record.uniqueIdentifier)
|
|
@@ -484,16 +492,19 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
484
492
|
}
|
|
485
493
|
|
|
486
494
|
clearRecordDraft(uniqueIdentifier: string): void {
|
|
495
|
+
if (this.disableDraft) return
|
|
487
496
|
this.removeRecordFromLocalStorage(uniqueIdentifier)
|
|
488
497
|
this._draftsChanged.next()
|
|
489
498
|
}
|
|
490
499
|
|
|
491
500
|
recordHasDraft(uniqueIdentifier: string): boolean {
|
|
501
|
+
if (this.disableDraft) return false
|
|
492
502
|
return this.getRecordFromLocalStorage(uniqueIdentifier) !== null
|
|
493
503
|
}
|
|
494
504
|
|
|
495
505
|
// generated by copilot
|
|
496
506
|
getAllDrafts(): Observable<CatalogRecord[]> {
|
|
507
|
+
if (this.disableDraft) return of([])
|
|
497
508
|
const items = { ...window.localStorage }
|
|
498
509
|
const drafts = Object.keys(items)
|
|
499
510
|
.filter((key) => key.startsWith('geonetwork-ui-draft-'))
|
|
@@ -509,6 +520,7 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
509
520
|
}
|
|
510
521
|
|
|
511
522
|
getDraftsCount(): Observable<number> {
|
|
523
|
+
if (this.disableDraft) return of(0)
|
|
512
524
|
const items = { ...window.localStorage }
|
|
513
525
|
const draftCount = Object.keys(items)
|
|
514
526
|
.filter((key) => key.startsWith('geonetwork-ui-draft-'))
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from './platform/gn4-platform.service'
|
|
7
7
|
import { Gn4PlatformMapper } from './platform/gn4-platform.mapper'
|
|
8
8
|
import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
|
|
9
|
-
import { Gn4Repository } from './gn4-repository'
|
|
9
|
+
import { Gn4Repository, DISABLE_DRAFT } from './gn4-repository'
|
|
10
10
|
import { AvatarServiceInterface, GravatarService } from './auth'
|
|
11
11
|
import { OrganizationsServiceInterface } from '../../../../../../libs/common/domain/src/lib/organizations.service.interface'
|
|
12
12
|
import {
|
|
@@ -22,6 +22,7 @@ import { TranslateService } from '@ngx-translate/core'
|
|
|
22
22
|
|
|
23
23
|
interface Gn4ProvideOptions {
|
|
24
24
|
disableAuth?: boolean
|
|
25
|
+
disableDraft?: boolean
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
export function provideGn4(provideOptions?: Gn4ProvideOptions): Provider[] {
|
|
@@ -30,6 +31,10 @@ export function provideGn4(provideOptions?: Gn4ProvideOptions): Provider[] {
|
|
|
30
31
|
provide: DISABLE_AUTH,
|
|
31
32
|
useValue: provideOptions?.disableAuth,
|
|
32
33
|
},
|
|
34
|
+
{
|
|
35
|
+
provide: DISABLE_DRAFT,
|
|
36
|
+
useValue: provideOptions?.disableDraft,
|
|
37
|
+
},
|
|
33
38
|
{
|
|
34
39
|
provide: PlatformServiceInterface,
|
|
35
40
|
useClass: Gn4PlatformService,
|
|
@@ -254,10 +254,20 @@ export interface DatasetTemporalExtent {
|
|
|
254
254
|
end?: Date
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Represents a source dataset referenced from a lineage entry.
|
|
259
|
+
*/
|
|
260
|
+
export interface SourceRecord {
|
|
261
|
+
uuid?: string
|
|
262
|
+
title?: string
|
|
263
|
+
href?: string
|
|
264
|
+
}
|
|
265
|
+
|
|
257
266
|
export interface DatasetRecord extends BaseRecord {
|
|
258
267
|
kind: 'dataset'
|
|
259
268
|
status: RecordStatus
|
|
260
269
|
lineage: string // Explanation of the origin of this record (e.g: how, why)"
|
|
270
|
+
sourceRecords: Array<SourceRecord>
|
|
261
271
|
onlineResources: Array<DatasetOnlineResource>
|
|
262
272
|
spatialExtents: Array<DatasetSpatialExtent>
|
|
263
273
|
temporalExtents: Array<DatasetTemporalExtent>
|
|
@@ -285,6 +295,7 @@ export interface ServiceRecord extends BaseRecord {
|
|
|
285
295
|
export interface ReuseRecord extends BaseRecord {
|
|
286
296
|
kind: 'reuse'
|
|
287
297
|
lineage: string // Explanation of the origin of this record (e.g: how, why)"
|
|
298
|
+
sourceRecords: Array<SourceRecord>
|
|
288
299
|
onlineResources: Array<DatasetOnlineResource>
|
|
289
300
|
reuseType: ReuseType
|
|
290
301
|
spatialExtents: Array<DatasetSpatialExtent>
|
|
@@ -134,6 +134,7 @@ Cette section contient des *caractères internationaux* (ainsi que des "caractè
|
|
|
134
134
|
lineage: `This record was edited manually to test the conversion processes
|
|
135
135
|
|
|
136
136
|
As such, **it is not very interesting at all.**`,
|
|
137
|
+
sourceRecords: [],
|
|
137
138
|
licenses: [
|
|
138
139
|
{
|
|
139
140
|
text: 'Licence ODbL mai 2013 (basée sur ODbL 1.0)',
|
|
@@ -310,6 +311,7 @@ Malgré l'attention portée à la création de ces données, il est rappelé que
|
|
|
310
311
|
],
|
|
311
312
|
lineage: `Document d’urbanisme numérisé conformément aux prescriptions nationales du CNIG par le Service d'Information Géographique de l'Agglomération de la Région de Compiègne.
|
|
312
313
|
Ce lot de données produit en 2019, a été numérisé à partir du PCI Vecteur de 2019 et contrôlé par le Service d'Information Géographique de l'Agglomération de la Région de Compiègne.`,
|
|
314
|
+
sourceRecords: [],
|
|
313
315
|
legalConstraints: [],
|
|
314
316
|
securityConstraints: [],
|
|
315
317
|
otherConstraints: [],
|
|
@@ -357,10 +359,12 @@ export const simpleDatasetRecordFixture = (): DatasetRecord => ({
|
|
|
357
359
|
securityConstraints: [],
|
|
358
360
|
otherConstraints: [],
|
|
359
361
|
lineage: 'This record was edited manually to test the conversion processes',
|
|
362
|
+
sourceRecords: [],
|
|
360
363
|
spatialRepresentation: 'grid',
|
|
361
364
|
overviews: [],
|
|
362
365
|
spatialExtents: [],
|
|
363
366
|
temporalExtents: [],
|
|
367
|
+
sourceRecords: [],
|
|
364
368
|
onlineResources: [
|
|
365
369
|
{
|
|
366
370
|
type: 'download',
|
|
@@ -413,6 +417,7 @@ export const simpleDatasetRecordWithFcatsFixture = (): DatasetRecord => ({
|
|
|
413
417
|
overviews: [],
|
|
414
418
|
spatialExtents: [],
|
|
415
419
|
temporalExtents: [],
|
|
420
|
+
sourceRecords: [],
|
|
416
421
|
onlineResources: [],
|
|
417
422
|
updateFrequency: { per: 'month', updatedTimes: 3 },
|
|
418
423
|
translations: {},
|
|
@@ -978,6 +983,7 @@ export const multilingualDatasetFixture: () => DatasetRecord = () => ({
|
|
|
978
983
|
title: 'English Title',
|
|
979
984
|
abstract: 'English Abstract',
|
|
980
985
|
lineage: 'English Lineage',
|
|
986
|
+
sourceRecords: [],
|
|
981
987
|
translations: {
|
|
982
988
|
title: { fr: 'Titre Français', de: 'Titel DE' },
|
|
983
989
|
abstract: { fr: 'Résumé Français', de: 'Beschreibung DE' },
|
|
@@ -994,6 +1000,7 @@ export const multilingualDatasetFixture: () => DatasetRecord = () => ({
|
|
|
994
1000
|
},
|
|
995
1001
|
},
|
|
996
1002
|
],
|
|
1003
|
+
sourceRecords: [],
|
|
997
1004
|
onlineResources: [],
|
|
998
1005
|
licenses: [],
|
|
999
1006
|
legalConstraints: [],
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createAction, props } from '@ngrx/store'
|
|
2
2
|
import {
|
|
3
3
|
CatalogRecord,
|
|
4
|
+
CatalogRecordKeys,
|
|
4
5
|
LanguageCode,
|
|
5
6
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
7
|
import { SaveRecordError } from './editor.models'
|
|
@@ -73,3 +74,8 @@ export const canEditRecord = createAction(
|
|
|
73
74
|
'[Editor] User can edit record',
|
|
74
75
|
props<{ canEditRecord: boolean }>()
|
|
75
76
|
)
|
|
77
|
+
|
|
78
|
+
export const setFocusedField = createAction(
|
|
79
|
+
'[Editor] Set focused field',
|
|
80
|
+
props<{ model: CatalogRecordKeys }>()
|
|
81
|
+
)
|
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from './editor.selectors'
|
|
13
13
|
import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
|
|
14
14
|
import { PlatformServiceInterface } from '../../../../../../libs/common/domain/src/lib/platform.service.interface'
|
|
15
|
-
|
|
16
15
|
@Injectable()
|
|
17
16
|
export class EditorEffects {
|
|
18
17
|
private actions$ = inject(Actions)
|
|
@@ -4,9 +4,10 @@ import * as EditorActions from './editor.actions'
|
|
|
4
4
|
import * as EditorSelectors from './editor.selectors'
|
|
5
5
|
import {
|
|
6
6
|
CatalogRecord,
|
|
7
|
+
CatalogRecordKeys,
|
|
7
8
|
LanguageCode,
|
|
8
9
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
9
|
-
import { filter } from 'rxjs'
|
|
10
|
+
import { filter, map } from 'rxjs'
|
|
10
11
|
import { Actions, ofType } from '@ngrx/effects'
|
|
11
12
|
import { EditorConfig, EditorFieldIdentification } from '../models'
|
|
12
13
|
|
|
@@ -37,6 +38,10 @@ export class EditorFacade {
|
|
|
37
38
|
)
|
|
38
39
|
isPublished$ = this.store.pipe(select(EditorSelectors.selectIsPublished))
|
|
39
40
|
canEditRecord$ = this.store.pipe(select(EditorSelectors.selectCanEditRecord))
|
|
41
|
+
focusedField$ = this.actions$.pipe(
|
|
42
|
+
ofType(EditorActions.setFocusedField),
|
|
43
|
+
map(({ model }) => model)
|
|
44
|
+
)
|
|
40
45
|
|
|
41
46
|
openRecord(record: CatalogRecord, recordSource: string) {
|
|
42
47
|
this.store.dispatch(
|
|
@@ -77,6 +82,10 @@ export class EditorFacade {
|
|
|
77
82
|
this.store.dispatch(EditorActions.setCurrentPage({ page }))
|
|
78
83
|
}
|
|
79
84
|
|
|
85
|
+
setFocusedField(model: CatalogRecordKeys) {
|
|
86
|
+
this.store.dispatch(EditorActions.setFocusedField({ model }))
|
|
87
|
+
}
|
|
88
|
+
|
|
80
89
|
setFieldVisibility(field: EditorFieldIdentification, visible: boolean) {
|
|
81
90
|
this.store.dispatch(EditorActions.setFieldVisibility({ field, visible }))
|
|
82
91
|
}
|
|
File without changes
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<div class="flex flex-col gap-7">
|
|
2
|
+
<div class="grid grid-cols-2 gap-4">
|
|
3
|
+
<div class="min-w-0">
|
|
4
|
+
<h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
|
|
5
|
+
editor.record.form.field.contactDetails.lastName
|
|
6
|
+
</h3>
|
|
7
|
+
<gn-ui-text-input
|
|
8
|
+
class="block w-full"
|
|
9
|
+
extraClass="w-full"
|
|
10
|
+
[(value)]="contact.lastName"
|
|
11
|
+
(valueChange)="emitContactChange()"
|
|
12
|
+
[placeholder]="
|
|
13
|
+
'editor.record.form.field.contactDetails.lastName.placeholder'
|
|
14
|
+
| translate
|
|
15
|
+
"
|
|
16
|
+
data-test="contactDetailsLastName"
|
|
17
|
+
></gn-ui-text-input>
|
|
18
|
+
</div>
|
|
19
|
+
<div class="min-w-0">
|
|
20
|
+
<h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
|
|
21
|
+
editor.record.form.field.contactDetails.firstName
|
|
22
|
+
</h3>
|
|
23
|
+
<gn-ui-text-input
|
|
24
|
+
class="block w-full"
|
|
25
|
+
extraClass="w-full"
|
|
26
|
+
[(value)]="contact.firstName"
|
|
27
|
+
(valueChange)="emitContactChange()"
|
|
28
|
+
[placeholder]="
|
|
29
|
+
'editor.record.form.field.contactDetails.firstName.placeholder'
|
|
30
|
+
| translate
|
|
31
|
+
"
|
|
32
|
+
data-test="contactDetailsFirstName"
|
|
33
|
+
></gn-ui-text-input>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
<div>
|
|
37
|
+
<h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
|
|
38
|
+
editor.record.form.field.contactDetails.email
|
|
39
|
+
</h3>
|
|
40
|
+
<gn-ui-text-input
|
|
41
|
+
class="block w-full"
|
|
42
|
+
extraClass="w-full"
|
|
43
|
+
[value]="contact.organization?.email ?? ''"
|
|
44
|
+
(valueChange)="handleOrganizationChange({ email: $event })"
|
|
45
|
+
[placeholder]="
|
|
46
|
+
'editor.record.form.field.contactDetails.email.placeholder' | translate
|
|
47
|
+
"
|
|
48
|
+
data-test="contactDetailsEmail"
|
|
49
|
+
></gn-ui-text-input>
|
|
50
|
+
</div>
|
|
51
|
+
<div>
|
|
52
|
+
<h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
|
|
53
|
+
editor.record.form.field.contactDetails.organization
|
|
54
|
+
</h3>
|
|
55
|
+
<gn-ui-text-input
|
|
56
|
+
class="block w-full"
|
|
57
|
+
extraClass="w-full"
|
|
58
|
+
[value]="contact.organization?.name ?? ''"
|
|
59
|
+
(valueChange)="handleOrganizationChange({ name: $event })"
|
|
60
|
+
[placeholder]="
|
|
61
|
+
'editor.record.form.field.contactDetails.organization.placeholder'
|
|
62
|
+
| translate
|
|
63
|
+
"
|
|
64
|
+
data-test="contactDetailsOrganization"
|
|
65
|
+
></gn-ui-text-input>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ChangeDetectionStrategy,
|
|
3
|
+
Component,
|
|
4
|
+
EventEmitter,
|
|
5
|
+
Input,
|
|
6
|
+
Output,
|
|
7
|
+
} from '@angular/core'
|
|
8
|
+
import {
|
|
9
|
+
Individual,
|
|
10
|
+
Organization,
|
|
11
|
+
} from '../../../../../../../libs/common/domain/src/lib/model/record'
|
|
12
|
+
import { TextInputComponent } from '../../../../../../../libs/ui/inputs/src'
|
|
13
|
+
import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
|
|
14
|
+
|
|
15
|
+
@Component({
|
|
16
|
+
selector: 'gn-ui-contact-details-form',
|
|
17
|
+
templateUrl: './contact-details-form.component.html',
|
|
18
|
+
styleUrls: ['./contact-details-form.component.css'],
|
|
19
|
+
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
20
|
+
standalone: true,
|
|
21
|
+
imports: [TextInputComponent, TranslateDirective, TranslatePipe],
|
|
22
|
+
})
|
|
23
|
+
export class ContactDetailsFormComponent {
|
|
24
|
+
@Input() contact: Individual
|
|
25
|
+
@Output() contactChange = new EventEmitter<Individual>()
|
|
26
|
+
|
|
27
|
+
emitContactChange() {
|
|
28
|
+
this.contactChange.emit(this.contact)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
handleOrganizationChange(change: Partial<Organization>) {
|
|
32
|
+
this.contact.organization = {
|
|
33
|
+
...(this.contact.organization ?? ({} as Organization)),
|
|
34
|
+
...change,
|
|
35
|
+
} as Organization
|
|
36
|
+
|
|
37
|
+
this.emitContactChange()
|
|
38
|
+
}
|
|
39
|
+
}
|