geonetwork-ui 2.8.0-dev.83aaa1736 → 2.8.0-dev.8b715be88

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 (146) hide show
  1. package/esm2022/index.mjs +2 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/common/distribution.mapper.mjs +3 -1
  3. package/esm2022/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.mjs +3 -3
  4. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +25 -1
  5. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.mjs +7 -7
  6. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +3 -2
  7. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +4 -3
  8. package/esm2022/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.mjs +10 -10
  9. package/esm2022/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.mjs +3 -2
  10. package/esm2022/libs/common/domain/src/index.mjs +3 -0
  11. package/esm2022/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.mjs +1 -1
  12. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +2 -1
  13. package/esm2022/libs/common/domain/src/lib/model/search/sort-by.model.mjs +6 -1
  14. package/esm2022/libs/common/domain/src/lib/platform.service.interface.mjs +1 -1
  15. package/esm2022/libs/feature/dataviz/src/index.mjs +2 -1
  16. package/esm2022/libs/feature/dataviz/src/lib/chart-view/chart-view.component.mjs +3 -1
  17. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +18 -7
  18. package/esm2022/libs/feature/dataviz/src/lib/stac-view/stac-view.component.mjs +51 -0
  19. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +23 -3
  20. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +2 -2
  21. package/esm2022/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.mjs +13 -4
  22. package/esm2022/libs/feature/record/src/lib/data-view-web-component/data-view-web-component.component.mjs +23 -8
  23. package/esm2022/libs/feature/record/src/lib/state/mdview.facade.mjs +14 -1
  24. package/esm2022/libs/feature/router/src/lib/default/router.service.mjs +5 -1
  25. package/esm2022/libs/feature/router/src/lib/default/state/router.effects.mjs +9 -7
  26. package/esm2022/libs/feature/search/src/lib/sort-by/sort-by.component.mjs +8 -12
  27. package/esm2022/libs/ui/elements/src/index.mjs +2 -1
  28. package/esm2022/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.mjs +37 -0
  29. package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +3 -3
  30. package/esm2022/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.mjs +2 -3
  31. package/esm2022/libs/util/shared/src/lib/links/link-classifier.service.mjs +3 -1
  32. package/esm2022/libs/util/shared/src/lib/utils/sort-by.mjs +9 -6
  33. package/esm2022/translations/de.json +13 -3
  34. package/esm2022/translations/en.json +13 -4
  35. package/esm2022/translations/es.json +12 -2
  36. package/esm2022/translations/fr.json +13 -3
  37. package/esm2022/translations/it.json +14 -4
  38. package/esm2022/translations/nl.json +12 -2
  39. package/esm2022/translations/pt.json +12 -2
  40. package/esm2022/translations/sk.json +13 -3
  41. package/fesm2022/geonetwork-ui.mjs +340 -83
  42. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  43. package/index.d.ts +1 -0
  44. package/index.d.ts.map +1 -1
  45. package/index.ts +1 -0
  46. package/libs/api/metadata-converter/src/lib/common/distribution.mapper.d.ts.map +1 -1
  47. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  48. package/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.d.ts.map +1 -1
  49. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +5 -1
  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.map +1 -1
  52. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts +7 -7
  53. package/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.d.ts.map +1 -1
  54. package/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.d.ts.map +1 -1
  55. package/libs/common/domain/src/index.d.ts +3 -0
  56. package/libs/common/domain/src/index.d.ts.map +1 -0
  57. package/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.d.ts +1 -1
  58. package/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.d.ts.map +1 -1
  59. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +7 -2
  60. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  61. package/libs/common/domain/src/lib/model/search/sort-by.model.d.ts.map +1 -1
  62. package/libs/common/domain/src/lib/platform.service.interface.d.ts +1 -1
  63. package/libs/common/domain/src/lib/platform.service.interface.d.ts.map +1 -1
  64. package/libs/feature/dataviz/src/index.d.ts +1 -0
  65. package/libs/feature/dataviz/src/index.d.ts.map +1 -1
  66. package/libs/feature/dataviz/src/lib/chart-view/chart-view.component.d.ts.map +1 -1
  67. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  68. package/libs/feature/dataviz/src/lib/stac-view/stac-view.component.d.ts +16 -0
  69. package/libs/feature/dataviz/src/lib/stac-view/stac-view.component.d.ts.map +1 -0
  70. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +2 -0
  71. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  72. package/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.d.ts +3 -2
  73. package/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.d.ts.map +1 -1
  74. package/libs/feature/record/src/lib/data-view-web-component/data-view-web-component.component.d.ts +3 -2
  75. package/libs/feature/record/src/lib/data-view-web-component/data-view-web-component.component.d.ts.map +1 -1
  76. package/libs/feature/record/src/lib/state/mdview.facade.d.ts +28 -24
  77. package/libs/feature/record/src/lib/state/mdview.facade.d.ts.map +1 -1
  78. package/libs/feature/router/src/lib/default/router.service.d.ts +2 -0
  79. package/libs/feature/router/src/lib/default/router.service.d.ts.map +1 -1
  80. package/libs/feature/router/src/lib/default/state/router.effects.d.ts +3 -1
  81. package/libs/feature/router/src/lib/default/state/router.effects.d.ts.map +1 -1
  82. package/libs/feature/search/src/lib/sort-by/sort-by.component.d.ts +4 -3
  83. package/libs/feature/search/src/lib/sort-by/sort-by.component.d.ts.map +1 -1
  84. package/libs/ui/elements/src/index.d.ts +1 -0
  85. package/libs/ui/elements/src/index.d.ts.map +1 -1
  86. package/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.d.ts +8 -0
  87. package/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.d.ts.map +1 -0
  88. package/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.d.ts.map +1 -1
  89. package/libs/util/shared/src/lib/links/link-classifier.service.d.ts.map +1 -1
  90. package/libs/util/shared/src/lib/utils/sort-by.d.ts.map +1 -1
  91. package/package.json +1 -1
  92. package/src/libs/api/metadata-converter/src/lib/common/distribution.mapper.ts +1 -0
  93. package/src/libs/api/metadata-converter/src/lib/dcat-ap/dcat-ap.converter.ts +2 -2
  94. package/src/libs/api/metadata-converter/src/lib/fixtures/generic.records.ts +1 -1
  95. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.service+eaux-usees.ts +1 -1
  96. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +5 -2
  97. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -1
  98. package/src/libs/api/metadata-converter/src/lib/fixtures/georhena.records.ts +1 -1
  99. package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +2 -2
  100. package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.reuse.ts +1 -1
  101. package/src/libs/api/metadata-converter/src/lib/fixtures/wallonie.records.service+napitswallonia.ts +1 -1
  102. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +27 -0
  103. package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +13 -6
  104. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +6 -2
  105. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +4 -2
  106. package/src/libs/api/repository/src/lib/gn4/platform/gn4-platform.service.ts +37 -36
  107. package/src/libs/api/repository/src/lib/gn4/settings/gn4-settings.service.ts +3 -2
  108. package/src/libs/common/domain/src/index.ts +2 -0
  109. package/src/libs/common/domain/src/lib/model/dataviz/dataviz-configuration.model.ts +1 -1
  110. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +10 -1
  111. package/src/libs/common/domain/src/lib/model/search/sort-by.model.ts +5 -0
  112. package/src/libs/common/domain/src/lib/platform.service.interface.ts +1 -1
  113. package/src/libs/common/fixtures/src/lib/elasticsearch/metadata-links.fixtures.ts +5 -0
  114. package/src/libs/common/fixtures/src/lib/link.fixtures.ts +10 -0
  115. package/src/libs/feature/dataviz/src/index.ts +1 -0
  116. package/src/libs/feature/dataviz/src/lib/chart-view/chart-view.component.ts +1 -0
  117. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +16 -5
  118. package/src/libs/feature/dataviz/src/lib/stac-view/stac-view.component.css +0 -0
  119. package/src/libs/feature/dataviz/src/lib/stac-view/stac-view.component.html +40 -0
  120. package/src/libs/feature/dataviz/src/lib/stac-view/stac-view.component.ts +62 -0
  121. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +3 -3
  122. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +30 -0
  123. package/src/libs/feature/editor/src/lib/fields.config.ts +1 -1
  124. package/src/libs/feature/record/src/lib/data-view-permalink/data-view-permalink.component.ts +7 -1
  125. package/src/libs/feature/record/src/lib/data-view-web-component/data-view-web-component.component.ts +23 -4
  126. package/src/libs/feature/record/src/lib/state/mdview.facade.ts +30 -1
  127. package/src/libs/feature/router/src/lib/default/router.service.ts +8 -0
  128. package/src/libs/feature/router/src/lib/default/state/router.effects.ts +6 -7
  129. package/src/libs/feature/search/src/lib/sort-by/sort-by.component.ts +8 -12
  130. package/src/libs/ui/elements/src/index.ts +1 -0
  131. package/src/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.css +0 -0
  132. package/src/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.html +31 -0
  133. package/src/libs/ui/elements/src/lib/metadata-doi/metadata-doi.component.ts +30 -0
  134. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +56 -14
  135. package/src/libs/ui/inputs/src/lib/dropdown-selector/dropdown-selector.component.ts +4 -2
  136. package/src/libs/util/shared/src/lib/links/link-classifier.service.ts +2 -0
  137. package/src/libs/util/shared/src/lib/utils/sort-by.ts +8 -5
  138. package/translations/de.json +13 -3
  139. package/translations/en.json +13 -4
  140. package/translations/es.json +12 -2
  141. package/translations/fr.json +13 -3
  142. package/translations/it.json +14 -4
  143. package/translations/nl.json +12 -2
  144. package/translations/pt.json +12 -2
  145. package/translations/sk.json +13 -3
  146. package/src/libs/common/domain/src/lib/index.ts +0 -2
