geonetwork-ui 2.7.0-dev.8ac6cd7aa → 2.7.0-dev.9895bd35c

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 (178) 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/utils/status.mapper.mjs +4 -1
  8. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +8 -4
  9. package/esm2022/libs/api/repository/src/index.mjs +2 -2
  10. package/esm2022/libs/api/repository/src/lib/gn4/auth/auth.service.mjs +5 -5
  11. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/constant.mjs +4 -6
  12. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +55 -12
  13. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +3 -3
  14. package/esm2022/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.mjs +3 -3
  15. package/esm2022/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.mjs +3 -3
  16. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +20 -6
  17. package/esm2022/libs/api/repository/src/lib/metadata-language.token.mjs +3 -0
  18. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +15 -1
  19. package/esm2022/libs/feature/catalog/src/lib/sources/sources.service.mjs +3 -3
  20. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +2 -2
  21. package/esm2022/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.mjs +2 -2
  22. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.mjs +79 -0
  23. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +8 -3
  24. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/index.mjs +2 -1
  25. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +77 -1
  26. package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +3 -5
  27. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +4 -2
  28. package/esm2022/libs/feature/router/src/lib/default/state/router.facade.mjs +3 -2
  29. package/esm2022/libs/feature/search/src/lib/state/reducer.mjs +5 -2
  30. package/esm2022/libs/ui/elements/src/lib/api-card/api-card.component.mjs +3 -3
  31. package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +5 -4
  32. package/esm2022/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.mjs +5 -4
  33. package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +1 -4
  34. package/esm2022/libs/ui/elements/src/lib/metadata-quality-item/metadata-quality-item.component.mjs +7 -7
  35. package/esm2022/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.mjs +5 -4
  36. package/esm2022/libs/util/app-config/src/lib/app-config.mjs +3 -1
  37. package/esm2022/libs/util/app-config/src/lib/fixtures.mjs +2 -2
  38. package/esm2022/libs/util/app-config/src/lib/model.mjs +1 -1
  39. package/esm2022/libs/util/app-config/src/lib/parse-utils.mjs +5 -4
  40. package/esm2022/libs/util/i18n/src/lib/language-codes.mjs +50 -9
  41. package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +4 -2
  42. package/esm2022/libs/util/shared/src/lib/record/quality-score.util.mjs +9 -8
  43. package/esm2022/libs/util/shared/src/lib/utils/geojson.mjs +58 -1
  44. package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
  45. package/esm2022/libs/util/shared/src/lib/utils/mobile-screen.mjs +9 -0
  46. package/esm2022/translations/de.json +41 -7
  47. package/esm2022/translations/en.json +40 -6
  48. package/esm2022/translations/es.json +40 -6
  49. package/esm2022/translations/fr.json +41 -7
  50. package/esm2022/translations/it.json +40 -6
  51. package/esm2022/translations/nl.json +40 -6
  52. package/esm2022/translations/pt.json +40 -6
  53. package/esm2022/translations/sk.json +40 -6
  54. package/fesm2022/geonetwork-ui.mjs +3005 -2836
  55. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  56. package/libs/api/metadata-converter/src/lib/dcat-ap/read-parts.d.ts.map +1 -1
  57. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts +1 -1
  58. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  59. package/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.d.ts.map +1 -1
  60. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  61. package/libs/api/repository/src/index.d.ts +1 -1
  62. package/libs/api/repository/src/index.d.ts.map +1 -1
  63. package/libs/api/repository/src/lib/gn4/elasticsearch/constant.d.ts.map +1 -1
  64. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts +1 -2
  65. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
  66. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +2 -0
  67. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  68. package/libs/api/repository/src/lib/metadata-language.token.d.ts +5 -0
  69. package/libs/api/repository/src/lib/metadata-language.token.d.ts.map +1 -0
  70. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +4 -0
  71. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  72. package/libs/feature/catalog/src/lib/sources/sources.service.d.ts.map +1 -1
  73. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  74. package/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.d.ts.map +1 -1
  75. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.d.ts +28 -0
  76. 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
  77. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +1 -0
  78. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  79. package/libs/feature/editor/src/lib/components/record-form/form-field/index.d.ts +1 -0
  80. package/libs/feature/editor/src/lib/components/record-form/form-field/index.d.ts.map +1 -1
  81. package/libs/feature/editor/src/lib/fields.config.d.ts +8 -1
  82. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  83. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts +2 -2
  84. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
  85. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  86. package/libs/feature/router/src/lib/default/state/router.facade.d.ts.map +1 -1
  87. package/libs/feature/search/src/lib/state/reducer.d.ts.map +1 -1
  88. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -0
  89. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts.map +1 -1
  90. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts +1 -0
  91. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts.map +1 -1
  92. package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts +0 -1
  93. package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts.map +1 -1
  94. package/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.d.ts +1 -0
  95. package/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.d.ts.map +1 -1
  96. package/libs/util/app-config/src/lib/app-config.d.ts.map +1 -1
  97. package/libs/util/app-config/src/lib/model.d.ts +1 -0
  98. package/libs/util/app-config/src/lib/model.d.ts.map +1 -1
  99. package/libs/util/app-config/src/lib/parse-utils.d.ts.map +1 -1
  100. package/libs/util/i18n/src/lib/language-codes.d.ts +91 -31
  101. package/libs/util/i18n/src/lib/language-codes.d.ts.map +1 -1
  102. package/libs/util/shared/src/lib/links/link-utils.d.ts +1 -1
  103. package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
  104. package/libs/util/shared/src/lib/record/quality-score.util.d.ts.map +1 -1
  105. package/libs/util/shared/src/lib/utils/geojson.d.ts +7 -2
  106. package/libs/util/shared/src/lib/utils/geojson.d.ts.map +1 -1
  107. package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
  108. package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
  109. package/libs/util/shared/src/lib/utils/mobile-screen.d.ts +2 -0
  110. package/libs/util/shared/src/lib/utils/mobile-screen.d.ts.map +1 -0
  111. package/package.json +11 -10
  112. package/src/libs/api/metadata-converter/src/lib/dcat-ap/read-parts.ts +3 -6
  113. package/src/libs/api/metadata-converter/src/lib/dcat-ap/utils/status.mapper.ts +3 -0
  114. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +47 -22
  115. package/src/libs/api/metadata-converter/src/lib/gn4/metadata-url.service.ts +2 -2
  116. package/src/libs/api/metadata-converter/src/lib/iso19115-3/read-parts.ts +2 -2
  117. package/src/libs/api/metadata-converter/src/lib/iso19115-3/write-parts.ts +2 -2
  118. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +3 -3
  119. package/src/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.ts +3 -0
  120. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +7 -3
  121. package/src/libs/api/repository/src/index.ts +1 -1
  122. package/src/libs/api/repository/src/lib/gn4/auth/auth.service.ts +4 -4
  123. package/src/libs/api/repository/src/lib/gn4/elasticsearch/constant.ts +3 -5
  124. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +65 -14
  125. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +2 -2
  126. package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-groups.service.ts +2 -2
  127. package/src/libs/api/repository/src/lib/gn4/organizations/organizations-from-metadata.service.ts +2 -2
  128. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +21 -8
  129. package/src/libs/api/repository/src/lib/metadata-language.token.ts +8 -0
  130. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +20 -0
  131. package/src/libs/feature/catalog/src/lib/sources/sources.service.ts +2 -5
  132. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +3 -1
  133. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.ts +1 -4
  134. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.css +0 -0
  135. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.html +20 -0
  136. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-inspire-field/form-field-inspire-theme.component.ts +85 -0
  137. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +6 -0
  138. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +5 -0
  139. package/src/libs/feature/editor/src/lib/components/record-form/form-field/index.ts +1 -0
  140. package/src/libs/feature/editor/src/lib/fields.config.ts +85 -1
  141. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +8 -8
  142. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +3 -1
  143. package/src/libs/feature/router/src/lib/default/state/router.facade.ts +2 -1
  144. package/src/libs/feature/search/src/lib/state/reducer.ts +4 -1
  145. package/src/libs/ui/elements/src/lib/api-card/api-card.component.html +4 -1
  146. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.html +12 -11
  147. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.ts +7 -1
  148. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.html +4 -1
  149. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.ts +7 -1
  150. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +0 -4
  151. package/src/libs/ui/elements/src/lib/metadata-quality-item/metadata-quality-item.component.ts +6 -6
  152. package/src/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.html +7 -1
  153. package/src/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.ts +3 -1
  154. package/src/libs/util/app-config/src/lib/app-config.ts +2 -0
  155. package/src/libs/util/app-config/src/lib/fixtures.ts +1 -1
  156. package/src/libs/util/app-config/src/lib/model.ts +1 -0
  157. package/src/libs/util/app-config/src/lib/parse-utils.ts +4 -7
  158. package/src/libs/util/i18n/src/lib/language-codes.ts +62 -11
  159. package/src/libs/util/shared/src/lib/links/link-utils.ts +2 -1
  160. package/src/libs/util/shared/src/lib/record/quality-score.util.ts +13 -10
  161. package/src/libs/util/shared/src/lib/utils/geojson.ts +72 -2
  162. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  163. package/src/libs/util/shared/src/lib/utils/mobile-screen.ts +14 -0
  164. package/translations/de.json +41 -7
  165. package/translations/en.json +40 -6
  166. package/translations/es.json +40 -6
  167. package/translations/fr.json +41 -7
  168. package/translations/it.json +40 -6
  169. package/translations/nl.json +40 -6
  170. package/translations/pt.json +40 -6
  171. package/translations/sk.json +40 -6
  172. package/esm2022/libs/api/repository/src/lib/metadata-language.mjs +0 -3
  173. package/esm2022/libs/util/app-config/src/lib/constants.mjs +0 -439
  174. package/libs/api/repository/src/lib/metadata-language.d.ts +0 -3
  175. package/libs/api/repository/src/lib/metadata-language.d.ts.map +0 -1
  176. package/libs/util/app-config/src/lib/constants.d.ts +0 -2
  177. package/libs/util/app-config/src/lib/constants.d.ts.map +0 -1
  178. package/src/libs/api/repository/src/lib/metadata-language.ts +0 -3
