geonetwork-ui 2.2.0-dev.95b40cd8 → 2.2.0-dev.9d7dfa2e

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 (124) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/atomic-operations.mjs +27 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +23 -11
  3. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.mjs +4 -2
  4. package/esm2022/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.mjs +1 -1
  5. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.mjs +14 -0
  6. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/converter.mjs +12 -9
  7. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +33 -8
  8. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +31 -14
  9. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.mjs +2 -2
  10. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  11. package/esm2022/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.mjs +13 -13
  12. package/esm2022/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.mjs +3 -3
  13. package/esm2022/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.mjs +3 -3
  14. package/esm2022/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.mjs +3 -3
  15. package/esm2022/libs/ui/elements/src/lib/max-lines/max-lines.component.mjs +5 -3
  16. package/esm2022/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.mjs +3 -3
  17. package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +19 -7
  18. package/esm2022/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.mjs +2 -2
  19. package/esm2022/libs/ui/elements/src/lib/thumbnail/thumbnail.component.mjs +3 -3
  20. package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +4 -4
  21. package/esm2022/libs/ui/inputs/src/lib/button/button.component.mjs +3 -3
  22. package/esm2022/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.mjs +3 -3
  23. package/esm2022/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.mjs +3 -3
  24. package/esm2022/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.mjs +3 -3
  25. package/esm2022/libs/ui/inputs/src/lib/text-area/text-area.component.mjs +3 -3
  26. package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +6 -6
  27. package/esm2022/libs/ui/layout/src/lib/carousel/carousel.component.mjs +3 -3
  28. package/esm2022/libs/util/i18n/src/lib/i18n.constants.mjs +18 -1
  29. package/esm2022/libs/util/shared/src/lib/utils/index.mjs +2 -1
  30. package/esm2022/libs/util/shared/src/lib/utils/temporal-extent-union.mjs +32 -0
  31. package/esm2022/translations/de.json +34 -27
  32. package/esm2022/translations/en.json +26 -19
  33. package/esm2022/translations/es.json +23 -16
  34. package/esm2022/translations/fr.json +44 -37
  35. package/esm2022/translations/it.json +38 -31
  36. package/esm2022/translations/nl.json +24 -17
  37. package/esm2022/translations/pt.json +23 -16
  38. package/fesm2022/geonetwork-ui.mjs +465 -258
  39. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  40. package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts +2 -0
  41. package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts.map +1 -1
  42. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  43. package/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.d.ts.map +1 -1
  44. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts +4 -5
  45. package/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.d.ts.map +1 -1
  46. package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts +3 -0
  47. package/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.d.ts.map +1 -0
  48. package/libs/api/metadata-converter/src/lib/iso19139/converter.d.ts.map +1 -1
  49. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +3 -3
  50. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
  51. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts +1 -1
  52. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  53. package/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.d.ts.map +1 -1
  54. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +16 -2
  55. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  56. package/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.d.ts +1 -1
  57. package/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.d.ts.map +1 -1
  58. package/libs/ui/elements/src/lib/max-lines/max-lines.component.d.ts.map +1 -1
  59. package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts +9 -3
  60. package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts.map +1 -1
  61. package/libs/ui/elements/src/lib/ui-elements.module.d.ts +13 -13
  62. package/libs/ui/inputs/src/lib/button/button.component.d.ts +1 -1
  63. package/libs/ui/inputs/src/lib/button/button.component.d.ts.map +1 -1
  64. package/libs/ui/inputs/src/lib/text-area/text-area.component.d.ts +1 -1
  65. package/libs/ui/inputs/src/lib/text-area/text-area.component.d.ts.map +1 -1
  66. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +40 -40
  67. package/libs/ui/layout/src/lib/interactive-table/interactive-table-column/interactive-table-column.component.d.ts +1 -1
  68. package/libs/util/i18n/src/lib/i18n.constants.d.ts +17 -0
  69. package/libs/util/i18n/src/lib/i18n.constants.d.ts.map +1 -1
  70. package/libs/util/shared/src/lib/utils/index.d.ts +1 -0
  71. package/libs/util/shared/src/lib/utils/index.d.ts.map +1 -1
  72. package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts +5 -0
  73. package/libs/util/shared/src/lib/utils/temporal-extent-union.d.ts.map +1 -0
  74. package/package.json +1 -1
  75. package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +57 -2
  76. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +52 -6
  77. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +207 -20
  78. package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +29 -0
  79. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +30 -11
  80. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.metadata.mapper.ts +3 -1
  81. package/src/libs/api/metadata-converter/src/lib/gn4/types/metadata.model.ts +4 -5
  82. package/src/libs/api/metadata-converter/src/lib/iso19139/codelists/keyword.mapper.ts +16 -0
  83. package/src/libs/api/metadata-converter/src/lib/iso19139/converter.ts +11 -9
  84. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +58 -20
  85. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +86 -38
  86. package/src/libs/api/repository/src/lib/gn4/elasticsearch/elasticsearch.service.ts +1 -1
  87. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +20 -3
  88. package/src/libs/common/fixtures/src/lib/elasticsearch/full-response.ts +1 -1
  89. package/src/libs/common/fixtures/src/lib/records.fixtures.ts +46 -8
  90. package/src/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.ts +12 -12
  91. package/src/libs/feature/search/src/lib/favorites/favorite-star/favorite-star.component.html +3 -4
  92. package/src/libs/ui/catalog/src/lib/language-switcher/language-switcher.component.html +1 -1
  93. package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.css +5 -0
  94. package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.html +39 -0
  95. package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.ts +58 -0
  96. package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.ts +1 -0
  97. package/src/libs/ui/elements/src/lib/max-lines/max-lines.component.html +5 -1
  98. package/src/libs/ui/elements/src/lib/max-lines/max-lines.component.ts +1 -0
  99. package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +1 -1
  100. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +113 -25
  101. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +20 -3
  102. package/src/libs/ui/elements/src/lib/metadata-quality/metadata-quality.component.ts +1 -1
  103. package/src/libs/ui/elements/src/lib/thumbnail/thumbnail.component.html +2 -2
  104. package/src/libs/ui/elements/src/lib/ui-elements.module.ts +1 -1
  105. package/src/libs/ui/inputs/src/lib/button/button.component.ts +1 -0
  106. package/src/libs/ui/inputs/src/lib/dropdown-multiselect/dropdown-multiselect.component.html +1 -1
  107. package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.html +3 -1
  108. package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.css +3 -0
  109. package/src/libs/ui/inputs/src/lib/navigation-button/navigation-button.component.html +1 -1
  110. package/src/libs/ui/inputs/src/lib/text-area/text-area.component.ts +1 -0
  111. package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +2 -2
  112. package/src/libs/ui/layout/src/lib/carousel/carousel.component.html +1 -0
  113. package/src/libs/util/i18n/src/lib/i18n.constants.ts +18 -0
  114. package/src/libs/util/shared/src/lib/utils/index.ts +1 -0
  115. package/src/libs/util/shared/src/lib/utils/temporal-extent-union.ts +32 -0
  116. package/tailwind.base.css +2 -2
  117. package/translations/de.json +34 -27
  118. package/translations/en.json +26 -19
  119. package/translations/es.json +23 -16
  120. package/translations/fr.json +44 -37
  121. package/translations/it.json +38 -31
  122. package/translations/nl.json +24 -17
  123. package/translations/pt.json +23 -16
  124. package/translations/sk.json +24 -17