@@ -0,0 +1,40 @@
1
+ <div
2
+ class="w-full h-full flex flex-row mt-6 bg-white border border-gray-300 rounded-lg overflow-hidden"
3
+ >
4
+ <div class="flex-1 flex flex-col">
5
+ <div class="m-8">
6
+ <p class="mb-4" translate>stac.filter.period</p>
7
+ <p translate>stac.filter.from</p>
8
+ <gn-ui-date-picker
9
+ id="start-date-picker"
10
+ [date]="currentTemporalExtent?.start"
11
+ (dateChange)="onStartDateChange($event)"
12
+ />
13
+ <p class="mt-4" translate>stac.filter.to</p>
14
+ <gn-ui-date-picker
15
+ id="end-date-picker"
16
+ [date]="currentTemporalExtent?.end"
17
+ (dateChange)="onEndDateChange($event)"
18
+ />
19
+ </div>
20
+
21
+ <div class="mt-auto mb-8 mx-8" *ngIf="isTemporalFilterModified">
22
+ <button
23
+ id="reset-filters-button"
24
+ type="button"
25
+ class="flex items-center"
26
+ (click)="onResetFilters()"
27
+ >
28
+ <span translate>stac.filter.reset</span>
29
+ <ng-icon
30
+ name="matDeleteOutline"
31
+ class="pointer-events-none ml-2"
32
+ ></ng-icon>
33
+ </button>
34
+ </div>
35
+ </div>
36
+
37
+ <div class="w-[655px] flex-shrink-0 flex items-center justify-center">
38
+ <span>Map...</span>
39
+ </div>
40
+ </div>
@@ -0,0 +1,62 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import {
3
+ ChangeDetectionStrategy,
4
+ Component,
5
+ Input,
6
+ OnInit,
7
+ } from '@angular/core'
8
+ import {
9
+ DatasetServiceDistribution,
10
+ DatasetTemporalExtent,
11
+ } from '../../../../../../libs/common/domain/src/lib/model/record'
12
+ import { DatePickerComponent } from '../../../../../../libs/ui/inputs/src'
13
+ import { NgIconComponent, provideIcons } from '@ng-icons/core'
14
+ import { matDeleteOutline } from '@ng-icons/material-icons/outline'
15
+ import { TranslateDirective } from '@ngx-translate/core'
16
+
17
+ @Component({
18
+ selector: 'gn-ui-stac-view',
19
+ templateUrl: './stac-view.component.html',
20
+ styleUrls: ['./stac-view.component.css'],
21
+ changeDetection: ChangeDetectionStrategy.OnPush,
22
+ standalone: true,
23
+ imports: [
24
+ CommonModule,
25
+ DatePickerComponent,
26
+ NgIconComponent,
27
+ TranslateDirective,
28
+ ],
29
+ viewProviders: [provideIcons({ matDeleteOutline })],
30
+ })
31
+ export class StacViewComponent implements OnInit {
32
+ @Input() link: DatasetServiceDistribution
33
+ @Input() initialTemporalExtent: DatasetTemporalExtent | null
34
+
35
+ currentTemporalExtent: DatasetTemporalExtent | null = null
36
+ isTemporalFilterModified = false
37
+
38
+ onStartDateChange(date: Date) {
39
+ this.currentTemporalExtent = {
40
+ ...this.currentTemporalExtent,
41
+ start: date,
42
+ }
43
+ this.isTemporalFilterModified = true
44
+ }
45
+
46
+ onEndDateChange(date: Date) {
47
+ this.currentTemporalExtent = {
48
+ ...this.currentTemporalExtent,
49
+ end: date,
50
+ }
51
+ this.isTemporalFilterModified = true
52
+ }
53
+
54
+ onResetFilters() {
55
+ this.currentTemporalExtent = this.initialTemporalExtent
56
+ this.isTemporalFilterModified = false
57
+ }
58
+
59
+ ngOnInit() {
60
+ this.currentTemporalExtent = this.initialTemporalExtent
61
+ }
62
+ }
@@ -69,11 +69,11 @@
69
69
  (valueChange)="valueChange.emit($event)"
