geonetwork-ui 2.8.0-dev.e22966206 → 2.8.0-dev.e46888fcc

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 (158) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.mjs +3 -3
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +24 -1
  3. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.mjs +7 -7
  4. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +3 -2
  5. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +4 -3
  6. package/esm2022/libs/api/repository/src/lib/gn4/elasticsearch/constant.mjs +1 -2
  7. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  8. package/esm2022/libs/feature/dataviz/src/index.mjs +1 -2
  9. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +9 -2
  10. package/esm2022/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.mjs +3 -3
  11. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +23 -3
  12. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +2 -2
  13. package/esm2022/libs/feature/record/src/index.mjs +2 -1
  14. package/esm2022/libs/feature/record/src/lib/stac-view/stac-view.component.mjs +138 -0
  15. package/esm2022/libs/feature/record/src/lib/state/mdview.facade.mjs +13 -1
  16. package/esm2022/libs/feature/search/src/lib/constants.mjs +1 -2
  17. package/esm2022/libs/ui/elements/src/index.mjs +3 -1
  18. package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +1 -1
  19. package/esm2022/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.mjs +37 -0
  20. package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +5 -9
  21. package/esm2022/libs/ui/elements/src/lib/stac-items-result-grid/stac-items-result-grid.component.mjs +18 -0
  22. package/esm2022/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.mjs +5 -5
  23. package/esm2022/libs/ui/inputs/src/index.mjs +2 -1
  24. package/esm2022/libs/ui/inputs/src/lib/date-picker/date-picker.component.mjs +21 -7
  25. package/esm2022/libs/ui/inputs/src/lib/date-range-inputs/date-range-inputs.component.mjs +35 -0
  26. package/esm2022/libs/ui/layout/src/lib/paginable.interface.mjs +1 -1
  27. package/esm2022/libs/ui/layout/src/lib/previous-next-buttons/previous-next-buttons.component.mjs +13 -5
  28. package/esm2022/libs/util/i18n/src/lib/date-locales.mjs +33 -0
  29. package/esm2022/libs/util/shared/src/index.mjs +2 -1
  30. package/esm2022/libs/util/shared/src/lib/humanize-date.directive.mjs +33 -0
  31. package/esm2022/libs/util/shared/src/lib/services/date.service.mjs +19 -2
  32. package/esm2022/translations/de.json +12 -4
  33. package/esm2022/translations/en.json +12 -4
  34. package/esm2022/translations/es.json +8 -0
  35. package/esm2022/translations/fr.json +12 -4
  36. package/esm2022/translations/it.json +12 -4
  37. package/esm2022/translations/nl.json +8 -0
  38. package/esm2022/translations/pt.json +8 -0
  39. package/esm2022/translations/sk.json +9 -1
  40. package/fesm2022/geonetwork-ui-date-locales-MYnkDJ5h.mjs +35 -0
  41. package/fesm2022/geonetwork-ui-date-locales-MYnkDJ5h.mjs.map +1 -0
  42. package/fesm2022/geonetwork-ui.mjs +458 -156
  43. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  44. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  45. package/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.d.ts.map +1 -1
  46. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +5 -1
  47. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
  48. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  49. package/libs/api/repository/src/lib/gn4/elasticsearch/constant.d.ts.map +1 -1
  50. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +6 -1
  51. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  52. package/libs/feature/dataviz/src/index.d.ts +0 -1
  53. package/libs/feature/dataviz/src/index.d.ts.map +1 -1
  54. package/libs/feature/dataviz/src/lib/service/data.service.d.ts +2 -1
  55. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  56. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +2 -0
  57. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  58. package/libs/feature/record/src/index.d.ts +1 -0
  59. package/libs/feature/record/src/index.d.ts.map +1 -1
  60. package/libs/feature/record/src/lib/stac-view/stac-view.component.d.ts +35 -0
  61. package/libs/feature/record/src/lib/stac-view/stac-view.component.d.ts.map +1 -0
  62. package/libs/feature/record/src/lib/state/mdview.facade.d.ts +4 -0
  63. package/libs/feature/record/src/lib/state/mdview.facade.d.ts.map +1 -1
  64. package/libs/feature/search/src/lib/constants.d.ts.map +1 -1
  65. package/libs/ui/elements/src/index.d.ts +2 -0
  66. package/libs/ui/elements/src/index.d.ts.map +1 -1
  67. package/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.d.ts +8 -0
  68. package/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.d.ts.map +1 -0
  69. package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts +0 -2
  70. package/libs/ui/elements/src/lib/metadata-info/metadata-info.component.d.ts.map +1 -1
  71. package/libs/ui/elements/src/lib/stac-items-result-grid/stac-items-result-grid.component.d.ts +8 -0
  72. package/libs/ui/elements/src/lib/stac-items-result-grid/stac-items-result-grid.component.d.ts.map +1 -0
  73. package/libs/ui/inputs/src/index.d.ts +1 -0
  74. package/libs/ui/inputs/src/index.d.ts.map +1 -1
  75. package/libs/ui/inputs/src/lib/date-picker/date-picker.component.d.ts +5 -0
  76. package/libs/ui/inputs/src/lib/date-picker/date-picker.component.d.ts.map +1 -1
  77. package/libs/ui/inputs/src/lib/date-range-inputs/date-range-inputs.component.d.ts +12 -0
  78. package/libs/ui/inputs/src/lib/date-range-inputs/date-range-inputs.component.d.ts.map +1 -0
  79. package/libs/ui/layout/src/lib/paginable.interface.d.ts +3 -3
  80. package/libs/ui/layout/src/lib/paginable.interface.d.ts.map +1 -1
  81. package/libs/ui/layout/src/lib/previous-next-buttons/previous-next-buttons.component.d.ts +2 -1
  82. package/libs/ui/layout/src/lib/previous-next-buttons/previous-next-buttons.component.d.ts.map +1 -1
  83. package/libs/util/i18n/src/lib/date-locales.d.ts +5 -0
  84. package/libs/util/i18n/src/lib/date-locales.d.ts.map +1 -0
  85. package/libs/util/shared/src/index.d.ts +1 -0
  86. package/libs/util/shared/src/index.d.ts.map +1 -1
  87. package/libs/util/shared/src/lib/humanize-date.directive.d.ts +15 -0
  88. package/libs/util/shared/src/lib/humanize-date.directive.d.ts.map +1 -0
  89. package/libs/util/shared/src/lib/services/date.service.d.ts +4 -0
  90. package/libs/util/shared/src/lib/services/date.service.d.ts.map +1 -1
  91. package/package.json +1 -1
  92. package/src/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.ts +2 -2
  93. package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +1 -1
  94. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.service+eaux-usees.ts +1 -1
  95. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +5 -2
  96. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -1
  97. package/src/libs/api/metadata-converter/src/lib/fixtures/georhena.records.ts +1 -1
  98. package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +2 -2
  99. package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.reuse.ts +1 -1
  100. package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.service+napitswallonia.ts +1 -1
  101. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +26 -0
  102. package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +13 -6
  103. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +6 -2
  104. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +4 -2
  105. package/src/libs/api/repository/src/lib/gn4/elasticsearch/constant.ts +0 -1
  106. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +8 -1
  107. package/src/libs/feature/dataviz/src/index.ts +0 -1
  108. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +14 -0
  109. package/src/libs/feature/editor/src/lib/components/multilingual-panel/multilingual-panel.component.html +1 -0
  110. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +3 -3
  111. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +30 -0
  112. package/src/libs/feature/editor/src/lib/fields.config.ts +1 -1
  113. package/src/libs/feature/record/src/index.ts +1 -0
  114. package/src/libs/feature/record/src/lib/stac-view/stac-view.component.css +3 -0
  115. package/src/libs/feature/record/src/lib/stac-view/stac-view.component.html +68 -0
  116. package/src/libs/feature/record/src/lib/stac-view/stac-view.component.ts +190 -0
  117. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +19 -0
  118. package/src/libs/feature/search/src/lib/constants.ts +0 -1
  119. package/src/libs/ui/elements/src/index.ts +2 -0
  120. package/src/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.html +31 -0
  121. package/src/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.ts +30 -0
  122. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +16 -12
  123. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.ts +2 -9
  124. package/src/libs/ui/elements/src/lib/stac-items-result-grid/stac-items-result-grid.component.css +0 -0
  125. package/src/libs/ui/elements/src/lib/stac-items-result-grid/stac-items-result-grid.component.html +13 -0
  126. package/src/libs/ui/elements/src/lib/stac-items-result-grid/stac-items-result-grid.component.ts +15 -0
  127. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.html +1 -1
  128. package/src/libs/ui/elements/src/lib/user-feedback-item/user-feedback-item.component.ts +2 -2
  129. package/src/libs/ui/inputs/src/index.ts +1 -0
  130. package/src/libs/ui/inputs/src/lib/date-picker/date-picker.component.ts +17 -1
  131. package/src/libs/ui/inputs/src/lib/date-range-inputs/date-range-inputs.component.css +0 -0
  132. package/src/libs/ui/inputs/src/lib/date-range-inputs/date-range-inputs.component.html +15 -0
  133. package/src/libs/ui/inputs/src/lib/date-range-inputs/date-range-inputs.component.ts +41 -0
  134. package/src/libs/ui/layout/src/lib/paginable.interface.ts +3 -3
  135. package/src/libs/ui/layout/src/lib/previous-next-buttons/previous-next-buttons.component.html +12 -6
  136. package/src/libs/ui/layout/src/lib/previous-next-buttons/previous-next-buttons.component.ts +4 -1
  137. package/src/libs/util/i18n/src/lib/date-locales.ts +63 -0
  138. package/src/libs/util/shared/src/index.ts +1 -0
  139. package/src/libs/util/shared/src/lib/humanize-date.directive.ts +35 -0
  140. package/src/libs/util/shared/src/lib/services/date.service.ts +27 -1
  141. package/translations/de.json +12 -4
  142. package/translations/en.json +12 -4
  143. package/translations/es.json +8 -0
  144. package/translations/fr.json +12 -4
  145. package/translations/it.json +12 -4
  146. package/translations/nl.json +8 -0
  147. package/translations/pt.json +8 -0
  148. package/translations/sk.json +9 -1
  149. package/esm2022/libs/feature/dataviz/src/lib/stac-view/stac-view.component.mjs +0 -22
  150. package/esm2022/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.mjs +0 -59
  151. package/libs/feature/dataviz/src/lib/stac-view/stac-view.component.d.ts +0 -11
  152. package/libs/feature/dataviz/src/lib/stac-view/stac-view.component.d.ts.map +0 -1
  153. package/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.d.ts +0 -11
  154. package/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.d.ts.map +0 -1
  155. package/src/libs/feature/dataviz/src/lib/stac-view/stac-view.component.html +0 -5
  156. package/src/libs/feature/dataviz/src/lib/stac-view/stac-view.component.ts +0 -27
  157. package/src/libs/ui/elements/src/lib/user-feedback-item/time-since.pipe.ts +0 -54
  158. /package/src/libs/{feature/dataviz/src/lib/stac-view/stac-view.component.css → ui/elements/src/lib/metadata-doi/metadata-doi.component.css} +0 -0