@@ -0,0 +1,58 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ EventEmitter,
6
+ Input,
7
+ Output,
8
+ } from '@angular/core'
9
+ import { FormsModule } from '@angular/forms'
10
+ import { MarkdownParserComponent } from '../markdown-parser/markdown-parser.component'
11
+ import { TranslateModule } from '@ngx-translate/core'
12
+ import { ButtonComponent, TextAreaComponent } from '../../../../../../libs/ui/inputs/src'
13
+ import { MatIconModule } from '@angular/material/icon'
14
+ import { MatTooltipModule } from '@angular/material/tooltip'
15
+
16
+ @Component({
17
+ selector: 'gn-ui-markdown-editor',
18
+ templateUrl: './markdown-editor.component.html',
19
+ styleUrls: ['./markdown-editor.component.css'],
20
+ changeDetection: ChangeDetectionStrategy.OnPush,
21
+ standalone: true,
22
+ imports: [
23
+ CommonModule,
24
+ FormsModule,
25
+ MatIconModule,
26
+ MatTooltipModule,
27
+ ButtonComponent,
28
+ TextAreaComponent,
29
+ MarkdownParserComponent,
30
+ TranslateModule,
31
+ ],
32
+ })
33
+ export class MarkdownEditorComponent {
34
+ @Input() label: string
35
+ @Input() tooltip?: string
36
+ @Input() helperText?: string
37
+ @Input() placeholder: string
38
+ @Input() textContent: string
39
+ @Output() textContentChanged: EventEmitter<string> =
40
+ new EventEmitter<string>()
41
+
42
+ preview = false
43
+
44
+ getButtonExtraClass() {
45
+ return `${
46
+ this.preview ? 'text-gray-200 bg-gray-900' : 'text-gray-900 bg-gray-200'
47
+ } rounded-[1.25rem] p-[0.375rem] text-xs font-medium w-24`
48
+ }
49
+
50
+ togglePreview() {
51
+ this.preview = !this.preview
52
+ }
53
+
54
+ textContentChangedHandler(textContent: string) {
55
+ this.textContent = textContent
56
+ this.textContentChanged.emit(this.textContent)
57
+ }
58
+ }
@@ -6,6 +6,7 @@ import { marked } from 'marked'
6
6
  templateUrl: './markdown-parser.component.html',