70
70
  ></gn-ui-form-field-overviews>
71
71
  </ng-container>
72
- <ng-container *ngSwitchCase="'resourceIdentifier'">
72
+ <ng-container *ngSwitchCase="'resourceIdentifiers'">
73
73
  <gn-ui-form-field-simple
74
74
  [type]="'text'"
75
- [value]="valueAsString"
76
- (valueChange)="valueChange.emit($event)"
75
+ [value]="valueAsResourceIdentifierCode"
76
+ (valueChange)="handleResourceIdentifierChange($event)"
77
77
  ></gn-ui-form-field-simple>
78
78
  </ng-container>
79
79
  <ng-container *ngSwitchCase="'resourceCreated'">
@@ -142,4 +142,34 @@ export class FormFieldComponent {
142
142
  get valueAsOnlineResources() {
143
143
  return this.value as Array<OnlineResource>
144
144
  }
145
+ get valueAsResourceIdentifierCode() {
146
+ const identifiers = this.value as Array<{
147
+ code: string
148
+ codeSpace?: string
149
+ url?: string
150
+ }>
151
+ return identifiers?.[0]?.code || ''
152
+ }
153
+
154
+ handleResourceIdentifierChange(code: string) {
155
+ const identifiers = this.value as Array<{
156
+ code: string
157
+ codeSpace?: string
158
+ url?: string
159
+ }>
160
+
161
+ if (!code) {
162
+ this.valueChange.emit(identifiers?.slice(1) || [])
163
+ return
164
+ }
165
+
166
+ if (identifiers?.[0]) {
167
+ this.valueChange.emit([
168
+ { ...identifiers[0], code },
169
+ ...identifiers.slice(1),
170
+ ])
171
+ } else {
172
+ this.valueChange.emit([{ code }])
173
+ }
174
+ }
145
175
  }
