geonetwork-ui 2.7.0-dev.d500b08cc → 2.7.0-dev.d6c0958d7

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 (144) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.mjs +4 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +5 -1
  3. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/constant.mjs +4 -6
  4. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +28 -4
  5. package/esm2022/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.mjs +1 -1
  6. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +5 -1
  7. package/esm2022/libs/common/domain/src/lib/platform.service.interface.mjs +1 -1
  8. package/esm2022/libs/feature/dataviz/src/lib/chart-view/chart-view.component.mjs +10 -2
  9. package/esm2022/libs/feature/editor/src/index.mjs +2 -1
  10. package/esm2022/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.mjs +80 -0
  11. package/esm2022/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.mjs +3 -3
  12. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +1 -3
  13. package/esm2022/libs/feature/record/src/lib/data-view/data-view.component.mjs +31 -12
  14. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +76 -27
  15. package/esm2022/libs/feature/record/src/lib/state/mdview.effects.mjs +4 -2
  16. package/esm2022/libs/ui/dataviz/src/lib/data-table/data-table.component.mjs +4 -3
  17. package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +5 -4
  18. package/esm2022/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.mjs +5 -4
  19. package/esm2022/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.mjs +4 -4
  20. package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +21 -43
  21. package/esm2022/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.mjs +5 -4
  22. package/esm2022/libs/ui/map/src/lib/components/map-legend/map-legend.component.mjs +2 -2
  23. package/esm2022/libs/util/app-config/src/lib/app-config.mjs +3 -1
  24. package/esm2022/libs/util/app-config/src/lib/model.mjs +1 -1
  25. package/esm2022/libs/util/shared/src/index.mjs +2 -2
  26. package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +12 -2
  27. package/esm2022/libs/util/shared/src/lib/record/index.mjs +3 -0
  28. package/esm2022/libs/util/shared/src/lib/record/quality-score.util.mjs +45 -0
  29. package/esm2022/libs/util/shared/src/lib/record/record.util.mjs +56 -0
  30. package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
  31. package/esm2022/libs/util/shared/src/lib/utils/mobile-screen.mjs +9 -0
  32. package/esm2022/translations/de.json +9 -1
  33. package/esm2022/translations/en.json +9 -1
  34. package/esm2022/translations/es.json +9 -1
  35. package/esm2022/translations/fr.json +10 -2
  36. package/esm2022/translations/it.json +9 -1
  37. package/esm2022/translations/nl.json +9 -1
  38. package/esm2022/translations/pt.json +9 -1
  39. package/esm2022/translations/sk.json +9 -1
  40. package/fesm2022/geonetwork-ui.mjs +403 -114
  41. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  42. package/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.d.ts.map +1 -1
  43. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  44. package/libs/api/repository/src/lib/gn4/elasticsearch/constant.d.ts.map +1 -1
  45. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +2 -0
  46. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  47. package/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.d.ts +1 -0
  48. package/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.d.ts.map +1 -1
  49. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  50. package/libs/common/domain/src/lib/platform.service.interface.d.ts +1 -0
  51. package/libs/common/domain/src/lib/platform.service.interface.d.ts.map +1 -1
  52. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts +3 -2
  53. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts.map +1 -1
  54. package/libs/feature/editor/src/index.d.ts +1 -0
  55. package/libs/feature/editor/src/index.d.ts.map +1 -1
  56. package/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.d.ts +19 -0
  57. package/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.d.ts.map +1 -0
  58. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  59. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts +8 -4
  60. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts.map +1 -1
  61. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +12 -5
  62. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  63. package/libs/feature/record/src/lib/state/mdview.effects.d.ts.map +1 -1
  64. package/libs/ui/dataviz/src/lib/data-table/data-table.component.d.ts.map +1 -1
  65. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -0
  66. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts.map +1 -1
  67. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts +1 -0
  68. package/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.d.ts.map +1 -1
  69. package/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.d.ts.map +1 -1
  70. package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts +7 -6
  71. package/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.d.ts.map +1 -1
  72. package/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.d.ts +1 -0
  73. package/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.d.ts.map +1 -1
  74. package/libs/util/app-config/src/lib/app-config.d.ts.map +1 -1
  75. package/libs/util/app-config/src/lib/model.d.ts +1 -0
  76. package/libs/util/app-config/src/lib/model.d.ts.map +1 -1
  77. package/libs/util/shared/src/index.d.ts +1 -1
  78. package/libs/util/shared/src/index.d.ts.map +1 -1
  79. package/libs/util/shared/src/lib/links/link-utils.d.ts +2 -1
  80. package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
  81. package/libs/util/shared/src/lib/record/index.d.ts +3 -0
  82. package/libs/util/shared/src/lib/record/index.d.ts.map +1 -0
  83. package/libs/util/shared/src/lib/record/quality-score.util.d.ts +13 -0
  84. package/libs/util/shared/src/lib/record/quality-score.util.d.ts.map +1 -0
  85. package/libs/util/shared/src/lib/record/record.util.d.ts +3 -0
  86. package/libs/util/shared/src/lib/record/record.util.d.ts.map +1 -0
  87. package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
  88. package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
  89. package/libs/util/shared/src/lib/utils/mobile-screen.d.ts +2 -0
  90. package/libs/util/shared/src/lib/utils/mobile-screen.d.ts.map +1 -0
  91. package/package.json +1 -1
  92. package/src/libs/api/metadata-converter/src/lib/dcat-ap/utils/status.mapper.ts +3 -0
  93. package/src/libs/api/metadata-converter/src/lib/iso19139/utils/status.mapper.ts +3 -0
  94. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +4 -0
  95. package/src/libs/api/repository/src/lib/gn4/elasticsearch/constant.ts +3 -5
  96. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +36 -4
  97. package/src/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.ts +1 -0
  98. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +4 -0
  99. package/src/libs/common/domain/src/lib/platform.service.interface.ts +2 -0
  100. package/src/libs/common/fixtures/src/lib/editor/editor.fixtures.ts +0 -3
  101. package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +10 -1
  102. package/src/libs/feature/editor/src/index.ts +1 -0
  103. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.css +0 -0
  104. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.html +37 -0
  105. package/src/libs/feature/editor/src/lib/components/metadata-quality-panel/metadata-quality-panel.component.ts +90 -0
  106. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.html +2 -1
  107. package/src/libs/feature/editor/src/lib/fields.config.ts +0 -2
  108. package/src/libs/feature/record/src/lib/data-view/data-view.component.html +2 -0
  109. package/src/libs/feature/record/src/lib/data-view/data-view.component.ts +34 -15
  110. package/src/libs/feature/record/src/lib/map-view/map-view.component.html +5 -2
  111. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +70 -23
  112. package/src/libs/feature/record/src/lib/state/mdview.effects.ts +5 -1
  113. package/src/libs/ui/dataviz/src/lib/data-table/data-table.component.ts +6 -1
  114. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.html +12 -11
  115. package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.ts +7 -1
  116. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.html +4 -1
  117. package/src/libs/ui/elements/src/lib/geo-data-badge/geo-data-badge.component.ts +7 -1
  118. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.html +1 -0
  119. package/src/libs/ui/elements/src/lib/internal-link-card/internal-link-card.component.ts +5 -1
  120. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.html +1 -0
  121. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +21 -54
  122. package/src/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.html +7 -1
  123. package/src/libs/ui/inputs/src/lib/search-feature-catalog/search-feature-catalog.component.ts +3 -1
  124. package/src/libs/ui/map/src/lib/components/map-legend/map-legend.component.ts +1 -1
  125. package/src/libs/util/app-config/src/lib/app-config.ts +2 -0
  126. package/src/libs/util/app-config/src/lib/model.ts +1 -0
  127. package/src/libs/util/shared/src/index.ts +1 -1
  128. package/src/libs/util/shared/src/lib/links/link-utils.ts +11 -1
  129. package/src/libs/util/shared/src/lib/record/index.ts +2 -0
  130. package/src/libs/util/shared/src/lib/record/quality-score.util.ts +69 -0
  131. package/src/libs/util/shared/src/lib/{record.util.ts → record/record.util.ts} +1 -1
  132. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  133. package/src/libs/util/shared/src/lib/utils/mobile-screen.ts +14 -0
  134. package/translations/de.json +9 -1
  135. package/translations/en.json +9 -1
  136. package/translations/es.json +9 -1
  137. package/translations/fr.json +10 -2
  138. package/translations/it.json +9 -1
  139. package/translations/nl.json +9 -1
  140. package/translations/pt.json +9 -1
  141. package/translations/sk.json +9 -1
  142. package/esm2022/libs/util/shared/src/lib/record.util.mjs +0 -56
  143. package/libs/util/shared/src/lib/record.util.d.ts +0 -3
  144. package/libs/util/shared/src/lib/record.util.d.ts.map +0 -1