7
7
  styleUrls: ['./markdown-parser.component.css'],
8
8
  changeDetection: ChangeDetectionStrategy.OnPush,
9
+ standalone: true,
9
10
  })
10
11
  export class MarkdownParserComponent {
11
12
  @Input() textContent: string
@@ -1,10 +1,14 @@
1
1
  <div
2
2
  #container
3
- class="max-lines overflow-hidden transition-[max-height] duration-300"
3
+ class="max-lines overflow-hidden transition-[max-height] duration-300 relative"
4
4
  [ngClass]="isExpanded ? 'ease-in' : 'ease-out'"
5
5
  [style.maxHeight]="maxHeight"
6
6
  >
7
7
  <ng-content></ng-content>
8
+ <div
9
+ *ngIf="showToggleButton && !isExpanded"
10
+ class="absolute inset-x-0 bottom-0 bg-gradient-to-b from-transparent to-white h-3"
11
+ ></div>
8
12
  </div>
9
13
  <div
10
14
  *ngIf="showToggleButton"
@@ -78,6 +78,7 @@ export class MaxLinesComponent implements AfterViewInit, OnDestroy {
78
78
  }
79
79
 
80
80
  ngOnDestroy(): void {
81
+ if (!this.observer) return
81
82
  this.observer.unobserve(this.container.nativeElement.children[0])
82
83
  }
83
84
  }
@@ -1,5 +1,5 @@
1
1
  <div class="py-5 px-5 rounded bg-gray-100 text-black mb-6">
2
- <div class="grid gap-3">
2
+ <div class="grid gap-3 overflow-hidden">
3
3
  <div>
4
4
  <p class="text-sm font-medium" translate>record.metadata.contact</p>
5
5
  </div>
@@ -55,29 +55,82 @@
55
55
  </div>
56
56
  </gn-ui-expandable-panel>
57
57
  <gn-ui-expandable-panel
58
- class="metadata-origin"
59
58
  *ngIf="
60
59
  metadata.lineage ||
61
60
  metadata.recordUpdated ||
62
61
  metadata.updateFrequency ||
63
62
  metadata.status
64
63
  "
65
- [title]="'record.metadata.origin' | translate"
64
+ [title]="'record.metadata.details' | translate"
66
65
  >
67
- <p
68
- *ngIf="metadata.lineage"
69
- class="mb-5 pt-4 whitespace-pre-line break-words text-gray-900"
70
- gnUiLinkify
71
- >
72
- {{ metadata.lineage }}
73
- </p>
66
+ <div *ngIf="metadata.lineage" class="text-gray-900 flex flex-col mt-4 gap-2">
67
+ <p class="whitespace-pre-line break-words text-gray-900" gnUiLinkify>
68
+ {{ metadata.lineage }}
69
+ </p>
70
+ </div>
71
+ <div class="flex flex-row gap-6 mt-5 mb-8" *ngIf="resourceContact">
72
+ <div
73
+ *ngIf="resourceContact.organization?.logoUrl?.href"
74
+ class="flex items-center justify-center border-solid border border-gray-300 rounded-md bg-white h-32 overflow-hidden"
75
+ >
76
+ <gn-ui-thumbnail
77
+ class="relative h-full w-full"
78
+ [thumbnailUrl]="resourceContact.organization.logoUrl.href"
79
+ fit="contain"
80
+ ></gn-ui-thumbnail>
81
+ </div>
82
+ <div class="flex flex-col gap-1">
83
+ <p class="text-sm font-medium" translate>record.metadata.producer</p>
84
+ <div
85
+ class="text-primary font-title text-21 mr-2 cursor-pointer hover:underline"
86
+ data-cy="organization-name"
87
+ >
88
+ {{ resourceContact.organization?.name }}
89
+ </div>
90
+ <div *ngIf="resourceContact.organization?.website">
91
+ <a
92
+ [href]="resourceContact.organization.website"
93
+ target="_blank"
94
+ class="contact-website text-primary text-sm cursor-pointer hover:underline transition-all"
95
+ >{{ resourceContact.organization.website }}
96
+ <mat-icon
97
+ class="material-symbols-outlined !w-[12px] !h-[12px] !text-[12px] opacity-75 shrink-0"
98
+ >open_in_new</mat-icon
99
+ >
100
+ </a>
101
+ </div>
102
+ <div class="mt-4" *ngIf="resourceContact.email">
103
+ <div class="flex">
104
+ <mat-icon
105
+ class="material-symbols-outlined !w-5 !h-5 !text-[20px] opacity-75 shrink-0"
106
+ >
107
+ mail_outline</mat-icon
108
+ >
109
+ <a
110
+ *ngIf="resourceContact.email"
111
+ [href]="'mailto:' + resourceContact.email"
112
+ class="text-sm hover:underline ml-2"
113
+ target="_blank"
114
+ data-cy="contact-email"
115
+ >{{ resourceContact?.email }}</a
116
+ >
117
+ </div>
118
+ </div>
119
+ </div>
120
+ </div>
74
121
  <div
