geonetwork-ui 2.10.0-dev.dc713c01a → 2.10.0-dev.e2dc4fd62

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.
Files changed (133) hide show
  1. package/fesm2022/geonetwork-ui.mjs +872 -5806
  2. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  3. package/index.d.ts +212 -89
  4. package/index.d.ts.map +1 -1
  5. package/material-styles.css +483 -0
  6. package/package.json +25 -35
  7. package/src/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.ts +9 -0
  8. package/src/libs/api/metadata-converter/src/lib/fixtures/eu.dcat-ap.records.ts +2 -0
  9. package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +1 -0
  10. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+ongules.ts +7 -0
  11. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.reuse+roilaye.ts +1 -0
  12. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +1 -0
  13. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -0
  14. package/src/libs/api/metadata-converter/src/lib/fixtures/georhena.records.ts +1 -0
  15. package/src/libs/api/metadata-converter/src/lib/fixtures/metadata-for-i18n.records.ts +2 -0
  16. package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +1 -0
  17. package/src/libs/api/metadata-converter/src/lib/fixtures/opendataswiss.records.ts +1 -0
  18. package/src/libs/api/metadata-converter/src/lib/fixtures/sextant.records.ts +2 -0
  19. package/src/libs/api/metadata-converter/src/lib/fixtures/vlaanderen.dcat-ap.records.ts +1 -0
  20. package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.reuse.ts +8 -0
  21. package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +48 -7
  22. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.converter.ts +1 -0
  23. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +5 -4
  24. package/src/libs/api/metadata-converter/src/lib/gn4/metadata-url.service.ts +2 -2
  25. package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +1 -0
  26. package/src/libs/api/metadata-converter/src/lib/iso19115-3/iso19115-3.converter.ts +7 -0
  27. package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +8 -0
  28. package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +8 -0
  29. package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +11 -0
  30. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +33 -0
  31. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +33 -0
  32. package/src/libs/api/repository/src/lib/gn4/auth/auth.service.ts +8 -4
  33. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +2 -2
  34. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +68 -34
  35. package/src/libs/api/repository/src/lib/gn4/gn4.provider.ts +6 -1
  36. package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts +1 -1
  37. package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts +1 -1
  38. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +48 -2
  39. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +13 -5
  40. package/src/libs/common/domain/src/lib/model/thesaurus/thesaurus.model.ts +2 -1
  41. package/src/libs/common/domain/src/lib/model/user/group.model.ts +8 -0
  42. package/src/libs/common/domain/src/lib/model/user/index.ts +1 -0
  43. package/src/libs/common/domain/src/lib/platform.service.interface.ts +2 -0
  44. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +5 -0
  45. package/src/libs/feature/catalog/src/lib/sources/sources.service.ts +5 -2
  46. package/src/libs/feature/editor/src/lib/+state/editor.actions.ts +6 -0
  47. package/src/libs/feature/editor/src/lib/+state/editor.effects.ts +0 -1
  48. package/src/libs/feature/editor/src/lib/+state/editor.facade.ts +10 -1
  49. package/src/libs/feature/editor/src/lib/components/constraint-card/constraint-card.component.ts +0 -2
  50. package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.css +0 -0
  51. package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.html +67 -0
  52. package/src/libs/feature/editor/src/lib/components/contact-details/contact-details-form.component.ts +39 -0
  53. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.html +18 -3
  54. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.ts +33 -40
  55. package/src/libs/feature/editor/src/lib/components/record-form/form-field/field-focus.directive.ts +41 -0
  56. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-constraints-shortcuts/form-field-constraints-shortcuts.component.ts +32 -34
  57. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html +13 -13
  58. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.ts +18 -4
  59. 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
  60. 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
  61. 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
  62. 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
  63. 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
  64. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-topics/form-field-topics.component.ts +2 -2
  65. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.css +3 -0
  66. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +1 -0
  67. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +5 -0
  68. package/src/libs/feature/editor/src/lib/components/record-form/form-field/index.ts +1 -0
  69. package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.css +35 -0
  70. package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.html +5 -1
  71. package/src/libs/feature/editor/src/lib/components/record-form/record-form.component.ts +77 -5
  72. package/src/libs/feature/editor/src/lib/fields.config.ts +60 -47
  73. package/src/libs/feature/editor/src/lib/models/editor-config.model.ts +4 -0
  74. package/src/libs/feature/editor/src/lib/services/editor.service.ts +1 -1
  75. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +33 -0
  76. package/src/libs/feature/notify-reuse/src/index.ts +1 -0
  77. package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.css +0 -0
  78. package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.html +1 -0
  79. package/src/libs/feature/notify-reuse/src/lib/notify-reuse-form/notify-reuse-form.component.ts +21 -0
  80. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +9 -1
  81. package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.ts +2 -2
  82. package/src/libs/ui/dataviz/src/index.ts +0 -1
  83. package/src/libs/ui/elements/src/index.ts +2 -0
  84. package/src/libs/ui/elements/src/lib/contact-details/contact-details.component.html +88 -0
  85. package/src/libs/ui/elements/src/lib/contact-details/contact-details.component.ts +45 -0
  86. package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.html +41 -0
  87. package/src/libs/ui/elements/src/lib/contact-pill/contact-pill.component.ts +70 -0
  88. package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.css +13 -0
  89. package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.html +13 -3
  90. package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.ts +43 -6
  91. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +1 -1
  92. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +0 -1
  93. package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.ts +2 -2
  94. package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.ts +2 -5
  95. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.css +0 -4
  96. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +39 -68
  97. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +59 -11
  98. package/src/libs/ui/inputs/src/lib/button/button.component.ts +8 -0
  99. package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +2 -2
  100. package/src/libs/ui/inputs/src/lib/url-input/url-input.component.html +2 -2
  101. package/src/libs/ui/inputs/src/lib/url-input/url-input.component.ts +2 -1
  102. package/src/libs/ui/map/src/lib/components/map-container/map-container.component.ts +2 -1
  103. package/src/libs/ui/map/src/lib/components/spatial-extent/spatial-extent.component.ts +15 -64
  104. package/src/libs/ui/map/src/lib/map-utils.ts +48 -0
  105. package/src/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.ts +1 -1
  106. package/src/libs/ui/search/src/lib/record-preview-row/record-preview-row.component.html +0 -1
  107. package/src/libs/ui/widgets/src/lib/popover/popover.component.ts +7 -1
  108. package/src/libs/util/app-config/src/lib/app-config.ts +70 -9
  109. package/src/libs/util/app-config/src/lib/model.ts +7 -0
  110. package/src/libs/util/app-config/src/lib/parse-utils.ts +50 -1
  111. package/src/libs/util/data-fetcher/src/lib/readers/base-file.ts +1 -2
  112. package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +6 -3
  113. package/src/libs/util/i18n/src/index.ts +0 -1
  114. package/src/libs/util/i18n/src/lib/i18n.constants.ts +17 -11
  115. package/src/libs/util/i18n/src/lib/i18n.interceptor.ts +2 -2
  116. package/src/libs/util/i18n/src/lib/i18n.providers.ts +14 -17
  117. package/src/libs/util/i18n/src/lib/test.translate.loader.ts +48 -0
  118. package/src/libs/util/shared/src/lib/links/link-utils.ts +1 -1
  119. package/src/libs/util/shared/src/lib/record/quality-score.util.ts +33 -18
  120. package/src/libs/util/shared/src/lib/services/date.service.ts +3 -3
  121. package/src/libs/util/shared/src/lib/utils/geojson.ts +58 -1
  122. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  123. package/src/libs/util/shared/src/lib/utils/user-display.ts +32 -0
  124. package/style.css +0 -1
  125. package/tailwind.base.css +19 -2
  126. package/translations/de.json +33 -20
  127. package/translations/en.json +33 -20
  128. package/translations/es.json +33 -20
  129. package/translations/fr.json +33 -20
  130. package/translations/it.json +33 -20
  131. package/translations/nl.json +33 -20
  132. package/translations/pt.json +33 -20
  133. package/translations/sk.json +33 -20
