geonetwork-ui 2.6.0-dev.492bf4497 → 2.6.0-dev.4a61a87f9

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 (192) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +39 -4
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
  3. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.mjs +8 -4
  4. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.mjs +5 -2
  5. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +4 -4
  6. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +2 -2
  7. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/constant.mjs +2 -1
  8. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +3 -3
  9. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +62 -11
  10. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +7 -1
  11. package/esm2022/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.mjs +2 -1
  12. package/esm2022/libs/common/domain/src/lib/repository/records-repository.interface.mjs +1 -1
  13. package/esm2022/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.mjs +266 -11
  14. package/esm2022/libs/feature/record/src/index.mjs +2 -3
  15. package/esm2022/libs/feature/record/src/lib/state/mdview.actions.mjs +3 -1
  16. package/esm2022/libs/feature/record/src/lib/state/mdview.effects.mjs +7 -1
  17. package/esm2022/libs/feature/record/src/lib/state/mdview.facade.mjs +3 -1
  18. package/esm2022/libs/feature/record/src/lib/state/mdview.reducer.mjs +7 -1
  19. package/esm2022/libs/feature/record/src/lib/state/mdview.selectors.mjs +3 -1
  20. package/esm2022/libs/feature/search/src/lib/constants.mjs +2 -1
  21. package/esm2022/libs/feature/search/src/lib/results-list/results-list.container.component.mjs +6 -2
  22. package/esm2022/libs/feature/search/src/lib/results-table/results-table-container.component.mjs +13 -10
  23. package/esm2022/libs/ui/elements/src/index.mjs +2 -1
  24. package/esm2022/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.mjs +55 -0
  25. package/esm2022/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.mjs +42 -83
  26. package/esm2022/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.mjs +59 -0
  27. package/esm2022/libs/ui/elements/src/lib/kind-badge/kind-badge.component.mjs +22 -5
  28. package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +3 -3
  29. package/esm2022/libs/ui/elements/src/lib/related-record-card/related-record-card.component.mjs +17 -7
  30. package/esm2022/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.mjs +12 -4
  31. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +10 -4
  32. package/esm2022/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.mjs +3 -3
  33. package/esm2022/libs/ui/inputs/src/lib/star-toggle/star-toggle.component.mjs +3 -3
  34. package/esm2022/libs/ui/layout/src/lib/interactive-table/interactive-table.component.mjs +20 -10
  35. package/esm2022/libs/ui/search/src/index.mjs +2 -1
  36. package/esm2022/libs/ui/search/src/lib/record-preview-row/record-preview-row.component.mjs +4 -8
  37. package/esm2022/libs/ui/search/src/lib/results-hits-search-kind/results-hits-search-kind.component.mjs +3 -3
  38. package/esm2022/libs/ui/search/src/lib/results-list/results-layout.config.mjs +2 -2
  39. package/esm2022/libs/ui/search/src/lib/results-list/results-list.component.mjs +3 -3
  40. package/esm2022/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.mjs +21 -12
  41. package/esm2022/libs/ui/search/src/lib/results-table/results-table.component.mjs +39 -18
  42. package/esm2022/libs/ui/search/src/lib/ui-search.module.mjs +10 -4
  43. package/esm2022/libs/util/i18n/src/lib/i18n.constants.mjs +42 -1
  44. package/esm2022/libs/util/i18n/src/lib/language-codes.mjs +24 -2
  45. package/esm2022/translations/de.json +34 -12
  46. package/esm2022/translations/en.json +34 -14
  47. package/esm2022/translations/es.json +33 -11
  48. package/esm2022/translations/fr.json +34 -14
  49. package/esm2022/translations/it.json +66 -44
  50. package/esm2022/translations/nl.json +33 -11
  51. package/esm2022/translations/pt.json +33 -11
  52. package/fesm2022/geonetwork-ui.mjs +1441 -727
  53. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  54. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  55. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +0 -1
  56. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
  57. package/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.d.ts +1 -0
  58. package/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.d.ts.map +1 -1
  59. package/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.d.ts.map +1 -1
  60. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
  61. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  62. package/libs/api/repository/src/lib/gn4/elasticsearch/constant.d.ts.map +1 -1
  63. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts +1 -1
  64. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
  65. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +13 -2
  66. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
  67. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +2 -0
  68. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  69. package/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.d.ts +1 -0
  70. package/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.d.ts.map +1 -1
  71. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts +6 -0
  72. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts.map +1 -1
  73. package/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.d.ts +48 -3
  74. package/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.d.ts.map +1 -1
  75. package/libs/feature/record/src/index.d.ts +1 -2
  76. package/libs/feature/record/src/index.d.ts.map +1 -1
  77. package/libs/feature/record/src/lib/state/mdview.actions.d.ts +10 -0
  78. package/libs/feature/record/src/lib/state/mdview.actions.d.ts.map +1 -1
  79. package/libs/feature/record/src/lib/state/mdview.effects.d.ts +6 -0
  80. package/libs/feature/record/src/lib/state/mdview.effects.d.ts.map +1 -1
  81. package/libs/feature/record/src/lib/state/mdview.facade.d.ts +2 -0
  82. package/libs/feature/record/src/lib/state/mdview.facade.d.ts.map +1 -1
  83. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts +2 -0
  84. package/libs/feature/record/src/lib/state/mdview.reducer.d.ts.map +1 -1
  85. package/libs/feature/record/src/lib/state/mdview.selectors.d.ts +2 -0
  86. package/libs/feature/record/src/lib/state/mdview.selectors.d.ts.map +1 -1
  87. package/libs/feature/search/src/lib/constants.d.ts.map +1 -1
  88. package/libs/feature/search/src/lib/results-list/results-list.container.component.d.ts +1 -1
  89. package/libs/feature/search/src/lib/results-list/results-list.container.component.d.ts.map +1 -1
  90. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts +6 -5
  91. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts.map +1 -1
  92. package/libs/ui/elements/src/index.d.ts +1 -0
  93. package/libs/ui/elements/src/index.d.ts.map +1 -1
  94. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts +15 -0
  95. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts.map +1 -0
  96. package/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.d.ts +6 -13
  97. package/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.d.ts.map +1 -1
  98. package/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.d.ts +14 -0
  99. package/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.d.ts.map +1 -0
  100. package/libs/ui/elements/src/lib/kind-badge/kind-badge.component.d.ts +3 -1
  101. package/libs/ui/elements/src/lib/kind-badge/kind-badge.component.d.ts.map +1 -1
  102. package/libs/ui/elements/src/lib/related-record-card/related-record-card.component.d.ts +8 -1
  103. package/libs/ui/elements/src/lib/related-record-card/related-record-card.component.d.ts.map +1 -1
  104. package/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.d.ts +1 -0
  105. package/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.d.ts.map +1 -1
  106. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +2 -1
  107. package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
  108. package/libs/ui/layout/src/lib/interactive-table/interactive-table.component.d.ts +4 -2
  109. package/libs/ui/layout/src/lib/interactive-table/interactive-table.component.d.ts.map +1 -1
  110. package/libs/ui/search/src/index.d.ts +1 -0
  111. package/libs/ui/search/src/index.d.ts.map +1 -1
  112. package/libs/ui/search/src/lib/results-list/results-list.component.d.ts.map +1 -1
  113. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts +4 -3
  114. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts.map +1 -1
  115. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts +10 -4
  116. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts.map +1 -1
  117. package/libs/ui/search/src/lib/ui-search.module.d.ts +2 -1
  118. package/libs/ui/search/src/lib/ui-search.module.d.ts.map +1 -1
  119. package/libs/util/i18n/src/lib/i18n.constants.d.ts +1 -0
  120. package/libs/util/i18n/src/lib/i18n.constants.d.ts.map +1 -1
  121. package/libs/util/i18n/src/lib/language-codes.d.ts +23 -1
  122. package/libs/util/i18n/src/lib/language-codes.d.ts.map +1 -1
  123. package/package.json +1 -1
  124. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -1
  125. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +61 -4
  126. package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +0 -1
  127. package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +13 -3
  128. package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +5 -1
  129. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +8 -4
  130. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +4 -1
  131. package/src/libs/api/repository/src/lib/gn4/elasticsearch/constant.ts +1 -0
  132. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +2 -2
  133. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +101 -11
  134. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +11 -0
  135. package/src/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.ts +3 -0
  136. package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +6 -0
  137. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +50 -1
  138. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.html +117 -11
  139. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.ts +316 -6
  140. package/src/libs/feature/record/src/index.ts +1 -2
  141. package/src/libs/feature/record/src/lib/state/mdview.actions.ts +10 -0
  142. package/src/libs/feature/record/src/lib/state/mdview.effects.ts +22 -0
  143. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +4 -0
  144. package/src/libs/feature/record/src/lib/state/mdview.reducer.ts +12 -0
  145. package/src/libs/feature/record/src/lib/state/mdview.selectors.ts +9 -0
  146. package/src/libs/feature/search/src/lib/constants.ts +1 -0
  147. package/src/libs/feature/search/src/lib/results-list/results-list.container.component.ts +2 -0
  148. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.html +1 -0
  149. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +13 -3
  150. package/src/libs/ui/elements/src/index.ts +1 -0
  151. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.css +4 -0
  152. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.html +13 -0
  153. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.ts +54 -0
  154. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +68 -141
  155. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +38 -97
  156. package/src/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.html +69 -0
  157. package/src/libs/ui/elements/src/lib/internal-link-card-contact/internal-link-card-contact.component.ts +61 -0
  158. package/src/libs/ui/elements/src/lib/kind-badge/kind-badge.component.html +7 -5
  159. package/src/libs/ui/elements/src/lib/kind-badge/kind-badge.component.ts +21 -2
  160. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.html +1 -1
  161. package/src/libs/ui/elements/src/lib/related-record-card/related-record-card.component.html +8 -29
  162. package/src/libs/ui/elements/src/lib/related-record-card/related-record-card.component.ts +14 -1
  163. package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.html +15 -1
  164. package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.ts +9 -1
  165. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +3 -0
  166. package/src/libs/ui/inputs/src/lib/autocomplete/autocomplete.component.html +1 -1
  167. package/src/libs/ui/inputs/src/lib/star-toggle/star-toggle.component.html +1 -2
  168. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.html +3 -2
  169. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.ts +13 -6
  170. package/src/libs/ui/search/src/index.ts +1 -0
  171. package/src/libs/ui/search/src/lib/record-preview-row/record-preview-row.component.html +9 -81
  172. package/src/libs/ui/search/src/lib/results-hits-search-kind/results-hits-search-kind.component.html +1 -0
  173. package/src/libs/ui/search/src/lib/results-list/results-layout.config.ts +2 -2
  174. package/src/libs/ui/search/src/lib/results-list/results-list.component.html +1 -1
  175. package/src/libs/ui/search/src/lib/results-list/results-list.component.ts +0 -1
  176. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.html +16 -6
  177. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.ts +15 -11
  178. package/src/libs/ui/search/src/lib/results-table/results-table.component.css +4 -0
  179. package/src/libs/ui/search/src/lib/results-table/results-table.component.html +31 -27
  180. package/src/libs/ui/search/src/lib/results-table/results-table.component.ts +33 -15
  181. package/src/libs/ui/search/src/lib/ui-search.module.ts +3 -0
  182. package/src/libs/util/i18n/src/lib/i18n.constants.ts +42 -0
  183. package/src/libs/util/i18n/src/lib/language-codes.ts +23 -1
  184. package/tailwind.base.css +1 -1
  185. package/translations/de.json +34 -12
  186. package/translations/en.json +34 -14
  187. package/translations/es.json +33 -11
  188. package/translations/fr.json +34 -14
  189. package/translations/it.json +66 -44
  190. package/translations/nl.json +33 -11
  191. package/translations/pt.json +33 -11
  192. package/translations/sk.json +33 -11