@@ -0,0 +1,31 @@
1
+ <div
2
+ class="border border-gray-300 rounded-lg py-4 px-5 text-black flex justify-between items-center gap-4"
3
+ >
4
+ <div class="overflow-hidden flex-1">
5
+ <p class="text-base font-medium mb-3">DOI</p>
6
+ <p
7
+ class="text-base font-medium overflow-hidden text-ellipsis whitespace-nowrap"
8
+ [title]="code"
9
+ >
10
+ {{ code }}
11
+ </p>
12
+ </div>
13
+ <div class="flex gap-2 items-start">
14
+ <gn-ui-copy-text-button
15
+ [text]="code"
16
+ [displayText]="false"
17
+ [tooltipText]="'record.metadata.doi.copy' | translate"
18
+ class="[&>div]:flex [&>div]:items-center [&>div]:justify-center [&_button]:w-[40px] [&_button]:h-[32px] [&_button]:flex [&_button]:items-center [&_button]:justify-center [&_button]:hover:bg-gray-100 [&_button]:rounded-lg [&_button]:transition-colors [&_button]:border [&_button]:border-gray-300 [&_button]:px-2 [&_button]:py-1 [&_ng-icon]:w-5 [&_ng-icon]:h-5"
19
+ ></gn-ui-copy-text-button>
20
+ <a
21
+ *ngIf="link"
22
+ [href]="link"
23
+ target="_blank"
24
+ rel="noopener noreferrer"
25
+ class="w-[40px] h-[32px] flex items-center justify-center hover:bg-gray-100 rounded-lg transition-colors border border-gray-300 px-2 py-1"
26
+ [matTooltip]="'record.metadata.doi.open' | translate"
27
+ >
28
+ <ng-icon name="matOpenInNew" size="20"></ng-icon>
29
+ </a>
30
+ </div>
31
+ </div>
@@ -0,0 +1,30 @@
1
+ import { Component, Input } from '@angular/core'
2
+ import { CommonModule } from '@angular/common'
3
+ import { NgIcon, provideIcons } from '@ng-icons/core'
4
+ import { MatTooltipModule } from '@angular/material/tooltip'
5
+ import { matOpenInNew } from '@ng-icons/material-icons/baseline'
6
+ import { TranslatePipe } from '@ngx-translate/core'
7
+ import { CopyTextButtonComponent } from '../../../../../../libs/ui/inputs/src'
8
+
9
+ @Component({
10
+ selector: 'gn-ui-metadata-doi',
11
+ standalone: true,
12
+ imports: [
13
+ CommonModule,
14
+ MatTooltipModule,
15
+ NgIcon,
16
+ TranslatePipe,
17
+ CopyTextButtonComponent,
18
+ ],
19
+ templateUrl: './metadata-doi.component.html',
20
+ styleUrl: './metadata-doi.component.css',
21
+ viewProviders: [
22
+ provideIcons({
23
+ matOpenInNew,
24
+ }),
25
+ ],
26
+ })
27
+ export class MetadataDoiComponent {
28
+ @Input() code!: string
29
+ @Input() link?: string
30
+ }
@@ -186,27 +186,30 @@
186
186
  data-test="details-panel-resource-created"