@@ -1,25 +1,25 @@
1
1
  import { Injectable } from '@angular/core'
2
- import { extend, Extent } from 'ol/extent'
3
- import GeoJSON from 'ol/format/GeoJSON'
2
+ import { extend } from 'ol/extent'
4
3
  import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
5
-
6
- const GEOJSON = new GeoJSON()
4
+ import { BoundingBox, getGeometryBoundingBox } from '../../../../../../libs/util/shared/src'
7
5
 
8
6
  @Injectable({
9
7
  providedIn: 'root',
10
8
  })
11
9
  export class MapUtilsService {
12
- getRecordExtent(record: Partial<CatalogRecord>): Extent {
10
+ getRecordExtent(record: Partial<CatalogRecord>): BoundingBox {
13
11
  if (!('spatialExtents' in record) || record.spatialExtents.length === 0) {
14
12
  return null
15
13
  }
16
14
  // extend all the spatial extents into an including bbox
17
15
  return record.spatialExtents.reduce(
18
16
  (prev, curr) => {
19
- if ('bbox' in curr) return extend(prev, curr.bbox)
17
+ if ('bbox' in curr) return extend(prev, curr.bbox) as BoundingBox
20
18
  else if ('geometry' in curr) {
21
- const geom = GEOJSON.readGeometry(curr.geometry)
22
- return extend(prev, geom.getExtent())
19
+ return extend(
20
+ prev,
21
+ getGeometryBoundingBox(curr.geometry)
22
+ ) as BoundingBox
23
23
  }
24
24
  return prev
25
25
  },
@@ -389,7 +389,9 @@ export class MapViewComponent implements AfterViewInit {
389
389
  ) {
390
390
  // FIXME: here we're assuming that the TMS serves vector tiles only; should be checked with ogc-client first
391
391
  return of({
392
- url: link.url.toString().replace(/\/?$/, '/{z}/{x}/{y}.pbf'),
392
+ url: link.url
393
+ .toString()
394
+ .replace(/\/?$/, `/${link.name}/{z}/{x}/{y}.pbf`),
393
395
  type: 'xyz',
394
396
  tileFormat: 'application/vnd.mapbox-vector-tile',
395
397
  name: link.name,
@@ -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('/', '')
67
+ const path = `${this.routerService.getOrganizationPageRoute()}/${safeOrgName}`
67
68
  this.go({
68
69
  path,
69
70
  queryParamsHandling: '',
@@ -8,6 +8,7 @@ import {
8
8
  SortByField,
9
9
  } from '../../../../../../libs/common/domain/src/lib/model/search'
10
10
  import { DEFAULT_PAGE_SIZE, FIELDS_SUMMARY } from '../constants'
11
+ import { getOptionalSearchConfig } from '../../../../../../libs/util/app-config/src'
11
12
  import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
12
13
 
13
14
  export const SEARCH_FEATURE_KEY = 'searchState'
@@ -55,7 +56,9 @@ export const initSearch = (): SearchStateSearch => {
55
56
  },
56
57
  params: {
57
58
  filters: {},
58
- pageSize: DEFAULT_PAGE_SIZE,
59
+ pageSize: getOptionalSearchConfig()?.LIMIT
60
+ ? getOptionalSearchConfig().LIMIT
61
+ : DEFAULT_PAGE_SIZE,
59
62
  currentPage: 0,
60
63
  favoritesOnly: false,
61
64
  useSpatialFilter: true,
@@ -67,7 +67,10 @@
67
67
  [ngClass]="{
68
68
  '!bg-primary': currentlyActive,
69
69
  }"
70
- >{{ link.accessServiceProtocol }}</span
70
+ translate
71
+ >record.metadata.api.accessServiceProtocol.{{
72
+ link.accessServiceProtocol
73
+ }}</span
71
74
  >
72
75
  <span
73
76
  *ngIf="link.accessServiceProtocol === 'GPFDL'"
@@ -13,8 +13,7 @@
13
13
  <span class="px-3">({{ linksCount }})</span>
14
14
  </div>
15
15
  <gn-ui-previous-next-buttons
16
- class="md:block hidden"
17
- *ngIf="_list?.pagesCount > 1"
16
+ *ngIf="(isMobile$ | async) === false && _list?.pagesCount > 1"
18
17
  [listComponent]="_list"
19
18
  ></gn-ui-previous-next-buttons>
20
19
  </div>
@@ -40,7 +39,7 @@
40
39
 
41
40
  <ng-container>
42
41
  <gn-ui-block-list
43
- class="md:block hidden"
42
+ *ngIf="(isMobile$ | async) === false"
44
43
  #blockList
45
44
  (listChanges)="updateList($event)"
46
45
  containerClass="gap-4 pt-5 pb-7"
@@ -57,12 +56,14 @@
57
56
  </gn-ui-block-list>
58
57
  </ng-container>
59
58
 
60
- <div class="mb-5 md:hidden block" *ngFor="let link of filteredLinks">
61
- <gn-ui-download-item
62
- size="M"
63
- [link]="link"
64
- [color]="getLinkColor(link)"
65
- [format]="getLinkFormat(link)"
66
- [isFromApi]="isFromApi(link)"
67
- ></gn-ui-download-item>
59
+ <div class="mb-5" *ngFor="let link of filteredLinks">
60
+ <ng-container *ngIf="(isMobile$ | async) === true">
61
+ <gn-ui-download-item
62
+ size="M"
63
+ [link]="link"
64
+ [color]="getLinkColor(link)"
65
+ [format]="getLinkFormat(link)"
66
+ [isFromApi]="isFromApi(link)"
67
+ ></gn-ui-download-item>
68
+ </ng-container>
68
69
  </div>
@@ -6,7 +6,11 @@ import {
6
6
  } from '@angular/core'
7
7
  import { TranslateDirective, TranslateService } from '@ngx-translate/core'
8
8
  import { marker } from '@biesbjerg/ngx-translate-extract-marker'
9
- import { getBadgeColor, getFileFormat } from '../../../../../../libs/util/shared/src'
9
+ import {
10
+ getBadgeColor,
11
+ getFileFormat,
12
+ getIsMobile,
13
+ } from '../../../../../../libs/util/shared/src'
10
14
  import { DatasetDownloadDistribution } from '../../../../../../libs/common/domain/src/lib/model/record'
11
15
  import { CommonModule } from '@angular/common'
12
16
  import { ButtonComponent } from '../../../../../../libs/ui/inputs/src'
@@ -50,6 +54,8 @@ export class DownloadsListComponent {
50
54
  return this.filteredLinks?.length || 0
51
55
  }
52
56
 
57
+ isMobile$ = getIsMobile()
58
+
53
59
  activeFilterFormats: FilterFormat[] = ['all']
54
60
 
55
61
  updateList($event: BlockListComponent) {
@@ -7,7 +7,10 @@
7
7
  class="shrink-0 text-[0.75em]"
8
8
  name="matLocationSearchingOutline"
9
9
  ></ng-icon>
10
- <span class="ml-1 hidden sm:inline-block shrink-0" *ngIf="showLabel" translate
10
+ <span
11
+ class="ml-1 inline-block shrink-0"
12
+ *ngIf="(isMobile$ | async) === false && showLabel"
13
+ translate
11
14
  >record.metadata.isGeographical</span
12
15
  >
13
16
  </div>
@@ -4,7 +4,11 @@ import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/mode
4
4
  import { CommonModule } from '@angular/common'
5
5
  import { TranslateDirective, TranslatePipe } from '@ngx-translate/core'
6
6
  import { NgIcon, provideIcons } from '@ng-icons/core'
7
- import { LinkClassifierService, LinkUsage } from '../../../../../../libs/util/shared/src'
7
+ import {
8
+ getIsMobile,
9
+ LinkClassifierService,
10
+ LinkUsage,
11
+ } from '../../../../../../libs/util/shared/src'
8
12
 
9
13
  @Component({
10
14
  selector: 'gn-ui-geo-data-badge',
@@ -24,6 +28,8 @@ export class GeoDataBadgeComponent {
24
28
  @Input() styling = 'default'
25
29
  @Input() record: CatalogRecord
26
30
 
31
+ isMobile$ = getIsMobile()
32
+
27
33
  isGeodata() {
28
34
  const links =
29
35
  'onlineResources' in this.record ? this.record.onlineResources : []
@@ -74,10 +74,6 @@ export class MetadataQualityComponent implements OnChanges {
74
74
  )
75
75
  }
76
76
 
77
- hasGetCapabilities(url: string): boolean {
78
- return url.toLowerCase().includes('capabilities')
79
- }
80
-
81
77
  initialize() {
82
78
  if (!this.propsToValidate) {
83
79
  this.propsToValidate = getAllKeysValidator()
@@ -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')
@@ -1,5 +1,8 @@
1
1
  <div
2
2
  class="flex items-center justify-between p-3 mt-8 bg-white rounded-lg border-b solid border-gray-300"
3
+ *ngIf="
4
+ (isMobile$ | async) === false || featureCatalog?.featureTypes?.length > 1
5
+ "
3
6
  >
4
7
  <div
5
8
  class="relative shrink-0"
@@ -17,7 +20,10 @@
17
20
  name="iconoirSearch"
18
21
  ></ng-icon>
19
22
  </div>
20
- <div class="text-sm px-1 ml-auto hidden sm:inline">
23
+ <div
24
+ *ngIf="(isMobile$ | async) === false"
25
+ class="text-sm px-1 ml-auto inline"
26
+ >
21
27
  <ng-container *ngIf="featureCatalog?.featureTypes?.length > 1">
22
28
  <span
23
29
  class="text-sm font-medium text-gray-900"
@@ -6,7 +6,7 @@ import { DatasetFeatureCatalog } from '../../../../../../libs/common/domain/src/
6
6
  import { FormsModule } from '@angular/forms'
7
7
  import { of } from 'rxjs'
8
8
  import { debounceTime, distinctUntilChanged, tap } from 'rxjs/operators'
9
- import { createFuzzyFilter } from '../../../../../../libs/util/shared/src'
9
+ import { createFuzzyFilter, getIsMobile } from '../../../../../../libs/util/shared/src'
10
10
  import { iconoirSearch } from '@ng-icons/iconoir'
11
11
 
12
12
  @Component({
@@ -39,6 +39,8 @@ export class SearchFeatureCatalogComponent {
39
39
  return this._featureCatalog
40
40
  }
41
41
 
42
+ isMobile$ = getIsMobile()
43
+
42
44
  @Output() filteredFeatureCatalogChange =
43
45
  new EventEmitter<DatasetFeatureCatalog>()
44
46
  filteredFeatureCatalog: DatasetFeatureCatalog
@@ -231,6 +231,7 @@ export function loadAppConfig() {
231
231
  'filter_geometry_url',
232
232
  'search_preset',
233
233
  'advanced_filters',
234
+ 'limit',
234
235
  ],
235
236
  warnings,
236
237
  errors
@@ -257,6 +258,7 @@ export function loadAppConfig() {
257
258
  filters: param.filters,
258
259
  })),
259
260
  ADVANCED_FILTERS: parsedSearchSection.advanced_filters,
261
+ LIMIT: parsedSearchSection.limit,
260
262
  } as SearchConfig)
261
263
 
262
264
  const parsedMetadataQualitySection = parseConfigSection(
@@ -124,7 +124,7 @@ export const wrongLanguageCodeConfigFixture = () => `
124
124
  [global]
125
125
  geonetwork4_api_url = "/geonetwork/srv/api"
126
126
  proxy_path = "/proxy/?url="
127
- metadata_language = "fra"
127
+ metadata_language = "abc"
128
128
 
129
129
  [map]
130
130
 
@@ -60,6 +60,7 @@ export interface SearchConfig {
60
60
  FILTER_GEOMETRY_DATA?: string
61
61
  SEARCH_PRESET?: SearchPreset[]
62
62
  ADVANCED_FILTERS?: []
63
+ LIMIT?: number
63
64
  }
64
65
 
65
66
  export interface MetadataQualityConfig {
@@ -1,4 +1,4 @@
1
- import { LANGUAGE_CODES_ISO_3 } from './constants'
1
+ import { toLang2 } from '../../../../../libs/util/i18n/src'
2
2
 
3
3
  const flatten = (
4
4
  base: string,
@@ -129,13 +129,10 @@ export function checkMetadataLanguage(
129
129
  parsedConfigSection: any,
130
130
  outWarnings: string[]
131
131
  ) {
132
- if (
133
- LANGUAGE_CODES_ISO_3.indexOf(
134
- parsedConfigSection.metadata_language.toLowerCase()
135
- ) === -1
136
- ) {
132
+ const lang2 = toLang2(parsedConfigSection.metadata_language.toLowerCase())
133
+ if (lang2?.length !== 2) {
137
134
  outWarnings.push(
138
- `In the [global] section: metadata_language = "${parsedConfigSection.metadata_language}" is not in ISO 639-2/B format`
135
+ `In the [global] section: metadata_language = "${parsedConfigSection.metadata_language}" is not a recognized ISO 639 language code`
139
136
  )
140
137
  }
141
138
  return parsedConfigSection
@@ -1,20 +1,32 @@
1
1
  import { marker } from '@biesbjerg/ngx-translate-extract-marker'
2
2
 
3
+ /**
4
+ * Taken from https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
5
+ * Note: some languages have multiple 3-char codes, like 'fre' and 'fra'; in that case, the one to be used
6
+ * in priority is the one defined last
7
+ */
3
8
  const LANG_3_TO_2_MAPPER = {
4
9
  eng: 'en',
10
+ nld: 'nl', // duplicate for "dut"
5
11
  dut: 'nl',
12
+ fra: 'fr', // duplicate for "fre"
6
13
  fre: 'fr',
14
+ deu: 'de', // duplicate for "ger"
7
15
  ger: 'de',
8
16
  kor: 'ko',
9
17
  spa: 'es',
18
+ ces: 'cs', // duplicate for "cze"
10
19
  cze: 'cs',
11
20
  cat: 'ca',
12
21
  fin: 'fi',
22
+ isl: 'is', // duplicate for "ice"
13
23
  ice: 'is',
14
24
  ita: 'it',
15
25
  por: 'pt',
16
26
  rus: 'ru',
27
+ zho: 'zh', // duplicate for "chi"
17
28
  chi: 'zh',
29
+ slk: 'sk', // duplicate for "slo"
18
30
  slo: 'sk',
19
31
  roh: 'rm',
20
32
  ara: 'ar',
@@ -25,10 +37,12 @@ const LANG_3_TO_2_MAPPER = {
25
37
  tur: 'tr',
26
38
  arm: 'hy',
27
39
  aze: 'az',
40
+ kat: 'ka', // duplicate for "geo"
28
41
  geo: 'ka',
29
42
  ukr: 'uk',
43
+ cym: 'cy', // duplicate for "wel"
30
44
  wel: 'cy',
31
- }
45
+ } as const
32
46
 
33
47
  export const LANGUAGE_NAMES = {
34
48
  en: 'English',
@@ -58,26 +72,63 @@ export const LANGUAGE_NAMES = {
58
72
  ka: 'ქართული',
59
73
  uk: 'українська',
60
74
  wel: 'Cymraeg',
61
- }
75
+ } as const
76
+
77
+ export type LanguageCode3 = keyof typeof LANG_3_TO_2_MAPPER
78
+ export type LanguageCode2 = (typeof LANG_3_TO_2_MAPPER)[LanguageCode3]
62
79
 
63
80
  export const LANG_2_TO_3_MAPPER = Object.entries(LANG_3_TO_2_MAPPER).reduce(
64
81
  (mapperObject, langEntry) => {
65
82
  return { ...mapperObject, [langEntry[1]]: langEntry[0] }
66
83
  },
67
84
  {}
68
- )
85
+ ) as Record<LanguageCode2, LanguageCode3>
69
86
 
70
- export function getLang3FromLang2(lang2: string): string {
71
- return LANG_2_TO_3_MAPPER[lang2] ?? lang2
72
- }
87
+ /**
88
+ * This can be:
89
+ * - an ISO 639-2 language code in 3 characters (e.g. 'eng', 'fre', 'ger')
90
+ * - an ISO 639-1 language code in 2 characters (e.g. 'en', 'fr', 'de')
91
+ * - a 2-character language code with locale (e.g. 'fr_FR', 'fr_CA')
92
+ */
93
+ export type LanguageCodeLike = LanguageCode2 | LanguageCode3 | string
73
94
 
74
- export function getLang2FromLang3(lang3: string): string {
75
- return LANG_3_TO_2_MAPPER[lang3] ?? lang3
95
+ /**
96
+ * Converts a language code in any format to the ISO 639-2 format (3 characters)
97
+ * Returns the given string if the corresponding language code could not be recognized
98
+ */
99
+ export function toLang3(lang: LanguageCodeLike): LanguageCode3 | string {
100
+ if (!lang) {
101
+ // also handle falsy values just in case
102
+ return lang
103
+ }
104
+ if (lang.length === 3) {
105
+ return LANG_2_TO_3_MAPPER[LANG_3_TO_2_MAPPER[lang.toLowerCase()]] ?? lang
106
+ }
107
+ const lang2 = lang.toLowerCase().substring(0, 2)
108
+ return LANG_2_TO_3_MAPPER[lang2] ?? lang
76
109
  }
77
110
 
78
- export function getLocalizedIndexKey(lang2: string): string {
79
- const lang3 = getLang3FromLang2(lang2)
80
- return lang3 ? `lang${lang3}` : null
111
+ /**
112
+ * Converts a language code in any format to the ISO 639-1 format (2 characters)
113
+ * Returns the given string if the corresponding language code could not be recognized
114
+ */
115
+ export function toLang2(lang: LanguageCodeLike): LanguageCode2 | string {
116
+ if (!lang) {
117
+ // also handle falsy values just in case
118
+ return lang
119
+ }
120
+ if (lang.length === 3) {
121
+ return LANG_3_TO_2_MAPPER[lang.toLowerCase()] ?? lang
122
+ }
123
+ const lang2 = lang.toLowerCase().substring(0, 2)
124
+ if (lang2 in LANG_2_TO_3_MAPPER) {
125
+ return lang2
126
+ }
127
+ if (lang.match(/[a-z]{2}_[A-Z]{2}/)) {
128
+ // remove locale code even if the language code is not known
129
+ return lang2
130
+ }
131
+ return lang
81
132
  }
82
133
 
83
134
  marker('language.en')
@@ -23,8 +23,8 @@ export const FORMATS = {
23
23
  excel: {
24
24
  extensions: [
25
25
  'excel',
26
- 'xls',
27
26
  'xlsx',
27
+ 'xls',
28
28
  'ms-excel',
29
29
  'openxmlformats-officedocument',
30
30
  ],
@@ -190,6 +190,7 @@ export function isFormatInQueryParam(
190
190
  alias: string
191
191
  ): boolean {
192
192
  const queryParams = link.url.searchParams
193
+ if (!queryParams) return false
193
194
  for (const [key, value] of queryParams.entries()) {
194
195
  if (key === 'format' || key === 'f') {
195
196
  return value === alias
@@ -11,15 +11,18 @@ const ValidatorMapper: TValidatorMapper = {
11
11
  title: (record) => !!record?.title,
12
12
  abstract: (record) => !!record?.abstract,
13
13
  keywords: (record) => (record?.keywords?.length ?? 0) > 0,
14
- legalConstraints: (record) => (record?.legalConstraints?.length ?? 0) > 0,
15
- contacts: (record) => !!record?.contacts?.[0]?.email,
16
- updateFrequency: (record) => !!record?.updateFrequency,
14
+ legalConstraints: (record) =>
15
+ !!(
16
+ record?.legalConstraints?.length &&
17
+ record.legalConstraints.some((c) => c?.text?.trim().length > 0)
18
+ ),
19
+ contacts: (record) =>
20
+ !!record?.contacts?.[0]?.email &&
21
+ record.contacts[0].email !== 'missing@missing.com',
22
+ updateFrequency: (record) =>
23
+ !!record?.updateFrequency && record.updateFrequency !== 'unknown',
17
24
  topics: (record) => (record?.topics?.length ?? 0) > 0,
18
25
  organisation: (record) => !!record?.contacts?.[0]?.organization?.name,
19
- capabilities: (record) =>
20
- record?.onlineResources?.some((resource) =>
21
- resource?.url?.href.toLowerCase().includes('capabilities')
22
- ),
23
26
  source: (record) => !!record?.extras?.sourcesIdentifiers,
24
27
  } as const
25
28
 
@@ -40,12 +43,12 @@ function getMappersFromKind(kind: RecordKind) {
40
43
  ]
41
44
 
42
45
  switch (kind) {
43
- case 'service':
44
- kindKeys = ['capabilities']
45
- break
46
46
  case 'reuse':
47
47
  kindKeys = ['topics', 'organisation', 'source']
48
48
  break
49
+ case 'service':
50
+ kindKeys = []
51
+ break
49
52
  case 'dataset':
50
53
  default:
51
54
  kindKeys = ['updateFrequency', 'topics', 'organisation']
@@ -1,8 +1,11 @@
1
- import { Feature, FeatureCollection, Geometry } from 'geojson'
1
+ import type { Feature, FeatureCollection, Geometry, Position } from 'geojson'
2
2
 
3
+ /**
4
+ * @returns The geometry if available, otherwise null.
5
+ */
3
6
  export function getGeometryFromGeoJSON(
4
7
  data: FeatureCollection | Feature | Geometry
5
- ): Geometry {
8
+ ): Geometry | null {
6
9
  if (data.type === 'FeatureCollection') {
7
10
  return data?.features?.[0]?.geometry || null
8
11
  }
@@ -24,3 +27,70 @@ export function getGeometryFromGeoJSON(
24
27
  }
25
28
  return null
26
29
  }
30
+
31
+ // FIXME: this type should be more generic across the project
32
+ export type BoundingBox = [number, number, number, number]
33
+
34
+ export function getGeometryBoundingBox(geometry: Geometry): BoundingBox {
35
+ // use the bounding box if specified in the GeoJSON object
36
+ if (geometry.bbox) {
37
+ return geometry.bbox.length > 4
38
+ ? [geometry.bbox[0], geometry.bbox[1], geometry.bbox[3], geometry.bbox[4]]
39
+ : (geometry.bbox as BoundingBox)
40
+ }
41
+
42
+ const coordinatesReducer = (prev: BoundingBox, coords: Position) =>
43
+ [
44
+ Math.min(prev[0], coords[0]),
45
+ Math.min(prev[1], coords[1]),
46
+ Math.max(prev[2], coords[0]),
47
+ Math.max(prev[3], coords[1]),
48
+ ] as BoundingBox
49
+ const coordinatesArrayReducer = (
50
+ prev: BoundingBox,
51
+ coordsArray: Position[]
52
+ ) => {
53
+ const bbox = coordsArray.reduce(coordinatesReducer, emptyExtent)
54
+ return [
55
+ Math.min(prev[0], bbox[0]),
56
+ Math.min(prev[1], bbox[1]),
57
+ Math.max(prev[2], bbox[2]),
58
+ Math.max(prev[3], bbox[3]),
59
+ ] as BoundingBox
60
+ }
61
+ const emptyExtent = [Infinity, Infinity, -Infinity, -Infinity] as BoundingBox
62
+
63
+ switch (geometry.type) {
64
+ case 'MultiPolygon':
65
+ return geometry.coordinates.reduce((prev, polygonCoords) => {
66
+ const bbox = polygonCoords.reduce(coordinatesArrayReducer, emptyExtent)
67
+ return [
68
+ Math.min(prev[0], bbox[0]),
69
+ Math.min(prev[1], bbox[1]),
70
+ Math.max(prev[2], bbox[2]),
71
+ Math.max(prev[3], bbox[3]),
72
+ ] as BoundingBox
73
+ }, emptyExtent)
74
+ case 'GeometryCollection':
75
+ return geometry.geometries.reduce((prev, geom) => {
76
+ const bbox = getGeometryBoundingBox(geom)
77
+ return [
78
+ Math.min(prev[0], bbox[0]),
79
+ Math.min(prev[1], bbox[1]),
80
+ Math.max(prev[2], bbox[2]),
81
+ Math.max(prev[3], bbox[3]),
82
+ ] as BoundingBox
83
+ }, emptyExtent)
84
+ case 'Polygon':
85
+ case 'MultiLineString':
86
+ return geometry.coordinates.reduce(coordinatesArrayReducer, emptyExtent)
87
+ case 'LineString':
88
+ case 'MultiPoint':
89
+ return geometry.coordinates.reduce<BoundingBox>(
90
+ coordinatesReducer,
91
+ emptyExtent
92
+ )
93
+ case 'Point':
94
+ return coordinatesReducer(emptyExtent, geometry.coordinates)
95
+ }
96
+ }
@@ -4,6 +4,7 @@ export * from './format-fields'
4
4
  export * from './fuzzy-filter'
5
5
  export * from './geojson'
6
6
  export * from './image-resize'
7
+ export * from './mobile-screen'
7
8
  export * from './no-duplicate-file-name'
8
9
  export * from './parse'
9
10
  export * from './remove-whitespace'
@@ -0,0 +1,14 @@
1
+ import { fromEvent, startWith, map, shareReplay } from 'rxjs'
2
+
3
+ /**
4
+ * This returns true when the screen size is under 768px, which is the mobile threshold.
5
+ */
6
+ const MOBILE_MAX_WIDTH = 768
7
+
8
+ export function getIsMobile() {
9
+ return fromEvent(window, 'resize').pipe(
10
+ startWith(window.innerWidth),
11
+ map(() => window.innerWidth < MOBILE_MAX_WIDTH),
12
+ shareReplay({ bufferSize: 1, refCount: true })
13
+ )
14
+ }