@@ -529,7 +529,11 @@ export function writeOnlineResources(
529
529
  }
530
530
 
531
531
  function writeLocaleElement(language: LanguageCode) {
532
- const lang3 = LANG_2_TO_3_MAPPER[language.toLowerCase()]
532
+ const normalizedLang = language.toLowerCase()
533
+ const lang3 =
534
+ normalizedLang.length === 2
535
+ ? LANG_2_TO_3_MAPPER[normalizedLang]
536
+ : normalizedLang
533
537
  return pipe(
534
538
  findChildOrCreate('lan:PT_Locale'),
535
539
  writeAttribute('id', language.toUpperCase()),
@@ -65,7 +65,8 @@ export function extractCharacterString(): ChainableFunction<
65
65
  return pipe(
66
66
  fallback(
67
67
  findChildElement('gco:CharacterString', false),
68
- findChildElement('gmx:Anchor', false)
68
+ findChildElement('gmx:Anchor', false),
69
+ findChildElement('gmx:MimeFileType', false)
69
70
  ),
70
71
  readText()
71
72
  )
@@ -1161,11 +1162,14 @@ export function readOtherLanguages(rootEl: XmlElement): LanguageCode[] {
1161
1162
  findChildrenElement('gmd:locale', false),
1162
1163
  mapArray(
1163
1164
  pipe(
1164
- findChildElement('gmd:LanguageCode'),
1165
+ findChildElement('lan:LanguageCode'),
1165
1166
  readAttribute('codeListValue'),
1166
- map((lang) => LANG_3_TO_2_MAPPER[lang.toLowerCase()])
1167
+ map((lang) => LANG_3_TO_2_MAPPER[lang.toLowerCase()] ?? lang)
1167
1168
  )
1168
1169
  ),
1170
+ map((languages) =>
1171
+ languages.filter((lang): lang is LanguageCode => lang !== null)
1172
+ ),
1169
1173
  map((languages) => (languages.length ? languages : [defaultLanguage]))
1170
1174
  )(rootEl)
1171
1175
  }
@@ -1173,7 +1177,7 @@ export function readOtherLanguages(rootEl: XmlElement): LanguageCode[] {
1173
1177
  export function readDefaultLanguage(rootEl: XmlElement): LanguageCode {
1174
1178
  return pipe(
1175
1179
  findChildElement('gmd:language', false),
1176
- findChildElement('gmd:LanguageCode'),
1180
+ findChildElement('lan:LanguageCode'),
1177
1181
  readAttribute('codeListValue'),
1178
1182
  map((lang) => (lang ? LANG_3_TO_2_MAPPER[lang.toLowerCase()] : null))
1179
1183
  )(rootEl)
@@ -1471,7 +1471,10 @@ export function writeLanguages(record: DatasetRecord, rootEl: XmlElement) {
1471
1471
  writeAttribute('id', lang.toUpperCase()),
1472
1472
  createNestedChild('gmd:languageCode', 'gmd:LanguageCode'),
1473
1473
  writeAttribute('codeList', 'http://www.loc.gov/standards/iso639-2/'),
1474
- writeAttribute('codeListValue', LANG_2_TO_3_MAPPER[lang])
1474
+ writeAttribute(
1475
+ 'codeListValue',
1476
+ lang.length === 2 ? LANG_2_TO_3_MAPPER[lang] : lang
1477
+ )
1475
1478
  )
1476
1479
 
1477
1480
  // add new languages (only if other than default one)
@@ -8,6 +8,7 @@ export const ES_SOURCE_SUMMARY = [
8
8
  'overview',
9
9
  'logo',
10
10
  'codelist_status_text',
11
+ 'link',
11
12
  'linkProtocol',
12
13
  'contactForResource.organisation',
13
14
  'contact.organisation',
@@ -124,11 +124,11 @@ export class ElasticsearchService {
124
124
  this.runtimeFields[fieldName] = expression
125
125
  }
126
126
 
127
- getMetadataByIdPayload(uuid: string): EsSearchParams {
127
+ getMetadataByIdsPayload(uuids: string[]): EsSearchParams {
128
128
  return {
129
129
  query: {
130
130
  ids: {
131
- values: [uuid],
131
+ values: uuids,
132
132
  },
133
133
  },
134
134
  }
@@ -14,8 +14,8 @@ import {
14
14
  import { PublicationVersionError } from '../../../../../../libs/common/domain/src/lib/model/error'
15
15
  import {
16
16
  CatalogRecord,
17
- DatasetFeatureType,
18
17
  DatasetFeatureCatalog,
18
+ DatasetFeatureType,
19
19
  } from '../../../../../../libs/common/domain/src/lib/model/record'
20
20
  import {
21
21
  Aggregations,
@@ -29,10 +29,11 @@ import {
29
29
  import { PlatformServiceInterface } from '../../../../../../libs/common/domain/src/lib/platform.service.interface'
30
30
  import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
31
31
  import {
32
+ LanguagesApiService,
32
33
  RecordsApiService,
33
34
  SearchApiService,
34
- FeatureResponseApiModel,
35
35
  } from '../../../../../../libs/data-access/gn4/src'
36
+ import { LANG_3_TO_2_MAPPER } from '../../../../../../libs/util/i18n/src'
36
37
  import {
37
38
  combineLatest,
38
39
  exhaustMap,
@@ -47,6 +48,7 @@ import {
47
48
  import { catchError, map, tap } from 'rxjs/operators'
48
49
  import { lt } from 'semver'
49
50
  import { ElasticsearchService } from './elasticsearch'
51
+ import { Gn4SettingsService } from './settings/gn4-settings.service'
50
52
 
51
53
  const minPublicationApiVersion = '4.2.5'
52
54
 
@@ -65,7 +67,9 @@ export class Gn4Repository implements RecordsRepositoryInterface {
65
67
  private gn4SearchHelper: ElasticsearchService,
66
68
  private gn4Mapper: Gn4Converter,
67
69
  private gn4RecordsApi: RecordsApiService,
68
- private platformService: PlatformServiceInterface
70
+ private platformService: PlatformServiceInterface,
71
+ private gn4LanguagesApi: LanguagesApiService,
72
+ private settingsService: Gn4SettingsService
69
73
  ) {}
70
74
 
71
75
  search({
@@ -129,9 +133,9 @@ export class Gn4Repository implements RecordsRepositoryInterface {
129
133
  return this.gn4SearchApi
130
134
  .search(
131
135
  'bucket',
132
- ['fcats'],
136
+ ['fcats', 'hassources'],
133
137
  JSON.stringify(
134
- this.gn4SearchHelper.getMetadataByIdPayload(uniqueIdentifier)
138
+ this.gn4SearchHelper.getMetadataByIdsPayload([uniqueIdentifier])
135
139
  )
136
140
  )
137
141
  .pipe(
@@ -142,6 +146,27 @@ export class Gn4Repository implements RecordsRepositoryInterface {
142
146
  )
143
147
  }
144
148
 
149
+ getMultipleRecords(
150
+ uniqueIdentifiers: string[]
151
+ ): Observable<CatalogRecord[] | null> {
152
+ return this.gn4SearchApi
153
+ .search(
154
+ 'bucket',
155
+ undefined,
156
+ JSON.stringify(
157
+ this.gn4SearchHelper.getMetadataByIdsPayload(uniqueIdentifiers)
158
+ )
159
+ )
160
+ .pipe(
161
+ map((results: Gn4SearchResults) => results.hits.hits),
162
+ switchMap((records) =>
163
+ records && records.length > 0
164
+ ? this.gn4Mapper.readRecords(records)
165
+ : of(null)
166
+ )
167
+ )
168
+ }
169
+
145
170
  private mapEmbeddedFeatureCatalog(
146
171
  featureTypes: Array<DatasetFeatureType>
147
172
  ): DatasetFeatureCatalog {
@@ -203,6 +228,24 @@ export class Gn4Repository implements RecordsRepositoryInterface {
203
228
  )
204
229
  }
205
230
 
231
+ getSources(record: CatalogRecord): Observable<CatalogRecord[]> {
232
+ const sourcesIdentifiers = record.extras?.['sourcesIdentifiers'] as string[]
233
+ if (sourcesIdentifiers && sourcesIdentifiers.length > 0) {
234
+ return this.getMultipleRecords(sourcesIdentifiers)
235
+ }
236
+ return of(null)
237
+ }
238
+
239
+ getSourceOf(record: CatalogRecord): Observable<CatalogRecord[]> {
240
+ const sourceOfIdentifiers = record.extras?.[
241
+ 'sourceOfIdentifiers'
242
+ ] as string[]
243
+ if (sourceOfIdentifiers && sourceOfIdentifiers.length > 0) {
244
+ return this.getMultipleRecords(sourceOfIdentifiers)
245
+ }
246
+ return of(null)
247
+ }
248
+
206
249
  aggregate(params: AggregationsParams): Observable<Aggregations> {
207
250
  // if aggregations are empty, return an empty object right away
208
251
  if (Object.keys(params).length === 0) return of({})
@@ -255,14 +298,46 @@ export class Gn4Repository implements RecordsRepositoryInterface {
255
298
  : of(true)
256
299
  }
257
300
 
258
- canEditRecord(uniqueIdentifier: string): Observable<boolean> {
259
- return this.getRecord(uniqueIdentifier).pipe(
260
- map((record) => {
261
- return record.extras['edit'] as boolean
301
+ canDuplicate(record: CatalogRecord): boolean {
302
+ return record.kind === 'dataset'
303
+ }
304
+
305
+ canDelete(record: CatalogRecord): Observable<boolean> {
306
+ return this.settingsService.allowEditHarvested$.pipe(
307
+ map((allowEditHarvested) => {
308
+ return (
309
+ record.extras['edit'] &&
310
+ (!record.extras['isHarvested'] || allowEditHarvested)
311
+ )
262
312
  })
263
313
  )
264
314
  }
265
315
 
316
+ private canEdit(record: CatalogRecord, allowEditHarvested: boolean): boolean {
317
+ return (
318
+ record.kind === 'dataset' &&
319
+ record.extras['edit'] &&
320
+ (!record.extras['isHarvested'] || allowEditHarvested)
321
+ )
322
+ }
323
+
324
+ canEditRecord(uniqueIdentifier: string): Observable<boolean> {
325
+ return combineLatest([
326
+ this.getRecord(uniqueIdentifier),
327
+ this.settingsService.allowEditHarvested$,
328
+ ]).pipe(
329
+ map(([record, allowEditHarvested]) =>
330
+ record ? this.canEdit(record, allowEditHarvested) : false
331
+ )
332
+ )
333
+ }
334
+
335
+ canEditIndexedRecord(record: CatalogRecord): Observable<boolean> {
336
+ return this.settingsService.allowEditHarvested$.pipe(
337
+ map((allowEditHarvested) => this.canEdit(record, allowEditHarvested))
338
+ )
339
+ }
340
+
266
341
  openRecordForEdition(
267
342
  uniqueIdentifier: string
268
343
  ): Observable<[CatalogRecord, string, boolean] | null> {
@@ -365,9 +440,12 @@ export class Gn4Repository implements RecordsRepositoryInterface {
365
440
  const record = await converter.readRecord(fetchedRecordAsXml)
366
441
 
367
442
  record.title = `${record.title} (Copy)`
368
- await converter.writeRecord(record, fetchedRecordAsXml)
443
+ const recordAsXml = await converter.writeRecord(
444
+ record,
445
+ fetchedRecordAsXml
446
+ )
369
447
 
370
- return this.saveRecord(record, '', false)
448
+ return this.saveRecord(record, recordAsXml, false)
371
449
  }),
372
450
  exhaustMap((uuidObservable: Observable<string>) => uuidObservable),
373
451
  catchError((error: HttpErrorResponse) => {
@@ -468,6 +546,18 @@ export class Gn4Repository implements RecordsRepositoryInterface {
468
546
  )
469
547
  }
470
548
 
549
+ getApplicationLanguages(): Observable<string[]> {
550
+ return this.gn4LanguagesApi
551
+ .getApplicationLanguages()
552
+ .pipe(
553
+ map((languages) =>
554
+ languages
555
+ .map((lang) => LANG_3_TO_2_MAPPER[lang.id ?? ''])
556
+ .filter((code): code is string => !!code)
557
+ )
558
+ )
559
+ }
560
+
471
561
  private getRecordAsXml(uniqueIdentifier: string): Observable<string | null> {
472
562
  return this.gn4RecordsApi
473
563
  .getRecordAs(
@@ -82,6 +82,13 @@ export class Gn4PlatformService implements PlatformServiceInterface {
82
82
  shareReplay(1)
83
83
  )
84
84
 
85
+ private readonly allowEditHarvestedMd$ = this.settings$.pipe(
86
+ map((info) => {
87
+ return info['system/harvester/enableEditing'] as boolean
88
+ }),
89
+ shareReplay(1)
90
+ )
91
+
85
92
  /**
86
93
  * A map of already loaded thesauri (groups of keywords); the key is a URI
87
94
  * @private
@@ -123,6 +130,10 @@ export class Gn4PlatformService implements PlatformServiceInterface {
123
130
  return this.apiVersion$
124
131
  }
125
132
 
133
+ getAllowEditHarvestedMd(): Observable<boolean> {
134
+ return this.allowEditHarvestedMd$
135
+ }
136
+
126
137
  getMe(): Observable<UserModel> {
127
138
  return this.me$
128
139
  }
@@ -11,6 +11,9 @@ export class Gn4SettingsService {
11
11
  'system/users/identicon'
12
12
  )
13
13
 
14
+ public allowEditHarvested$: Observable<boolean> =
15
+ this.getSettingsSetValueByKey('system/harvester/enableEditing')
16
+
14
17
  constructor(private siteApiService: SiteApiService) {}
15
18
 
16
19
  private getSettingsSetValueByKey(key: string) {
@@ -19,8 +19,13 @@ export abstract class RecordsRepositoryInterface {
19
19
  abstract getSimilarRecords(
20
20
  similarTo: CatalogRecord
21
21
  ): Observable<CatalogRecord[]>
22
+ abstract getSources(record: CatalogRecord): Observable<CatalogRecord[]>
23
+ abstract getSourceOf(record: CatalogRecord): Observable<CatalogRecord[]>
22
24
  abstract fuzzySearch(query: string): Observable<SearchResults>
25
+ abstract canDuplicate(record: CatalogRecord): boolean
26
+ abstract canDelete(record: CatalogRecord): Observable<boolean>
23
27
  abstract canEditRecord(uniqueIdentifier: string): Observable<boolean>
28
+ abstract canEditIndexedRecord(record: CatalogRecord): Observable<boolean>
24
29
  /**
25
30
  * This emits once:
26
31
  * - record object; if a draft exists, this will return it
@@ -95,4 +100,5 @@ export abstract class RecordsRepositoryInterface {
95
100
  localRecord: CatalogRecord
96
101
  ): Observable<{ user: string; date: Date }>
97
102
  abstract getRecordPublicationStatus(uuid: string): Observable<boolean>
103
+ abstract getApplicationLanguages(): Observable<string[]>
98
104
  }
@@ -3,6 +3,7 @@ import {
3
3
  DatasetRecord,
4
4
  DatasetSpatialExtent,
5
5
  Keyword,
6
+ ServiceRecord,
6
7
  } from '../../../../../libs/common/domain/src/lib/model/record'
7
8
 
8
9
  export const datasetRecordsFixture: () => CatalogRecord[] = () => [
@@ -231,7 +232,7 @@ As such, **it is not very interesting at all.**`,
231
232
  recordUpdated: new Date('2022-04-15T14:18:19'),
232
233
  resourceUpdated: new Date('2022-03-29'),
233
234
  title:
234
- "Plan local d'urbanisme (PLU) dématérialisé - commune d'Avrigny - approbation du 29/03/2022",
235
+ "Plan local d'urbanisme (PLU) dématérialisé - commune d'Avrigny - approbation du 29/03/2022 (Ce lot informe du droit à bâtir sur la commune d'Avrigny)",
235
236
  abstract: `Plan local d'urbanisme (PLU) dématérialisé - commune d'Avrigny - approbation du 29/03/2022.
236
237
 
237
238
  Ce lot informe du droit à bâtir sur la commune d'Avrigny.
@@ -811,6 +812,54 @@ export const importDatasetRecordAsXmlFixture = (): string => `
811
812
  </gmd:identificationInfo>
812
813
  </gmd:MD_Metadata>`
813
814
 
815
+ export const simpleServiceRecordFixture = (): ServiceRecord => ({
816
+ kind: 'service',
817
+ status: null,
818
+ lineage: null,
819
+ recordUpdated: new Date('2023-03-17T07:38:08.875Z'),
820
+ recordPublished: null,
821
+ ownerOrganization: null,
822
+ licenses: [],
823
+ legalConstraints: [],
824
+ securityConstraints: [],
825
+ otherConstraints: [],
826
+ contacts: [],
827
+ contactsForResource: [],
828
+ keywords: [],
829
+ topics: [],
830
+ spatialExtents: [],
831
+ temporalExtents: [],
832
+ overviews: [],
833
+ defaultLanguage: null,
834
+ otherLanguages: [],
835
+ title: 'Sites de gestion des déchets miniers - Service de visualisation WMS',
836
+ onlineResources: [
837
+ {
838
+ name: 'Service de visualisation WMS',
839
+ description:
840
+ 'Adresse de connexion au service de visualisation WMS de la série de couches de données "Sites de gestion des déchets miniers"',
841
+ type: 'service',
842
+ url: new URL(
843
+ 'https://geoservices.wallonie.be/arcgis/services/SOL_SOUS_SOL/DECHETS_MINIERS/MapServer/WMSServer?request=GetCapabilities&service=WMS'
844
+ ),
845
+ accessServiceProtocol: 'wms',
846
+ accessRestricted: false,
847
+ },
848
+ ],
849
+ uniqueIdentifier: '00b22798-ec8e-4500-89e8-90eeeda45919',
850
+ landingPage: new URL(
851
+ 'http://localhost:4200/geonetwork/srv/fre/catalog.search#/metadata/00b22798-ec8e-4500-89e8-90eeeda45919'
852
+ ),
853
+ extras: {
854
+ isPublishedToAll: true,
855
+ id: '723',
856
+ isHarvested: true,
857
+ ownerInfo: 'admin|admin|admin|Administrator',
858
+ edit: true,
859
+ },
860
+ recordCreated: new Date('2023-03-17T07:38:08.875Z'),
861
+ })
862
+
814
863
  export const NATIONAL_KEYWORD = {
815
864
  key: 'http://inspire.ec.europa.eu/metadata-codelist/SpatialScope/national',
816
865
  label: 'National',
@@ -1,14 +1,120 @@
1
1
  <div
2
- class="flex flex-col h-full w-[302px] bg-neutral-100 border-l border-gray-300 py-9 px-3 gap-8"
2
+ class="flex flex-col h-full w-[302px] bg-neutral-100 border-l border-gray-300 py-8 px-3 gap-6 overflow-auto"
3
3
  >
4
- <span class="text-3xl font-title text-black/80 px-2" translate
5
- >editor.record.form.multilingual.title</span
6
- >
7
- <gn-ui-check-toggle
8
- class="p-2"
9
- [label]="'editor.record.form.multilingual.enable' | translate"
10
- [color]="'primary'"
11
- [value]="translationsEnabled"
12
- (toggled)="translationsEnabled = $event"
13
- ></gn-ui-check-toggle>
4
+ <div class="flex flex-row px-2 justify-between">
5
+ <span class="text-3xl font-title text-black/80" translate
6
+ >editor.record.form.multilingual.title</span
7
+ >
8
+ <button
9
+ [title]="'editor.record.form.multilingual.open' | translate"
10
+ (click)="toggleLanguageSelection()"
11
+ *ngIf="isMultilingual"
12
+ data-test="activateSelection"
13
+ >
14
+ <ng-icon class="mt-1" name="iconoirSettings"></ng-icon>
15
+ </button>
16
+ </div>
17
+ <div class="flex flex-col gap-2" *ngIf="editTranslations || !isMultilingual">
18
+ <gn-ui-check-toggle
19
+ class="p-2"
20
+ [label]="'editor.record.form.multilingual.enable' | translate"
21
+ [color]="'primary'"
22
+ [(value)]="isMultilingual"
23
+ (toggled)="switchMultilingual($event)"
24
+ ></gn-ui-check-toggle>
25
+ <div *ngIf="isMultilingual" class="flex flex-col gap-2">
26
+ <div class="flex flex-row justify-between border-t border-gray-300 p-3">
27
+ <span class="mt-2 text-sm text-gray-600" translate
28
+ >editor.record.form.multilingual.activate</span
29
+ >
30
+ <gn-ui-button
31
+ extraClass="w-16 h-8 font-bold"
32
+ type="gray"
33
+ (buttonClick)="validateTranslations()"
34
+ data-test="validateSelection"
35
+ >{{ 'editor.record.form.multilingual.validate' | translate }}
36
+ </gn-ui-button>
37
+ </div>
38
+ <ng-container *ngIf="supportedLanguages$ | async as languages">
39
+ <div
40
+ class="flex flex-col gap-2 w-full px-2"
41
+ data-test="langAvailable"
42
+ *ngFor="let lang of languages"
43
+ >
44
+ <gn-ui-button
45
+ [extraClass]="getExtraClass(lang)"
46
+ type="gray"
47
+ (buttonClick)="toggleLanguage(lang)"
48
+ [disabled]="lang === _record.defaultLanguage"
49
+ [title]="getToggleTitle(lang)"
50
+ >
51
+ <span [class]="getIconClass(lang)"></span>
52
+ <span class="ml-2">{{ 'language.' + lang | translate }}</span>
53
+ </gn-ui-button>
54
+ </div>
55
+ </ng-container>
56
+ </div>
57
+ </div>
58
+ <div *ngIf="!editTranslations && isMultilingual" class="flex flex-col gap-2">
59
+ <gn-ui-button
60
+ *ngFor="let recordLang of sortLanguages(recordLanguages); let i = index"
61
+ extraClass="flex flex-row justify-between bg-white border border-white rounded mb-1 h-[34px] w-full"
62
+ [ngClass]="{
63
+ 'mt-8': isFirstUnsupported(i),
64
+ '': true,
65
+ }"
66
+ (buttonClick)="switchFormLang(recordLang)"
67
+ type="outline"
68
+ data-test="langSwitch"
69
+ >
70
+ <div class="flex flex-row gap-2 items-center">
71
+ <ng-icon
72
+ *ngIf="recordLang === formLanguage"
73
+ class="text-primary mt-1"
74
+ name="iconoirCheckCircle"
75
+ ></ng-icon>
76
+ <ng-icon
77
+ *ngIf="recordLang !== formLanguage"
78
+ class="text-gray-800 mt-1"
79
+ name="iconoirCircle"
80
+ ></ng-icon>
81
+ <span
82
+ *ngIf="recordLang.length === 2"
83
+ [class]="getIconClass(recordLang) + 'mt-1'"
84
+ ></span>
85
+ <span [ngClass]="recordLang === formLanguage ? 'text-black' : ''">{{
86
+ isLangSupported(recordLang)
87
+ ? ('language.' + recordLang | translate)
88
+ : recordLang.toUpperCase()
89
+ }}</span>
90
+ </div>
91
+ <div class="flex flex-row gap-2 items-center">
92
+ <span
93
+ *ngIf="recordLang === formLanguage"
94
+ class="text-xs text-base"
95
+ translate
96
+ >editor.record.form.multilingual.default</span
97
+ >
98
+ <button
99
+ (click)="
100
+ openActionMenu(recordLang, template); $event.stopPropagation()
101
+ "
102
+ cdkOverlayOrigin
103
+ #actionMenuButton
104
+ >
105
+ <ng-icon class="pb-5" name="matMoreHorizOutline"></ng-icon>
106
+ </button>
107
+ <ng-template #template>
108
+ <gn-ui-action-menu
109
+ [canDelete]="recordLang !== _record.defaultLanguage"
110
+ page="record"
111
+ (delete)="confirmDeleteAction(recordLang)"
112
+ (closeActionMenu)="closeActionMenu()"
113
+ (switch)="switchDefaultLang(recordLang)"
114
+ >
115
+ </gn-ui-action-menu>
116
+ </ng-template>
117
+ </div>
118
+ </gn-ui-button>
119
+ </div>
14
120
  </div>