@@ -81,7 +81,7 @@ export const RECORD_RESOURCE_CREATED_FIELD: EditorField = {
81
81
  }
82
82
 
83
83
  export const RESOURCE_IDENTIFIER_FIELD: EditorField = {
84
- model: 'resourceIdentifier',
84
+ model: 'resourceIdentifiers',
85
85
  formFieldConfig: {
86
86
  labelKey: marker('editor.record.form.field.resourceIdentifier'),
87
87
  },
@@ -12,7 +12,7 @@ import { MdViewFacade } from '../state'
12
12
  import { CopyTextButtonComponent } from '../../../../../../libs/ui/inputs/src'
13
13
  import { CommonModule } from '@angular/common'
14
14
  import { TranslatePipe } from '@ngx-translate/core'
15
- import { GEONETWORK_UI_TAG_NAME } from '../../../../../../libs/util/shared/src'
15
+ import { GEONETWORK_UI_TAG_NAME, PROXY_PATH } from '../../../../../../libs/util/shared/src'
16
16
 
17
17
  export const WEB_COMPONENT_EMBEDDER_URL = new InjectionToken<string>(
18
18
  'webComponentEmbedderUrl'
@@ -60,6 +60,9 @@ export class DataViewPermalinkComponent {
60
60
  url.searchParams.append('e', `gn-dataset-view-map`)
61
61
  }
62
62
  url.searchParams.append('a', `api-url=${this.config.basePath}`)
63
+ if (this.proxyPath) {
64
+ url.searchParams.append('a', `proxy-path=${this.proxyPath}`)
65
+ }
63
66
  url.searchParams.append('a', `dataset-id=${metadata.uniqueIdentifier}`)
64
67
  url.searchParams.append('a', `primary-color=#0f4395`)
65
68
  url.searchParams.append('a', `secondary-color=#8bc832`)
@@ -72,6 +75,9 @@ export class DataViewPermalinkComponent {
72
75
  constructor(
73
76
  @Inject(Configuration) private config: Configuration,
74
77
  @Optional()
78
+ @Inject(PROXY_PATH)
79
+ private proxyPath: string,
80
+ @Optional()
75
81
  @Inject(WEB_COMPONENT_EMBEDDER_URL)
76
82
  protected wcEmbedderBaseUrl: string,
77
83
  private facade: MdViewFacade
@@ -3,6 +3,7 @@ import {
3
3
  Component,
4
4
  Inject,
5
5
  Input,
6
+ Optional,
6
7
  } from '@angular/core'
7
8
  import { Configuration } from '../../../../../../libs/data-access/gn4/src'
8
9
  import { MdViewFacade } from '../state'
@@ -10,7 +11,7 @@ import { BehaviorSubject, combineLatest, map } from 'rxjs'
10
11
  import { CopyTextButtonComponent } from '../../../../../../libs/ui/inputs/src'
11
12
  import { CommonModule } from '@angular/common'
12
13
  import { TranslatePipe } from '@ngx-translate/core'
13
- import { GEONETWORK_UI_TAG_NAME } from '../../../../../../libs/util/shared/src'
14
+ import { GEONETWORK_UI_TAG_NAME, PROXY_PATH } from '../../../../../../libs/util/shared/src'
14
15
 
15
16
  @Component({
16
17
  selector: 'gn-ui-data-view-web-component',
@@ -42,7 +43,12 @@ export class DataViewWebComponentComponent {
42
43
  api-url="${new URL(
43
44
  this.config.basePath,
44
45
  window.location.origin
45
- ).toString()}"
46
+ ).toString()}"${
47
+ this.proxyPath
48
+ ? `
49
+ proxy-path="${this.proxyPath}"`
50
+ : ''
51
+ }
46
52
  dataset-id="${metadata.uniqueIdentifier}"
47
53
  aggregation="${aggregation}"
48
54
  x-property="${xProperty}"
@@ -65,7 +71,12 @@ export class DataViewWebComponentComponent {
65
71
  api-url="${new URL(
66
72
  this.config.basePath,
67
73
  window.location.origin
68
- ).toString()}"
74
+ ).toString()}"${
75
+ this.proxyPath
76
+ ? `
77
+ proxy-path="${this.proxyPath}"`
78
+ : ''
79
+ }
69
80
  dataset-id="${metadata.uniqueIdentifier}"