187
187
  >
188
188
  <p class="text-sm" translate>record.metadata.creation</p>
189
- <p class="text-primary font-medium mt-1 resource-created">
190
- {{ formatDate(metadata.resourceCreated) }}
191
- </p>
189
+ <p
190
+ class="text-primary font-medium mt-1 resource-created"
191
+ [gnUiHumanizeDate]="metadata.resourceCreated"
192
+ ></p>
192
193
  </div>
193
194
  <div
194
195
  *ngIf="metadata.resourcePublished"
195
196
  data-test="details-panel-resource-published"
196
197
  >
197
198
  <p class="text-sm" translate>record.metadata.publication</p>
198
- <p class="text-primary font-medium mt-1 resource-published">
199
- {{ formatDate(metadata.resourcePublished) }}
200
- </p>
199
+ <p
200
+ class="text-primary font-medium mt-1 resource-published"
201
+ [gnUiHumanizeDate]="metadata.resourcePublished"
202
+ ></p>
201
203
  </div>
202
204
  <div
203
205
  *ngIf="metadata.resourceUpdated"
204
206
  data-test="details-panel-resource-updated"
205
207
  >
206
208
  <p class="text-sm" translate>record.metadata.update</p>
207
- <p class="text-primary font-medium mt-1 resource-updated">
208
- {{ formatDate(metadata.resourceUpdated) }}
209
- </p>
209
+ <p
210
+ class="text-primary font-medium mt-1 resource-updated"
211
+ [gnUiHumanizeDate]="metadata.resourceUpdated"
212
+ ></p>
210
213
  </div>