@@ -206,6 +206,7 @@ export const GEORHENA_REUSE_SOLAIRE_RECORD: ReuseRecord = {
206
206
  },
207
207
  },
208
208
  lineage: null,
209
+ sourceRecords: [],
209
210
  temporalExtents: [
210
211
  {
211
212
  start: new Date('2016-01-01T00:00:00.000Z'),
@@ -2170,6 +2170,7 @@ export const METADATA_FOR_I18N_DATASET_RECORD: DatasetRecord = {
2170
2170
  },
2171
2171
  status: 'completed',
2172
2172
  lineage: 'This is a statement about the lineage.',
2173
+ sourceRecords: [],
2173
2174
  spatialRepresentation: 'vector',
2174
2175
  temporalExtents: [],
2175
2176
  updateFrequency: 'continual',
@@ -4234,6 +4235,7 @@ export const METADATA_FOR_I18N_NO_OTHERLANGUAGE: DatasetRecord = {
4234
4235
  translations: { lineage: {}, title: {}, abstract: {} },
4235
4236
  status: 'completed',
4236
4237
  lineage: 'This is a statement about the lineage.',
4238
+ sourceRecords: [],
4237
4239
  spatialRepresentation: 'vector',
4238
4240
  temporalExtents: [],
4239
4241
  updateFrequency: 'continual',
@@ -419,6 +419,7 @@ Cette donnée a été intégrée dans la base de données routière (BDR). Les D
419
419
 
420
420
  Ces données, intégrées dans la Banque de Données routières (BDR), ont fait l’objet d’une mise à jour massive en 2014-2015.
421
421
  Depuis, ce sont les Districts routiers qui assurent la tenue à jour de ces informations directement dans la base de données.`,
422
+ sourceRecords: [],
422
423
  otherConstraints: [],
423
424
  overviews: [
424
425
  {
@@ -370,6 +370,7 @@ export const OPENDATASWISS_DATASET_RECORD: DatasetRecord = {
370
370
  'http://dcat-ap.ch/vocabulary/themes/geography',
371
371
  ],
372
372
  lineage: '',
373
+ sourceRecords: [],
373
374
  ownerOrganization: {
374
375
  name: 'Bundesamt für Energie',
375
376
  },
@@ -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
  }
@@ -101,27 +101,68 @@ export const mapContact = (
101
101
  }
102
102
  }
103
103
 
104
- export const mapKeywords = (thesauri: Thesaurus[], language: string) => {
104
+ export interface KeywordTree {
105
+ default?: string[]
106
+ }
107
+
108
+ /**
109
+ * Resolves a keyword's ancestor path within its thesaurus tree, or null for a
110
+ * root-level keyword (no ancestors to show). Tree entries are `^`-joined label
111
+ * paths (default language); they aren't index-aligned with the keywords, so we
112
+ * match on the last segment (not by position/URI), shortest path on poly-hierarchy.
113
+ */
114
+ export const getKeywordHierarchyPath = (
115
+ keywordDefaultLabel: string,
116
+ tree?: KeywordTree | null
117
+ ): string[] | null => {
118
+ if (!keywordDefaultLabel || !tree?.default) return null
119
+ const shortest = tree.default
120
+ .map((entry) => entry.split('^'))
121
+ .filter((path) => path[path.length - 1] === keywordDefaultLabel)
122
+ .reduce(
123
+ (shortest, path) =>
124
+ !shortest || path.length < shortest.length ? path : shortest,
125
+ null
126
+ )
127
+ return shortest?.length > 1 ? shortest : null
128
+ }
129
+
130
+ export const mapKeywords = (
131
+ thesauri: Record<string, Thesaurus>,
132
+ language: string,
133
+ source?: SourceWithUnknownProps
134
+ ) => {
105
135
  const keywords = []
106
136
  for (const thesaurusId in thesauri) {
107
137
  const rawThesaurus = thesauri[thesaurusId]
138
+ // thesauri have an `id` (registered) or a `multilingualTitle` (cited);
139
+ // free-keyword groups only have a machine-key `title` like "otherKeywords-theme"
140
+ const { id, multilingualTitle, link = null } = rawThesaurus
108
141
  let thesaurus = null
109
- if (rawThesaurus.id) {
110
- const thesaurusSource: SourceWithUnknownProps = { ...rawThesaurus }
111
- const url = getAsUrl(selectField(thesaurusSource, 'link'))
112
- const name = selectField(thesaurusSource, 'title')
142
+ if (id || multilingualTitle) {
143
+ const url = getAsUrl(link)
144
+ const name = multilingualTitle
145
+ ? selectTranslatedValue<string>(multilingualTitle, language)
146
+ : rawThesaurus.title
113
147
  thesaurus = {
114
- id: rawThesaurus.id,
148
+ ...(id && { id }),
115
149
  ...(name && { name }),
116
150
  ...(url && { url }),
117
151
  }
118
152
  }
153
+ const tree =
154
+ source && selectField<KeywordTree>(source, `${thesaurusId}_tree`)
155
+ // free-keyword groups have no `theme` field; their type is in the group key
156
+ const typeCode =
157
+ rawThesaurus.theme || thesaurusId.match(/otherKeywords-(\w+)$/)?.[1]
119
158
  for (const keyword of rawThesaurus.keywords) {
159
+ const hierarchyPath = getKeywordHierarchyPath(keyword.default, tree)
120
160
  keywords.push({
121
161
  label: selectTranslatedValue<string>(keyword, language),
122
- type: getKeywordTypeFromKeywordTypeCode(rawThesaurus.theme),
162
+ type: getKeywordTypeFromKeywordTypeCode(typeCode),
123
163
  ...(keyword.link && { key: keyword.link }),
124
164
  ...(thesaurus && { thesaurus }),
165
+ ...(hierarchyPath && { hierarchyPath }),
125
166
  })
126
167
  }
127
168
  }
@@ -24,6 +24,7 @@ export class Gn4Converter extends BaseConverter<Gn4Record> {
24
24
  kind: 'dataset',
25
25
  status: null,
26
26
  lineage: null,
27
+ sourceRecords: [],
27
28
  recordUpdated: null,
28
29
  recordPublished: null,
29
30
  ownerOrganization: null,
@@ -14,7 +14,7 @@ import {
14
14
  toDate,
15
15
  } from './atomic-operations'
16
16
  import { MetadataUrlService } from './metadata-url.service'
17
- import { Injectable, inject } from '@angular/core'
17
+ import { inject, Injectable } from '@angular/core'
18
18
  import { getStatusFromStatusCode } from '../iso19139/utils/status.mapper'
19
19
  import { getUpdateFrequencyFromFrequencyCode } from '../iso19139/utils/update-frequency.mapper'
20
20
  import {
@@ -49,7 +49,7 @@ export class Gn4FieldMapper {
49
49
  private translateService = inject(TranslateService)
50
50
 
51
51
  private get getLocalizedIndexKey() {
52
- return `lang${toLang3(this.translateService.currentLang)}`
52
+ return `lang${toLang3(this.translateService.getCurrentLang())}`
53
53
  }
54
54
 
55
55
  protected fields: Record<string, EsFieldMapperFn> = {
@@ -240,8 +240,9 @@ export class Gn4FieldMapper {
240
240
  allKeywords: (output, source) => ({
241
241
  ...output,
242
242
  keywords: mapKeywords(
243
- selectField<Thesaurus[]>(source, 'allKeywords'),
244
- this.getLocalizedIndexKey
243
+ selectField<Record<string, Thesaurus>>(source, 'allKeywords'),
244
+ this.getLocalizedIndexKey,
245
+ source
245
246
  ),
246
247
  }),
247
248
  inspireTheme: (output, source) => ({
@@ -1,4 +1,4 @@
1
- import { Injectable, inject } from '@angular/core'
1
+ import { inject, Injectable } from '@angular/core'
2
2
  import { Configuration } from '../../../../../../libs/data-access/gn4/src'
3
3
  import { TranslateService } from '@ngx-translate/core'
4
4
  import { toLang3 } from '../../../../../../libs/util/i18n/src'
@@ -13,7 +13,7 @@ export class MetadataUrlService {
13
13
  getUrl(uuid: string, apiPath: string = this.apiConfiguration.basePath) {
14
14
  const prefix = `${apiPath}/../`
15
15
  return `${prefix}${toLang3(
16
- this.translate.currentLang
16
+ this.translate.getCurrentLang()
17
17
  )}/catalog.search#/metadata/${uuid}`
18
18
  }
19
19
  }
@@ -62,6 +62,7 @@ type ThesaurusName = string
62
62
  export interface Thesaurus {
63
63
  id?: string
64
64
  title?: string
65
+ multilingualTitle?: MultilingualField
65
66
  theme?: string
66
67
  link?: string
67
68
  keywords: MultilingualField[]
@@ -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':
@@ -1,4 +1,4 @@
1
- import { Injectable, InjectionToken, inject } from '@angular/core'
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('${lang2}', toLang2(this.translateService.currentLang))
48
- .replace('${lang3}', toLang3(this.translateService.currentLang))
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.currentLang)
62
+ toLang3(this.translateService.getCurrentLang())
59
63
  )
60
64
  }
61
65
  }
@@ -1,4 +1,4 @@
1
- import { Injectable, Injector, inject } from '@angular/core'
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.currentLang
237
+ ? this.translateService.getCurrentLang()
238
238
  : this.metadataLang
239
239
  )
240
240
  return `lang${lang3}`