70
81
  primary-color="#0f4395"
71
82
  secondary-color="#8bc832"
@@ -82,7 +93,12 @@ export class DataViewWebComponentComponent {
82
93
  api-url="${new URL(
83
94
  this.config.basePath,
84
95
  window.location.origin
85
- ).toString()}"
96
+ ).toString()}"${
97
+ this.proxyPath
98
+ ? `
99
+ proxy-path="${this.proxyPath}"`
100
+ : ''
101
+ }
86
102
  dataset-id="${metadata.uniqueIdentifier}"
87
103
  primary-color="#0f4395"
88
104
  secondary-color="#8bc832"
@@ -97,6 +113,9 @@ export class DataViewWebComponentComponent {
97
113
 
98
114
  constructor(
99
115
  @Inject(Configuration) private config: Configuration,
116
+ @Optional()
117
+ @Inject(PROXY_PATH)
118
+ private proxyPath: string,
100
119
  private facade: MdViewFacade
101
120
  ) {}
102
121
  }
@@ -20,7 +20,7 @@ import {
20
20
  } from '../../../../../../libs/common/domain/src/lib/model/record'
21
21
  import { AvatarServiceInterface } from '../../../../../../libs/api/repository/src'
22
22
  import { OgcApiRecord } from '@camptocamp/ogc-client'
23
- import { from, of, Observable } from 'rxjs'
23
+ import { from, of } from 'rxjs'
24
24
  import { DataService } from '../../../../../../libs/feature/dataviz/src'
25
25
 
26
26
  @Injectable()
@@ -89,6 +89,25 @@ export class MdViewFacade {
89
89
  shareReplay(1)
90
90
  )
91
91
 