211
214
  <div
212
215
  *ngIf="metadata.kind === 'dataset' && metadata.updateFrequency"
@@ -294,9 +297,10 @@
294
297
  <div class="flex flex-col gap-4 mr-4 py-5 rounded text-gray-700">
295
298
  <div *ngIf="metadata.recordUpdated">
296
299
  <p class="text-sm" translate>record.metadata.updatedOn</p>
297
- <p class="text-primary font-medium">
298
- {{ metadata.recordUpdated && formatDateTime(metadata.recordUpdated) }}
299
- </p>
300
+ <p
301
+ class="text-primary font-medium"
302
+ [gnUiHumanizeDate]="metadata.recordUpdated"
303
+ ></p>
300
304
  </div>
301
305
  <div *ngIf="metadata.landingPage">
302
306
  <p class="text-sm" translate>record.metadata.sheet</p>
@@ -26,7 +26,7 @@ import { matOpenInNew } from '@ng-icons/material-icons/baseline'
26
26
  import { matMailOutline } from '@ng-icons/material-icons/outline'
27
27
  import { ThumbnailComponent } from '../thumbnail/thumbnail.component'
28
28
  import { GnUiLinkifyDirective } from './linkify.directive'
29
-
29
+ import { GnUiHumanizeDateDirective } from '../../../../../../libs/util/shared/src'
30
30
  import { CommonModule } from '@angular/common'
31
31
  import { SpatialExtentComponent } from '../../../../../../libs/ui/map/src'
32
32
 
@@ -49,6 +49,7 @@ import { SpatialExtentComponent } from '../../../../../../libs/ui/map/src'
49
49
  CopyTextButtonComponent,
50
50
  NgIcon,
51
51
  GnUiLinkifyDirective,
52
+ GnUiHumanizeDateDirective,
52
53
  SpatialExtentComponent,
53
54
  ],