@@ -23,7 +23,11 @@ export class MdViewEffects {
23
23
  ofType(MdViewActions.loadFullMetadata),
24
24
  switchMap(({ uuid }) => this.recordsRepository.getRecord(uuid)),
25
25
  map((record) => {
26
- if (record === null || !this.router.url.includes(record.kind)) {
26
+ if (
27
+ record === null ||
28
+ (this.router.url !== '/' && // FIXME: special case for WC, find a better way
29
+ !this.router.url.includes(record.kind))
30
+ ) {
27
31
  return MdViewActions.loadFullMetadataFailure({ notFound: true })
28
32
  }
29
33
  return MdViewActions.loadFullMetadataSuccess({ full: record })
@@ -14,7 +14,11 @@ import {
14
14
  } from '@angular/core'
15
15
  import { MatSort, MatSortModule } from '@angular/material/sort'
16
16
  import { MatTableModule } from '@angular/material/table'
17
- import { TranslatePipe, TranslateService } from '@ngx-translate/core'
17
+ import {
18
+ TranslateDirective,
19
+ TranslatePipe,
20
+ TranslateService,
21
+ } from '@ngx-translate/core'
18
22
  import { DataTableDataSource } from './data-table.data.source'
19
23
  import { BaseReader, FetchError } from '../../../../../../libs/util/data-fetcher/src'
20
24
  import {
@@ -53,6 +57,7 @@ export interface TableItemModel {
53
57
  PopupAlertComponent,
54
58
  LetDirective,
55
59
  TranslatePipe,
60
+ TranslateDirective,
56
61
  ],
57
62
  providers: [{ provide: MatPaginatorIntl, useClass: CustomMatPaginatorIntl }],
58
63
  selector: 'gn-ui-data-table',
@@ -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 : []
@@ -68,6 +68,7 @@
68
68
  [smaller]="true"
69
69
  [metadata]="record"
70
70
  [metadataQualityDisplay]="metadataQualityDisplay"
71
+ [popoverDisplay]="true"
71
72
  ></gn-ui-metadata-quality>
72
73
  </div>
73
74
  <div
@@ -21,7 +21,11 @@ import { KindBadgeComponent } from '../kind-badge/kind-badge.component'
21
21
  import { MarkdownParserComponent } from '../markdown-parser/markdown-parser.component'
22
22
  import { MetadataQualityComponent } from '../metadata-quality/metadata-quality.component'
23
23
  import { ThumbnailComponent } from '../thumbnail/thumbnail.component'
24
- import { removeWhitespace, stripHtml } from '../../../../../../libs/util/shared/src'
24
+ import {
25
+ removeWhitespace,
26
+ stripHtml,
27
+ type ValidatorMapperKeys,
28
+ } from '../../../../../../libs/util/shared/src'
25
29
 
26
30
  type CardSize = 'L' | 'M' | 'S' | 'XS'
27
31
 
@@ -10,6 +10,7 @@
10
10
  class="flex-grow"
11
11
  ></gn-ui-progress-bar>
12
12
  <gn-ui-popover
13
+ *ngIf="popoverDisplay"
13
14
  [content]="popoverItems"
14
15
  theme="light-border"
15
16
  [class]="smaller ? 'ml-2' : 'ml-2 mt-1'"
@@ -14,15 +14,16 @@ import {
14
14
  PopoverComponent,
15
15
  ProgressBarComponent,
16
16
  } from '../../../../../../libs/ui/widgets/src'
17
+ import {
18
+ getQualityValidators,
19
+ getAllKeysValidator,
20
+ type ValidatorMapperKeys,
21
+ } from '../../../../../../libs/util/shared/src'
17
22
  import { CommonModule } from '@angular/common'
18
23
  import { TranslateDirective } from '@ngx-translate/core'
19
24
  import { NgIcon, provideIcons, provideNgIconsConfig } from '@ng-icons/core'
20
25
  import { matInfoOutline } from '@ng-icons/material-icons/outline'
21
26
 
22
- type QualityChecks = {
23
- [key: string]: (metadata: Partial<CatalogRecord>) => boolean
24
- }
25
-
26
27
  @Component({
27
28
  selector: 'gn-ui-metadata-quality',
28
29
  templateUrl: './metadata-quality.component.html',
@@ -48,77 +49,43 @@ type QualityChecks = {
48
49
  ],
49
50
  })
50
51
  export class MetadataQualityComponent implements OnChanges {
51
- @Input() metadata: Partial<CatalogRecord>
52
+ @Input() metadata: CatalogRecord
52
53
  @Input() smaller = false
53
54
  @Input() metadataQualityDisplay: boolean
55
+ @Input() popoverDisplay = true
56
+ @Input() propsToValidate?: ValidatorMapperKeys[]
57
+ @Input() forceComputeScore = false // Instead of returning es' quality score
54
58
 
55
59
  items: MetadataQualityItem[] = []
56
60
 
57
61
  get qualityScore() {
58
- const qualityScore = this.metadata?.extras?.qualityScore
62
+ const qualityScore = !this.forceComputeScore
63
+ ? this.metadata?.extras?.qualityScore
64
+ : this.computedQualityScore
65
+
59
66
  return typeof qualityScore === 'number'
60
67
  ? qualityScore
61
- : this.calculatedQualityScore
68
+ : this.computedQualityScore
62
69
  }
63
70
 
64
- get calculatedQualityScore(): number {
71
+ get computedQualityScore(): number {
65
72
  return Math.round(
66
73
  (this.items.filter(({ value }) => value).length * 100) / this.items.length
67
74
  )
68
75
  }
69
76
 
70
- private add(name: string, value: boolean) {
71
- if (this.metadataQualityDisplay?.[name] !== false) {
72
- this.items.push({ name, value })
73
- }
74
- }
75
77
  hasGetCapabilities(url: string): boolean {
76
78
  return url.toLowerCase().includes('capabilities')
77
79
  }
78
80
 
79
- private readonly COMMON_CHECKS: QualityChecks = {
80
- title: (metadata) => !!metadata?.title,
81
- description: (metadata) => !!metadata?.abstract,
82
- keywords: (metadata) => (metadata?.keywords?.length ?? 0) > 0,
83
- legalConstraints: (metadata) =>
84
- (metadata?.legalConstraints?.length ?? 0) > 0,
85
- contact: (metadata) => !!metadata?.contacts?.[0]?.email,
86
- }
87
-
88
- private readonly SPECIFIC_CHECKS: Record<string, QualityChecks> = {
89
- dataset: {
90
- updateFrequency: (metadata) => !!metadata?.updateFrequency,
91
- topic: (metadata) => (metadata?.topics?.length ?? 0) > 0,
92
- organisation: (metadata) => !!metadata?.contacts?.[0]?.organization?.name,
93
- },
94
- service: {
95
- capabilities: (metadata) =>
96
- (metadata?.onlineResources ?? []).some((resource) =>
97
- this.hasGetCapabilities(resource?.url?.href ?? '')
98
- ),
99
- },
100
- reuse: {
101
- topic: (metadata) => (metadata?.topics?.length ?? 0) > 0,
102
- organisation: (metadata) => !!metadata?.contacts?.[0]?.organization?.name,
103
- source: (metadata) => !!metadata?.extras?.sourcesIdentifiers,
104
- },
105
- }
106
-
107
81
  initialize() {
108
- this.items = []
109
-
110
- Object.entries(this.COMMON_CHECKS).forEach(([name, check]) => {
111
- this.add(name, check(this.metadata))
112
- })
113
-
114
- const datasetType = this.metadata?.kind
115
- if (datasetType && this.SPECIFIC_CHECKS[datasetType]) {
116
- Object.entries(this.SPECIFIC_CHECKS[datasetType]).forEach(
117
- ([name, check]) => {
118
- this.add(name, check(this.metadata))
119
- }
120
- )
82
+ if (!this.propsToValidate) {
83
+ this.propsToValidate = getAllKeysValidator()
121
84
  }
85
+
86
+ this.items = getQualityValidators(this.metadata, this.propsToValidate).map(
87
+ ({ name, validator }) => ({ name, value: validator() })
88
+ )
122
89
  }
123
90
 
124
91
  ngOnChanges(changes: SimpleChanges): void {
@@ -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
@@ -27,7 +27,7 @@ export class MapLegendComponent implements OnChanges {
27
27
  async ngOnChanges(changes: SimpleChanges) {
28
28
  if ('context' in changes) {
29
29
  const mapContext = changes['context'].currentValue
30
- if (mapContext.layers && mapContext.layers.length > 0) {
30
+ if (mapContext?.layers && mapContext.layers.length > 0) {
31
31
  const mapContextLayer = mapContext.layers[0]
32
32
  this.legendHTML = await createLegendFromLayer(mapContextLayer)
33
33
  if (this.legendHTML) {
@@ -102,6 +102,7 @@ export function loadAppConfig() {
102
102
  'web_component_embedder_url',
103
103
  'languages',
104
104
  'contact_email',
105
+ 'reuse_form_url',
105
106
  ],
106
107
  warnings,
107
108
  errors
@@ -131,6 +132,7 @@ export function loadAppConfig() {
131
132
  parsedGlobalSection.web_component_embedder_url,
132
133
  LANGUAGES: parsedGlobalSection.languages,
133
134
  CONTACT_EMAIL: parsedGlobalSection.contact_email,
135
+ REUSE_FORM_URL: parsedGlobalSection.reuse_form_url,
134
136
  } as GlobalConfig)
135
137
 
136
138
  const parsedLayersSections = parseMultiConfigSection(
@@ -11,6 +11,7 @@ export interface GlobalConfig {
11
11
  WEB_COMPONENT_EMBEDDER_URL?: string
12
12
  LANGUAGES?: string[]
13
13
  CONTACT_EMAIL?: string
14
+ REUSE_FORM_URL?: string
14
15
  }
15
16
 
16
17
  export interface LayerConfig {
@@ -3,4 +3,4 @@ export * from './lib/utils'
3
3
  export * from './lib/links'
4
4
  export * from './lib/image-fallback.directive'
5
5
  export * from './lib/gn-ui-version'
6
- export * from './lib/record.util'
6
+ export * from './lib/record'
@@ -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
@@ -230,6 +231,15 @@ export function getBadgeColor(linkFormat: FileFormat): string {
230
231
  return 'var(--color-gray-700)' // Default color ?
231
232
  }
232
233
 
234
+ export function getLinkId(link: DatasetOnlineResource): string {
235
+ const href = link.url.href ?? link.url
236
+ return `${getLinkLabel(link)
237
+ .replace(/é/g, 'e')
238
+ .replace(/è/g, 'e')
239
+ .normalize('NFD')
240
+ .replace(/[\u0300-\u036f]/g, '')}-${href}`
241
+ }
242
+
233
243
  export function getLinkLabel(
234
244
  link: DatasetOnlineResource | ServiceOnlineResource
235
245
  ): string {
@@ -0,0 +1,2 @@
1
+ export * from './quality-score.util'
2
+ export * from './record.util'
@@ -0,0 +1,69 @@
1
+ import {
2
+ CatalogRecord,
3
+ RecordKind,
4
+ } from '../../../../../../libs/common/domain/src/lib/model/record'
5
+
6
+ type TValidatorMapper = {
7
+ [key: string]: (metadata: Partial<CatalogRecord>) => boolean
8
+ }
9
+
10
+ const ValidatorMapper: TValidatorMapper = {
11
+ title: (record) => !!record?.title,
12
+ abstract: (record) => !!record?.abstract,
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,
17
+ topics: (record) => (record?.topics?.length ?? 0) > 0,
18
+ organisation: (record) => !!record?.contacts?.[0]?.organization?.name,
19
+ capabilities: (record) =>
20
+ record?.onlineResources?.some((resource) =>
21
+ resource?.url?.href.toLowerCase().includes('capabilities')
22
+ ),
23
+ source: (record) => !!record?.extras?.sourcesIdentifiers,
24
+ } as const
25
+
26
+ export type ValidatorMapperKeys = keyof typeof ValidatorMapper & string
27
+
28
+ export function getAllKeysValidator() {
29
+ return Object.keys(ValidatorMapper)
30
+ }
31
+
32
+ function getMappersFromKind(kind: RecordKind) {
33
+ let kindKeys = <ValidatorMapperKeys[]>[]
34
+ const commonsKeys = <ValidatorMapperKeys[]>[
35
+ 'title',
36
+ 'abstract',
37
+ 'keywords',
38
+ 'legalConstraints',
39
+ 'contacts',
40
+ ]
41
+
42
+ switch (kind) {
43
+ case 'service':
44
+ kindKeys = ['capabilities']
45
+ break
46
+ case 'reuse':
47
+ kindKeys = ['topics', 'organisation', 'source']
48
+ break
49
+ case 'dataset':
50
+ default:
51
+ kindKeys = ['updateFrequency', 'topics', 'organisation']
52
+ }
53
+
54
+ return [...commonsKeys, ...kindKeys]
55
+ }
56
+
57
+ export function getQualityValidators(
58
+ record: Partial<CatalogRecord>,
59
+ propsToValidate: ValidatorMapperKeys[]
60
+ ) {
61
+ const filteredProps = propsToValidate.filter((prop) =>
62
+ getMappersFromKind(record.kind).includes(prop)
63
+ )
64
+
65
+ return filteredProps.map((name) => ({
66
+ name,
67
+ validator: () => ValidatorMapper[name](record),
68
+ }))
69
+ }
@@ -10,7 +10,7 @@ import {
10
10
  OnlineLinkResource,
11
11
  Organization,
12
12
  ServiceEndpoint,
13
- } from '../../../../../libs/common/domain/src/lib/model/record'
13
+ } from '../../../../../../libs/common/domain/src/lib/model/record'
14
14
 
15
15
  type TranslatedRecordObjects =
16
16
  | BaseRecord
@@ -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
+ }
@@ -86,7 +86,9 @@
86
86
  "domain.record.status.completed": "Abgeschlossen",
87
87
  "domain.record.status.deprecated": "Veraltet",
88
88
  "domain.record.status.ongoing": "Kontinuierliche Aktualisierung",
89
+ "domain.record.status.planned": "",
89
90
  "domain.record.status.removed": "Entfernt",
91
+ "domain.record.status.required": "",
90
92
  "domain.record.status.under_development": "In Erstellung",
91
93
  "domain.record.updateFrequency.annually": "Daten werden jedes Jahr aktualisiert",
92
94
  "domain.record.updateFrequency.asNeeded": "Daten werden nach Bedarf aktualisiert",
@@ -142,6 +144,7 @@
142
144
  "editor.record.form.draft.updateAlert": "",
143
145
  "editor.record.form.field.abstract": "Kurzbeschreibung",
144
146
  "editor.record.form.field.constraintsShortcuts": "",
147
+ "editor.record.form.field.contacts": "Ansprechpartner - Email",
145
148
  "editor.record.form.field.contacts.noContact": "",
146
149
  "editor.record.form.field.contacts.placeholder": "",
147
150
  "editor.record.form.field.contactsForResource.noContact": "",
@@ -166,6 +169,7 @@
166
169
  "editor.record.form.field.onlineResource.toggle.dataset": "",
167
170
  "editor.record.form.field.onlineResource.toggle.service": "",
168
171
  "editor.record.form.field.onlineResources": "",
172
+ "editor.record.form.field.organisation": "Ansprechpartner - Organisation",
169
173
  "editor.record.form.field.otherConstraints": "Allgemeine Einschränkung",
170
174
  "editor.record.form.field.overviews": "",
171
175
  "editor.record.form.field.recordUpdated": "Datensatz zuletzt aktualisiert",
@@ -177,6 +181,7 @@
177
181
  "editor.record.form.field.temporalExtents": "Zeitlicher Umfang",
178
182
  "editor.record.form.field.title": "Metadaten-Titel",
179
183
  "editor.record.form.field.title.placeholder": "Geben Sie einen Titel ein",
184
+ "editor.record.form.field.topics": "Kategorien",
180
185
  "editor.record.form.field.uniqueIdentifier": "Eindeutige Kennung (ID)",
181
186
  "editor.record.form.field.updateFrequency": "Aktualisierungshäufigkeit",
182
187
  "editor.record.form.keywords.place.placeholder": "",
@@ -191,6 +196,8 @@
191
196
  "editor.record.form.license.odc-by": "",
192
197
  "editor.record.form.license.pddl": "",
193
198
  "editor.record.form.license.unknown": "",
199
+ "editor.record.form.metadataQuality.open": "Öffnen Sie das Panel zur Metadatenqualität",
200
+ "editor.record.form.metadataQuality.title": "Vollständigkeit",
194
201
  "editor.record.form.multilingual.activate": "",
195
202
  "editor.record.form.multilingual.default": "",
196
203
  "editor.record.form.multilingual.enable": "",
@@ -340,6 +347,7 @@
340
347
  "map.layer.add": "Hinzufügen",
341
348
  "map.layers.available": "Verfügbare Layer",
342
349
  "map.layers.list": "Ebenen",
350
+ "map.legend.title": "Legende",
343
351
  "map.loading.data": "Kartendaten werden geladen...",
344
352
  "map.loading.service": "Dienst wird geladen...",
345
353
  "map.navigation.message": "Bitte verwenden Sie STRG + Maus (oder zwei Finger auf einem Mobilgerät), um die Karte zu navigieren",
@@ -373,7 +381,6 @@
373
381
  "record.action.rollback": "",
374
382
  "record.action.switchLang": "",
375
383
  "record.action.view": "Anzeigen",
376
- "record.card.metadata.contact": "",
377
384
  "record.externalViewer.open": "In externem Kartenviewer öffnen",
378
385
  "record.feature.catalog.number.total.attribute": "",
379
386
  "record.feature.catalog.number.total.object": "",
@@ -579,6 +586,7 @@
579
586
  "service.metadata.filter.noLayers": "",
580
587
  "service.metadata.other": "",
581
588
  "service.metadata.question": "",
589
+ "service.metadata.reuse": "",
582
590
  "service.metadata.search": "",
583
591
  "service.metadata.search.clear": "",
584
592
  "service.metadata.spatialExtent": "",
@@ -86,7 +86,9 @@
86
86
  "domain.record.status.completed": "Completed",
87
87
  "domain.record.status.deprecated": "Deprecated",
88
88
  "domain.record.status.ongoing": "Ongoing",
89
+ "domain.record.status.planned": "Planned",
89
90
  "domain.record.status.removed": "Removed",
91
+ "domain.record.status.required": "Required",
90
92
  "domain.record.status.under_development": "Under development",
91
93
  "domain.record.updateFrequency.annually": "Data is updated every year",
92
94
  "domain.record.updateFrequency.asNeeded": "Data is updated as deemed necessary",
@@ -142,6 +144,7 @@
142
144
  "editor.record.form.draft.updateAlert": "Since you created this draft, the dataset has been updated on { date } by { user }. Publishing your draft might erase their edits. To avoid this, you need to either cancel your changes or knowingly publish your own version.",
143
145
  "editor.record.form.field.abstract": "Abstract",
144
146
  "editor.record.form.field.constraintsShortcuts": "",
147
+ "editor.record.form.field.contacts": "Point of contact - Email",
145
148
  "editor.record.form.field.contacts.noContact": "Please provide at least one point of contact.",
146
149
  "editor.record.form.field.contacts.placeholder": "Choose a contact",
147
150
  "editor.record.form.field.contactsForResource.noContact": "Please provide at least one point of contact responsible for the data.",
@@ -166,6 +169,7 @@
166
169
  "editor.record.form.field.onlineResource.toggle.dataset": "Link to a file",
167
170
  "editor.record.form.field.onlineResource.toggle.service": "Link to a service",
168
171
  "editor.record.form.field.onlineResources": "Distribution",
172
+ "editor.record.form.field.organisation": "Point of contact - Organization",
169
173
  "editor.record.form.field.otherConstraints": "Other constraint",
170
174
  "editor.record.form.field.overviews": "Overview",
171
175
  "editor.record.form.field.recordUpdated": "Record updated",
@@ -177,6 +181,7 @@
177
181
  "editor.record.form.field.temporalExtents": "Temporal extents",
178
182
  "editor.record.form.field.title": "Metadata title",
179
183
  "editor.record.form.field.title.placeholder": "Enter a title",
184
+ "editor.record.form.field.topics": "Categories",
180
185
  "editor.record.form.field.uniqueIdentifier": "Unique identifier",
181
186
  "editor.record.form.field.updateFrequency": "Update frequency",
182
187
  "editor.record.form.keywords.place.placeholder": "Search for place keywords",
@@ -191,6 +196,8 @@
191
196
  "editor.record.form.license.odc-by": "Open Data Commons ODC-By",
192
197
  "editor.record.form.license.pddl": "Open Data Commons PDDL",
193
198
  "editor.record.form.license.unknown": "Unknown or absent",
199
+ "editor.record.form.metadataQuality.open": "Open the metadata quality panel",
200
+ "editor.record.form.metadataQuality.title": "Completeness",
194
201
  "editor.record.form.multilingual.activate": "Activate the languages",
195
202
  "editor.record.form.multilingual.default": "Default",
196
203
  "editor.record.form.multilingual.enable": "Multilingual Mode",
@@ -340,6 +347,7 @@
340
347
  "map.layer.add": "Add",
341
348
  "map.layers.available": "Available Layers",
342
349
  "map.layers.list": "Layers",
350
+ "map.legend.title": "Legend",
343
351
  "map.loading.data": "Loading map data...",
344
352
  "map.loading.service": "Loading service...",
345
353
  "map.navigation.message": "Please use CTRL + mouse (or two fingers on mobile) to navigate the map",
@@ -373,7 +381,6 @@
373
381
  "record.action.rollback": "Rollback",
374
382
  "record.action.switchLang": "Switch to default",
375
383
  "record.action.view": "View",
376
- "record.card.metadata.contact": "Metadata Contact",
377
384
  "record.externalViewer.open": "Open in the external map viewer",
378
385
  "record.feature.catalog.number.total.attribute": "Total amount of objects",
379
386
  "record.feature.catalog.number.total.object": "Total amount of attributes",
@@ -579,6 +586,7 @@
579
586
  "service.metadata.filter.noLayers": "No layer matches your search",
580
587
  "service.metadata.other": "Other information",
581
588
  "service.metadata.question": "Ask a question",
589
+ "service.metadata.reuse": "Declare a reuse",
582
590
  "service.metadata.search": "Search through the layer list",
583
591
  "service.metadata.search.clear": "Clear the layer search",
584
592
  "service.metadata.spatialExtent": "Spatial extent",