geonetwork-ui 2.7.0-dev.816935147 → 2.7.0-dev.86624532b

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 (114) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/dcat-ap/read-parts.mjs +4 -7
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +20 -20
  3. package/esm2022/libs/api/metadata-converter/src/lib/gn4/metadata-url.service.mjs +3 -3
  4. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.mjs +3 -3
  5. package/esm2022/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.mjs +3 -3
  6. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +4 -4
  7. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +4 -4
  8. package/esm2022/libs/api/repository/src/index.mjs +2 -2
  9. package/esm2022/libs/api/repository/src/lib/gn4/auth/auth.service.mjs +5 -5
  10. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +9 -10
  11. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +3 -3
  12. package/esm2022/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.mjs +3 -3
  13. package/esm2022/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.mjs +3 -3
  14. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +3 -3
  15. package/esm2022/libs/api/repository/src/lib/metadata-language.token.mjs +3 -0
  16. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  17. package/esm2022/libs/feature/catalog/src/lib/sources/sources.service.mjs +3 -3
  18. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.mjs +79 -0
  19. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +8 -3
  20. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/index.mjs +2 -1
  21. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +77 -1
  22. package/esm2022/libs/feature/router/src/lib/default/state/query-params.utils.mjs +4 -3
  23. package/esm2022/libs/feature/router/src/lib/default/state/router.facade.mjs +3 -2
  24. package/esm2022/libs/ui/elements/src/lib/metadata-quality-item/metadata-quality-item.component.mjs +7 -7
  25. package/esm2022/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.mjs +1 -6
  26. package/esm2022/libs/util/app-config/src/lib/fixtures.mjs +2 -2
  27. package/esm2022/libs/util/app-config/src/lib/parse-utils.mjs +5 -4
  28. package/esm2022/libs/util/i18n/src/lib/language-codes.mjs +50 -9
  29. package/esm2022/libs/util/shared/src/lib/record/quality-score.util.mjs +6 -4
  30. package/esm2022/translations/de.json +42 -20
  31. package/esm2022/translations/en.json +43 -21
  32. package/esm2022/translations/es.json +29 -7
  33. package/esm2022/translations/fr.json +47 -25
  34. package/esm2022/translations/it.json +42 -20
  35. package/esm2022/translations/nl.json +29 -7
  36. package/esm2022/translations/pt.json +29 -7
  37. package/esm2022/translations/sk.json +33 -11
  38. package/fesm2022/geonetwork-ui.mjs +557 -634
  39. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  40. package/libs/api/metadata-converter/src/lib/dcat-ap/read-parts.d.ts.map +1 -1
  41. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts +1 -1
  42. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  43. package/libs/api/repository/src/index.d.ts +1 -1
  44. package/libs/api/repository/src/index.d.ts.map +1 -1
  45. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts +0 -1
  46. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
  47. package/libs/api/repository/src/lib/metadata-language.token.d.ts +5 -0
  48. package/libs/api/repository/src/lib/metadata-language.token.d.ts.map +1 -0
  49. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +4 -0
  50. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  51. package/libs/feature/catalog/src/lib/sources/sources.service.d.ts.map +1 -1
  52. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.d.ts +28 -0
  53. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.d.ts.map +1 -0
  54. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +1 -0
  55. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  56. package/libs/feature/editor/src/lib/components/record-form/form-field/index.d.ts +1 -0
  57. package/libs/feature/editor/src/lib/components/record-form/form-field/index.d.ts.map +1 -1
  58. package/libs/feature/editor/src/lib/fields.config.d.ts +8 -1
  59. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  60. package/libs/feature/router/src/lib/default/state/query-params.utils.d.ts.map +1 -1
  61. package/libs/feature/router/src/lib/default/state/router.facade.d.ts.map +1 -1
  62. package/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.d.ts.map +1 -1
  63. package/libs/util/app-config/src/lib/parse-utils.d.ts.map +1 -1
  64. package/libs/util/i18n/src/lib/language-codes.d.ts +91 -31
  65. package/libs/util/i18n/src/lib/language-codes.d.ts.map +1 -1
  66. package/libs/util/shared/src/lib/record/quality-score.util.d.ts.map +1 -1
  67. package/package.json +1 -1
  68. package/src/libs/api/metadata-converter/src/lib/dcat-ap/read-parts.ts +3 -6
  69. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +47 -22
  70. package/src/libs/api/metadata-converter/src/lib/gn4/metadata-url.service.ts +2 -2
  71. package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +2 -2
  72. package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +2 -2
  73. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +3 -3
  74. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +3 -3
  75. package/src/libs/api/repository/src/index.ts +1 -1
  76. package/src/libs/api/repository/src/lib/gn4/auth/auth.service.ts +4 -4
  77. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +15 -11
  78. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +2 -2
  79. package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts +2 -2
  80. package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts +2 -2
  81. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +2 -2
  82. package/src/libs/api/repository/src/lib/metadata-language.token.ts +8 -0
  83. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +5 -0
  84. package/src/libs/feature/catalog/src/lib/sources/sources.service.ts +2 -5
  85. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.css +0 -0
  86. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.html +20 -0
  87. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.ts +85 -0
  88. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +6 -0
  89. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +5 -0
  90. package/src/libs/feature/editor/src/lib/components/record-form/form-field/index.ts +1 -0
  91. package/src/libs/feature/editor/src/lib/fields.config.ts +85 -1
  92. package/src/libs/feature/router/src/lib/default/state/query-params.utils.ts +5 -2
  93. package/src/libs/feature/router/src/lib/default/state/router.facade.ts +2 -1
  94. package/src/libs/ui/elements/src/lib/metadata-quality-item/metadata-quality-item.component.ts +6 -6
  95. package/src/libs/ui/elements/src/lib/service-capabilities/service-capabilities.component.ts +0 -6
  96. package/src/libs/util/app-config/src/lib/fixtures.ts +1 -1
  97. package/src/libs/util/app-config/src/lib/parse-utils.ts +4 -7
  98. package/src/libs/util/i18n/src/lib/language-codes.ts +62 -11
  99. package/src/libs/util/shared/src/lib/record/quality-score.util.ts +10 -3
  100. package/translations/de.json +42 -20
  101. package/translations/en.json +43 -21
  102. package/translations/es.json +29 -7
  103. package/translations/fr.json +47 -25
  104. package/translations/it.json +42 -20
  105. package/translations/nl.json +29 -7
  106. package/translations/pt.json +29 -7
  107. package/translations/sk.json +33 -11
  108. package/esm2022/libs/api/repository/src/lib/metadata-language.mjs +0 -3
  109. package/esm2022/libs/util/app-config/src/lib/constants.mjs +0 -439
  110. package/libs/api/repository/src/lib/metadata-language.d.ts +0 -3
  111. package/libs/api/repository/src/lib/metadata-language.d.ts.map +0 -1
  112. package/libs/util/app-config/src/lib/constants.d.ts +0 -2
  113. package/libs/util/app-config/src/lib/constants.d.ts.map +0 -1
  114. package/src/libs/api/repository/src/lib/metadata-language.ts +0 -3