92
+ resourceDoi$ = this.metadata$.pipe(
93
+ map((record) => {
94
+ if (!record?.resourceIdentifiers?.length) return null
95
+ const doiIdentifier = record.resourceIdentifiers.find(
96
+ (id) =>
97
+ id.codeSpace?.toLowerCase().includes('doi.org') ||
98
+ id.code.startsWith('10.')
99
+ )
100
+
101
+ if (!doiIdentifier) return null
102
+
103
+ return {
104
+ code: doiIdentifier.code,
105
+ url: doiIdentifier.url ? doiIdentifier.url : null,
106
+ }
107
+ }),
108
+ shareReplay(1)
109
+ )
110
+
92
111
  apiLinks$ = this.allLinks$.pipe(
93
112
  map((links) =>
94
113
  links.filter((link) => this.linkClassifier.hasUsage(link, LinkUsage.API))
@@ -105,6 +124,16 @@ export class MdViewFacade {
105
124
  shareReplay(1)
106
125
  )
107
126
 
127
+ stacLinks$ = this.allLinks$.pipe(
128
+ map((links) =>
129
+ links.filter(
130
+ (link) =>
131
+ link.type === 'service' && link.accessServiceProtocol === 'stac'
132
+ )
133
+ ),
134
+ shareReplay(1)
135
+ )
136
+
108
137
  downloadLinks$ = this.allLinks$.pipe(
109
138
  map((links) =>
110
139
  links.filter((link) =>
@@ -8,6 +8,10 @@ import {
8
8
  } from '.'
9
9
  import { Router, Routes } from '@angular/router'
10
10
  import { ROUTER_CONFIG, RouterConfigModel } from './router.config'
11
+ import {
12
+ SortByEnum,
13
+ SortByField,
14
+ } from '../../../../../../libs/common/domain/src/lib/model/search'
11
15
 
12
16
  @Injectable({
13
17
  providedIn: 'root',
@@ -58,4 +62,8 @@ export class RouterService {
58
62
  getOrganizationPageRoute(): string {
59
63
  return ROUTER_ROUTE_ORGANIZATION
60
64
  }
65
+
66
+ getDefaultSort(): SortByField {
67
+ return SortByEnum.RESOURCE_DATES
68
+ }
61
69
  }
@@ -9,10 +9,7 @@ import {
9
9
  SetFilters,
10
10
  SetSortBy,
11
11
  } from '../../../../../../../libs/feature/search/src'
12
- import {
13
- FieldFilters,
14
- SortByEnum,
15
- } from '../../../../../../../libs/common/domain/src/lib/model/search'
12
+ import { FieldFilters } from '../../../../../../../libs/common/domain/src/lib/model/search'
16
13
  import { Actions, createEffect, ofType } from '@ngrx/effects'
17
14
  import { navigation } from '@ngrx/router-store/data-persistence'
18
15
  import { of, pairwise, startWith } from 'rxjs'
@@ -22,6 +19,7 @@ import { RouterFacade } from './router.facade'
22
19
  import { ROUTE_PARAMS } from '../constants'
23
20
  import { sortByFromString } from '../../../../../../../libs/util/shared/src'
24
21
  import { ROUTER_CONFIG, RouterConfigModel } from '../router.config'
22
+ import { RouterService } from '../router.service'
25
23
 
26
24
  @Injectable()
27
25
  export class RouterEffects {
@@ -31,7 +29,8 @@ export class RouterEffects {
31
29
  private _location: Location,
32
30
  private facade: RouterFacade,
33
31
  @Inject(ROUTER_CONFIG) private routerConfig: RouterConfigModel,
34
- private fieldsService: FieldsService
32
+ private fieldsService: FieldsService,
33
+ private routerService: RouterService
35
34
  ) {}
36
35
 
37
36
  navigate$ = createEffect(
@@ -61,7 +60,7 @@ export class RouterEffects {
61
60
  let sortBy =
62
61
  ROUTE_PARAMS.SORT in newParams
63
62
  ? sortByFromString(newParams[ROUTE_PARAMS.SORT])
64
- : SortByEnum.CHANGE_DATE
63
+ : this.routerService.getDefaultSort()
65
64
  let pageNumber =
66
65
  ROUTE_PARAMS.PAGE in newParams
67
66
  ? parseInt(newParams[ROUTE_PARAMS.PAGE])
@@ -70,7 +69,7 @@ export class RouterEffects {
70
69
  const oldSort =
71
70
  ROUTE_PARAMS.SORT in oldParams
72
71
  ? sortByFromString(oldParams[ROUTE_PARAMS.SORT])
73
- : SortByEnum.CHANGE_DATE
72
+ : this.routerService.getDefaultSort()
74
73
  if (JSON.stringify(sortBy) === JSON.stringify(oldSort)) {
75
74
  sortBy = null
76
75
  }
@@ -13,7 +13,7 @@ import { TranslatePipe } from '@ngx-translate/core'
13
13
 
14
14
  interface SortChoice {
15
15
  label: string
16
- value: string
16
+ value: SortByField
17
17
  }
18
18
 
19
19
  @Component({
@@ -27,24 +27,20 @@ export class SortByComponent implements OnInit {
27
27
  choices: SortChoice[] = [
28
28
  {
29
29
  label: marker('results.sortBy.relevancy'),
30
- value: SortByEnum.RELEVANCY.join(','),
30
+ value: SortByEnum.RELEVANCY,
31
31
  },
32
32
  {
33
33
  label: marker('results.sortBy.dateStamp'),
34
- value: SortByEnum.CREATE_DATE.join(','),
35
- },
36
- {
37
- label: marker('results.sortBy.changeDate'),
38
- value: SortByEnum.CHANGE_DATE.join(','),
34
+ value: SortByEnum.RESOURCE_DATES,
39
35
  },
40
36
  {
41
37
  label: marker('results.sortBy.popularity'),
42
- value: SortByEnum.POPULARITY.join(','),
38
+ value: SortByEnum.POPULARITY,
43
39
  },
44
40
  ]
45
41
  currentSortBy$ = this.facade.sortBy$.pipe(
46
42
  filter((sortBy) => !!sortBy),
47
- map((sortBy) => sortBy.join(','))
43
+ map((sortBy) => sortBy)
48
44
  )
49
45
 
50
46
  constructor(
@@ -56,12 +52,12 @@ export class SortByComponent implements OnInit {
56
52
  if (this.isQualitySortable) {
57
53
  this.choices.push({
58
54
  label: marker('results.sortBy.qualityScore'),
59
- value: SortByEnum.QUALITY_SCORE.join(','),
55
+ value: SortByEnum.QUALITY_SCORE,
60
56
  })
61
57
  }
62
58
  }
63
59
 
64
- changeSortBy(criteriaAsString: string) {
65
- this.searchService.setSortBy(criteriaAsString.split(',') as SortByField)
60
+ changeSortBy(criteria: SortByField): void {
61
+ this.searchService.setSortBy(criteria)
66
62
  }
67
63
  }
@@ -14,6 +14,7 @@ export * from './lib/markdown-editor/markdown-editor.component'
14
14
  export * from './lib/markdown-parser/markdown-parser.component'
15
15
  export * from './lib/metadata-catalog/metadata-catalog.component'
16
16
  export * from './lib/metadata-contact/metadata-contact.component'
17
+ export * from './lib/metadata-doi/metadata-doi.component'
17
18
  export * from './lib/metadata-info/metadata-info.component'
18
19
  export * from './lib/metadata-quality-item/metadata-quality-item.component'
19
20
  export * from './lib/metadata-quality/metadata-quality.component'
@@ -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
+ }
@@ -3,7 +3,11 @@
3
3
  ghostClass="h-[178px]"
4
4
  [showContent]="fieldReady('abstract')"
5
5
  >
6
- <gn-ui-max-lines [maxLines]="6" *ngIf="metadata.abstract">
6
+ <gn-ui-max-lines
7
+ [maxLines]="6"
8
+ *ngIf="metadata.abstract"
9
+ data-test="metadata-info-abstract"
10
+ >
7
11
  <div class="mb-6">
8
12
  <gn-ui-markdown-parser
9
13
  [textContent]="metadata.abstract"
@@ -101,19 +105,31 @@
101
105
  <gn-ui-expandable-panel
102
106
  *ngIf="
103
107
  (metadata.kind === 'dataset' && metadata.lineage) ||
108
+ resourceContact ||
109
+ metadata.resourceCreated ||
110
+ metadata.resourcePublished ||
104
111
  metadata.resourceUpdated ||
105
- metadata.updateFrequency ||
106
- (metadata.kind === 'dataset' && metadata.status)
112
+ (metadata.kind === 'dataset' && metadata.updateFrequency) ||
113
+ metadata.otherLanguages?.length ||
114
+ (metadata.kind === 'dataset' && temporalExtent)
107
115
  "
108
116
  [title]="'record.metadata.details' | translate"
109
117
  data-test="details-panel"
110
118
  >
111
- <div *ngIf="metadata.lineage" class="text-gray-900 flex flex-col mt-4 gap-2">
119
+ <div
120
+ *ngIf="metadata.kind === 'dataset' && metadata.lineage"
121
+ class="text-gray-900 flex flex-col mt-4 gap-2"
122
+ data-test="details-panel-lineage"
123
+ >
112
124
  <p class="whitespace-pre-line break-words text-gray-900" gnUiLinkify>
113
125
  {{ metadata.lineage }}
114
126
  </p>
115
127
  </div>
116
- <div class="flex flex-row gap-6 mt-5 mb-8" *ngIf="resourceContact">
128
+ <div
129
+ class="flex flex-row gap-6 mt-5 mb-8 resource-contact"
130
+ *ngIf="resourceContact"
131
+ data-test="details-panel-resource-contact"
132
+ >
117
133
  <div
118
134
  *ngIf="resourceContact.organization?.logoUrl?.href"
119
135
  class="flex items-center justify-center border-solid border border-gray-300 rounded-md bg-white h-32 overflow-hidden"
@@ -165,19 +181,37 @@
165
181
  <div
166
182
  class="py-6 px-6 rounded bg-gray-100 grid grid-cols-2 gap-y-6 gap-x-[20px] text-gray-700"
167
183
  >
168
- <div *ngIf="metadata.resourceCreated">
184
+ <div
185
+ *ngIf="metadata.resourceCreated"
186
+ data-test="details-panel-resource-created"
187
+ >
169
188
  <p class="text-sm" translate>record.metadata.creation</p>
170
- <p class="text-primary font-medium mt-1">
189
+ <p class="text-primary font-medium mt-1 resource-created">
171
190
  {{ formatDate(metadata.resourceCreated) }}
172
191
  </p>
173
192
  </div>
174
- <div *ngIf="metadata.resourcePublished">
193
+ <div
194
+ *ngIf="metadata.resourcePublished"
195
+ data-test="details-panel-resource-published"
196
+ >
175
197
  <p class="text-sm" translate>record.metadata.publication</p>
176
- <p class="text-primary font-medium mt-1">
198
+ <p class="text-primary font-medium mt-1 resource-published">
177
199
  {{ formatDate(metadata.resourcePublished) }}
178
200
  </p>
179
201
  </div>
180
- <div *ngIf="updateFrequency">
202
+ <div
203
+ *ngIf="metadata.resourceUpdated"
204
+ data-test="details-panel-resource-updated"
205
+ >
206
+ <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>
210
+ </div>
211
+ <div
212
+ *ngIf="metadata.kind === 'dataset' && metadata.updateFrequency"
213
+ data-test="details-panel-update-frequency"
214
+ >
181
215
  <p class="text-sm" translate>record.metadata.updateFrequency</p>
182
216
  <p
183
217
  class="text-primary font-medium mt-1 updateFrequency"
@@ -187,11 +221,14 @@
187
221
  {{ updateFrequency }}
188
222
  </p>
189
223
  </div>
190
- <div *ngIf="metadata.otherLanguages?.length">
224
+ <div
225
+ *ngIf="metadata.otherLanguages?.length"
226
+ data-test="details-panel-other-languages"
227
+ >
191
228
  <p class="text-sm mb-1" translate>record.metadata.languages</p>
192
229
  <div class="flex flex-row gap-1 flex-wrap">
193
230
  <p
194
- class="text-primary font-medium"
231
+ class="text-primary font-medium other-languages"
195
232
  translate
196
233
  *ngFor="let language of metadata.otherLanguages"
197
234
  >
@@ -199,9 +236,14 @@
199
236
  </p>
200
237
  </div>
201
238
  </div>
202
- <div *ngIf="temporalExtent">
239
+ <div
240
+ *ngIf="metadata.kind === 'dataset' && temporalExtent"
241
+ data-test="details-panel-temporal-extent"
242
+ >
203
243
  <p class="text-sm" translate>record.metadata.temporalExtent</p>
204
- <div class="flex flex-row gap-1 mb-1 text-primary font-medium">
244
+ <div
245
+ class="flex flex-row gap-1 mb-1 text-primary font-medium temporal-extent"
246
+ >
205
247
  <p
206
248
  *ngIf="temporalExtent.start && temporalExtent.end"
207
249
  translate
@@ -90,8 +90,10 @@ export class DropdownSelectorComponent implements OnInit {
90
90
 
91
91
  get selectedChoice(): DropdownChoice {
92
92
  return (
93
- this.choices.find((choice) => choice.value === this.selected) ??
94
- this.choices[0]
93
+ this.choices.find(
94
+ (choice) =>
95
+ JSON.stringify(choice.value) === JSON.stringify(this.selected)
96
+ ) ?? this.choices[0]
95
97
  )
96
98
  }
97
99
 
@@ -41,6 +41,8 @@ export class LinkClassifierService {
41
41
  return [LinkUsage.API]
42
42
  case 'postgis':
43
43
  return [LinkUsage.UNKNOWN]
44
+ case 'stac':
45
+ return [LinkUsage.API]
44
46
  default:
45
47
  return [LinkUsage.UNKNOWN]
46
48
  }