75
- class="py-4 px-6 rounded bg-gray-100 grid grid-cols-2 gap-y-[10px] gap-x-[20px] text-gray-700 info-grid"
122
+ class="py-6 px-6 rounded bg-gray-100 grid grid-cols-2 gap-y-6 gap-x-[20px] text-gray-700"
76
123
  >
77
- <div *ngIf="metadata.recordUpdated">
78
- <p class="text-sm" translate>record.metadata.updatedOn</p>
124
+ <div *ngIf="metadata.recordCreated">
125
+ <p class="text-sm" translate>record.metadata.creation</p>
79
126
  <p class="text-primary font-medium mt-1">
80
- {{ metadata.recordUpdated && metadata.recordUpdated.toLocaleString() }}
127
+ {{ metadata.recordCreated.toLocaleDateString() }}
128
+ </p>
129
+ </div>
130
+ <div *ngIf="metadata.recordPublished">
131
+ <p class="text-sm" translate>record.metadata.publication</p>
132
+ <p class="text-primary font-medium mt-1">
133
+ {{ metadata.recordPublished.toLocaleDateString() }}
81
134
  </p>
82
135
  </div>
83
136
  <div *ngIf="updateFrequency">
@@ -90,17 +143,52 @@
90
143
  {{ updateFrequency }}
91
144
  </p>
92
145
  </div>
93
- <div *ngIf="metadata.status">
94
- <p class="text-sm" translate>record.metadata.updateStatus</p>
95
- <p class="text-primary font-medium mt-1" translate>
96
- domain.record.status.{{ metadata.status }}
97
- </p>
146
+ <div *ngIf="metadata.languages">
147
+ <p class="text-sm mb-1" translate>record.metadata.languages</p>
148
+ <div class="flex flex-row gap-1 flex-wrap">
149
+ <p
150
+ class="text-primary font-medium"
151
+ translate
152
+ *ngFor="let language of metadata.languages"
153
+ >
154
+ language.{{ language }}
155
+ </p>
156
+ </div>
157
+ </div>
158
+ <div *ngIf="temporalExtent">
159
+ <p class="text-sm" translate>record.metadata.temporalExtent</p>
160
+ <div class="flex flex-row gap-1 mb-1 text-primary font-medium">
161
+ <p
162
+ *ngIf="temporalExtent.start && temporalExtent.end"
163
+ translate
164
+ [translateParams]="{
165
+ start: temporalExtent.start,
166
+ end: temporalExtent.end
167
+ }"
168
+ >
169
+ record.metadata.temporalExtent.fromDateToDate
170
+ </p>
171
+ <p
172
+ *ngIf="temporalExtent.start && !temporalExtent.end"
173
+ translate
174
+ [translateParams]="{ start: temporalExtent.start }"
175
+ >
176
+ record.metadata.temporalExtent.sinceDate
177
+ </p>
178
+ <p
179
+ *ngIf="!temporalExtent.start && temporalExtent.end"
180
+ translate
181
+ [translateParams]="{ end: temporalExtent.end }"
182
+ >
183
+ record.metadata.temporalExtent.untilDate
184
+ </p>
185
+ </div>
98
186
  </div>
99
187
  </div>
100
188
  </gn-ui-expandable-panel>
101
189
  <gn-ui-expandable-panel
102
190
  *ngIf="metadata.landingPage"
103
- [title]="'record.metadata.details' | translate"
191
+ [title]="'record.metadata.technical' | translate"
104
192
  >
105
193
  <div class="flex flex-col gap-4 mr-4 py-5 rounded text-gray-700">
106
194
  <div *ngIf="metadata.recordUpdated">
@@ -136,13 +224,13 @@
136
224
  </p>
137
225
  </div>
138
226
  </div>
139
- <div *ngIf="metadata.themes?.length">
140
- <p class="text-sm mb-1" translate>record.metadata.themes</p>
227
+ <div *ngIf="metadata.topics?.length">
228
+ <p class="text-sm mb-1" translate>record.metadata.topics</p>
141
229
  <div class="sm:pb-4 sm:pr-16">
142
230
  <gn-ui-badge