@@ -1,7 +1,7 @@
1
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
- import { getLang3FromLang2 } from '../../../../../../libs/util/i18n/src'
4
+ import { toLang3 } from '../../../../../../libs/util/i18n/src'
5
5
 
6
6
  @Injectable({
7
7
  providedIn: 'root',
@@ -14,7 +14,7 @@ export class MetadataUrlService {
14
14
 
15
15
  getUrl(uuid: string, apiPath: string = this.apiConfiguration.basePath) {
16
16
  const prefix = `${apiPath}/../`
17
- return `${prefix}${getLang3FromLang2(
17
+ return `${prefix}${toLang3(
18
18
  this.translate.currentLang
19
19
  )}/catalog.search#/metadata/${uuid}`
20
20
  }
@@ -41,7 +41,7 @@ import {
41
41
  } from '../../../../../../libs/common/domain/src/lib/model/record'
42
42
  import { matchMimeType } from '../common/distribution.mapper'
43
43
  import { fullNameToParts } from '../iso19139/utils/individual-name'
44
- import { getLang2FromLang3 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
44
+ import { toLang2 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
45
45
  import { getResourceType, getReuseType } from '../common/resource-types'
46
46
 
47
47
  export function readKind(rootEl: XmlElement): RecordKind {
@@ -370,7 +370,7 @@ export function readLocaleElement(): ChainableFunction<
370
370
  return pipe(
371
371
  findChildElement('lan:LanguageCode'),
372
372
  readAttribute('codeListValue'),
373
- map((lang) => getLang2FromLang3(lang?.toLowerCase()) ?? lang)
373
+ map((lang) => toLang2(lang?.toLowerCase()) ?? lang)
374
374
  )
375
375
  }
376
376
 
@@ -49,7 +49,7 @@ import {
49
49
  } from '../iso19139/write-parts'
50
50
  import { findIdentification } from '../iso19139/read-parts'
51
51
  import { namePartsToFull } from '../iso19139/utils/individual-name'
52
- import { getLang3FromLang2 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
52
+ import { toLang3 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
53
53
  import { kindToCodeListValue } from '../common/resource-types'
54
54
 
55
55
  export function writeUniqueIdentifier(
@@ -529,7 +529,7 @@ export function writeOnlineResources(
529
529
  }
530
530
 
531
531
  function writeLocaleElement(language: LanguageCode) {
532
- const lang3 = getLang3FromLang2(language.toLowerCase()) ?? language
532
+ const lang3 = toLang3(language.toLowerCase()) ?? language
533
533
  return pipe(
534
534
  findChildOrCreate('lan:PT_Locale'),
535
535
  writeAttribute('id', language.toUpperCase()),
@@ -55,7 +55,7 @@ import { getKeywordTypeFromKeywordTypeCode } from './utils/keyword.mapper'
55
55
  import { getRoleFromRoleCode } from './utils/role.mapper'
56
56
  import { getStatusFromStatusCode } from './utils/status.mapper'
57
57
  import { getUpdateFrequencyFromFrequencyCode } from './utils/update-frequency.mapper'
58
- import { getLang2FromLang3 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
58
+ import { toLang2 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
59
59
  import { getResourceType, getReuseType } from '../common/resource-types'
60
60
 
61
61
  export function extractCharacterString(): ChainableFunction<
@@ -1164,7 +1164,7 @@ export function readOtherLanguages(rootEl: XmlElement): LanguageCode[] {
1164
1164
  pipe(
1165
1165
  findChildElement('lan:LanguageCode'),
1166
1166
  readAttribute('codeListValue'),
1167
- map((lang) => getLang2FromLang3(lang?.toLowerCase()) ?? lang)
1167
+ map((lang) => toLang2(lang?.toLowerCase()) ?? lang)
1168
1168
  )
1169
1169
  ),
1170
1170
  map((languages) =>
@@ -1179,7 +1179,7 @@ export function readDefaultLanguage(rootEl: XmlElement): LanguageCode {
1179
1179
  findChildElement('gmd:language', false),
1180
1180
  findChildElement('lan:LanguageCode'),
1181
1181
  readAttribute('codeListValue'),
1182
- map((lang) => (lang ? getLang2FromLang3(lang.toLowerCase()) : null))
1182
+ map((lang) => (lang ? toLang2(lang.toLowerCase()) : null))
1183
1183
  )(rootEl)
1184
1184
  }
1185
1185
 
@@ -53,7 +53,7 @@ import {
53
53
  import { readKind } from './read-parts'
54
54
  import { writeGeometry } from './utils/geometry'
55
55
  import { namePartsToFull } from './utils/individual-name'
56
- import { getLang3FromLang2 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
56
+ import { toLang3 } from '../../../../../../libs/util/i18n/src/lib/language-codes'
57
57
  import { kindToCodeListValue } from '../common/resource-types'
58
58
 
59
59
  function writeLocalizedElement(
@@ -1476,7 +1476,7 @@ export function writeLanguages(record: DatasetRecord, rootEl: XmlElement) {
1476
1476
  writeAttribute('id', lang.toUpperCase()),
1477
1477
  createNestedChild('gmd:languageCode', 'gmd:LanguageCode'),
1478
1478
  writeAttribute('codeList', 'http://www.loc.gov/standards/iso639-2/'),
1479
- writeAttribute('codeListValue', getLang3FromLang2(lang) ?? lang)
1479
+ writeAttribute('codeListValue', toLang3(lang) ?? lang)
1480
1480
  )
1481
1481
 
1482
1482
  // add new languages (only if other than default one)
@@ -1490,7 +1490,7 @@ export function writeDefaultLanguage(
1490
1490
  record: DatasetRecord,
1491
1491
  rootEl: XmlElement
1492
1492
  ) {
1493
- const lang3 = getLang3FromLang2(record.defaultLanguage.toLowerCase())
1493
+ const lang3 = toLang3(record.defaultLanguage.toLowerCase())
1494
1494
  return pipe(
1495
1495
  findNestedChildOrCreate('gmd:language', 'gmd:LanguageCode'),
1496
1496
  writeAttribute('codeList', 'http://www.loc.gov/standards/iso639-2/'),
@@ -1,3 +1,3 @@
1
- export * from './lib/metadata-language'
1
+ export * from './lib/metadata-language.token'
2
2
  export * from './lib/repository-url'
3
3
  export * from './lib/gn4'
@@ -1,5 +1,5 @@
1
1
  import { Inject, Injectable, InjectionToken, Optional } from '@angular/core'
2
- import { getLang3FromLang2 } from '../../../../../../../libs/util/i18n/src'
2
+ import { toLang2, toLang3 } from '../../../../../../../libs/util/i18n/src'
3
3
  import { TranslateService } from '@ngx-translate/core'
4
4
  import { Location } from '@angular/common'
5
5
 
@@ -35,8 +35,8 @@ export class AuthService {
35
35
  '${current_url}',
36
36
  new URL(this.location.path(), window.location.href).toString()
37
37
  )
38
- .replace('${lang2}', this.translateService.currentLang)
39
- .replace('${lang3}', getLang3FromLang2(this.translateService.currentLang))
38
+ .replace('${lang2}', toLang2(this.translateService.currentLang))
39
+ .replace('${lang3}', toLang3(this.translateService.currentLang))
40
40
  }
41
41
 
42
42
  get logoutUrl() {
@@ -46,7 +46,7 @@ export class AuthService {
46
46
  get settingsUrl() {
47
47
  return this.baseSettingsUrl.replace(
48
48
  '${lang3}',
49
- getLang3FromLang2(this.translateService.currentLang)
49
+ toLang3(this.translateService.currentLang)
50
50
  )
51
51
  }
52
52
 
@@ -15,7 +15,7 @@ import {
15
15
  FiltersAggregationParams,
16
16
  SortByField,
17
17
  } from '../../../../../../../libs/common/domain/src/lib/model/search'
18
- import { METADATA_LANGUAGE } from '../../metadata-language'
18
+ import { METADATA_LANGUAGE } from '../../metadata-language.token'
19
19
  import {
20
20
  AggregationResult,
21
21
  EsSearchParams,
@@ -26,9 +26,12 @@ import {
26
26
  SortParams,
27
27
  TermsAggregationResult,
28
28
  } from '../../../../../../../libs/api/metadata-converter/src'
29
- import { getLang3FromLang2 } from '../../../../../../../libs/util/i18n/src'
29
+ import { toLang3 } from '../../../../../../../libs/util/i18n/src'
30
30
  import { formatDate, isDateRange } from './date-range.utils'
31
- import { CatalogRecord } from '../../../../../../../libs/common/domain/src/lib/model/record'
31
+ import {
32
+ CatalogRecord,
33
+ LanguageCode,
34
+ } from '../../../../../../../libs/common/domain/src/lib/model/record'
32
35
  import { TranslateService } from '@ngx-translate/core'
33
36
  import { getGeometryBoundingBox } from '../../../../../../../libs/util/shared/src'
34
37
  import { getLength as getGeodesicLength } from 'ol/sphere'
@@ -45,11 +48,9 @@ export class ElasticsearchService {
45
48
  private runtimeFields: Record<string, string> = {}
46
49
 
47
50
  // we're using getters in case the defined languages change over time
48
- private get lang3() {
49
- return getLang3FromLang2(this.translateService.currentLang)
50
- }
51
- private get metadataLang() {
52
- return this.injector.get(METADATA_LANGUAGE, null)
51
+ private get metadataLang(): LanguageCode {
52
+ const mdLangValue = this.injector.get(METADATA_LANGUAGE, null)
53
+ return typeof mdLangValue === 'function' ? mdLangValue() : mdLangValue
53
54
  }
54
55
 
55
56
  constructor(
@@ -233,9 +234,12 @@ export class ElasticsearchService {
233
234
 
234
235
  private getQueryLang(): string {
235
236
  if (this.metadataLang) {
236
- return this.isCurrentSearchLang()
237
- ? `lang${this.lang3}`
238
- : `lang${this.metadataLang}`
237
+ const lang3 = toLang3(
238
+ this.isCurrentSearchLang()
239
+ ? this.translateService.currentLang
240
+ : this.metadataLang
241
+ )
242
+ return `lang${lang3}`
239
243
  } else return '*'
240
244
  }
241
245
  private isCurrentSearchLang() {
@@ -48,7 +48,7 @@ import {
48
48
  import { catchError, map, tap } from 'rxjs/operators'
49
49
  import { lt } from 'semver'
50
50
  import { ElasticsearchService } from './elasticsearch'
51
- import { getLang2FromLang3 } from '../../../../../../libs/util/i18n/src'
51
+ import { toLang2 } from '../../../../../../libs/util/i18n/src'
52
52
  import { Gn4SettingsService } from './settings/gn4-settings.service'
53
53
 
54
54
  const minPublicationApiVersion = '4.2.5'
@@ -562,7 +562,7 @@ export class Gn4Repository implements RecordsRepositoryInterface {
562
562
  .pipe(
563
563
  map((languages) =>
564
564
  languages
565
- .map((lang) => getLang2FromLang3(lang.id))
565
+ .map((lang) => toLang2(lang.id))
566
566
  .filter((code): code is string => !!code)
567
567
  )
568
568
  )
@@ -7,7 +7,7 @@ import {
7
7
  import { forkJoin, Observable, of } from 'rxjs'
8
8
  import { map, shareReplay } from 'rxjs/operators'
9
9
  import { TranslateService } from '@ngx-translate/core'
10
- import { getLang3FromLang2 } from '../../../../../../../libs/util/i18n/src'
10
+ import { toLang3 } from '../../../../../../../libs/util/i18n/src'
11
11
  import { FieldFilters } from '../../../../../../../libs/common/domain/src/lib/model/search'
12
12
  import {
13
13
  CatalogRecord,
@@ -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 getLang3FromLang2(this.translateService.currentLang)
55
+ return toLang3(this.translateService.currentLang)
56
56
  }
57
57
 
58
58
  constructor(
@@ -33,7 +33,7 @@ import {
33
33
  tap,
34
34
  withLatestFrom,
35
35
  } from 'rxjs/operators'
36
- import { getLocalizedIndexKey } from '../../../../../../../libs/util/i18n/src'
36
+ import { toLang3 } from '../../../../../../../libs/util/i18n/src'
37
37
  import { PlatformServiceInterface } from '../../../../../../../libs/common/domain/src/lib/platform.service.interface'
38
38
  import { coerce, satisfies, valid } from 'semver'
39
39
  import { TranslateService } from '@ngx-translate/core'
@@ -126,7 +126,7 @@ export class OrganizationsFromMetadataService
126
126
  ) {}
127
127
 
128
128
  private get langIndex() {
129
- return getLocalizedIndexKey(this.translateService.currentLang)
129
+ return `lang${toLang3(this.translateService.currentLang)}`
130
130
  }
131
131
 
132
132
  equalsNormalizedStrings(
@@ -45,7 +45,7 @@ import {
45
45
  throwError,
46
46
  } from 'rxjs'
47
47
  import { TranslateService } from '@ngx-translate/core'
48
- import { getLang3FromLang2 } from '../../../../../../../libs/util/i18n/src'
48
+ import { toLang3 } from '../../../../../../../libs/util/i18n/src'
49
49
 
50
50
  const minApiVersion = '4.2.2'
51
51
 
@@ -98,7 +98,7 @@ export class Gn4PlatformService implements PlatformServiceInterface {
98
98
  private keywordsByThesauri: Record<string, Observable<Keyword[]>> = {}
99
99
 
100
100
  private get lang3() {
101
- return getLang3FromLang2(this.translateService.currentLang)
101
+ return toLang3(this.translateService.currentLang)
102
102
  }
103
103
 
104
104
  constructor(
@@ -0,0 +1,8 @@
1
+ import { InjectionToken } from '@angular/core'
2
+ import { LanguageCode } from '../../../../../libs/common/domain/src/lib/model/record'
3
+
4
+ export type LanguageCodeFactory = () => LanguageCode
5
+
6
+ export const METADATA_LANGUAGE = new InjectionToken<
7
+ LanguageCode | LanguageCodeFactory
8
+ >('metadata-language')
@@ -108,6 +108,11 @@ export interface Keyword {
108
108
  translations?: KeywordTranslations
109
109
  }
110
110
 
111
+ export interface INSPIRE_theme {
112
+ value: string
113
+ label: string
114
+ }
115
+
111
116
  export interface BaseRecord {
112
117
  uniqueIdentifier: Uuid
113
118
  ownerOrganization: Organization
@@ -4,7 +4,7 @@ import { Observable } from 'rxjs'
4
4
  import { filter, map, shareReplay } from 'rxjs/operators'
5
5
  import { CatalogSource } from './sources.model'
6
6
  import { TranslateService } from '@ngx-translate/core'
7
- import { getLang3FromLang2 } from '../../../../../../libs/util/i18n/src'
7
+ import { toLang3 } from '../../../../../../libs/util/i18n/src'
8
8
 
9
9
  @Injectable({
10
10
  providedIn: 'root',
@@ -23,10 +23,7 @@ export class SourcesService {
23
23
  return this.sources$.pipe(
24
24
  map((sources) => sources.filter((source) => source.uuid === uuid)[0]),
25
25
  filter((source) => !!source),
26
- map(
27
- (source) =>
28
- source.label[getLang3FromLang2(this.translateService.currentLang)]
29
- )
26
+ map((source) => source.label[toLang3(this.translateService.currentLang)])
30
27
  )
31
28
  }
32
29
  }
@@ -0,0 +1,20 @@
1
+ <div class="flex flex-col gap-3">
2
+ <div class="flex flex-col gap-4">
3
+ <gn-ui-autocomplete
4
+ [placeholder]="'editor.record.form.inspire.placeholder' | translate"
5
+ [displayWithFn]="displayWithFn"
6
+ [action]="autoCompleteAction"
7
+ (itemSelected)="handleItemSelection($event)"
8
+ [minCharacterCount]="1"
9
+ [clearOnSelection]="true"
10
+ ></gn-ui-autocomplete>
11
+ <div class="flex gap-2 flex-wrap">
12
+ <gn-ui-badge
13
+ *ngFor="let theme of themes"
14
+ [removable]="true"
15
+ (badgeRemoveClicked)="removeTheme(theme)"
16
+ >{{ getTranslatedTheme(theme) }}
17
+ </gn-ui-badge>
18
+ </div>
19
+ </div>
20
+ </div>
@@ -0,0 +1,85 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core'
2
+ import { CommonModule } from '@angular/common'
3
+ import { AutocompleteComponent, BadgeComponent } from '../../../../../../../../../libs/ui/inputs/src'
4
+ import { NgIconComponent } from '@ng-icons/core'
5
+ import { INSPIRE_THEMES } from '../../../../fields.config'
6
+ import { TranslatePipe, TranslateService } from '@ngx-translate/core'
7
+ import { of } from 'rxjs'
8
+
9
+ type AutocompleteItem = { title: string; value: string }
10
+
11
+ @Component({
12
+ selector: 'gn-ui-form-field-inspire-theme',
13
+ standalone: true,
14
+ imports: [
15
+ CommonModule,
16
+ AutocompleteComponent,
17
+ NgIconComponent,
18
+ BadgeComponent,
19
+ TranslatePipe,
20
+ ],
21
+ templateUrl: './form-field-inspire-theme.component.html',
22
+ styleUrl: './form-field-inspire-theme.component.css',
23
+ })
24
+ export class FormFieldInspireThemeComponent {
25
+ themes = []
26
+ @Input() set value(themes: string[]) {
27
+ this.themes = themes
28
+ }
29
+ @Output() valueChange: EventEmitter<string[]> = new EventEmitter()
30
+ availableThemes = INSPIRE_THEMES
31
+
32
+ displayWithFn = (item: AutocompleteItem) => {
33
+ return item?.title ? `${item.title}` : ''
34
+ }
35
+
36
+ autoCompleteAction = (query: string) => {
37
+ return of(
38
+ this.availableThemes
39
+ .filter((theme) =>
40
+ theme.value.toLowerCase().includes(query.toLowerCase())
41
+ )
42
+ .sort((a, b) => {
43
+ const aStarts = a.value.startsWith(query)
44
+ const bStarts = b.value.startsWith(query)
45
+
46
+ if (aStarts && !bStarts) return -1
47
+ if (!aStarts && bStarts) return 1
48
+ return 0
49
+ })
50
+ .map((theme) => {
51
+ return {
52
+ title: this.translateService.instant(theme.label),
53
+ value: theme.value,
54
+ }
55
+ })
56
+ )
57
+ }
58
+
59
+ constructor(private translateService: TranslateService) {}
60
+
61
+ handleItemSelection(item: AutocompleteItem) {
62
+ this.addTheme(item.value)
63
+ }
64
+
65
+ addTheme(theme: string) {
66
+ const duplicatedTheme = this.themes.find((t) => t === theme)
67
+ if (!duplicatedTheme) {
68
+ this.themes = [...this.themes, theme]
69
+ this.valueChange.emit(this.themes)
70
+ }
71
+ }
72
+
73
+ removeTheme(theme: string) {
74
+ console.log(this.themes)
75
+ this.themes = this.themes.filter((t) => t !== theme)
76
+ this.valueChange.emit(this.themes)
77
+ }
78
+
79
+ getTranslatedTheme(theme: string) {
80
+ const themeKey = this.availableThemes.find(
81
+ (avail) => avail.value === theme
82
+ )?.label
83
+ return themeKey ? this.translateService.instant(themeKey) : ''
84
+ }
85
+ }
@@ -109,6 +109,12 @@
109
109
  (valueChange)="valueChange.emit($event)"
110
110
  ></gn-ui-form-field-keywords>
111
111
  </ng-container>
112
+ <ng-container *ngSwitchCase="'topics'">
113
+ <gn-ui-form-field-inspire-theme
114
+ [value]="valueAsInspireTheme"
115
+ (valueChange)="valueChange.emit($event)"
116
+ ></gn-ui-form-field-inspire-theme>
117
+ </ng-container>
112
118
  <ng-container *ngSwitchCase="'licenses'">
113
119
  <gn-ui-form-field-license
114
120
  [label]="config.labelKey! | translate"
@@ -45,6 +45,7 @@ import { FormFieldConstraintsShortcutsComponent } from './form-field-constraints
45
45
  import { FormFieldConstraintsComponent } from './form-field-constraints/form-field-constraints.component'
46
46
  import { TextFieldModule } from '@angular/cdk/text-field'
47
47
  import { FormFieldSpatialToggleComponent } from './form-field-spatial-toggle/form-field-spatial-toggle.component'
48
+ import { FormFieldInspireThemeComponent } from './form-field-inspire-field/form-field-inspire-theme.component'
48
49
 
49
50
  @Component({
50
51
  selector: 'gn-ui-form-field',
@@ -73,6 +74,7 @@ import { FormFieldSpatialToggleComponent } from './form-field-spatial-toggle/for
73
74
  FormFieldConstraintsComponent,
74
75
  FormFieldConstraintsShortcutsComponent,
75
76
  FormFieldSpatialToggleComponent,
77
+ FormFieldInspireThemeComponent,
76
78
  TextFieldModule,
77
79
  ],
78
80
  })
@@ -128,6 +130,9 @@ export class FormFieldComponent {
128
130
  get valueAsKeywords() {
129
131
  return this.value as Array<Keyword>
130
132
  }
133
+ get valueAsInspireTheme() {
134
+ return this.value as Array<string>
135
+ }
131
136
  get valueAsConstraints() {
132
137
  return this.value as Array<Constraint>
133
138
  }
@@ -10,3 +10,4 @@ export * from './form-field-array/form-field-array.component'
10
10
  export * from './form-field-spatial-extent/form-field-spatial-extent.component'
11
11
  export * from './form-field.component'
12
12
  export * from './form-field-constraints-shortcuts/constraints.utils'
13
+ export * from './form-field-inspire-field/form-field-inspire-theme.component'
@@ -4,7 +4,10 @@ import {
4
4
  EditorField,
5
5
  EditorSection,
6
6
  } from './models/editor-config.model'
7
- import { Keyword } from '../../../../../libs/common/domain/src/lib/model/record'
7
+ import {
8
+ INSPIRE_theme,
9
+ Keyword,
10
+ } from '../../../../../libs/common/domain/src/lib/model/record'
8
11
 
9
12
  /**
10
13
  * This file contains the configuration of the fields that will be displayed in the editor.
@@ -64,6 +67,11 @@ export const RECORD_KEYWORDS_FIELD: EditorField = {
64
67
  formFieldConfig: {},
65
68
  }
66
69
 
70
+ export const RECORD_TOPICS_FIELD: EditorField = {
71
+ model: 'topics',
72
+ formFieldConfig: {},
73
+ }
74
+
67
75
  export const RECORD_RESOURCE_CREATED_FIELD: EditorField = {
68
76
  model: 'resourceCreated',
69
77
  formFieldConfig: {
@@ -235,6 +243,13 @@ export const CLASSIFICATION_SECTION: EditorSection = {
235
243
  fields: [RECORD_KEYWORDS_FIELD],
236
244
  }
237
245
 
246
+ export const INSPIRE_SECTION: EditorSection = {
247
+ labelKey: marker('editor.record.form.section.inspire.label'),
248
+ descriptionKey: marker('editor.record.form.section.inspire.description'),
249
+ hidden: false,
250
+ fields: [RECORD_TOPICS_FIELD],
251
+ }
252
+
238
253
  export const USE_AND_ACCESS_CONDITIONS_SECTION: EditorSection = {
239
254
  labelKey: marker('editor.record.form.section.useAndAccessConditions.label'),
240
255
  hidden: false,
@@ -274,6 +289,7 @@ export const DEFAULT_CONFIGURATION: EditorConfig = {
274
289
  sections: [
275
290
  TITLE_SECTION,
276
291
  CLASSIFICATION_SECTION,
292
+ INSPIRE_SECTION,
277
293
  ABOUT_SECTION,
278
294
  GEOGRAPHICAL_COVERAGE_SECTION,
279
295
  ],
@@ -341,3 +357,71 @@ export const SPATIAL_SCOPES: Keyword[] = [
341
357
  type: 'theme',
342
358
  },
343
359
  ]
360
+
361
+ /************************************************************
362
+ *************** INSPIRE THEMES **************
363
+ ************************************************************
364
+ */
365
+
366
+ export const INSPIRE_THEMES: INSPIRE_theme[] = [
367
+ { value: 'biota', label: 'editor.record.form.inspire.biota' },
368
+ { value: 'boundaries', label: 'editor.record.form.inspire.boundaries' },
369
+ {
370
+ value: 'climatologyMeteorologyAtmosphere',
371
+ label: 'editor.record.form.inspire.climatology',
372
+ },
373
+ { value: 'economy', label: 'editor.record.form.inspire.economy' },
374
+ { value: 'elevation', label: 'editor.record.form.inspire.elevation' },
375
+ { value: 'environment', label: 'editor.record.form.inspire.environnement' },
376
+ { value: 'farming', label: 'editor.record.form.inspire.farming' },
377
+ {
378
+ value: 'geoscientific information',
379
+ label: 'editor.record.form.inspire.geoscientific',
380
+ },
381
+ { value: 'health', label: 'editor.record.form.inspire.health' },
382
+ {
383
+ value: 'imageryBaseMapsEarthCover',
384
+ label: 'editor.record.form.inspire.imagery',
385
+ },
386
+ {
387
+ value: 'intelligenceMilitary',
388
+ label: 'editor.record.form.inspire.intelligence',
389
+ },
390
+ { value: 'Location', label: 'editor.record.form.inspire.location' },
391
+ { value: 'Oceans', label: 'editor.record.form.inspire.oceans' },
392
+ {
393
+ value: 'planningCadastre',
394
+ label: 'editor.record.form.inspire.planning',
395
+ },
396
+ { value: 'Society', label: 'editor.record.form.inspire.society' },
397
+ { value: 'Structure', label: 'editor.record.form.inspire.structure' },
398
+ {
399
+ value: 'Transportation',
400
+ label: 'editor.record.form.inspire.transportation',
401
+ },
402
+ {
403
+ value: 'utilitiesCommunication',
404
+ label: 'editor.record.form.inspire.utilities',
405
+ },
406
+ { value: 'inlandWaters', label: 'editor.record.form.inspire.waters' },
407
+ ]
408
+
409
+ marker('editor.record.form.inspire.biota')
410
+ marker('editor.record.form.inspire.boundaries')
411
+ marker('editor.record.form.inspire.climatology')
412
+ marker('editor.record.form.inspire.economy')
413
+ marker('editor.record.form.inspire.elevation')
414
+ marker('editor.record.form.inspire.environnement')
415
+ marker('editor.record.form.inspire.farming')
416
+ marker('editor.record.form.inspire.geoscientific')
417
+ marker('editor.record.form.inspire.health')
418
+ marker('editor.record.form.inspire.imagery')
419
+ marker('editor.record.form.inspire.intelligence')
420
+ marker('editor.record.form.inspire.location')
421
+ marker('editor.record.form.inspire.oceans')
422
+ marker('editor.record.form.inspire.planning')
423
+ marker('editor.record.form.inspire.society')
424
+ marker('editor.record.form.inspire.structure')
425
+ marker('editor.record.form.inspire.transportation')
426
+ marker('editor.record.form.inspire.utilities')
427
+ marker('editor.record.form.inspire.waters')
@@ -14,7 +14,10 @@ export function flattenQueryParams(
14
14
  Array.isArray(flattened[key]) &&
15
15
  (flattened[key] as string[]).length > 0
16
16
  ) {
17
- flattened[key] = [(flattened[key] as string[]).join(',')]
17
+ const encoded = (flattened[key] as string[]).map((value) =>
18
+ typeof value === 'string' ? value.replace(/,/g, '%2C') : value
19
+ )
20
+ flattened[key] = [encoded.join(',')]
18
21
  } else if (isDateRange(flattened[key] as DateRange)) {
19
22
  const start = (flattened[key] as DateRange).start
20
23
  const end = (flattened[key] as DateRange).end
@@ -48,7 +51,7 @@ export function expandQueryParams(
48
51
  ...(end && { end: new Date(`${end}T00:00:00`) }),
49
52
  }
50
53
  } else {
51
- expanded[key] = value.split(',')
54
+ expanded[key] = value.split(',').map((v) => v.replace(/%2C/g, ','))
52
55
  }
53
56
  }
54
57
  }
@@ -63,7 +63,8 @@ export class RouterFacade {
63
63
  }
64
64
 
65
65
  goToOrganization(organizationName: string) {
66
- const path = `${this.routerService.getOrganizationPageRoute()}/${organizationName}`
66
+ const safeOrgName = organizationName.replace(/\//g, '')
67
+ const path = `${this.routerService.getOrganizationPageRoute()}/${safeOrgName}`
67
68
  this.go({
68
69
  path,
69
70
  queryParamsHandling: '',
@@ -6,16 +6,16 @@ import { matCheck, matWarningAmber } from '@ng-icons/material-icons/baseline'
6
6
 
7
7
  marker('record.metadata.quality.title.success')
8
8
  marker('record.metadata.quality.title.failed')
9
- marker('record.metadata.quality.description.success')
10
- marker('record.metadata.quality.description.failed')
11
- marker('record.metadata.quality.topic.success')
12
- marker('record.metadata.quality.topic.failed')
9
+ marker('record.metadata.quality.abstract.success')
10
+ marker('record.metadata.quality.abstract.failed')
11
+ marker('record.metadata.quality.topics.success')
12
+ marker('record.metadata.quality.topics.failed')
13
13
  marker('record.metadata.quality.keywords.success')
14
14
  marker('record.metadata.quality.keywords.failed')
15
15
  marker('record.metadata.quality.legalConstraints.success')
16
16
  marker('record.metadata.quality.legalConstraints.failed')
17
- marker('record.metadata.quality.contact.success')
18
- marker('record.metadata.quality.contact.failed')
17
+ marker('record.metadata.quality.contacts.success')
18
+ marker('record.metadata.quality.contacts.failed')
19
19
  marker('record.metadata.quality.updateFrequency.success')
20
20
  marker('record.metadata.quality.updateFrequency.failed')
21
21
  marker('record.metadata.quality.organisation.success')