geonetwork-ui 2.2.0-dev.723017a4 → 2.2.0-dev.751c5530
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/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +16 -4
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.mjs +3 -1
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/converter.mjs +7 -2
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +4 -1
- package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +1 -1
- package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +2 -2
- package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
- package/esm2022/libs/feature/editor/src/index.mjs +6 -1
- package/esm2022/libs/feature/editor/src/lib/+state/editor.actions.mjs +8 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.effects.mjs +26 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.facade.mjs +30 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.models.mjs +2 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.reducer.mjs +42 -0
- package/esm2022/libs/feature/editor/src/lib/+state/editor.selectors.mjs +13 -0
- package/esm2022/libs/feature/editor/src/lib/expressions.mjs +13 -0
- package/esm2022/libs/feature/editor/src/lib/feature-editor.module.mjs +16 -4
- package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +34 -0
- package/esm2022/libs/feature/editor/src/lib/models/fields.model.mjs +2 -0
- package/esm2022/libs/feature/editor/src/lib/record-form/record-form.component.mjs +15 -11
- package/esm2022/libs/feature/editor/src/lib/services/editor.service.mjs +22 -44
- package/esm2022/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.mjs +13 -13
- package/esm2022/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.mjs +3 -3
- package/esm2022/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/max-lines/max-lines.component.mjs +5 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +17 -5
- package/esm2022/libs/ui/elements/src/lib/thumbnail/thumbnail.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/button/button.component.mjs +9 -9
- package/esm2022/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.mjs +3 -3
- package/esm2022/libs/ui/inputs/src/lib/form-field/form-field.component.mjs +4 -2
- package/esm2022/libs/ui/inputs/src/lib/form-field/form-field.model.mjs +1 -1
- package/esm2022/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.mjs +3 -3
- package/esm2022/libs/ui/layout/src/lib/carousel/carousel.component.mjs +3 -3
- package/esm2022/libs/util/i18n/src/lib/i18n.constants.mjs +18 -1
- package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
- package/esm2022/libs/util/shared/src/lib/utils/temporal-extent-union.mjs +32 -0
- package/esm2022/translations/de.json +35 -26
- package/esm2022/translations/en.json +27 -18
- package/esm2022/translations/es.json +24 -15
- package/esm2022/translations/fr.json +45 -36
- package/esm2022/translations/it.json +39 -30
- package/esm2022/translations/nl.json +25 -16
- package/esm2022/translations/pt.json +24 -15
- package/fesm2022/geonetwork-ui.mjs +581 -300
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +1 -0
- package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/converter.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +1 -0
- package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
- package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +3 -0
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
- package/libs/feature/editor/src/index.d.ts +5 -0
- package/libs/feature/editor/src/index.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/+state/editor.actions.d.ts +23 -0
- package/libs/feature/editor/src/lib/+state/editor.actions.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.effects.d.ts +15 -0
- package/libs/feature/editor/src/lib/+state/editor.effects.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.facade.d.ts +19 -0
- package/libs/feature/editor/src/lib/+state/editor.facade.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.models.d.ts +2 -0
- package/libs/feature/editor/src/lib/+state/editor.models.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts +18 -0
- package/libs/feature/editor/src/lib/+state/editor.reducer.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts +15 -0
- package/libs/feature/editor/src/lib/+state/editor.selectors.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/expressions.d.ts +4 -0
- package/libs/feature/editor/src/lib/expressions.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/feature-editor.module.d.ts +3 -1
- package/libs/feature/editor/src/lib/feature-editor.module.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/fields.config.d.ts +3 -0
- package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/models/fields.model.d.ts +15 -0
- package/libs/feature/editor/src/lib/models/fields.model.d.ts.map +1 -0
- package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts +10 -5
- package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/services/editor.service.d.ts +3 -13
- package/libs/feature/editor/src/lib/services/editor.service.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/max-lines/max-lines.component.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts +6 -0
- package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/button/button.component.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/form-field/form-field.component.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/form-field/form-field.model.d.ts +0 -1
- package/libs/ui/inputs/src/lib/form-field/form-field.model.d.ts.map +1 -1
- package/libs/util/i18n/src/lib/i18n.constants.d.ts +17 -0
- package/libs/util/i18n/src/lib/i18n.constants.d.ts.map +1 -1
- package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
- package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
- package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts +5 -0
- package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts.map +1 -0
- package/package.json +1 -1
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +4 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +19 -3
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/converter.ts +6 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +5 -1
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +8 -2
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +1 -1
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +4 -0
- package/src/libs/common/fixtures/src/lib/elasticsearch/full-response.ts +1 -1
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +33 -11
- package/src/libs/feature/editor/src/index.ts +5 -0
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +24 -0
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +49 -0
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +30 -0
- package/src/libs/feature/editor/src/lib/+state/editor.models.ts +1 -0
- package/src/libs/feature/editor/src/lib/+state/editor.reducer.ts +68 -0
- package/src/libs/feature/editor/src/lib/+state/editor.selectors.ts +39 -0
- package/src/libs/feature/editor/src/lib/expressions.ts +16 -0
- package/src/libs/feature/editor/src/lib/feature-editor.module.ts +11 -0
- package/src/libs/feature/editor/src/lib/fields.config.ts +35 -0
- package/src/libs/feature/editor/src/lib/models/fields.model.ts +29 -0
- package/src/libs/feature/editor/src/lib/record-form/record-form.component.html +9 -7
- package/src/libs/feature/editor/src/lib/record-form/record-form.component.ts +11 -5
- package/src/libs/feature/editor/src/lib/services/editor.service.ts +34 -73
- package/src/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.ts +12 -12
- package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.html +3 -4
- package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.html +1 -1
- package/src/libs/ui/elements/src/lib/max-lines/max-lines.component.html +5 -1
- package/src/libs/ui/elements/src/lib/max-lines/max-lines.component.ts +1 -0
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +1 -1
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +108 -20
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +14 -0
- package/src/libs/ui/elements/src/lib/thumbnail/thumbnail.component.html +2 -2
- package/src/libs/ui/inputs/src/lib/button/button.component.css +0 -5
- package/src/libs/ui/inputs/src/lib/button/button.component.html +0 -1
- package/src/libs/ui/inputs/src/lib/button/button.component.ts +6 -6
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html +3 -1
- package/src/libs/ui/inputs/src/lib/form-field/form-field.component.ts +3 -1
- package/src/libs/ui/inputs/src/lib/form-field/form-field.model.ts +0 -1
- package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.css +3 -0
- package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.html +1 -1
- package/src/libs/ui/layout/src/lib/carousel/carousel.component.html +1 -0
- package/src/libs/util/i18n/src/lib/i18n.constants.ts +18 -0
- package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
- package/src/libs/util/shared/src/lib/utils/temporal-extent-union.ts +32 -0
- package/tailwind.base.css +44 -15
- package/translations/de.json +35 -26
- package/translations/en.json +27 -18
- package/translations/es.json +24 -15
- package/translations/fr.json +45 -36
- package/translations/it.json +39 -30
- package/translations/nl.json +25 -16
- package/translations/pt.json +24 -15
- package/translations/sk.json +117 -108
|
@@ -27,6 +27,7 @@ export const GEOCAT_CH_DATASET_RECORD: DatasetRecord = {
|
|
|
27
27
|
],
|
|
28
28
|
contactsForResource: [],
|
|
29
29
|
recordCreated: new Date('2022-02-22T19:40:06'),
|
|
30
|
+
recordPublished: new Date('2022-02-22T19:40:06'),
|
|
30
31
|
recordUpdated: new Date('2022-02-22T19:40:06'),
|
|
31
32
|
datasetCreated: new Date('1999-01-01T00:00:00'),
|
|
32
33
|
datasetUpdated: new Date('2009-01-01'),
|
|
@@ -327,6 +328,7 @@ Die Quelle ist zu bezeichnen: „Quelle: Stadt Zürich“.`,
|
|
|
327
328
|
temporalExtents: [],
|
|
328
329
|
status: 'completed',
|
|
329
330
|
updateFrequency: 'asNeeded',
|
|
331
|
+
languages: [],
|
|
330
332
|
}
|
|
331
333
|
|
|
332
334
|
export const GEOCAT_CH_SERVICE_RECORD: ServiceRecord = {
|
|
@@ -359,6 +361,7 @@ export const GEOCAT_CH_SERVICE_RECORD: ServiceRecord = {
|
|
|
359
361
|
},
|
|
360
362
|
],
|
|
361
363
|
recordCreated: new Date('2022-03-07T01:15:51+01:00'),
|
|
364
|
+
recordPublished: new Date('2022-03-07T01:15:51+01:00'),
|
|
362
365
|
recordUpdated: new Date('2022-03-07T01:15:51+01:00'),
|
|
363
366
|
title: 'Verkehrsregelungsanlagen (WMS)',
|
|
364
367
|
abstract: `Diese Karte beinhaltet die Verkehrsregelungsanlagen des Kantons St.Gallen.`,
|
|
@@ -420,4 +423,5 @@ export const GEOCAT_CH_SERVICE_RECORD: ServiceRecord = {
|
|
|
420
423
|
legalConstraints: [],
|
|
421
424
|
securityConstraints: [],
|
|
422
425
|
otherConstraints: [],
|
|
426
|
+
languages: [],
|
|
423
427
|
}
|
|
@@ -28,8 +28,8 @@ import {
|
|
|
28
28
|
OnlineLinkResource,
|
|
29
29
|
} from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
30
30
|
import { matchProtocol } from '../common/distribution.mapper'
|
|
31
|
-
import { LangService } from '../../../../../../libs/util/i18n/src'
|
|
32
31
|
import { Thesaurus } from './types'
|
|
32
|
+
import { LANG_3_TO_2_MAPPER, LangService } from '../../../../../../libs/util/i18n/src'
|
|
33
33
|
|
|
34
34
|
type ESResponseSource = SourceWithUnknownProps
|
|
35
35
|
|
|
@@ -132,6 +132,22 @@ export class Gn4FieldMapper {
|
|
|
132
132
|
...output,
|
|
133
133
|
recordUpdated: toDate(selectField<string>(source, 'changeDate')),
|
|
134
134
|
}),
|
|
135
|
+
publicationDateForResource: (output, source) => ({
|
|
136
|
+
...output,
|
|
137
|
+
recordPublished: toDate(
|
|
138
|
+
selectField<string>(source, 'publicationDateForResource')
|
|
139
|
+
),
|
|
140
|
+
}),
|
|
141
|
+
resourceLanguage: (output, source) => {
|
|
142
|
+
const langList = getAsArray(
|
|
143
|
+
selectField<string>(source, 'resourceLanguage')
|
|
144
|
+
)
|
|
145
|
+
const languages = langList.map((lang) => LANG_3_TO_2_MAPPER[lang])
|
|
146
|
+
return {
|
|
147
|
+
...output,
|
|
148
|
+
languages,
|
|
149
|
+
}
|
|
150
|
+
},
|
|
135
151
|
link: (output, source) => {
|
|
136
152
|
const rawLinks = getAsArray(
|
|
137
153
|
selectField<SourceWithUnknownProps[]>(source, 'link')
|
|
@@ -292,9 +308,9 @@ export class Gn4FieldMapper {
|
|
|
292
308
|
],
|
|
293
309
|
}
|
|
294
310
|
},
|
|
295
|
-
|
|
311
|
+
resourceTemporalExtentDateRange: (output, source) => {
|
|
296
312
|
const ranges = getAsArray(
|
|
297
|
-
selectField(source, '
|
|
313
|
+
selectField(source, 'resourceTemporalExtentDateRange')
|
|
298
314
|
)
|
|
299
315
|
return {
|
|
300
316
|
...output,
|
|
@@ -24,6 +24,7 @@ export class Gn4MetadataMapper extends MetadataBaseMapper<Gn4Record> {
|
|
|
24
24
|
status: null,
|
|
25
25
|
lineage: null,
|
|
26
26
|
recordUpdated: null,
|
|
27
|
+
recordPublished: null,
|
|
27
28
|
ownerOrganization: null,
|
|
28
29
|
licenses: [],
|
|
29
30
|
legalConstraints: [],
|
|
@@ -36,6 +37,7 @@ export class Gn4MetadataMapper extends MetadataBaseMapper<Gn4Record> {
|
|
|
36
37
|
spatialExtents: [],
|
|
37
38
|
temporalExtents: [],
|
|
38
39
|
overviews: [],
|
|
40
|
+
languages: [],
|
|
39
41
|
}
|
|
40
42
|
const record: CatalogRecord = Object.keys(_source).reduce(
|
|
41
43
|
(prev, fieldName) =>
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
readOverviews,
|
|
52
52
|
readOwnerOrganization,
|
|
53
53
|
readRecordUpdated,
|
|
54
|
+
readRecordPublished,
|
|
54
55
|
readSecurityConstraints,
|
|
55
56
|
readSpatialExtents,
|
|
56
57
|
readSpatialRepresentation,
|
|
@@ -74,6 +75,7 @@ export function toModel(xml: string): CatalogRecord {
|
|
|
74
75
|
const contacts = readContacts(rootEl)
|
|
75
76
|
const recordUpdated = readRecordUpdated(rootEl)
|
|
76
77
|
const recordCreated = recordUpdated
|
|
78
|
+
const recordPublished = readRecordPublished(rootEl)
|
|
77
79
|
const keywords = readKeywords(rootEl)
|
|
78
80
|
const topics = readIsoTopics(rootEl)
|
|
79
81
|
const legalConstraints = readLegalConstraints(rootEl)
|
|
@@ -96,8 +98,10 @@ export function toModel(xml: string): CatalogRecord {
|
|
|
96
98
|
return {
|
|
97
99
|
uniqueIdentifier,
|
|
98
100
|
kind,
|
|
101
|
+
languages: [],
|
|
99
102
|
recordCreated,
|
|
100
103
|
recordUpdated,
|
|
104
|
+
recordPublished,
|
|
101
105
|
status,
|
|
102
106
|
title,
|
|
103
107
|
abstract,
|
|
@@ -125,8 +129,10 @@ export function toModel(xml: string): CatalogRecord {
|
|
|
125
129
|
return {
|
|
126
130
|
uniqueIdentifier,
|
|
127
131
|
kind,
|
|
132
|
+
languages: [],
|
|
128
133
|
recordCreated,
|
|
129
134
|
recordUpdated,
|
|
135
|
+
recordPublished,
|
|
130
136
|
title,
|
|
131
137
|
abstract,
|
|
132
138
|
ownerOrganization,
|
|
@@ -450,7 +450,7 @@ function findIdentification() {
|
|
|
450
450
|
}
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
-
function extractCitationDate(type: 'creation' | 'revision') {
|
|
453
|
+
function extractCitationDate(type: 'creation' | 'revision' | 'publication') {
|
|
454
454
|
return pipe(
|
|
455
455
|
findIdentification(),
|
|
456
456
|
findNestedElements('gmd:citation', 'gmd:CI_Citation', 'gmd:date'),
|
|
@@ -517,6 +517,10 @@ export function readRecordUpdated(rootEl: XmlElement): Date {
|
|
|
517
517
|
return pipe(findChildElement('gmd:dateStamp'), extractDateTime())(rootEl)
|
|
518
518
|
}
|
|
519
519
|
|
|
520
|
+
export function readRecordPublished(rootEl: XmlElement): Date {
|
|
521
|
+
return pipe(findChildElement('gmd:dateStamp'), extractDateTime())(rootEl)
|
|
522
|
+
}
|
|
523
|
+
|
|
520
524
|
export function readTitle(rootEl: XmlElement): string {
|
|
521
525
|
return pipe(
|
|
522
526
|
findIdentification(),
|
|
@@ -291,7 +291,10 @@ function appendResponsibleParty(contact: Individual) {
|
|
|
291
291
|
)
|
|
292
292
|
}
|
|
293
293
|
|
|
294
|
-
function updateCitationDate(
|
|
294
|
+
function updateCitationDate(
|
|
295
|
+
date: Date,
|
|
296
|
+
type: 'revision' | 'creation' | 'publication'
|
|
297
|
+
) {
|
|
295
298
|
return pipe(
|
|
296
299
|
findNestedElements('gmd:date', 'gmd:CI_Date'),
|
|
297
300
|
filterArray(
|
|
@@ -308,7 +311,10 @@ function updateCitationDate(date: Date, type: 'revision' | 'creation') {
|
|
|
308
311
|
)
|
|
309
312
|
}
|
|
310
313
|
|
|
311
|
-
function appendCitationDate(
|
|
314
|
+
function appendCitationDate(
|
|
315
|
+
date,
|
|
316
|
+
type: 'revision' | 'creation' | 'publication'
|
|
317
|
+
) {
|
|
312
318
|
return appendChildren(
|
|
313
319
|
pipe(
|
|
314
320
|
createElement('gmd:date'),
|
|
@@ -73,6 +73,8 @@ export interface Keyword {
|
|
|
73
73
|
type: KeywordType
|
|
74
74
|
thesaurus?: KeywordThesaurus
|
|
75
75
|
}
|
|
76
|
+
// languages should be expressed using two-letters ISO 639-1 codes
|
|
77
|
+
export type LanguageCode = string
|
|
76
78
|
|
|
77
79
|
export interface BaseRecord {
|
|
78
80
|
uniqueIdentifier: Uuid
|
|
@@ -82,6 +84,8 @@ export interface BaseRecord {
|
|
|
82
84
|
abstract: string
|
|
83
85
|
recordCreated?: Date
|
|
84
86
|
recordUpdated: Date
|
|
87
|
+
recordPublished?: Date
|
|
88
|
+
languages: Array<LanguageCode>
|
|
85
89
|
kind: RecordKind
|
|
86
90
|
topics: Array<string> // TODO: handle codelists
|
|
87
91
|
keywords: Array<Keyword>
|
|
@@ -131,7 +131,7 @@ export const ES_FIXTURE_FULL_RESPONSE = deepFreeze({
|
|
|
131
131
|
creationDateForResource: ['2012-01-01T00:00:00.000Z'],
|
|
132
132
|
creationYearForResource: '2012',
|
|
133
133
|
creationMonthForResource: '2012-01',
|
|
134
|
-
publicationDateForResource:
|
|
134
|
+
publicationDateForResource: '2021-04-01T00:00:00.000Z',
|
|
135
135
|
publicationYearForResource: '2021',
|
|
136
136
|
publicationMonthForResource: '2021-04',
|
|
137
137
|
resourceDate: [
|
|
@@ -71,19 +71,19 @@ Cette section contient des *caractères internationaux* (ainsi que des "caractè
|
|
|
71
71
|
],
|
|
72
72
|
keywords: [
|
|
73
73
|
{
|
|
74
|
-
|
|
74
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
75
75
|
type: 'other',
|
|
76
|
-
|
|
76
|
+
label: 'international',
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
|
-
|
|
79
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
80
80
|
type: 'other',
|
|
81
|
-
|
|
81
|
+
label: 'test',
|
|
82
82
|
},
|
|
83
83
|
{
|
|
84
|
-
|
|
84
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
85
85
|
type: 'other',
|
|
86
|
-
|
|
86
|
+
label: '_another_keyword_',
|
|
87
87
|
},
|
|
88
88
|
],
|
|
89
89
|
topics: ['testData', 'exampleData'],
|
|
@@ -149,6 +149,7 @@ As such, **it is not very interesting at all.**`,
|
|
|
149
149
|
updatedTimes: 3,
|
|
150
150
|
per: 'month',
|
|
151
151
|
},
|
|
152
|
+
languages: ['en'],
|
|
152
153
|
},
|
|
153
154
|
{
|
|
154
155
|
uniqueIdentifier: '7d002c4c-92ef-4b9f-a568-d732f740b99e',
|
|
@@ -186,11 +187,31 @@ Malgré l'attention portée à la création de ces données, il est rappelé que
|
|
|
186
187
|
},
|
|
187
188
|
],
|
|
188
189
|
keywords: [
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
190
|
+
{
|
|
191
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
192
|
+
type: 'other',
|
|
193
|
+
label: 'planification',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
197
|
+
type: 'other',
|
|
198
|
+
label: 'PLU',
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
202
|
+
type: 'other',
|
|
203
|
+
label: "Plan local d'urbanisme",
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
207
|
+
type: 'other',
|
|
208
|
+
label: 'données ouvertes',
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
thesaurus: { id: 'geonetwork.thesaurus.local' },
|
|
212
|
+
type: 'other',
|
|
213
|
+
label: 'Avrigny*60036',
|
|
214
|
+
},
|
|
194
215
|
],
|
|
195
216
|
topics: ['Usage des sols', "document d'urbanisme"],
|
|
196
217
|
spatialRepresentation: 'vector',
|
|
@@ -220,5 +241,6 @@ Ce lot de données produit en 2019, a été numérisé à partir du PCI Vecteur
|
|
|
220
241
|
temporalExtents: [],
|
|
221
242
|
status: 'completed',
|
|
222
243
|
updateFrequency: 'unknown',
|
|
244
|
+
languages: ['fr', 'de'],
|
|
223
245
|
},
|
|
224
246
|
])
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export * from './lib/+state/editor.facade'
|
|
2
|
+
export * from './lib/+state/editor.models'
|
|
3
|
+
export * from './lib/+state/editor.selectors'
|
|
4
|
+
export * from './lib/+state/editor.reducer'
|
|
5
|
+
export * from './lib/+state/editor.actions'
|
|
1
6
|
export * from './lib/feature-editor.module'
|
|
2
7
|
export * from './lib/services/editor.service'
|
|
3
8
|
export * from './lib/record-form/record-form.component'
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createAction, props } from '@ngrx/store'
|
|
2
|
+
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
3
|
+
import { SaveRecordError } from './editor.models'
|
|
4
|
+
|
|
5
|
+
export const openRecord = createAction(
|
|
6
|
+
'[Editor] Open record',
|
|
7
|
+
props<{ record: CatalogRecord }>()
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
export const updateRecordField = createAction(
|
|
11
|
+
'[Editor] Update record field',
|
|
12
|
+
props<{ field: string; value: unknown }>()
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
export const markRecordAsChanged = createAction(
|
|
16
|
+
'[Editor] Mark record as changed'
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
export const saveRecord = createAction('[Editor] Save record')
|
|
20
|
+
export const saveRecordSuccess = createAction('[Editor] Save record success')
|
|
21
|
+
export const saveRecordFailure = createAction(
|
|
22
|
+
'[Editor] Save record failure',
|
|
23
|
+
props<{ error: SaveRecordError }>()
|
|
24
|
+
)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
|
+
import { Actions, createEffect, ofType } from '@ngrx/effects'
|
|
3
|
+
import { of, withLatestFrom } from 'rxjs'
|
|
4
|
+
import { catchError, map, switchMap } from 'rxjs/operators'
|
|
5
|
+
import * as EditorActions from './editor.actions'
|
|
6
|
+
import { EditorService } from '../services/editor.service'
|
|
7
|
+
import { Store } from '@ngrx/store'
|
|
8
|
+
import { selectRecord, selectRecordFieldsConfig } from './editor.selectors'
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class EditorEffects {
|
|
12
|
+
private actions$ = inject(Actions)
|
|
13
|
+
private editorService = inject(EditorService)
|
|
14
|
+
private store = inject(Store)
|
|
15
|
+
|
|
16
|
+
saveRecord$ = createEffect(() =>
|
|
17
|
+
this.actions$.pipe(
|
|
18
|
+
ofType(EditorActions.saveRecord),
|
|
19
|
+
withLatestFrom(
|
|
20
|
+
this.store.select(selectRecord),
|
|
21
|
+
this.store.select(selectRecordFieldsConfig)
|
|
22
|
+
),
|
|
23
|
+
switchMap(([, record, fieldsConfig]) =>
|
|
24
|
+
this.editorService.saveRecord(record, fieldsConfig).pipe(
|
|
25
|
+
switchMap((newRecord) =>
|
|
26
|
+
of(
|
|
27
|
+
EditorActions.saveRecordSuccess(),
|
|
28
|
+
EditorActions.openRecord({ record: newRecord })
|
|
29
|
+
)
|
|
30
|
+
),
|
|
31
|
+
catchError((error) =>
|
|
32
|
+
of(
|
|
33
|
+
EditorActions.saveRecordFailure({
|
|
34
|
+
error: error.message,
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
)
|
|
40
|
+
)
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
markAsChanged$ = createEffect(() =>
|
|
44
|
+
this.actions$.pipe(
|
|
45
|
+
ofType(EditorActions.updateRecordField),
|
|
46
|
+
map(() => EditorActions.markRecordAsChanged())
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { inject, Injectable } from '@angular/core'
|
|
2
|
+
import { select, Store } from '@ngrx/store'
|
|
3
|
+
import * as EditorActions from './editor.actions'
|
|
4
|
+
import * as EditorSelectors from './editor.selectors'
|
|
5
|
+
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
6
|
+
|
|
7
|
+
@Injectable()
|
|
8
|
+
export class EditorFacade {
|
|
9
|
+
private readonly store = inject(Store)
|
|
10
|
+
|
|
11
|
+
record$ = this.store.pipe(select(EditorSelectors.selectRecord))
|
|
12
|
+
saving$ = this.store.pipe(select(EditorSelectors.selectRecordSaving))
|
|
13
|
+
saveError$ = this.store.pipe(select(EditorSelectors.selectRecordSaveError))
|
|
14
|
+
changedSinceSave$ = this.store.pipe(
|
|
15
|
+
select(EditorSelectors.selectRecordChangedSinceSave)
|
|
16
|
+
)
|
|
17
|
+
recordFields$ = this.store.pipe(select(EditorSelectors.selectRecordFields))
|
|
18
|
+
|
|
19
|
+
openRecord(record: CatalogRecord) {
|
|
20
|
+
this.store.dispatch(EditorActions.openRecord({ record }))
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
saveRecord() {
|
|
24
|
+
this.store.dispatch(EditorActions.saveRecord())
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
updateRecordField(field: string, value: unknown) {
|
|
28
|
+
this.store.dispatch(EditorActions.updateRecordField({ field, value }))
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type SaveRecordError = string
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Action, createReducer, on } from '@ngrx/store'
|
|
2
|
+
import * as EditorActions from './editor.actions'
|
|
3
|
+
import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
|
|
4
|
+
import { SaveRecordError } from './editor.models'
|
|
5
|
+
import { EditorFieldsConfig } from '../models/fields.model'
|
|
6
|
+
import { DEFAULT_FIELDS } from '../fields.config'
|
|
7
|
+
|
|
8
|
+
export const EDITOR_FEATURE_KEY = 'editor'
|
|
9
|
+
|
|
10
|
+
export interface EditorState {
|
|
11
|
+
record: CatalogRecord | null
|
|
12
|
+
saving: boolean
|
|
13
|
+
saveError: SaveRecordError | null
|
|
14
|
+
changedSinceSave: boolean
|
|
15
|
+
fieldsConfig: EditorFieldsConfig
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface EditorPartialState {
|
|
19
|
+
readonly [EDITOR_FEATURE_KEY]: EditorState
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export const initialEditorState: EditorState = {
|
|
23
|
+
record: null,
|
|
24
|
+
saving: false,
|
|
25
|
+
saveError: null,
|
|
26
|
+
changedSinceSave: false,
|
|
27
|
+
fieldsConfig: DEFAULT_FIELDS,
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const reducer = createReducer(
|
|
31
|
+
initialEditorState,
|
|
32
|
+
on(EditorActions.openRecord, (state, { record }) => ({
|
|
33
|
+
...state,
|
|
34
|
+
changedSinceSave: false,
|
|
35
|
+
record,
|
|
36
|
+
})),
|
|
37
|
+
on(EditorActions.saveRecord, (state) => ({
|
|
38
|
+
...state,
|
|
39
|
+
saving: true,
|
|
40
|
+
saveError: null,
|
|
41
|
+
})),
|
|
42
|
+
on(EditorActions.saveRecordSuccess, (state) => ({
|
|
43
|
+
...state,
|
|
44
|
+
saving: false,
|
|
45
|
+
saveError: null,
|
|
46
|
+
changedSinceSave: false,
|
|
47
|
+
})),
|
|
48
|
+
on(EditorActions.saveRecordFailure, (state, { error }) => ({
|
|
49
|
+
...state,
|
|
50
|
+
saving: false,
|
|
51
|
+
saveError: error,
|
|
52
|
+
})),
|
|
53
|
+
on(EditorActions.updateRecordField, (state, { field, value }) => ({
|
|
54
|
+
...state,
|
|
55
|
+
record: {
|
|
56
|
+
...state.record,
|
|
57
|
+
[field]: value,
|
|
58
|
+
},
|
|
59
|
+
})),
|
|
60
|
+
on(EditorActions.markRecordAsChanged, (state) => ({
|
|
61
|
+
...state,
|
|
62
|
+
changedSinceSave: true,
|
|
63
|
+
}))
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
export function editorReducer(state: EditorState | undefined, action: Action) {
|
|
67
|
+
return reducer(state, action)
|
|
68
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createFeatureSelector, createSelector } from '@ngrx/store'
|
|
2
|
+
import { EDITOR_FEATURE_KEY, EditorState } from './editor.reducer'
|
|
3
|
+
|
|
4
|
+
export const selectEditorState =
|
|
5
|
+
createFeatureSelector<EditorState>(EDITOR_FEATURE_KEY)
|
|
6
|
+
|
|
7
|
+
export const selectRecord = createSelector(
|
|
8
|
+
selectEditorState,
|
|
9
|
+
(state: EditorState) => state.record
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
export const selectRecordSaving = createSelector(
|
|
13
|
+
selectEditorState,
|
|
14
|
+
(state: EditorState) => state.saving
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
export const selectRecordSaveError = createSelector(
|
|
18
|
+
selectEditorState,
|
|
19
|
+
(state: EditorState) => state.saveError
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
export const selectRecordChangedSinceSave = createSelector(
|
|
23
|
+
selectEditorState,
|
|
24
|
+
(state: EditorState) => state.changedSinceSave
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
export const selectRecordFieldsConfig = createSelector(
|
|
28
|
+
selectEditorState,
|
|
29
|
+
(state: EditorState) => state.fieldsConfig
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
export const selectRecordFields = createSelector(
|
|
33
|
+
selectEditorState,
|
|
34
|
+
(state: EditorState) =>
|
|
35
|
+
state.fieldsConfig.map((fieldConfig) => ({
|
|
36
|
+
config: fieldConfig,
|
|
37
|
+
value: state.record?.[fieldConfig.model] || null,
|
|
38
|
+
}))
|
|
39
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { EditorFieldState, EditorFieldValue } from './models/fields.model'
|
|
2
|
+
|
|
3
|
+
export type ExpressionEvaluator = (field: EditorFieldState) => EditorFieldValue
|
|
4
|
+
|
|
5
|
+
export function evaluate(expression: string): ExpressionEvaluator {
|
|
6
|
+
if (expression.match(/^\${.*}$/)) {
|
|
7
|
+
return evaluate(expression.slice(2, -1))
|
|
8
|
+
}
|
|
9
|
+
const operator = expression.split('(')[0]
|
|
10
|
+
switch (operator) {
|
|
11
|
+
case 'dateNow':
|
|
12
|
+
return () => new Date()
|
|
13
|
+
default:
|
|
14
|
+
throw new Error(`Unknown operator: ${operator}`)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -10,6 +10,11 @@ import { TranslateModule } from '@ngx-translate/core'
|
|
|
10
10
|
import { WizardSummarizeComponent } from './components/wizard-summarize/wizard-summarize.component'
|
|
11
11
|
import { CommonModule } from '@angular/common'
|
|
12
12
|
import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'
|
|
13
|
+
import { StoreModule } from '@ngrx/store'
|
|
14
|
+
import { EffectsModule } from '@ngrx/effects'
|
|
15
|
+
import * as fromEditor from './+state/editor.reducer'
|
|
16
|
+
import { EditorEffects } from './+state/editor.effects'
|
|
17
|
+
import { EditorFacade } from './+state/editor.facade'
|
|
13
18
|
|
|
14
19
|
@NgModule({
|
|
15
20
|
declarations: [
|
|
@@ -27,8 +32,14 @@ import { HttpClientModule, HttpClientXsrfModule } from '@angular/common/http'
|
|
|
27
32
|
MatFormFieldModule,
|
|
28
33
|
HttpClientModule,
|
|
29
34
|
HttpClientXsrfModule,
|
|
35
|
+
StoreModule.forFeature(
|
|
36
|
+
fromEditor.EDITOR_FEATURE_KEY,
|
|
37
|
+
fromEditor.editorReducer
|
|
38
|
+
),
|
|
39
|
+
EffectsModule.forFeature([EditorEffects]),
|
|
30
40
|
],
|
|
31
41
|
exports: [WizardComponent, WizardSummarizeComponent],
|
|
42
|
+
providers: [EditorFacade],
|
|
32
43
|
})
|
|
33
44
|
export class FeatureEditorModule {}
|
|
34
45
|
export * from './services/wizard.service'
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { EditorFieldsConfig } from './models/fields.model'
|
|
2
|
+
|
|
3
|
+
export const DEFAULT_FIELDS: EditorFieldsConfig = [
|
|
4
|
+
{
|
|
5
|
+
model: 'title',
|
|
6
|
+
formFieldConfig: {
|
|
7
|
+
labelKey: 'Metadata title',
|
|
8
|
+
type: 'text',
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
model: 'abstract',
|
|
13
|
+
formFieldConfig: {
|
|
14
|
+
labelKey: 'Abstract',
|
|
15
|
+
type: 'rich',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
model: 'uniqueIdentifier',
|
|
20
|
+
formFieldConfig: {
|
|
21
|
+
labelKey: 'Unique identifier',
|
|
22
|
+
type: 'text',
|
|
23
|
+
locked: true,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
model: 'recordUpdated',
|
|
28
|
+
formFieldConfig: {
|
|
29
|
+
labelKey: 'Record Updated',
|
|
30
|
+
type: 'text',
|
|
31
|
+
locked: true,
|
|
32
|
+
},
|
|
33
|
+
onSaveProcess: '${dateNow()}',
|
|
34
|
+
},
|
|
35
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { FormFieldConfig } from '../../../../../../libs/ui/inputs/src'
|
|
2
|
+
|
|
3
|
+
// Expressions should be enclosed in `${}` to be recognized as such
|
|
4
|
+
// eg. ${dateNow()}
|
|
5
|
+
export type EditorFieldExpression = `$\{${string}}`
|
|
6
|
+
|
|
7
|
+
export interface EditorFieldConfig {
|
|
8
|
+
// configuration of the form field used as presentation; optional, nothing shown if not defined
|
|
9
|
+
formFieldConfig?: FormFieldConfig
|
|
10
|
+
|
|
11
|
+
// name of the target field in the record; will not change the record directly if not defined
|
|
12
|
+
model?: string
|
|
13
|
+
|
|
14
|
+
// a hidden field won't show but can still be used to modify the record
|
|
15
|
+
// FIXME: currently this is redundant with an absence of formFieldConfig but necessary for clarity
|
|
16
|
+
hidden?: boolean
|
|
17
|
+
|
|
18
|
+
// the result of this expression will replace the field value on save
|
|
19
|
+
onSaveProcess?: EditorFieldExpression
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type EditorFieldsConfig = EditorFieldConfig[]
|
|
23
|
+
|
|
24
|
+
export type EditorFieldValue = string | number | boolean | unknown
|
|
25
|
+
|
|
26
|
+
export interface EditorFieldState {
|
|
27
|
+
config: EditorFieldConfig
|
|
28
|
+
value: string | number | boolean | unknown
|
|
29
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
<div class="flex flex-col gap-6">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
<div class="flex flex-col gap-6 p-6">
|
|
2
|
+
<ng-container *ngFor="let field of fields$ | async; trackBy: fieldTracker">
|
|
3
|
+
<gn-ui-form-field
|
|
4
|
+
*ngIf="field.config.formFieldConfig && !field.config.hidden"
|
|
5
|
+
[config]="field.config.formFieldConfig"
|
|
6
|
+
[value]="field.value"
|
|
7
|
+
(valueChange)="handleFieldValueChange(field, $event)"
|
|
8
|
+
></gn-ui-form-field>
|
|
9
|
+
</ng-container>
|
|
8
10
|
</div>
|