143
- class="inline-block mr-2 lowercase"
144
- *ngFor="let theme of metadata.themes"
145
- >{{ theme }}</gn-ui-badge
231
+ class="inline-block mr-2 mb-2 lowercase"
232
+ *ngFor="let topic of metadata.topics"
233
+ >{{ topic }}</gn-ui-badge
146
234
  >
147
235
  </div>
148
236
  </div>
@@ -154,7 +242,7 @@
154
242
  (click)="onKeywordClick(keyword)"
155
243
  [clickable]="true"
156
244
  *ngFor="let keyword of metadata.keywords"
157
- >{{ keyword }}</gn-ui-badge
245
+ >{{ keyword.label }}</gn-ui-badge
158
246
  >
159
247
  </div>
160
248
  </div>
@@ -5,7 +5,11 @@ import {
5
5
  Input,
6
6
  Output,
7
7
  } from '@angular/core'
8
- import { DatasetRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
8
+ import {
9
+ DatasetRecord,
10
+ Keyword,
11
+ } from '../../../../../../libs/common/domain/src/lib/model/record'
12
+ import { getTemporalRangeUnion } from '../../../../../../libs/util/shared/src'
9
13
 
10
14
  @Component({
11
15
  selector: 'gn-ui-metadata-info',
@@ -16,7 +20,7 @@ import { DatasetRecord } from '../../../../../../libs/common/domain/src/lib/mode
16
20
  export class MetadataInfoComponent {
17
21
  @Input() metadata: Partial<DatasetRecord>
18
22
  @Input() incomplete: boolean
19
- @Output() keyword = new EventEmitter<string>()
23
+ @Output() keyword = new EventEmitter<Keyword>()
20
24
  updatedTimes: number
21
25
 
22
26
  get hasUsage() {
@@ -73,11 +77,24 @@ export class MetadataInfoComponent {
73
77
  }
74
78
  }
75
79
 
80
+ get temporalExtent(): { start: string; end: string } {
81
+ const temporalExtents = this.metadata.temporalExtents
82
+ return getTemporalRangeUnion(temporalExtents)
83
+ }
84
+
85
+ get shownOrganization() {
86
+ return this.metadata.ownerOrganization
87
+ }
88
+
89
+ get resourceContact() {
90
+ return this.metadata.contactsForResource?.[0]
91
+ }
92
+
76
93
  fieldReady(propName: string) {
77
94
  return !this.incomplete || propName in this.metadata
78
95
  }
79
96
 
80
- onKeywordClick(keyword: string) {
97
+ onKeywordClick(keyword: Keyword) {
81
98
  this.keyword.emit(keyword)
82
99
  }
83
100
  }
@@ -55,7 +55,7 @@ export class MetadataQualityComponent implements OnChanges {
55
55
  this.items = []
56
56
  this.add('title', !!this.metadata?.title)
57
57
  this.add('description', !!this.metadata?.abstract)
58
- this.add('topic', this.metadata?.themes?.length > 0)
58
+ this.add('topic', this.metadata?.topics?.length > 0)
59
59
  this.add('keywords', this.metadata?.keywords?.length > 0)
60
60
  this.add('legalConstraints', this.metadata?.legalConstraints?.length > 0)
61
61
  this.add('organisation', !!contact?.organization)
@@ -1,13 +1,13 @@
1
1
  <div
2
2
  #containerElement
3
- class="h-full w-full relative shrink-0 overflow-hidden flex items-center"
3
+ class="h-full w-full relative shrink-0 overflow-hidden flex items-center justify-center"
4
4
  [ngClass]="isPlaceholder ? 'bg-gray-100' : 'bg-white'"
5
5
  [attr.data-cy-is-placeholder]="isPlaceholder.toString()"
6
6
  >
7
7
  <img
8
8
  #imageElement
9
9
  class="relative w-full object-center"
10
- [ngClass]="imgFit === 'contain' ? 'h-4/5' : 'h-full'"
10
+ [ngClass]="imgFit === 'contain' ? 'h-4/5 w-4/5' : 'h-full'"
11
11
  [ngStyle]="{ objectFit: imgFit }"
12
12
  alt="thumbnail"
13
13
  loading="lazy"
@@ -45,6 +45,7 @@ import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-over
45
45
  UiInputsModule,
46
46
  FormsModule,
47
47
  NgOptimizedImage,
48
+ MarkdownParserComponent,
48
49
  ],
49
50
  declarations: [
50
51
  MetadataInfoComponent,
@@ -67,7 +68,6 @@ import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-over
67
68
  PaginationButtonsComponent,
68
69
  MaxLinesComponent,
69
70
  RecordApiFormComponent,
70
- MarkdownParserComponent,
71
71
  ImageOverlayPreviewComponent,
72
72
  ],
73
73
  exports: [
@@ -12,6 +12,7 @@ import { propagateToDocumentOnly } from '../../../../../../libs/util/shared/src'
12
12
  templateUrl: './button.component.html',
13
13
  styleUrls: ['./button.component.css'],
14
14
  changeDetection: ChangeDetectionStrategy.OnPush,
15
+ standalone: true,
15
16
  })
16
17
  export class ButtonComponent {
17
18
  private btnClass: string
@@ -1,6 +1,6 @@
1
1
  <gn-ui-button
2
2
  type="outline"
3
- extraClass="w-full !p-[8px] !pl-[16px]"
3
+ extraClass="bg-background w-full !p-[8px] !pl-[16px]"
4
4
  [title]="title"
5
5
  [attr.aria-owns]="id"
6
6
  (buttonClick)="openOverlay()"
@@ -9,7 +9,9 @@
9
9
  <gn-ui-button
10
10
  type="outline"
11
11
  class="grow min-w-0"
12
- extraClass="!p-[8px] !pl-[16px] flex flex-row w-full {{ extraBtnClass }}"
12
+ extraClass="bg-background !p-[8px] !pl-[16px] flex flex-row w-full {{
13
+ extraBtnClass
14
+ }}"
13
15
  [title]="title"
14
16
  [attr.aria-owns]="id"
15
17
  (buttonClick)="openOverlay()"
@@ -0,0 +1,3 @@
1
+ button {
2
+ color: var(--navigation-button-color, --color-background);
3
+ }
@@ -1,5 +1,5 @@
1
1
  <button
2
- class="group flex items-center justify-center gap-1 backdrop-blur p-1 bg-primary-opacity-30 text-white rounded content-center"
2
+ class="group flex items-center justify-center gap-1 backdrop-blur p-1 bg-primary-opacity-30 rounded content-center"
3
3
  >
4
4
  <mat-icon class="material-symbols-outlined align-middle w-[18px]">{{
5
5
  icon
@@ -12,6 +12,7 @@ import { distinctUntilChanged } from 'rxjs/operators'
12
12
  selector: 'gn-ui-text-area',
13
13
  templateUrl: './text-area.component.html',
14
14
  styleUrls: ['./text-area.component.css'],
15
+ standalone: true,
15
16
  })
16
17
  export class TextAreaComponent implements AfterViewInit {
17
18
  @Input() value = ''
@@ -47,10 +47,8 @@ import { EditableLabelDirective } from './editable-label/editable-label.directiv
47
47
  declarations: [
48
48
  DropdownSelectorComponent,
49
49
  AutocompleteComponent,
50
- ButtonComponent,
51
50
  TextInputComponent,
52
51
  DragAndDropFileInputComponent,
53
- TextAreaComponent,
54
52
  ChipsInputComponent,
55
53
  NavigationButtonComponent,
56
54
  StarToggleComponent,
@@ -89,6 +87,8 @@ import { EditableLabelDirective } from './editable-label/editable-label.directiv
89
87
  MatDatepickerModule,
90
88
  MatNativeDateModule,
91
89
  EditableLabelDirective,
90
+ TextAreaComponent,
91
+ ButtonComponent,
92
92
  ],
93
93
  exports: [
94
94
  DropdownSelectorComponent,
@@ -4,6 +4,7 @@
4
4
  </div>
5
5
  </div>
6
6
  <div
7
+ *ngIf="steps.length > 1"
7
8
  class="absolute right-0 top-0 flex flex-row justify-center gap-[10px] p-1"
8
9
  [ngClass]="stepsContainerClass"
9
10
  >
@@ -40,6 +40,24 @@ export const LANG_3_TO_2_MAPPER = {
40
40
  slo: 'sk',
41
41
  }
42
42
 
43
+ export const LANGUAGE_NAMES = {
44
+ en: 'English',
45
+ nl: 'Nederlands',
46
+ fr: 'Français',
47
+ de: 'Deutsch',
48
+ ko: '한국어',
49
+ es: 'Español',
50
+ cs: 'Čeština',
51
+ ca: 'Català',
52
+ fi: 'Suomi',
53
+ is: 'Íslenska',
54
+ it: 'Italiano',
55
+ pt: 'Português',
56
+ ru: 'Русский',
57
+ zh: '中文',
58
+ sk: 'Slovenčina',
59
+ }
60
+
43
61
  // Caution: changing this can break language selection from third parties!
44
62
  export const LANGUAGE_STORAGE_KEY = 'geonetwork-ui-language'
45
63
 
@@ -6,3 +6,4 @@ export * from './sort-by'
6
6
  export * from './url'
7
7
  export * from './event'
8
8
  export * from './fuzzy-filter'
9
+ export * from './temporal-extent-union'
@@ -0,0 +1,32 @@
1
+ export function getTemporalRangeUnion(ranges) {
2
+ let earliestStartDate = Infinity
3
+ let latestEndDate = -Infinity
4
+ if (ranges.length) {
5
+ for (let i = 0; i < ranges.length; i++) {
6
+ const rangeStart = ranges[i].start
7
+ ? new Date(ranges[i].start).getTime()
8
+ : -Infinity
9
+ const rangeEnd = ranges[i].end
10
+ ? new Date(ranges[i].end).getTime()
11
+ : Infinity
12
+ if (rangeStart < earliestStartDate) {
13
+ earliestStartDate = rangeStart
14
+ }
15
+ if (rangeEnd > latestEndDate) {
16
+ latestEndDate = rangeEnd
17
+ }
18
+ }
19
+ return {
20
+ start:
21
+ earliestStartDate !== -Infinity
22
+ ? new Date(earliestStartDate).toLocaleDateString()
23
+ : undefined,
24
+ end:
25
+ latestEndDate !== Infinity
26
+ ? new Date(latestEndDate).toLocaleDateString()
27
+ : undefined,
28
+ }
29
+ } else {
30
+ return undefined
31
+ }
32
+ }
package/tailwind.base.css CHANGED
@@ -31,8 +31,8 @@
31
31
 
32
32
  .btn-outline {
33
33
  @apply btn text-main
34
- bg-white hover:text-primary-darker focus:text-primary-darker active:text-primary-black
35
- border border-gray-300 hover:border-primary-lighter focus:border-primary-lighter focus:ring-4 focus:ring-primary-lightest active:border-primary-darker;
34
+ bg-transparent hover:text-primary-darker focus:text-primary-darker active:text-primary-black
35
+ border border-gray-300 hover:border-primary-lighter focus:border-primary-lighter focus:ring-4 focus:ring-primary-lightest active:border-primary-darker;
36
36
  }
37
37
 
38
38
  .btn-light {
@@ -16,7 +16,7 @@
16
16
  "chart.type.line": "Liniendiagramm",
17
17
  "chart.type.lineSmooth": "Geglättes Liniendiagramm",
18
18
  "chart.type.pie": "Kreisdiagramm",
19
- "dashboard.createRecord": "",
19
+ "dashboard.createRecord": "Neuer Eintrag",
20
20
  "dashboard.labels.mySpace": "Mein Bereich",
21
21
  "dashboard.records.all": "Katalog",
22
22
  "dashboard.records.myDraft": "Meine Entwürfe",
@@ -29,8 +29,8 @@
29
29
  "dashboard.records.userEmail": "E-Mail",
30
30
  "dashboard.records.username": "Benutzername",
31
31
  "dashboard.records.users": "{count, plural, =1{Benutzer} other{Benutzer}}",
32
- "dashboard.results.listMetadata": "",
33
- "dashboard.results.listResources": "",
32
+ "dashboard.results.listMetadata": "Metadaten anzeigen",
33
+ "dashboard.results.listResources": "Ressourcen anzeigen",
34
34
  "datafeeder.analysisProgressBar.illustration.fileFormatDetection": "Dateiformat-Erkennung",
35
35
  "datafeeder.analysisProgressBar.illustration.gatheringDatasetInformation": "Sammeln von Datensatzinformationen",
36
36
  "datafeeder.analysisProgressBar.illustration.samplingData": "Datenauswahl",
@@ -157,28 +157,28 @@
157
157
  "facets.block.title.tag.default": "Stichwort",
158
158
  "facets.block.title.th_regions_tree.default": "Regionen",
159
159
  "favorite.not.authenticated.tooltip": "<div><a href=' {link} '>Anmelden</a>, um auf diese Funktion zuzugreifen</div>",
160
- "language.ca": "Català",
161
- "language.cs": "Čeština",
160
+ "language.ca": "Katalanisch",
161
+ "language.cs": "Tschechisch",
162
162
  "language.de": "Deutsch",
163
- "language.en": "English",
164
- "language.es": "Español",
165
- "language.fi": "Suomi",
166
- "language.fr": "Français",
167
- "language.is": "Íslenska",
168
- "language.it": "Italiano",
169
- "language.ko": "한국어",
170
- "language.nl": "Nederlands",
171
- "language.pt": "Português",
172
- "language.ru": "Русский",
173
- "language.sk": "Slovenčina",
174
- "language.zh": "中文",
163
+ "language.en": "Englisch",
164
+ "language.es": "Spanisch",
165
+ "language.fi": "Finnisch",
166
+ "language.fr": "Französisch",
167
+ "language.is": "Isländisch",
168
+ "language.it": "Italienisch",
169
+ "language.ko": "Koreanisch",
170
+ "language.nl": "Niederländisch",
171
+ "language.pt": "Portugiesisch",
172
+ "language.ru": "Russisch",
173
+ "language.sk": "Slowakisch",
174
+ "language.zh": "Chinesisch",
175
175
  "map.add.layer": "Eine Ebene hinzufügen",
176
176
  "map.add.layer.catalog": "Aus dem Katalog",
177
177
  "map.add.layer.file": "Aus einer Datei",
178
178
  "map.add.layer.wfs": "Aus WFS",
179
179
  "map.add.layer.wms": "Aus WMS",
180
180
  "map.addFromFile.placeholder": "Klicke hier oder ziehe eine Datei herein",
181
- "map.geocoding.placeholder": "",
181
+ "map.geocoding.placeholder": "Nach einem Ort suchen",
182
182
  "map.help.addFromFile": "Klicke oder ziehe eine Datei herein um eine Karte hinzuzufügen (momentan wird nur das GeoJSON-Format unterstützt).",
183
183
  "map.layer.add": "Hinzufügen",
184
184
  "map.layers.available": "Verfügbare Layer",
@@ -222,17 +222,20 @@
222
222
  "record.metadata.author": "Autor",
223
223
  "record.metadata.catalog": "Katalog",
224
224
  "record.metadata.contact": "Kontakt",
225
- "record.metadata.details": "Technische Informationen",
225
+ "record.metadata.creation": "Erstellungsdatum",
226
+ "record.metadata.details": "Über die Daten",
226
227
  "record.metadata.download": "Downloads",
227
228
  "record.metadata.formats": "Formate",
228
229
  "record.metadata.keywords": "Stichworte",
229
- "record.metadata.lastUpdate": "Zuletzt aktualisiert am",
230
+ "record.metadata.languages": "Sprachen",
231
+ "record.metadata.lastUpdate": "Zuletzt aktualisiert am {date}",
230
232
  "record.metadata.links": "Links",
231
233
  "record.metadata.noUsage": "Für diesen Datensatz sind keine Nutzungsbedingungen angegeben.",
232
- "record.metadata.origin": "Über die Daten",
233
- "record.metadata.otherConstraints": "",
234
- "record.metadata.owner": "",
234
+ "record.metadata.otherConstraints": "Zusätzliche Bedingungen",
235
+ "record.metadata.owner": "Herkunftskatalog",
235
236
  "record.metadata.preview": "Vorschau",
237
+ "record.metadata.producer": "Datenproduzent",
238
+ "record.metadata.publication": "Veröffentlichungsdatum",
236
239
  "record.metadata.publications": "Veröffentlichungen",
237
240
  "record.metadata.quality": "Metadatenqualität",
238
241
  "record.metadata.quality.contact.failed": "Kontakt nicht angegeben",
@@ -254,13 +257,17 @@
254
257
  "record.metadata.quality.updateFrequency.success": "Aktualisierungsfrequenz angegeben",
255
258
  "record.metadata.related": "Ähnliche Datensätze",
256
259
  "record.metadata.sheet": "Weitere Informationen verfügbar unter:",
257
- "record.metadata.status": "",
258
- "record.metadata.themes": "Kategorien",
260
+ "record.metadata.status": "Status",
261
+ "record.metadata.technical": "Technische Informationen",
262
+ "record.metadata.temporalExtent": "Zeitlicher Umfang",
263
+ "record.metadata.temporalExtent.fromDateToDate": "Von {start} bis {end}",
264
+ "record.metadata.temporalExtent.sinceDate": "Seit {start}",
265
+ "record.metadata.temporalExtent.untilDate": "Bis {end}",
259
266
  "record.metadata.title": "Titel",
267
+ "record.metadata.topics": "Kategorien",
260
268
  "record.metadata.type": "Geographischer Datensatz",
261
269
  "record.metadata.uniqueId": "Eindeutige Kennung",
262
270
  "record.metadata.updateFrequency": "Aktualisierungsfrequenz der Daten",
263
- "record.metadata.updateStatus": "Aktualisierungsstatus der Daten",
264
271
  "record.metadata.updatedOn": "Letzte Aktualisierung der Dateninformationen",
265
272
  "record.metadata.usage": "Nutzung und Einschränkungen",
266
273
  "record.more.details": "Weitere Details",
@@ -323,7 +330,7 @@
323
330
  "table.object.count": "Objekte in diesem Datensatz",
324
331
  "table.select.data": "Datenquelle",
325
332
  "tooltip.html.copy": "HTML kopieren",
326
- "tooltip.id.copy": "",
333
+ "tooltip.id.copy": "Eindeutige Kennung kopieren",
327
334
  "tooltip.url.copy": "URL kopieren",
328
335
  "tooltip.url.open": "URL öffnen",
329
336
  "ui.readLess": "Weniger lesen",