geonetwork-ui 2.10.0-dev.fc6515c0b → 2.10.0
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 +1459 -6139
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/index.d.ts +214 -171
- package/index.d.ts.map +1 -1
- package/package.json +25 -35
- package/src/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.ts +20 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/eu.dcat-ap.records.ts +4 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +23 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+ongules.ts +8 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+roilaye.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 +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/georhena.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/metadata-for-i18n.records.ts +4 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +23 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/opendataswiss.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/sextant.records.ts +4 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/vlaanderen.dcat-ap.records.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.reuse.ts +9 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +48 -7
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.converter.ts +2 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +6 -5
- package/src/libs/api/metadata-converter/src/lib/gn4/metadata-url.service.ts +2 -2
- package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +1 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.ts +11 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +21 -0
- package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +52 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +24 -1
- package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +73 -0
- package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +79 -0
- package/src/libs/api/repository/src/lib/gn4/auth/auth.service.ts +8 -4
- package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +2 -2
- package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +66 -40
- package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts +1 -1
- package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts +1 -1
- package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +37 -2
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +23 -5
- package/src/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.ts +2 -1
- package/src/libs/common/domain/src/lib/model/user/group.model.ts +8 -0
- package/src/libs/common/domain/src/lib/model/user/index.ts +1 -0
- package/src/libs/common/domain/src/lib/platform.service.interface.ts +2 -0
- package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +2 -1
- package/src/libs/common/fixtures/src/lib/records.fixtures.ts +62 -0
- package/src/libs/feature/catalog/src/lib/sources/sources.service.ts +5 -2
- package/src/libs/feature/editor/src/index.ts +1 -0
- package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +4 -1
- package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +26 -19
- package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +5 -1
- package/src/libs/feature/editor/src/lib/components/constraint-card/constraint-card.component.ts +0 -2
- 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 +68 -0
- package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.ts +41 -0
- package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.html +5 -14
- package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.ts +3 -28
- package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html +5 -5
- package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts +2 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/field-focus.directive.ts +4 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-constraints-shortcuts/form-field-constraints-shortcuts.component.ts +7 -7
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html +9 -2
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.ts +12 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts +1 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts +12 -5
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.html +4 -4
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-rich/form-field-rich.component.ts +7 -0
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-topics/form-field-topics.component.ts +2 -2
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.html +6 -2
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.ts +3 -1
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.css +0 -34
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +28 -16
- package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +11 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.css +35 -0
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.html +18 -5
- package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +76 -19
- package/src/libs/feature/editor/src/lib/expressions.ts +380 -8
- package/src/libs/feature/editor/src/lib/fields.config.ts +354 -337
- package/src/libs/feature/editor/src/lib/models/editor-config.model.ts +10 -3
- package/src/libs/feature/editor/src/lib/services/editor.service.ts +9 -13
- package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +33 -0
- package/src/libs/feature/notify-reuse/src/index.ts +1 -0
- package/src/libs/feature/notify-reuse/src/lib/edit-delete-reuse-buttons/edit-delete-reuse-buttons.component.css +0 -0
- package/src/libs/feature/notify-reuse/src/lib/edit-delete-reuse-buttons/edit-delete-reuse-buttons.component.html +23 -0
- package/src/libs/feature/notify-reuse/src/lib/edit-delete-reuse-buttons/edit-delete-reuse-buttons.component.ts +114 -0
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.html +111 -1
- package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.ts +219 -8
- package/src/libs/feature/notify-reuse/src/lib/utils/url.ts +16 -0
- package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +9 -1
- package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +10 -5
- package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.ts +2 -2
- package/src/libs/ui/dataviz/src/index.ts +0 -1
- package/src/libs/ui/elements/src/index.ts +1 -0
- package/src/libs/ui/elements/src/lib/contact-details/contact-details.component.html +48 -56
- package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.html +7 -3
- package/src/libs/ui/elements/src/lib/external-link-card/external-link-card.component.html +2 -1
- package/src/libs/ui/elements/src/lib/external-link-card/external-link-card.component.ts +2 -2
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.css +13 -0
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.html +13 -3
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.ts +43 -6
- package/src/libs/ui/elements/src/lib/keyword-badge/keyword-badge.component.html +14 -0
- package/src/libs/ui/elements/src/lib/keyword-badge/keyword-badge.component.ts +85 -0
- package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.ts +2 -2
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.css +5 -0
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +5 -8
- package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +2 -2
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.html +4 -5
- package/src/libs/ui/elements/src/lib/record-api-form/record-api-form.component.ts +4 -0
- package/src/libs/ui/inputs/src/lib/badge/badge.component.html +33 -26
- package/src/libs/ui/inputs/src/lib/badge/badge.component.ts +9 -0
- package/src/libs/ui/inputs/src/lib/button/button.component.ts +4 -0
- package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +2 -2
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
- package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.ts +3 -3
- package/src/libs/ui/inputs/src/lib/text-input/text-input.component.css +0 -3
- package/src/libs/ui/inputs/src/lib/text-input/text-input.component.html +11 -7
- package/src/libs/ui/inputs/src/lib/text-input/text-input.component.ts +56 -30
- package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html +5 -5
- package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.ts +9 -1
- package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.html +1 -1
- package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.ts +3 -8
- package/src/libs/ui/layout/src/lib/sortable-list/sortable-list.component.html +7 -7
- package/src/libs/ui/layout/src/lib/sortable-list/sortable-list.component.ts +14 -1
- package/src/libs/ui/map/src/lib/components/spatial-extent/spatial-extent.component.ts +4 -54
- package/src/libs/ui/map/src/lib/map-utils.ts +48 -0
- package/src/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.ts +1 -1
- package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.html +12 -8
- package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.ts +3 -1
- package/src/libs/ui/search/src/lib/results-table/results-table.component.html +1 -0
- package/src/libs/ui/widgets/src/lib/popover/popover.component.ts +7 -1
- package/src/libs/ui/widgets/src/lib/spinning-loader/spinning-loader.component.html +1 -1
- package/src/libs/util/app-config/src/lib/app-config.ts +35 -10
- package/src/libs/util/app-config/src/lib/model.ts +3 -0
- package/src/libs/util/app-config/src/lib/parse-utils.ts +27 -0
- package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +1 -2
- package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +6 -3
- package/src/libs/util/i18n/src/index.ts +0 -1
- package/src/libs/util/i18n/src/lib/i18n.constants.ts +17 -11
- package/src/libs/util/i18n/src/lib/i18n.interceptor.ts +2 -2
- package/src/libs/util/i18n/src/lib/i18n.providers.ts +14 -17
- package/src/libs/util/i18n/src/lib/test.translate.loader.ts +48 -0
- package/src/libs/util/shared/src/lib/links/link-utils.ts +23 -1
- package/src/libs/util/shared/src/lib/services/date.service.ts +3 -3
- package/src/libs/util/shared/src/lib/utils/geojson.ts +58 -1
- package/style.css +0 -1
- package/tailwind.base.css +15 -0
- package/translations/de.json +110 -50
- package/translations/en.json +115 -55
- package/translations/es.json +84 -24
- package/translations/fr.json +112 -52
- package/translations/it.json +111 -51
- package/translations/nl.json +83 -23
- package/translations/pt.json +84 -24
- package/translations/sk.json +84 -24
- package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.css +0 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AssociatedRecord,
|
|
2
3
|
Constraint,
|
|
3
4
|
ConstraintTranslations,
|
|
4
5
|
DatasetOnlineResource,
|
|
@@ -8,6 +9,7 @@ import {
|
|
|
8
9
|
Keyword,
|
|
9
10
|
KeywordTranslations,
|
|
10
11
|
LanguageCode,
|
|
12
|
+
SourceRecord,
|
|
11
13
|
ModelTranslations,
|
|
12
14
|
OnlineLinkResource,
|
|
13
15
|
OnlineResource,
|
|
@@ -894,6 +896,77 @@ export function readLineage(
|
|
|
894
896
|
)(rootEl)
|
|
895
897
|
}
|
|
896
898
|
|
|
899
|
+
export function extractSourceRecords(liLineageEl: XmlElement): SourceRecord[] {
|
|
900
|
+
if (!liLineageEl) return []
|
|
901
|
+
return pipe(
|
|
902
|
+
findChildrenElement('gmd:source', false),
|
|
903
|
+
mapArray((el) => {
|
|
904
|
+
const uuid = readAttribute('uuidref')(el)
|
|
905
|
+
const title = readAttribute('xlink:title')(el)
|
|
906
|
+
const href = readAttribute('xlink:href')(el)
|
|
907
|
+
if (!uuid && !title && !href) return null
|
|
908
|
+
return {
|
|
909
|
+
...(uuid ? { uuid } : {}),
|
|
910
|
+
...(title ? { title } : {}),
|
|
911
|
+
...(href ? { href } : {}),
|
|
912
|
+
} as SourceRecord
|
|
913
|
+
}),
|
|
914
|
+
filterArray((s): s is SourceRecord => s !== null)
|
|
915
|
+
)(liLineageEl)
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
export function readSourceRecords(rootEl: XmlElement): SourceRecord[] {
|
|
919
|
+
return extractSourceRecords(
|
|
920
|
+
pipe(
|
|
921
|
+
findNestedElement(
|
|
922
|
+
'gmd:dataQualityInfo',
|
|
923
|
+
'gmd:DQ_DataQuality',
|
|
924
|
+
'gmd:lineage',
|
|
925
|
+
'gmd:LI_Lineage'
|
|
926
|
+
)
|
|
927
|
+
)(rootEl)
|
|
928
|
+
)
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
export function extractAssociatedRecords(
|
|
932
|
+
containerName: string,
|
|
933
|
+
aggregateName: string,
|
|
934
|
+
readUuid: ChainableFunction<XmlElement, string>
|
|
935
|
+
): ChainableFunction<XmlElement, AssociatedRecord[]> {
|
|
936
|
+
return pipe(
|
|
937
|
+
findChildrenElement(containerName, false),
|
|
938
|
+
mapArray((el) => {
|
|
939
|
+
const aggregateEl = findChildElement(aggregateName, false)(el)
|
|
940
|
+
const uuid = readUuid(aggregateEl)
|
|
941
|
+
const associationType = pipe(
|
|
942
|
+
findNestedElement('gmd:associationType', 'gmd:DS_AssociationTypeCode'),
|
|
943
|
+
readAttribute('codeListValue')
|
|
944
|
+
)(aggregateEl)
|
|
945
|
+
if (!uuid || !associationType) return null
|
|
946
|
+
return { uuid, associationType }
|
|
947
|
+
}),
|
|
948
|
+
filterArray((r): r is AssociatedRecord => r !== null)
|
|
949
|
+
)
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
export function readAssociatedRecords(rootEl: XmlElement): AssociatedRecord[] {
|
|
953
|
+
return pipe(
|
|
954
|
+
findIdentification(),
|
|
955
|
+
extractAssociatedRecords(
|
|
956
|
+
'gmd:aggregationInfo',
|
|
957
|
+
'gmd:MD_AggregateInformation',
|
|
958
|
+
pipe(
|
|
959
|
+
findNestedElement(
|
|
960
|
+
'gmd:aggregateDataSetIdentifier',
|
|
961
|
+
'gmd:MD_Identifier',
|
|
962
|
+
'gmd:code'
|
|
963
|
+
),
|
|
964
|
+
extractCharacterString()
|
|
965
|
+
)
|
|
966
|
+
)
|
|
967
|
+
)(rootEl)
|
|
968
|
+
}
|
|
969
|
+
|
|
897
970
|
export function readUpdateFrequency(rootEl: XmlElement): UpdateFrequency {
|
|
898
971
|
return pipe(
|
|
899
972
|
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,84 @@ 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(
|
|
1256
|
+
record: DatasetRecord | ReuseRecord,
|
|
1257
|
+
rootEl: XmlElement
|
|
1258
|
+
) {
|
|
1259
|
+
pipe(
|
|
1260
|
+
findNestedChildOrCreate(
|
|
1261
|
+
'gmd:dataQualityInfo',
|
|
1262
|
+
'gmd:DQ_DataQuality',
|
|
1263
|
+
'gmd:lineage',
|
|
1264
|
+
'gmd:LI_Lineage'
|
|
1265
|
+
),
|
|
1266
|
+
appendSourceRecords(record.sourceRecords)
|
|
1267
|
+
)(rootEl)
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
export function writeAssociatedRecords(
|
|
1271
|
+
record: DatasetRecord | ReuseRecord,
|
|
1272
|
+
rootEl: XmlElement
|
|
1273
|
+
) {
|
|
1274
|
+
pipe(
|
|
1275
|
+
findOrCreateIdentification(),
|
|
1276
|
+
removeChildrenByName('gmd:aggregationInfo'),
|
|
1277
|
+
appendChildren(
|
|
1278
|
+
...record.associatedRecords
|
|
1279
|
+
.filter((assoc) => assoc.uuid && assoc.associationType)
|
|
1280
|
+
.map((assoc) =>
|
|
1281
|
+
pipe(
|
|
1282
|
+
createNestedElement(
|
|
1283
|
+
'gmd:aggregationInfo',
|
|
1284
|
+
'gmd:MD_AggregateInformation'
|
|
1285
|
+
),
|
|
1286
|
+
appendChildren(
|
|
1287
|
+
pipe(
|
|
1288
|
+
createNestedElement(
|
|
1289
|
+
'gmd:aggregateDataSetIdentifier',
|
|
1290
|
+
'gmd:MD_Identifier',
|
|
1291
|
+
'gmd:code'
|
|
1292
|
+
),
|
|
1293
|
+
writeCharacterString(assoc.uuid)
|
|
1294
|
+
),
|
|
1295
|
+
pipe(
|
|
1296
|
+
createNestedElement(
|
|
1297
|
+
'gmd:associationType',
|
|
1298
|
+
'gmd:DS_AssociationTypeCode'
|
|
1299
|
+
),
|
|
1300
|
+
writeAttribute(
|
|
1301
|
+
'codeList',
|
|
1302
|
+
'http://standards.iso.org/iso/19139/resources/gmxCodelists.xml#DS_AssociationTypeCode'
|
|
1303
|
+
),
|
|
1304
|
+
writeAttribute('codeListValue', assoc.associationType)
|
|
1305
|
+
)
|
|
1306
|
+
)
|
|
1307
|
+
)
|
|
1308
|
+
)
|
|
1309
|
+
)
|
|
1310
|
+
)(rootEl)
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1234
1313
|
export function getServiceEndpointProtocol(endpoint: ServiceEndpoint): string {
|
|
1235
1314
|
switch (endpoint.accessServiceProtocol.toLowerCase()) {
|
|
1236
1315
|
case 'wfs':
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Injectable, InjectionToken
|
|
1
|
+
import { inject, Injectable, InjectionToken } from '@angular/core'
|
|
2
2
|
import { toLang2, toLang3 } from '../../../../../../../libs/util/i18n/src'
|
|
3
3
|
import { TranslateService } from '@ngx-translate/core'
|
|
4
4
|
import { Location } from '@angular/common'
|
|
@@ -44,8 +44,12 @@ export class AuthService {
|
|
|
44
44
|
window.location.href
|
|
45
45
|
).toString()
|
|
46
46
|
)
|
|
47
|
-
.replace(
|
|
48
|
-
|
|
47
|
+
.replace(
|
|
48
|
+
'${current_path}',
|
|
49
|
+
this.location.prepareExternalUrl(this.location.path())
|
|
50
|
+
)
|
|
51
|
+
.replace('${lang2}', toLang2(this.translateService.getCurrentLang()))
|
|
52
|
+
.replace('${lang3}', toLang3(this.translateService.getCurrentLang()))
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
get logoutUrl() {
|
|
@@ -55,7 +59,7 @@ export class AuthService {
|
|
|
55
59
|
get settingsUrl() {
|
|
56
60
|
return this.baseSettingsUrl.replace(
|
|
57
61
|
'${lang3}',
|
|
58
|
-
toLang3(this.translateService.
|
|
62
|
+
toLang3(this.translateService.getCurrentLang())
|
|
59
63
|
)
|
|
60
64
|
}
|
|
61
65
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Injectable, Injector
|
|
1
|
+
import { inject, Injectable, Injector } from '@angular/core'
|
|
2
2
|
import type { Geometry } from 'geojson'
|
|
3
3
|
import {
|
|
4
4
|
ES_QUERY_FIELDS_PRIORITY,
|
|
@@ -234,7 +234,7 @@ export class ElasticsearchService {
|
|
|
234
234
|
if (this.metadataLang) {
|
|
235
235
|
const lang3 = toLang3(
|
|
236
236
|
this.isCurrentSearchLang()
|
|
237
|
-
? this.translateService.
|
|
237
|
+
? this.translateService.getCurrentLang()
|
|
238
238
|
: this.metadataLang
|
|
239
239
|
)
|
|
240
240
|
return `lang${lang3}`
|
|
@@ -3,9 +3,10 @@ import {
|
|
|
3
3
|
HttpErrorResponse,
|
|
4
4
|
HttpHeaders,
|
|
5
5
|
} from '@angular/common/http'
|
|
6
|
-
import { Injectable, InjectionToken
|
|
6
|
+
import { inject, Injectable, InjectionToken } from '@angular/core'
|
|
7
7
|
import {
|
|
8
8
|
assertValidXml,
|
|
9
|
+
BaseConverter,
|
|
9
10
|
findConverterForDocument,
|
|
10
11
|
Gn4Converter,
|
|
11
12
|
Gn4SearchResults,
|
|
@@ -61,6 +62,12 @@ export const DISABLE_DRAFT = new InjectionToken<boolean>('gnDisableDraft', {
|
|
|
61
62
|
factory: () => false,
|
|
62
63
|
})
|
|
63
64
|
|
|
65
|
+
export const DEFAULT_RECORD_CONVERTER = new InjectionToken<
|
|
66
|
+
BaseConverter<string>
|
|
67
|
+
>('defaultRecordConverter', {
|
|
68
|
+
factory: () => new Iso19139Converter(),
|
|
69
|
+
})
|
|
70
|
+
|
|
64
71
|
@Injectable()
|
|
65
72
|
export class Gn4Repository implements RecordsRepositoryInterface {
|
|
66
73
|
private httpClient = inject(HttpClient)
|
|
@@ -72,6 +79,7 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
72
79
|
private gn4LanguagesApi = inject(LanguagesApiService)
|
|
73
80
|
private settingsService = inject(Gn4SettingsService)
|
|
74
81
|
private disableDraft = inject(DISABLE_DRAFT, { optional: true }) ?? false
|
|
82
|
+
private defaultConverter = inject(DEFAULT_RECORD_CONVERTER)
|
|
75
83
|
|
|
76
84
|
_draftsChanged = new Subject<void>()
|
|
77
85
|
draftsChanged$ = this._draftsChanged.asObservable()
|
|
@@ -319,8 +327,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
319
327
|
return this.settingsService.allowEditHarvested$.pipe(
|
|
320
328
|
map((allowEditHarvested) => {
|
|
321
329
|
return (
|
|
322
|
-
|
|
323
|
-
|
|
330
|
+
(this.platformService.supportsAuthentication() &&
|
|
331
|
+
record.extras?.['edit'] &&
|
|
332
|
+
(!record.extras?.['isHarvested'] || allowEditHarvested)) ??
|
|
333
|
+
false
|
|
324
334
|
)
|
|
325
335
|
})
|
|
326
336
|
)
|
|
@@ -328,10 +338,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
328
338
|
|
|
329
339
|
private canEdit(record: CatalogRecord, allowEditHarvested: boolean): boolean {
|
|
330
340
|
return (
|
|
331
|
-
this.platformService.supportsAuthentication() &&
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
341
|
+
(this.platformService.supportsAuthentication() &&
|
|
342
|
+
record.extras?.['edit'] &&
|
|
343
|
+
(!record.extras?.['isHarvested'] || allowEditHarvested)) ??
|
|
344
|
+
false
|
|
335
345
|
)
|
|
336
346
|
}
|
|
337
347
|
|
|
@@ -353,8 +363,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
353
363
|
}
|
|
354
364
|
|
|
355
365
|
openRecordForEdition(
|
|
356
|
-
uniqueIdentifier: string
|
|
366
|
+
uniqueIdentifier: string,
|
|
367
|
+
disableDraft?: boolean
|
|
357
368
|
): Observable<[CatalogRecord, string, boolean] | null> {
|
|
369
|
+
this.disableDraft = disableDraft ?? this.disableDraft
|
|
358
370
|
const draft$ = this.disableDraft
|
|
359
371
|
? of(null)
|
|
360
372
|
: of(this.getRecordFromLocalStorage(uniqueIdentifier))
|
|
@@ -377,38 +389,52 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
377
389
|
openRecordForDuplication(
|
|
378
390
|
uniqueIdentifier: string
|
|
379
391
|
): Observable<[CatalogRecord, string, true] | null> {
|
|
380
|
-
return this.
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
392
|
+
return this.platformService.getUserPermissionsByGroup().pipe(
|
|
393
|
+
map((permissions) => {
|
|
394
|
+
const groupId =
|
|
395
|
+
permissions.find((p) => p.canApprove)?.groupId?.toString() ??
|
|
396
|
+
permissions.find((p) => p.canEdit)?.groupId?.toString()
|
|
397
|
+
if (!groupId)
|
|
398
|
+
throw new Error(
|
|
399
|
+
'Current user has no writable group to duplicate into'
|
|
400
|
+
)
|
|
401
|
+
return groupId
|
|
402
|
+
}),
|
|
403
|
+
switchMap((groupId) =>
|
|
404
|
+
this.gn4RecordsApi
|
|
405
|
+
.create(
|
|
406
|
+
uniqueIdentifier,
|
|
407
|
+
groupId,
|
|
408
|
+
'METADATA',
|
|
409
|
+
'',
|
|
410
|
+
false,
|
|
411
|
+
undefined,
|
|
412
|
+
true,
|
|
413
|
+
false,
|
|
414
|
+
undefined,
|
|
415
|
+
'body',
|
|
416
|
+
false,
|
|
417
|
+
{
|
|
418
|
+
httpHeaderAccept: 'application/json',
|
|
419
|
+
httpContentTypeSelected: 'application/json;charset=UTF-8',
|
|
420
|
+
}
|
|
421
|
+
)
|
|
422
|
+
.pipe(
|
|
423
|
+
switchMap((uniqueIdentifier) => {
|
|
424
|
+
return this.getRecordAsXml(uniqueIdentifier)
|
|
425
|
+
}),
|
|
426
|
+
switchMap((xml) => {
|
|
427
|
+
return from(
|
|
428
|
+
findConverterForDocument(xml)
|
|
429
|
+
.readRecord(xml)
|
|
430
|
+
.then((record) => {
|
|
431
|
+
return [record, xml, true] as [CatalogRecord, string, true]
|
|
432
|
+
})
|
|
433
|
+
)
|
|
434
|
+
})
|
|
409
435
|
)
|
|
410
|
-
})
|
|
411
436
|
)
|
|
437
|
+
)
|
|
412
438
|
}
|
|
413
439
|
|
|
414
440
|
saveRecord(
|
|
@@ -605,10 +631,10 @@ export class Gn4Repository implements RecordsRepositoryInterface {
|
|
|
605
631
|
record: CatalogRecord,
|
|
606
632
|
referenceRecordSource?: string
|
|
607
633
|
): Observable<string> {
|
|
608
|
-
// if there's a reference record, use that standard; otherwise, use
|
|
634
|
+
// if there's a reference record, use that standard; otherwise, use standard based on configuration or default
|
|
609
635
|
const converter = referenceRecordSource
|
|
610
636
|
? findConverterForDocument(referenceRecordSource)
|
|
611
|
-
:
|
|
637
|
+
: this.defaultConverter
|
|
612
638
|
return from(converter.writeRecord(record, referenceRecordSource))
|
|
613
639
|
}
|
|
614
640
|
|
package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts
CHANGED
|
@@ -52,7 +52,7 @@ export class OrganizationsFromGroupsService
|
|
|
52
52
|
organisationsCount$ = this.organisations$.pipe(map((orgs) => orgs.length))
|
|
53
53
|
|
|
54
54
|
private get lang3() {
|
|
55
|
-
return toLang3(this.translateService.
|
|
55
|
+
return toLang3(this.translateService.getCurrentLang())
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
constructor(
|
package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts
CHANGED
|
@@ -128,7 +128,7 @@ export class OrganizationsFromMetadataService
|
|
|
128
128
|
) {}
|
|
129
129
|
|
|
130
130
|
private get langIndex() {
|
|
131
|
-
return `lang${toLang3(this.translateService.
|
|
131
|
+
return `lang${toLang3(this.translateService.getCurrentLang())}`
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
equalsNormalizedStrings(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HttpClient, HttpEventType } from '@angular/common/http'
|
|
2
|
-
import { Injectable, InjectionToken
|
|
2
|
+
import { inject, Injectable, InjectionToken } from '@angular/core'
|
|
3
3
|
import {
|
|
4
4
|
KeywordApiResponse,
|
|
5
5
|
ThesaurusApiResponse,
|
|
@@ -12,11 +12,13 @@ import {
|
|
|
12
12
|
} from '../../../../../../../libs/common/domain/src/lib/model/record'
|
|
13
13
|
import { KeywordType } from '../../../../../../../libs/common/domain/src/lib/model/thesaurus'
|
|
14
14
|
import { UserModel } from '../../../../../../../libs/common/domain/src/lib/model/user/user.model'
|
|
15
|
+
import { GroupModel } from '../../../../../../../libs/common/domain/src/lib/model/user/group.model'
|
|
15
16
|
import {
|
|
16
17
|
PlatformServiceInterface,
|
|
17
18
|
UploadEvent,
|
|
18
19
|
} from '../../../../../../../libs/common/domain/src/lib/platform.service.interface'
|
|
19
20
|
import {
|
|
21
|
+
GroupsApiService,
|
|
20
22
|
MeApiService,
|
|
21
23
|
RecordsApiService,
|
|
22
24
|
RegistriesApiService,
|
|
@@ -57,6 +59,7 @@ export const DISABLE_AUTH = new InjectionToken<boolean>('gnDisableAuth', {
|
|
|
57
59
|
export class Gn4PlatformService implements PlatformServiceInterface {
|
|
58
60
|
private meApi = inject(MeApiService)
|
|
59
61
|
private usersApi = inject(UsersApiService)
|
|
62
|
+
private groupsApi = inject(GroupsApiService)
|
|
60
63
|
private mapper = inject(Gn4PlatformMapper)
|
|
61
64
|
private toolsApiService = inject(ToolsApiService)
|
|
62
65
|
private registriesApiService = inject(RegistriesApiService)
|
|
@@ -97,7 +100,7 @@ export class Gn4PlatformService implements PlatformServiceInterface {
|
|
|
97
100
|
private keywordsByThesauri: Record<string, Observable<Keyword[]>> = {}
|
|
98
101
|
|
|
99
102
|
private get lang3() {
|
|
100
|
-
return toLang3(this.translateService.
|
|
103
|
+
return toLang3(this.translateService.getCurrentLang())
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
constructor() {
|
|
@@ -155,6 +158,38 @@ export class Gn4PlatformService implements PlatformServiceInterface {
|
|
|
155
158
|
return this.users$
|
|
156
159
|
}
|
|
157
160
|
|
|
161
|
+
getUserPermissionsByGroup(): Observable<GroupModel[]> {
|
|
162
|
+
if (this.disableAuth) return of([])
|
|
163
|
+
return combineLatest([this.meApi.getMe(), this.groupsApi.getGroups()]).pipe(
|
|
164
|
+
map(([meResponse, groups]) => {
|
|
165
|
+
if (!meResponse) return []
|
|
166
|
+
if (meResponse.admin) {
|
|
167
|
+
return groups.map((group) => ({
|
|
168
|
+
groupId: group.id,
|
|
169
|
+
groupName: group.name,
|
|
170
|
+
isMember: true,
|
|
171
|
+
canEdit: true,
|
|
172
|
+
canApprove: true,
|
|
173
|
+
canAdministrate: true,
|
|
174
|
+
}))
|
|
175
|
+
}
|
|
176
|
+
const reviewerIds = meResponse.groupsWithReviewer ?? []
|
|
177
|
+
const editorIds = meResponse.groupsWithEditor ?? []
|
|
178
|
+
const memberIds = meResponse.groupsWithRegisteredUser ?? []
|
|
179
|
+
const adminIds = meResponse.groupsWithUserAdmin ?? []
|
|
180
|
+
|
|
181
|
+
return groups.map((group) => ({
|
|
182
|
+
groupId: group.id,
|
|
183
|
+
groupName: group.name,
|
|
184
|
+
isMember: memberIds.includes(group.id),
|
|
185
|
+
canEdit: editorIds.includes(group.id),
|
|
186
|
+
canApprove: reviewerIds.includes(group.id),
|
|
187
|
+
canAdministrate: adminIds.includes(group.id),
|
|
188
|
+
}))
|
|
189
|
+
})
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
|
|
158
193
|
translateKey(key: string): Observable<string> {
|
|
159
194
|
// if the key is a URI, use the registries API to look for the translation
|
|
160
195
|
if (key.match(/^https?:\/\//)) {
|
|
@@ -104,15 +104,12 @@ export interface Keyword {
|
|
|
104
104
|
type: KeywordType
|
|
105
105
|
thesaurus?: ThesaurusModel
|
|
106
106
|
bbox?: [number, number, number, number]
|
|
107
|
+
// thesaurus hierarchy path incl. the keyword as last element; unset for root-level keywords
|
|
108
|
+
hierarchyPath?: string[]
|
|
107
109
|
|
|
108
110
|
translations?: KeywordTranslations
|
|
109
111
|
}
|
|
110
112
|
|
|
111
|
-
export interface INSPIRE_topic {
|
|
112
|
-
value: string
|
|
113
|
-
label: string
|
|
114
|
-
}
|
|
115
|
-
|
|
116
113
|
export interface ResourceIdentifier {
|
|
117
114
|
code: string
|
|
118
115
|
codeSpace?: string
|
|
@@ -254,10 +251,29 @@ export interface DatasetTemporalExtent {
|
|
|
254
251
|
end?: Date
|
|
255
252
|
}
|
|
256
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Represents a source dataset referenced from a lineage entry.
|
|
256
|
+
*/
|
|
257
|
+
export interface SourceRecord {
|
|
258
|
+
uuid?: string
|
|
259
|
+
title?: string
|
|
260
|
+
href?: string
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Represents another record associated with this one (e.g. a parent/sibling dataset).
|
|
265
|
+
*/
|
|
266
|
+
export interface AssociatedRecord {
|
|
267
|
+
uuid: string
|
|
268
|
+
associationType: string
|
|
269
|
+
}
|
|
270
|
+
|
|
257
271
|
export interface DatasetRecord extends BaseRecord {
|
|
258
272
|
kind: 'dataset'
|
|
259
273
|
status: RecordStatus
|
|
260
274
|
lineage: string // Explanation of the origin of this record (e.g: how, why)"
|
|
275
|
+
sourceRecords: Array<SourceRecord>
|
|
276
|
+
associatedRecords: Array<AssociatedRecord>
|
|
261
277
|
onlineResources: Array<DatasetOnlineResource>
|
|
262
278
|
spatialExtents: Array<DatasetSpatialExtent>
|
|
263
279
|
temporalExtents: Array<DatasetTemporalExtent>
|
|
@@ -285,6 +301,8 @@ export interface ServiceRecord extends BaseRecord {
|
|
|
285
301
|
export interface ReuseRecord extends BaseRecord {
|
|
286
302
|
kind: 'reuse'
|
|
287
303
|
lineage: string // Explanation of the origin of this record (e.g: how, why)"
|
|
304
|
+
sourceRecords: Array<SourceRecord>
|
|
305
|
+
associatedRecords: Array<AssociatedRecord>
|
|
288
306
|
onlineResources: Array<DatasetOnlineResource>
|
|
289
307
|
reuseType: ReuseType
|
|
290
308
|
spatialExtents: Array<DatasetSpatialExtent>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Observable } from 'rxjs'
|
|
2
2
|
import type { UserModel } from './model/user/user.model'
|
|
3
|
+
import type { GroupModel } from './model/user/group.model'
|
|
3
4
|
import type { Organization } from './model/record/organization.model'
|
|
4
5
|
import { CatalogRecord, Keyword, UserFeedback } from './model/record'
|
|
5
6
|
import { KeywordType } from './model/thesaurus'
|
|
@@ -28,6 +29,7 @@ export abstract class PlatformServiceInterface {
|
|
|
28
29
|
abstract getMe(): Observable<UserModel>
|
|
29
30
|
abstract isAnonymous(): Observable<boolean>
|
|
30
31
|
abstract getUsers(): Observable<UserModel[]>
|
|
32
|
+
abstract getUserPermissionsByGroup(): Observable<GroupModel[]>
|
|
31
33
|
abstract getUsersByOrganization(
|
|
32
34
|
organisation: Organization
|
|
33
35
|
): Observable<UserModel[]>
|
|
@@ -39,7 +39,8 @@ export abstract class RecordsRepositoryInterface {
|
|
|
39
39
|
* @returns Observable<[CatalogRecord, string, boolean] | null>
|
|
40
40
|
*/
|
|
41
41
|
abstract openRecordForEdition(
|
|
42
|
-
uniqueIdentifier: string
|
|
42
|
+
uniqueIdentifier: string,
|
|
43
|
+
disableDraft?: boolean
|
|
43
44
|
): Observable<[CatalogRecord, string, boolean] | null>
|
|
44
45
|
|
|
45
46
|
/**
|