54
55
  viewProviders: [
@@ -146,12 +147,4 @@ export class MetadataInfoComponent {
146
147
  onKeywordClick(keyword: Keyword) {
147
148
  this.keyword.emit(keyword)
148
149
  }
149
-
150
- formatDate(date: Date): string {
151
- return this.dateService.formatDate(date)
152
- }
153
-
154
- formatDateTime(date: Date): string {
155
- return this.dateService.formatDateTime(date)
156
- }
157
150
  }
@@ -0,0 +1,13 @@
1
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-[10px]">
2
+ <div *ngFor="let item of items">
3
+ <div
4
+ data-cy="stac-item-card"
5
+ class="h-[173px] flex flex-col justify-between gap-4 bg-white rounded-lg border border-gray-300 px-5 py-3 mx-auto"
6
+ >
7
+ <h2 class="text-xl text-black line-clamp-4 break-words">
8
+ {{ item.id }}
9
+ </h2>
10
+ <p class="truncate">{{ item.properties.datetime }}</p>
11
+ </div>
12
+ </div>
13
+ </div>
@@ -0,0 +1,15 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
3
+ import { StacItem } from '@camptocamp/ogc-client'
4
+
5
+ @Component({
6
+ selector: 'gn-ui-stac-items-result-grid',
7
+ standalone: true,
8
+ imports: [CommonModule],
9
+ templateUrl: './stac-items-result-grid.component.html',
10
+ styleUrl: './stac-items-result-grid.component.css',
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ })
13
+ export class StacItemsResultGridComponent {
14
+ @Input() items: StacItem[] = []
15
+ }
@@ -13,7 +13,7 @@
13
13
  </div>
14
14
  <div class="p-4 flex flex-col">
15
15
  <span>{{ userFeedbackParent.authorName }}</span>
16
- <span> {{ userFeedbackParent.date | timeSince }}</span>
16
+ <span [gnUiHumanizeDate]="userFeedbackParent.date"></span>
17
17
  </div>
18
18
  </div>
19
19
  <div data-cy="commentText" class="mt-4 whitespace-pre-line">
@@ -11,13 +11,13 @@ import {
11
11
  UserFeedbackViewModel,
12
12
  } from '../../../../../../libs/common/domain/src/lib/model/record'
13
13
  import { UserModel } from '../../../../../../libs/common/domain/src/lib/model/user'
14
- import { TimeSincePipe } from './time-since.pipe'
15
14
  import { CommonModule } from '@angular/common'
16
15
  import { ButtonComponent, TextAreaComponent } from '../../../../../../libs/ui/inputs/src'
17
16
  import { TranslatePipe } from '@ngx-translate/core'
18
17
  import { SpinningLoaderComponent } from '../../../../../../libs/ui/widgets/src'
19
18
  import { NgIcon, provideIcons } from '@ng-icons/core'
20
19
  import { matSendOutline } from '@ng-icons/material-icons/outline'
20
+ import { GnUiHumanizeDateDirective } from '../../../../../../libs/util/shared/src'
21
21
 
22
22
  @Component({
23
23
  selector: 'gn-ui-user-feedback-item',
@@ -27,11 +27,11 @@ import { matSendOutline } from '@ng-icons/material-icons/outline'
27
27
  standalone: true,
28
28
  imports: [
29
29
  CommonModule,
30
- TimeSincePipe,
31
30
  TextAreaComponent,
32
31
  TranslatePipe,
33
32
  ButtonComponent,
34
33
  SpinningLoaderComponent,
34
+ GnUiHumanizeDateDirective,
35
35
  NgIcon,
36
36
  ],
37
37
  viewProviders: [
@@ -24,3 +24,4 @@ export * from './lib/text-input/text-input.component'
24
24
  export * from './lib/url-input/url-input.component'
25
25
  export * from './lib/viewport-intersector/viewport-intersector.component'
26
26
  export * from './lib/search-feature-catalog/search-feature-catalog.component'
27
+ export * from './lib/date-range-inputs/date-range-inputs.component'
@@ -5,7 +5,11 @@ import {
5
5
  Input,
6
6
  Output,
7
7
  } from '@angular/core'
8
- import { MatNativeDateModule } from '@angular/material/core'
8
+ import {
9
+ DateAdapter,
10
+ MAT_DATE_LOCALE,
11
+ MatNativeDateModule,
12
+ } from '@angular/material/core'
9
13
  import { MatDatepickerModule } from '@angular/material/datepicker'
10
14
  import { ButtonComponent } from '../button/button.component'
11
15
  import {
@@ -14,6 +18,7 @@ import {
14
18
  provideNgIconsConfig,
15
19
  } from '@ng-icons/core'
16
20
  import { iconoirCalendar } from '@ng-icons/iconoir'
21
+ import { TranslateService } from '@ngx-translate/core'
17
22
 
18
23
  @Component({
19
24
  selector: 'gn-ui-date-picker',
@@ -32,9 +37,20 @@ import { iconoirCalendar } from '@ng-icons/iconoir'
32
37
  provideNgIconsConfig({
33
38
  size: '1.5rem',
34
39
  }),
40
+ {
41
+ provide: MAT_DATE_LOCALE,
42
+ useFactory: (locale: string) => locale,
43
+ },
35
44
  ],
36
45
  })
37
46
  export class DatePickerComponent {
38
47
  @Input() date: Date
39
48
  @Output() dateChange = new EventEmitter<Date>()
49
+
50
+ constructor(
51
+ private dateAdapter: DateAdapter<Date>,
52
+ private translate: TranslateService
53
+ ) {
54
+ this.dateAdapter.setLocale(this.translate.currentLang)
55
+ }
40
56
  }
@@ -0,0 +1,15 @@
1
+ <div class="m-8">
2
+ <p class="mb-4" translate>daterange.filter.period</p>
3
+ <p translate>daterange.filter.from</p>
4
+ <gn-ui-date-picker
5
+ id="start-date-picker"
6
+ [date]="temporalExtent?.start"
7
+ (dateChange)="onStartDateChange($event)"
8
+ ></gn-ui-date-picker>
9
+ <p class="mt-4" translate>daterange.filter.to</p>
10
+ <gn-ui-date-picker
11
+ id="end-date-picker"
12
+ [date]="temporalExtent?.end"
13
+ (dateChange)="onEndDateChange($event)"
14
+ ></gn-ui-date-picker>
15
+ </div>
@@ -0,0 +1,41 @@
1
+ import {
2
+ ChangeDetectionStrategy,
3
+ Component,
4
+ EventEmitter,
5
+ Input,
6
+ Output,
7
+ } from '@angular/core'
8
+ import { DatePickerComponent } from '../date-picker/date-picker.component'
9
+ import { DatasetTemporalExtent } from '../../../../../../libs/common/domain/src/lib/model/record/metadata.model'
10
+ import { TranslateDirective } from '@ngx-translate/core'
11
+ import { CommonModule } from '@angular/common'
12
+
13
+ @Component({
14
+ selector: 'gn-ui-date-range-inputs',
15
+ standalone: true,
16
+ imports: [CommonModule, TranslateDirective, DatePickerComponent],
17
+ templateUrl: './date-range-inputs.component.html',
18
+ styleUrl: './date-range-inputs.component.css',
19
+ changeDetection: ChangeDetectionStrategy.OnPush,
20
+ })
21
+ export class DateRangeInputsComponent {
22
+ @Input() temporalExtent: DatasetTemporalExtent | null
23
+ @Output() temporalExtentChange =
24
+ new EventEmitter<DatasetTemporalExtent | null>()
25
+
26
+ onStartDateChange(date: Date) {
27
+ this.temporalExtent = {
28
+ ...this.temporalExtent,
29
+ start: date,
30
+ }
31
+ this.temporalExtentChange.emit(this.temporalExtent)
32
+ }
33
+
34
+ onEndDateChange(date: Date) {
35
+ this.temporalExtent = {
36
+ ...this.temporalExtent,
37
+ end: date,
38
+ }
39
+ this.temporalExtentChange.emit(this.temporalExtent)
40
+ }
41
+ }
@@ -6,9 +6,9 @@
6
6
  export interface Paginable {
7
7
  isFirstPage: boolean
8
8
  isLastPage: boolean
9
- pagesCount: number
10
- currentPage: number
11
- goToPage(index: number): void
9
+ pagesCount?: number
10
+ currentPage?: number
11
+ goToPage?(index: number): void
12
12
  goToNextPage(): void
13
13
  goToPrevPage(): void
14
14
  }
@@ -3,28 +3,34 @@
3
3
  data-test="previousButton"
4
4
  type="light"
5
5
  [extraClass]="
6
- 'w-10 h-8 px-2 py-1 rounded-lg ' +
6
+ 'w-auto min-w-10 h-8 px-2 py-1 rounded-lg ' +
7
7
  (!listComponent.isFirstPage
8
- ? 'border border-gray-300'
9
- : 'border border-gray-100')
8
+ ? 'border border-gray-300 text-main'
9
+ : 'border border-gray-100 text-gray-300')
10
10
  "
11
11
  [disabled]="listComponent.isFirstPage"
12
12
  (buttonClick)="listComponent.goToPrevPage()"
13
13
  >
14
14
  <ng-icon name="matArrowBackIos"></ng-icon>
15
+ <span *ngIf="displayLabels" class="ml-2" translate
16
+ >pagination.previousPage</span
17
+ >
15
18
  </gn-ui-button>
16
19
  <gn-ui-button
17
20
  data-test="nextButton"
18
21
  type="light"
19
22
  [extraClass]="
20
- 'w-10 h-8 px-2 py-1 rounded-lg ' +
23
+ 'w-auto min-w-10 h-8 px-2 py-1 rounded-lg ' +
21
24
  (!listComponent.isLastPage
22
- ? 'border border-gray-300'
23
- : 'border border-gray-100')
25
+ ? 'border border-gray-300 text-main'
26
+ : 'border border-gray-100 text-gray-300')
24
27
  "
25
28
  [disabled]="listComponent.isLastPage"
26
29
  (buttonClick)="listComponent.goToNextPage()"
27
30
  >
31
+ <span *ngIf="displayLabels" class="mr-2" translate
32
+ >pagination.nextPage</span
33
+ >
28
34
  <ng-icon name="matArrowForwardIos"></ng-icon>
29
35
  </gn-ui-button>
30
36
  </div>
@@ -10,13 +10,15 @@ import {
10
10
  } from '@ng-icons/material-icons/baseline'
11
11
  import { Paginable } from '../paginable.interface'
12
12
  import { ButtonComponent } from '../../../../../../libs/ui/inputs/src'
13
+ import { CommonModule } from '@angular/common'
14
+ import { TranslateDirective } from '@ngx-translate/core'
13
15
 
14
16
  @Component({
15
17
  selector: 'gn-ui-previous-next-buttons',
16
18
  templateUrl: './previous-next-buttons.component.html',
17
19
  styleUrls: ['./previous-next-buttons.component.css'],
18
20
  standalone: true,
19
- imports: [ButtonComponent, NgIconComponent],
21
+ imports: [CommonModule, ButtonComponent, NgIconComponent, TranslateDirective],
20
22
  providers: [
21
23
  provideIcons({ matArrowBackIos, matArrowForwardIos }),
22
24
  provideNgIconsConfig({
@@ -26,4 +28,5 @@ import { ButtonComponent } from '../../../../../../libs/ui/inputs/src'
26
28
  })
27
29
  export class PreviousNextButtonsComponent {
28
30
  @Input() listComponent: Paginable
31
+ @Input() displayLabels = false
29
32
  }
@@ -0,0 +1,63 @@
1
+ import { LanguageCode2 } from './language-codes'
2
+ import {
3
+ ar,
4
+ az,
5
+ ca,
6
+ cs,
7
+ cy,
8
+ da,
9
+ de,
10
+ enUS,
11
+ es,
12
+ fi,
13
+ fr,
14
+ hy,
15
+ is,
16
+ it,
17
+ ka,
18
+ ko,
19
+ Locale,
20
+ nl,
21
+ nn,
22
+ pl,
23
+ pt,
24
+ ru,
25
+ sk,
26
+ sv,
27
+ tr,
28
+ uk,
29
+ zhCN,
30
+ } from 'date-fns/locale'
31
+
32
+ // all 2-char language codes should be listed here
33
+ const locales: Record<LanguageCode2, Locale> = {
34
+ en: enUS,
35
+ nl: nl,
36
+ fr: fr,
37
+ de: de,
38
+ ko: ko,
39
+ es: es,
40
+ cs: cs,
41
+ ca: ca,
42
+ fi: fi,
43
+ is: is,
44
+ it: it,
45
+ pt: pt,
46
+ ru: ru,
47
+ zh: zhCN,
48
+ sk: sk,
49
+ ar: ar,
50
+ da: da,
51
+ no: nn,
52
+ pl: pl,
53
+ sv: sv,
54
+ tr: tr,
55
+ hy: hy,
56
+ az: az,
57
+ ka: ka,
58
+ uk: uk,
59
+ cy: cy,
60
+ rm: enUS, // locale is unavailable
61
+ }
62
+
63
+ export default locales
@@ -4,3 +4,4 @@ export * from './lib/links'
4
4
  export * from './lib/image-fallback.directive'
5
5
  export * from './lib/gn-ui-version'
6
6
  export * from './lib/record'
7
+ export * from './lib/humanize-date.directive'
@@ -0,0 +1,35 @@
1
+ import { Renderer2, Directive, ElementRef, Input, OnInit } from '@angular/core'
2
+ import { DateService } from './services/date.service'
3
+
4
+ @Directive({
5
+ selector: '[gnUiHumanizeDate]',
6
+ standalone: true,
7
+ })
8
+ export class GnUiHumanizeDateDirective implements OnInit {
9
+ @Input() gnUiHumanizeDate: Date | string
10
+
11
+ constructor(
12
+ private dateService: DateService,
13
+ private el: ElementRef,
14
+ private renderer: Renderer2
15
+ ) {}
16
+
17
+ async ngOnInit() {
18
+ await this.updateElement()
19
+ }
20
+
21
+ private async updateElement(): Promise<void> {
22
+ const dateValue = this.gnUiHumanizeDate
23
+
24
+ const fullDateTime = this.dateService.formatDateTime(dateValue)
25
+ const relativeDate =
26
+ await this.dateService.formatRelativeDateTime(dateValue)
27
+
28
+ this.renderer.setAttribute(this.el.nativeElement, 'title', fullDateTime)
29
+ this.renderer.setProperty(
30
+ this.el.nativeElement,
31
+ 'textContent',
32
+ relativeDate
33
+ )
34
+ }
35
+ }
@@ -1,10 +1,18 @@
1
1
  import { Injectable } from '@angular/core'
2
2
  import { TranslateService } from '@ngx-translate/core'
3
+ import { type Locale } from 'date-fns/locale'
4
+ import { formatDistance } from 'date-fns/formatDistance'
5
+
6
+ const DEFAULT_LANGUAGE = 'en'
3
7
 
4
8
  @Injectable({
5
9
  providedIn: 'root',
6
10
  })
7
11
  export class DateService {
12
+ dateLocales = import('../../../../../../libs/util/i18n/src/lib/date-locales').then(
13
+ (obj) => obj.default
14
+ )
15
+
8
16
  constructor(private translateService: TranslateService) {}
9
17
 
10
18
  private getDateObject(date: Date | string): Date {
@@ -22,11 +30,17 @@ export class DateService {
22
30
  locale: string
23
31
  dateObj: Date
24
32
  } {
25
- const locale = this.translateService.currentLang || 'en-US'
33
+ const locale = this.translateService.currentLang || DEFAULT_LANGUAGE
26
34
  const dateObj = this.getDateObject(date)
27
35
  return { locale, dateObj }
28
36
  }
29
37
 
38
+ private async getDateLocale(): Promise<Locale> {
39
+ const lang = this.translateService.currentLang || DEFAULT_LANGUAGE
40
+ const locales = await this.dateLocales
41
+ return locales[lang]
42
+ }
43
+
30
44
  formatDate(
31
45
  date: Date | string,
32
46
  options?: Intl.DateTimeFormatOptions
@@ -42,4 +56,16 @@ export class DateService {
42
56
  const { locale, dateObj } = this.getLocaleAndDate(date)
43
57
  return dateObj.toLocaleString(locale, options)
44
58
  }
59
+
60
+ async formatRelativeDateTime(date: Date | string): Promise<string> {
61
+ const dateObj = this.getDateObject(date)
62
+
63
+ const now = new Date()
64
+ const locale = await this.getDateLocale()
65
+
66
+ return formatDistance(dateObj, now, {
67
+ addSuffix: true,
68
+ locale: locale,
69
+ })
70
+ }
45
71
  }
@@ -62,6 +62,9 @@
62
62
  "dataset.error.restrictedAccess": "",
63
63
  "dataset.error.unknown": "Die Daten können nicht angezeigt werden: \"{ info }\"",
64
64
  "dataset.error.unsupportedType": "Der folgende Inhaltstyp wird nicht unterstützt: \"{ info }\"",
65
+ "daterange.filter.from": "",
66
+ "daterange.filter.period": "",
67
+ "daterange.filter.to": "",
65
68
  "domain.contact.role.author": "",
66
69
  "domain.contact.role.collaborator": "",
67
70
  "domain.contact.role.contributor": "",
@@ -397,6 +400,7 @@
397
400
  "pagination.nextPage": "Nächste Seite",
398
401
  "pagination.page": "Seite",
399
402
  "pagination.pageOf": "von",
403
+ "pagination.previousPage": "Vorherige Seite",
400
404
  "record.action.delete": "Löschen",
401
405
  "record.action.download": "Herunterladen",
402
406
  "record.action.duplicate": "",
@@ -461,6 +465,8 @@
461
465
  "record.metadata.contact": "Kontakt",
462
466
  "record.metadata.creation": "Erstellungsdatum",
463
467
  "record.metadata.details": "Über die Daten",
468
+ "record.metadata.doi.copy": "",
469
+ "record.metadata.doi.open": "",
464
470
  "record.metadata.download": "Downloads",
465
471
  "record.metadata.feature.catalog": "",
466
472
  "record.metadata.formats": "Formate",
@@ -509,9 +515,9 @@
509
515
  "record.metadata.quality.updateFrequency.failed": "Aktualisierungsfrequenz nicht angegeben",
510
516
  "record.metadata.quality.updateFrequency.success": "Aktualisierungsfrequenz angegeben",
511
517
  "record.metadata.related": "Entdecken Sie den Katalog",
512
- "record.metadata.resourceCreated": "Erstellt am {date}",
513
- "record.metadata.resourcePublished": "Veröffentlicht am {date}",
514
- "record.metadata.resourceUpdated": "Zuletzt aktualisiert am {date}",
518
+ "record.metadata.resourceCreated": "Erstellt",
519
+ "record.metadata.resourcePublished": "Veröffentlicht",
520
+ "record.metadata.resourceUpdated": "Zuletzt aktualisiert",
515
521
  "record.metadata.ressources.and.links": "Ressourcen und Links",
516
522
  "record.metadata.sheet": "Weitere Informationen verfügbar unter:",
517
523
  "record.metadata.status": "Status",
@@ -526,7 +532,7 @@
526
532
  "record.metadata.uniqueId": "Eindeutige Kennung",
527
533
  "record.metadata.update": "Aktualisierungsdatum",
528
534
  "record.metadata.updateFrequency": "Aktualisierungsfrequenz der Daten",
529
- "record.metadata.updatedOn": "Informationen geändert am",
535
+ "record.metadata.updatedOn": "Informationen geändert",
530
536
  "record.metadata.usage": "Nutzung und Einschränkungen",
531
537
  "record.metadata.userFeedbacks": "",
532
538
  "record.metadata.userFeedbacks.anonymousUser": "",
@@ -633,6 +639,8 @@
633
639
  "service.metadata.spatialExtent": "",
634
640
  "share.tab.permalink": "Teilen",
635
641
  "share.tab.webComponent": "Integrieren",
642
+ "stac.filter.reset": "",
643
+ "stac.results.noResults": "Ihre Suchfilter lieferten keine Ergebnisse",
636
644
  "table.loading.data": "Daten werden geladen...",
637
645
  "table.object.count": "Objekte in diesem Datensatz",
638
646
  "table.paginator.firstPage": "Erste Seite",