geonetwork-ui 2.4.0-dev.aa5f997e → 2.4.0-dev.c5f4c491

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 (129) hide show
  1. package/esm2022/libs/api/metadata-converter/src/index.mjs +1 -2
  2. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.mjs +5 -5
  3. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +30 -2
  4. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.mjs +31 -0
  5. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +23 -1
  6. package/esm2022/libs/api/metadata-converter/src/lib/xml-utils.mjs +6 -1
  7. package/esm2022/libs/api/repository/src/lib/gn4/gn4-repository.mjs +21 -4
  8. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  9. package/esm2022/libs/common/domain/src/lib/repository/records-repository.interface.mjs +1 -1
  10. package/esm2022/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.mjs +131 -0
  11. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.mjs +21 -0
  12. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-temporal-extents/form-field-temporal-extents.component.mjs +7 -6
  13. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.mjs +19 -9
  14. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +12 -2
  15. package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +10 -5
  16. package/esm2022/libs/feature/search/src/lib/results-table/results-table-container.component.mjs +35 -7
  17. package/esm2022/libs/feature/search/src/lib/state/search.facade.mjs +6 -2
  18. package/esm2022/libs/ui/elements/src/index.mjs +2 -1
  19. package/esm2022/libs/ui/elements/src/lib/confirmation-dialog/confirmation-dialog.component.mjs +27 -0
  20. package/esm2022/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.mjs +4 -3
  21. package/esm2022/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.mjs +2 -2
  22. package/esm2022/libs/ui/elements/src/lib/metadata-info/metadata-info.component.mjs +3 -3
  23. package/esm2022/libs/ui/elements/src/lib/sortable-list/sortable-list.component.mjs +6 -3
  24. package/esm2022/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.mjs +3 -3
  25. package/esm2022/libs/ui/layout/src/lib/interactive-table/interactive-table.component.mjs +3 -3
  26. package/esm2022/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.mjs +49 -11
  27. package/esm2022/libs/ui/search/src/lib/results-table/results-table.component.mjs +18 -6
  28. package/esm2022/translations/de.json +16 -16
  29. package/esm2022/translations/en.json +9 -9
  30. package/esm2022/translations/es.json +9 -9
  31. package/esm2022/translations/fr.json +18 -18
  32. package/esm2022/translations/it.json +9 -9
  33. package/esm2022/translations/nl.json +9 -9
  34. package/esm2022/translations/pt.json +9 -9
  35. package/fesm2022/geonetwork-ui.mjs +610 -249
  36. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  37. package/libs/api/metadata-converter/src/index.d.ts +0 -1
  38. package/libs/api/metadata-converter/src/index.d.ts.map +1 -1
  39. package/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.d.ts.map +1 -1
  40. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts +8 -1
  41. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
  42. package/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.d.ts +5 -0
  43. package/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.d.ts.map +1 -0
  44. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts +3 -1
  45. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  46. package/libs/api/metadata-converter/src/lib/xml-utils.d.ts +1 -0
  47. package/libs/api/metadata-converter/src/lib/xml-utils.d.ts.map +1 -1
  48. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts +6 -1
  49. package/libs/api/repository/src/lib/gn4/gn4-repository.d.ts.map +1 -1
  50. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +2 -1
  51. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  52. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts +8 -0
  53. package/libs/common/domain/src/lib/repository/records-repository.interface.d.ts.map +1 -1
  54. package/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.d.ts +27 -0
  55. package/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.d.ts.map +1 -0
  56. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.d.ts +11 -0
  57. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.d.ts.map +1 -0
  58. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-temporal-extents/form-field-temporal-extents.component.d.ts +3 -1
  59. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-temporal-extents/form-field-temporal-extents.component.d.ts.map +1 -1
  60. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts +5 -1
  61. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.d.ts.map +1 -1
  62. package/libs/feature/editor/src/lib/fields.config.d.ts +1 -0
  63. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  64. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
  65. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts +11 -3
  66. package/libs/feature/search/src/lib/results-table/results-table-container.component.d.ts.map +1 -1
  67. package/libs/feature/search/src/lib/state/search.facade.d.ts +1 -0
  68. package/libs/feature/search/src/lib/state/search.facade.d.ts.map +1 -1
  69. package/libs/ui/elements/src/index.d.ts +1 -0
  70. package/libs/ui/elements/src/index.d.ts.map +1 -1
  71. package/libs/ui/elements/src/lib/confirmation-dialog/confirmation-dialog.component.d.ts +18 -0
  72. package/libs/ui/elements/src/lib/confirmation-dialog/confirmation-dialog.component.d.ts.map +1 -0
  73. package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -1
  74. package/libs/ui/elements/src/lib/record-api-form/record-api-form.component.d.ts +1 -1
  75. package/libs/ui/elements/src/lib/sortable-list/sortable-list.component.d.ts +3 -2
  76. package/libs/ui/elements/src/lib/sortable-list/sortable-list.component.d.ts.map +1 -1
  77. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts +10 -1
  78. package/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.d.ts.map +1 -1
  79. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts +6 -2
  80. package/libs/ui/search/src/lib/results-table/results-table.component.d.ts.map +1 -1
  81. package/package.json +1 -1
  82. package/src/libs/api/metadata-converter/src/index.ts +0 -1
  83. package/src/libs/api/metadata-converter/src/lib/fixtures/geo2france.records.ts +5 -1
  84. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +37 -12
  85. package/src/libs/api/metadata-converter/src/lib/fixtures/metawal.records.ts +5 -1
  86. package/src/libs/api/metadata-converter/src/lib/iso19139/iso19139.converter.ts +4 -2
  87. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +72 -2
  88. package/src/libs/api/metadata-converter/src/lib/iso19139/utils/geometry.ts +39 -0
  89. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +70 -1
  90. package/src/libs/api/metadata-converter/src/lib/xml-utils.ts +8 -0
  91. package/src/libs/api/repository/src/lib/gn4/gn4-repository.ts +24 -4
  92. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +2 -1
  93. package/src/libs/common/domain/src/lib/repository/records-repository.interface.ts +10 -0
  94. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.html +2 -1
  95. package/src/libs/feature/editor/src/lib/components/overview-upload/overview-upload.component.ts +110 -19
  96. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.css +0 -0
  97. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.html +5 -0
  98. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-overviews/form-field-overviews.component.ts +22 -0
  99. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-temporal-extents/form-field-temporal-extents.component.ts +8 -7
  100. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.html +6 -0
  101. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field.component.ts +13 -1
  102. package/src/libs/feature/editor/src/lib/fields.config.ts +12 -1
  103. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +8 -4
  104. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.html +2 -1
  105. package/src/libs/feature/search/src/lib/results-table/results-table-container.component.ts +40 -3
  106. package/src/libs/feature/search/src/lib/state/search.facade.ts +6 -0
  107. package/src/libs/ui/elements/src/index.ts +1 -0
  108. package/src/libs/ui/elements/src/lib/confirmation-dialog/confirmation-dialog.component.css +0 -0
  109. package/src/libs/ui/elements/src/lib/confirmation-dialog/confirmation-dialog.component.html +12 -0
  110. package/src/libs/ui/elements/src/lib/confirmation-dialog/confirmation-dialog.component.ts +37 -0
  111. package/src/libs/ui/elements/src/lib/markdown-editor/markdown-editor.component.html +4 -1
  112. package/src/libs/ui/elements/src/lib/markdown-parser/markdown-parser.component.css +2 -1
  113. package/src/libs/ui/elements/src/lib/metadata-info/metadata-info.component.html +12 -8
  114. package/src/libs/ui/elements/src/lib/sortable-list/sortable-list.component.html +3 -1
  115. package/src/libs/ui/elements/src/lib/sortable-list/sortable-list.component.ts +6 -2
  116. package/src/libs/ui/layout/src/lib/form-field-wrapper/form-field-wrapper.component.html +1 -1
  117. package/src/libs/ui/layout/src/lib/interactive-table/interactive-table.component.html +1 -0
  118. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.html +10 -1
  119. package/src/libs/ui/search/src/lib/results-table/action-menu/action-menu.component.ts +55 -3
  120. package/src/libs/ui/search/src/lib/results-table/results-table.component.html +7 -2
  121. package/src/libs/ui/search/src/lib/results-table/results-table.component.ts +9 -9
  122. package/translations/de.json +16 -16
  123. package/translations/en.json +9 -9
  124. package/translations/es.json +9 -9
  125. package/translations/fr.json +18 -18
  126. package/translations/it.json +9 -9
  127. package/translations/nl.json +9 -9
  128. package/translations/pt.json +9 -9
  129. package/translations/sk.json +9 -9
@@ -1,8 +1,9 @@
1
1
  <gn-ui-image-input
2
2
  [maxSizeMB]="5"
3
3
  [previewUrl]="resourceUrl"
4
- [altText]="resourceFileName"
4
+ [altText]="resourceAltText"
5
5
  (fileChange)="handleFileChange($event)"
6
6
  (urlChange)="handleUrlChange($event)"
7
+ (altTextChange)="handleAltTextChange($event)"
7
8
  (delete)="handleDelete()"
8
9
  ></gn-ui-image-input>
@@ -2,12 +2,18 @@ import {
2
2
  ChangeDetectionStrategy,
3
3
  ChangeDetectorRef,
4
4
  Component,
5
+ EventEmitter,
5
6
  Input,
7
+ OnChanges,
6
8
  OnInit,
9
+ Output,
10
+ SimpleChanges,
7
11
  } from '@angular/core'
8
12
  import { CommonModule } from '@angular/common'
9
13
  import { RecordsApiService } from '../../../../../../../libs/data-access/gn4/src'
10
14
  import { UiInputsModule } from '../../../../../../../libs/ui/inputs/src'
15
+ import { FormControl } from '@angular/forms'
16
+ import { GraphicOverview } from '../../../../../../../libs/common/domain/src/lib/model/record'
11
17
 
12
18
  @Component({
13
19
  selector: 'gn-ui-overview-upload',
@@ -17,9 +23,13 @@ import { UiInputsModule } from '../../../../../../../libs/ui/inputs/src'
17
23
  styleUrls: ['./overview-upload.component.css'],
18
24
  changeDetection: ChangeDetectionStrategy.OnPush,
19
25
  })
20
- export class OverviewUploadComponent implements OnInit {
26
+ export class OverviewUploadComponent implements OnInit, OnChanges {
21
27
  @Input() metadataUuid: string
28
+ @Input() formControl!: FormControl
29
+ @Output() overviewChange = new EventEmitter<GraphicOverview | null>()
30
+ @Output() altTextChange: EventEmitter<string> = new EventEmitter()
22
31
 
32
+ resourceAltText: string
23
33
  resourceFileName: string
24
34
  resourceUrl: string
25
35
 
@@ -29,42 +39,123 @@ export class OverviewUploadComponent implements OnInit {
29
39
  ) {}
30
40
 
31
41
  ngOnInit(): void {
32
- this.recordsApiService
33
- .getAllResources(this.metadataUuid)
34
- .subscribe((resources) => {
35
- this.resourceFileName = resources[0]?.filename
36
- this.resourceUrl = resources[0]?.url
42
+ this.recordsApiService.getAllResources(this.metadataUuid).subscribe({
43
+ next: (resources) => {
44
+ if (resources && resources.length > 0) {
45
+ this.resourceUrl = resources[0].url
46
+ this.resourceFileName = resources[0].filename
47
+ if (!this.resourceAltText) {
48
+ this.resourceAltText = this.resourceFileName
49
+ }
50
+ } else {
51
+ this.resourceUrl = ''
52
+ this.resourceAltText = ''
53
+ this.resourceFileName = ''
54
+ }
55
+
37
56
  this.cd.markForCheck()
38
- })
57
+ },
58
+ error: this.errorHandle,
59
+ })
39
60
  }
40
61
 
41
62
  handleFileChange(file: File) {
42
63
  this.recordsApiService
43
64
  .putResource(this.metadataUuid, file, 'public')
44
- .subscribe((resource) => {
45
- this.resourceFileName = resource.filename
46
- this.resourceUrl = resource.url
47
- this.cd.markForCheck()
65
+ .subscribe({
66
+ next: (resource) => {
67
+ this.resourceUrl = resource.url
68
+ this.resourceAltText = resource.filename
69
+
70
+ this.overviewChange.emit({
71
+ url: new URL(resource.url),
72
+ description: resource.filename,
73
+ })
74
+
75
+ this.cd.markForCheck()
76
+ },
77
+ error: this.errorHandle,
48
78
  })
49
79
  }
50
80
 
51
81
  handleUrlChange(url: string) {
52
82
  this.recordsApiService
53
83
  .putResourceFromURL(this.metadataUuid, url, 'public')
54
- .subscribe((resource) => {
55
- this.resourceFileName = resource.filename
56
- this.resourceUrl = resource.url
57
- this.cd.markForCheck()
84
+ .subscribe({
85
+ next: (resource) => {
86
+ this.resourceUrl = resource.url
87
+ this.resourceAltText = resource.filename
88
+
89
+ this.overviewChange.emit({
90
+ url: new URL(resource.url),
91
+ description: resource.filename,
92
+ })
93
+
94
+ this.cd.markForCheck()
95
+ },
96
+ error: this.errorHandle,
58
97
  })
59
98
  }
60
99
 
100
+ handleAltTextChange(newAltText: string) {
101
+ this.resourceAltText = newAltText
102
+
103
+ this.overviewChange.emit({
104
+ url: new URL(this.resourceUrl),
105
+ description: this.resourceAltText,
106
+ })
107
+
108
+ this.cd.markForCheck()
109
+ }
110
+
61
111
  handleDelete() {
112
+ //this.formControl.markAsDirty()
62
113
  this.recordsApiService
63
114
  .delResource(this.metadataUuid, this.resourceFileName)
64
- .subscribe(() => {
65
- this.resourceFileName = null
66
- this.resourceUrl = null
67
- this.cd.markForCheck()
115
+ .subscribe({
116
+ next: () => {
117
+ this.resourceAltText = ''
118
+ this.resourceUrl = ''
119
+
120
+ this.overviewChange.emit(null)
121
+
122
+ this.cd.markForCheck()
123
+ },
124
+ error: this.errorHandle,
68
125
  })
69
126
  }
127
+
128
+ private errorHandle = (error: never) => {
129
+ console.error(error)
130
+
131
+ this.resourceUrl = ''
132
+ this.resourceAltText = ''
133
+ this.resourceFileName = ''
134
+
135
+ this.overviewChange.emit(null)
136
+
137
+ this.cd.markForCheck()
138
+ }
139
+
140
+ ngOnChanges(changes: SimpleChanges): void {
141
+ const overviewChanges = changes['formControl']
142
+ if (
143
+ overviewChanges &&
144
+ overviewChanges.currentValue !== overviewChanges.previousValue
145
+ ) {
146
+ let overview: GraphicOverview
147
+ if (
148
+ overviewChanges.currentValue.value &&
149
+ overviewChanges.currentValue.value.length > 0
150
+ ) {
151
+ overview = overviewChanges.currentValue.value[0] as GraphicOverview
152
+ } else {
153
+ return
154
+ }
155
+ if (overview.description) {
156
+ this.resourceAltText = overview.description
157
+ this.cd.markForCheck()
158
+ }
159
+ }
160
+ }
70
161
  }
@@ -0,0 +1,5 @@
1
+ <gn-ui-overview-upload
2
+ [metadataUuid]="metadataUuid"
3
+ [formControl]="control"
4
+ (overviewChange)="handleOverviewChange($event)"
5
+ ></gn-ui-overview-upload>
@@ -0,0 +1,22 @@
1
+ import { CommonModule } from '@angular/common'
2
+ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
3
+ import { OverviewUploadComponent } from '../../../overview-upload/overview-upload.component'
4
+ import { FormControl } from '@angular/forms'
5
+ import { GraphicOverview } from '../../../../../../../../../libs/common/domain/src/lib/model/record'
6
+
7
+ @Component({
8
+ selector: 'gn-ui-form-field-overviews',
9
+ templateUrl: './form-field-overviews.component.html',
10
+ styleUrls: ['./form-field-overviews.component.css'],
11
+ changeDetection: ChangeDetectionStrategy.OnPush,
12
+ standalone: true,
13
+ imports: [CommonModule, OverviewUploadComponent],
14
+ })
15
+ export class FormFieldOverviewsComponent {
16
+ @Input() metadataUuid: string
17
+ @Input() control!: FormControl
18
+
19
+ handleOverviewChange(overView: GraphicOverview | null) {
20
+ this.control.setValue(overView ? [overView] : [])
21
+ }
22
+ }
@@ -62,9 +62,9 @@ export class FormFieldTemporalExtentsComponent implements OnInit, OnDestroy {
62
62
  )
63
63
  }
64
64
 
65
- onElementsChange(elements: any) {
65
+ onElementsChange(elements: { inputs: Record<string, unknown> }[]) {
66
66
  this.array.clear({ emitEvent: false })
67
- elements.forEach((e: any, i: number) =>
67
+ elements.forEach((e, i) =>
68
68
  this.array.push(e.inputs.control, {
69
69
  emitEvent: i === elements.length - 1,
70
70
  })
@@ -95,7 +95,7 @@ export class FormFieldTemporalExtentsComponent implements OnInit, OnDestroy {
95
95
 
96
96
  private resetValueFromInput(value) {
97
97
  this.array.clear({ emitEvent: false })
98
- this.elements = []
98
+ let newElements = []
99
99
  value.forEach((v: any) => {
100
100
  if ('start' in v && 'end' in v) {
101
101
  const rangeControl = new FormControl({
@@ -103,8 +103,8 @@ export class FormFieldTemporalExtentsComponent implements OnInit, OnDestroy {
103
103
  end: v.end,
104
104
  })
105
105
  this.array.push(rangeControl, { emitEvent: false })
106
- this.elements = [
107
- ...this.elements,
106
+ newElements = [
107
+ ...newElements,
108
108
  {
109
109
  component: FormFieldTemporalExtentsRangeComponent,
110
110
  inputs: {
@@ -115,8 +115,8 @@ export class FormFieldTemporalExtentsComponent implements OnInit, OnDestroy {
115
115
  } else {
116
116
  const dateControl = new FormControl({ start: v.start })
117
117
  this.array.push(dateControl, { emitEvent: false })
118
- this.elements = [
119
- ...this.elements,
118
+ newElements = [
119
+ ...newElements,
120
120
  {
121
121
  component: FormFieldTemporalExtentsDateComponent,
122
122
  inputs: {
@@ -126,5 +126,6 @@ export class FormFieldTemporalExtentsComponent implements OnInit, OnDestroy {
126
126
  ]
127
127
  }
128
128
  })
129
+ this.elements = newElements
129
130
  }
130
131
  }
@@ -76,6 +76,12 @@
76
76
  <ng-container *ngIf="isSpatialExtentField">
77
77
  <gn-ui-form-field-spatial-extent></gn-ui-form-field-spatial-extent>
78
78
  </ng-container>
79
+ <ng-container *ngIf="isGraphicOverview">
80
+ <gn-ui-form-field-overviews
81
+ [control]="formControl"
82
+ [metadataUuid]="metadataUuid$ | async"
83
+ ></gn-ui-form-field-overviews>
84
+ </ng-container>
79
85
  <ng-container *ngIf="isKeywords">
80
86
  <gn-ui-form-field-keywords
81
87
  [control]="formControl"
@@ -28,6 +28,9 @@ import { FormFieldSpatialExtentComponent } from './form-field-spatial-extent/for
28
28
  import { FormFieldUpdateFrequencyComponent } from './form-field-update-frequency/form-field-update-frequency.component'
29
29
  import { CatalogRecordKeys } from '../../../../../../../../libs/common/domain/src/lib/model/record'
30
30
  import { FormFieldKeywordsComponent } from './form-field-keywords/form-field-keywords.component'
31
+ import { FormFieldOverviewsComponent } from './form-field-overviews/form-field-overviews.component'
32
+ import { map, take } from 'rxjs/operators'
33
+ import { EditorFacade } from '../../../+state/editor.facade'
31
34
  import { FormFieldConfig } from '../../../models'
32
35
 
33
36
  @Component({
@@ -55,6 +58,7 @@ import { FormFieldConfig } from '../../../models'
55
58
  FormFieldArrayComponent,
56
59
  FormFieldKeywordsComponent,
57
60
  TranslateModule,
61
+ FormFieldOverviewsComponent,
58
62
  ],
59
63
  })
60
64
  export class FormFieldComponent {
@@ -70,9 +74,14 @@ export class FormFieldComponent {
70
74
 
71
75
  @ViewChild('titleInput') titleInput: ElementRef
72
76
 
77
+ metadataUuid$ = this.facade.record$.pipe(
78
+ take(1),
79
+ map((record) => record.uniqueIdentifier)
80
+ )
81
+
73
82
  formControl = new FormControl()
74
83
 
75
- constructor() {
84
+ constructor(private facade: EditorFacade) {
76
85
  this.valueChange = this.formControl.valueChanges
77
86
  }
78
87
 
@@ -101,6 +110,9 @@ export class FormFieldComponent {
101
110
  get isSpatialExtentField() {
102
111
  return this.model === 'spatialExtents'
103
112
  }
113
+ get isGraphicOverview() {
114
+ return this.model === 'overviews'
115
+ }
104
116
  get isSimpleField() {
105
117
  return this.model === 'uniqueIdentifier' || this.model === 'recordUpdated'
106
118
  }
@@ -83,6 +83,13 @@ export const RECORD_ABSTRACT_FIELD: EditorField = {
83
83
  },
84
84
  }
85
85
 
86
+ export const RECORD_GRAPHICAL_OVERVIEW_FIELD: EditorField = {
87
+ model: 'overviews',
88
+ formFieldConfig: {
89
+ labelKey: marker('editor.record.form.field.overviews'),
90
+ },
91
+ }
92
+
86
93
  /************************************************************
87
94
  *************** SECTIONS *****************
88
95
  ************************************************************
@@ -90,7 +97,11 @@ export const RECORD_ABSTRACT_FIELD: EditorField = {
90
97
 
91
98
  export const TITLE_SECTION: EditorSection = {
92
99
  hidden: false,
93
- fields: [RECORD_TITLE_FIELD, RECORD_ABSTRACT_FIELD],
100
+ fields: [
101
+ RECORD_TITLE_FIELD,
102
+ RECORD_ABSTRACT_FIELD,
103
+ RECORD_GRAPHICAL_OVERVIEW_FIELD,
104
+ ],
94
105
  }
95
106
 
96
107
  export const ABOUT_SECTION: EditorSection = {
@@ -32,7 +32,7 @@ import { ProxyService } from '../../../../../../libs/util/shared/src'
32
32
  import { WmsEndpoint, WmtsEndpoint } from '@camptocamp/ogc-client'
33
33
  import { LONLAT_CRS_CODES } from '../constant/projections'
34
34
  import { fromEPSGCode, register } from 'ol/proj/proj4'
35
- import proj4 from 'proj4/dist/proj4'
35
+ import proj4 from 'proj4'
36
36
  import { defaults as defaultControls } from 'ol/control/defaults'
37
37
 
38
38
  const FEATURE_PROJECTION = 'EPSG:3857'
@@ -220,11 +220,15 @@ export class MapUtilsService {
220
220
  if (!('spatialExtents' in record) || record.spatialExtents.length === 0) {
221
221
  return null
222
222
  }
223
- // transform an array of geojson geometries into a bbox
223
+ // extend all the spatial extents into an including bbox
224
224
  const totalExtent = record.spatialExtents.reduce(
225
225
  (prev, curr) => {
226
- const geom = GEOJSON.readGeometry(curr.geometry)
227
- return extend(prev, geom.getExtent())
226
+ if ('bbox' in curr) return extend(prev, curr.bbox)
227
+ else if ('geometry' in curr) {
228
+ const geom = GEOJSON.readGeometry(curr.geometry)
229
+ return extend(prev, geom.getExtent())
230
+ }
231
+ return prev
228
232
  },
229
233
  [Infinity, Infinity, -Infinity, -Infinity]
230
234
  )
@@ -1,10 +1,11 @@
1
1
  <gn-ui-results-table
2
2
  [records]="records$ | async"
3
- [recordHasDraft]="hasDraft"
3
+ [hasDraft]="hasDraft"
4
4
  [selectedRecordsIdentifiers]="selectedRecords$ | async"
5
5
  [sortOrder]="sortBy$ | async"
6
6
  (recordClick)="handleRecordClick($event)"
7
7
  (duplicateRecord)="handleDuplicateRecord($event)"
8
+ (deleteRecord)="handleDeleteRecord($event)"
8
9
  (recordsSelectedChange)="handleRecordsSelectedChange($event[0], $event[1])"
9
10
  (sortByChange)="handleSortByChange($event[0], $event[1])"
10
11
  ></gn-ui-results-table>
@@ -1,4 +1,4 @@
1
- import { Component, EventEmitter, Output } from '@angular/core'
1
+ import { Component, EventEmitter, OnDestroy, Output } from '@angular/core'
2
2
  import { CatalogRecord } from '../../../../../../libs/common/domain/src/lib/model/record'
3
3
  import { SearchFacade } from '../state/search.facade'
4
4
  import { SelectionService } from '../../../../../../libs/api/repository/src'
@@ -6,6 +6,9 @@ import { SearchService } from '../utils/service/search.service'
6
6
  import { RecordsRepositoryInterface } from '../../../../../../libs/common/domain/src/lib/repository/records-repository.interface'
7
7
  import { ResultsTableComponent } from '../../../../../../libs/ui/search/src'
8
8
  import { CommonModule } from '@angular/common'
9
+ import { Subscription } from 'rxjs'
10
+ import { NotificationsService } from '../../../../../../libs/feature/notifications/src'
11
+ import { TranslateService } from '@ngx-translate/core'
9
12
 
10
13
  @Component({
11
14
  selector: 'gn-ui-results-table-container',
@@ -14,10 +17,12 @@ import { CommonModule } from '@angular/common'
14
17
  standalone: true,
15
18
  imports: [CommonModule, ResultsTableComponent],
16
19
  })
17
- export class ResultsTableContainerComponent {
20
+ export class ResultsTableContainerComponent implements OnDestroy {
18
21
  @Output() recordClick = new EventEmitter<CatalogRecord>()
19
22
  @Output() duplicateRecord = new EventEmitter<CatalogRecord>()
20
23
 
24
+ subscription = new Subscription()
25
+
21
26
  records$ = this.searchFacade.results$
22
27
  selectedRecords$ = this.selectionService.selectedRecordsIdentifiers$
23
28
  sortBy$ = this.searchFacade.sortBy$
@@ -29,7 +34,9 @@ export class ResultsTableContainerComponent {
29
34
  private searchFacade: SearchFacade,
30
35
  private searchService: SearchService,
31
36
  private selectionService: SelectionService,
32
- private recordsRepository: RecordsRepositoryInterface
37
+ private recordsRepository: RecordsRepositoryInterface,
38
+ private notificationsService: NotificationsService,
39
+ private translateService: TranslateService
33
40
  ) {}
34
41
 
35
42
  handleRecordClick(item: unknown) {
@@ -40,6 +47,32 @@ export class ResultsTableContainerComponent {
40
47
  this.duplicateRecord.emit(item as CatalogRecord)
41
48
  }
42
49
 
50
+ async handleDeleteRecord(item: unknown) {
51
+ const uniqueIdentifier = (item as CatalogRecord).uniqueIdentifier
52
+ this.subscription.add(
53
+ this.recordsRepository.deleteRecord(uniqueIdentifier).subscribe({
54
+ next: () => {
55
+ this.recordsRepository.clearRecordDraft(uniqueIdentifier)
56
+ this.searchFacade.requestNewResults()
57
+ },
58
+ error: (error) => {
59
+ this.notificationsService.showNotification({
60
+ type: 'error',
61
+ title: this.translateService.instant(
62
+ 'editor.record.deleteError.title'
63
+ ),
64
+ text: `${this.translateService.instant(
65
+ 'editor.record.deleteError.body'
66
+ )} ${error}`,
67
+ closeMessage: this.translateService.instant(
68
+ 'editor.record.deleteError.closeMessage'
69
+ ),
70
+ })
71
+ },
72
+ })
73
+ )
74
+ }
75
+
43
76
  handleSortByChange(col: string, order: 'asc' | 'desc') {
44
77
  this.searchService.setSortBy([order, col])
45
78
  }
@@ -51,4 +84,8 @@ export class ResultsTableContainerComponent {
51
84
  this.selectionService.selectRecords(records)
52
85
  }
53
86
  }
87
+
88
+ ngOnDestroy() {
89
+ this.subscription.unsubscribe()
90
+ }
54
91
  }
@@ -8,6 +8,7 @@ import {
8
8
  Paginate,
9
9
  RequestMoreOnAggregation,
10
10
  RequestMoreResults,
11
+ RequestNewResults,
11
12
  SetConfigAggregations,
12
13
  SetConfigFilters,
13
14
  SetConfigRequestFields,
@@ -151,6 +152,11 @@ export class SearchFacade {
151
152
  return this
152
153
  }
153
154
 
155
+ requestNewResults(): SearchFacade {
156
+ this.store.dispatch(new RequestNewResults(this.searchId))
157
+ return this
158
+ }
159
+
154
160
  requestMoreOnAggregation(key: string, increment: number): SearchFacade {
155
161
  this.store.dispatch(
156
162
  new RequestMoreOnAggregation(key, increment, this.searchId)
@@ -1,5 +1,6 @@
1
1
  export * from './lib/api-card/api-card.component'
2
2
  export * from './lib/avatar/avatar.component'
3
+ export * from './lib/confirmation-dialog/confirmation-dialog.component'
3
4
  export * from './lib/content-ghost/content-ghost.component'
4
5
  export * from './lib/download-item/download-item.component'
5
6
  export * from './lib/downloads-list/downloads-list.component'
@@ -0,0 +1,12 @@
1
+ <h1 mat-dialog-title>{{ data.title }}</h1>
2
+ <div mat-dialog-content>{{ data.message }}</div>
3
+ <div mat-dialog-actions>
4
+ <gn-ui-button (buttonClick)="onCancel()">{{ data.cancelText }}</gn-ui-button>
5
+ <gn-ui-button
6
+ (buttonClick)="onConfirm()"
7
+ cdkFocusInitial
8
+ class="ml-2"
9
+ data-cy="confirm-button"
10
+ >{{ data.confirmText }}</gn-ui-button
11
+ >
12
+ </div>
@@ -0,0 +1,37 @@
1
+ import { ChangeDetectionStrategy, Component, Inject } from '@angular/core'
2
+ import {
3
+ MAT_DIALOG_DATA,
4
+ MatDialogModule,
5
+ MatDialogRef,
6
+ } from '@angular/material/dialog'
7
+ import { ButtonComponent } from '../../../../../../libs/ui/inputs/src'
8
+
9
+ export interface ConfirmationDialogData {
10
+ title: string
11
+ message: string
12
+ confirmText: string
13
+ cancelText: string
14
+ }
15
+
16
+ @Component({
17
+ selector: 'gn-ui-confirmation-dialog',
18
+ templateUrl: './confirmation-dialog.component.html',
19
+ styleUrls: ['./confirmation-dialog.component.css'],
20
+ changeDetection: ChangeDetectionStrategy.OnPush,
21
+ standalone: true,
22
+ imports: [MatDialogModule, ButtonComponent],
23
+ })
24
+ export class ConfirmationDialogComponent {
25
+ constructor(
26
+ public dialogRef: MatDialogRef<ConfirmationDialogComponent>,
27
+ @Inject(MAT_DIALOG_DATA) public data: ConfirmationDialogData
28
+ ) {}
29
+
30
+ onConfirm() {
31
+ this.dialogRef.close(true)
32
+ }
33
+
34
+ onCancel() {
35
+ this.dialogRef.close(false)
36
+ }
37
+ }
@@ -1,5 +1,8 @@
1
1
  <div class="h-full flex flex-col">
2
- <p class="flex-none mb-2 font-medium text-sm text-gray-900">
2
+ <p
3
+ *ngIf="helperText"
4
+ class="flex-none mb-2 font-medium text-sm text-gray-900"
5
+ >
3
6
  {{ helperText }}
4
7
  </p>
5
8
  <div class="flex-1" [hidden]="preview">
@@ -2,9 +2,10 @@
2
2
  :host ::ng-deep .markdown-body {
3
3
  -ms-text-size-adjust: 100%;
4
4
  -webkit-text-size-adjust: 100%;
5
- margin: 0px 0px 1.5rem 0px;
5
+ margin: 0;
6
6
  line-height: 1.5;
7
7
  word-wrap: break-word;
8
+ height: 100%;
8
9
  }
9
10
 
10
11
  /** Emphasis **/
@@ -1,7 +1,7 @@
1
1
  <div class="mb-6 md-description sm:mb-4 sm:pr-16">
2
2
  <gn-ui-content-ghost ghostClass="h-32" [showContent]="fieldReady('abstract')">
3
3
  <gn-ui-max-lines [maxLines]="6" *ngIf="metadata.abstract">
4
- <div>
4
+ <div class="mb-6">
5
5
  <gn-ui-markdown-parser
6
6
  [textContent]="metadata.abstract"
7
7
  ></gn-ui-markdown-parser>
@@ -47,19 +47,23 @@
47
47
  </ng-template>
48
48
  </ng-container>
49
49
  <ng-container *ngIf="legalConstraints.length">
50
- <gn-ui-markdown-parser
51
- *ngFor="let constraint of legalConstraints"
52
- [textContent]="constraint"
53
- >
54
- </gn-ui-markdown-parser>
50
+ <div class="mb-6">
51
+ <gn-ui-markdown-parser
52
+ *ngFor="let constraint of legalConstraints"
53
+ [textContent]="constraint"
54
+ >
55
+ </gn-ui-markdown-parser>
56
+ </div>
55
57
  </ng-container>
56
58
  <ng-container *ngIf="otherConstraints.length">
57
59
  <div gnUiLinkify *ngFor="let constraint of otherConstraints">
58
60
  <h5 translate class="font-medium text-black text-sm mb-[2px] mt-[16px]">
59
61
  record.metadata.otherConstraints
60
62
  </h5>
61
- <gn-ui-markdown-parser [textContent]="constraint">
62
- </gn-ui-markdown-parser>
63
+ <div class="mb-6">
64
+ <gn-ui-markdown-parser [textContent]="constraint">
65
+ </gn-ui-markdown-parser>
66
+ </div>
63
67
  </div>
64
68
  </ng-container>
65
69
 
@@ -12,7 +12,9 @@
12
12
  class="sortable-list flex flex-col gap-3 p-2"
13
13
  (cdkDropListDropped)="drop($event)"
14
14
  >
15
- <ng-container *ngFor="let element of elements; index as index">
15
+ <ng-container
16
+ *ngFor="let element of elements; index as index; trackBy: trackByFn"
17
+ >
16
18
  <div class="sortable-box bg-white flex items-center" cdkDrag>
17
19
  <span
18
20
  cdkDragHandle
@@ -18,8 +18,8 @@ import { MatIconModule } from '@angular/material/icon'
18
18
  import { ButtonComponent } from '../../../../../../libs/ui/inputs/src'
19
19
 
20
20
  type DynamicElement = {
21
- component: Type<any>
22
- inputs: Record<string, any>
21
+ component: Type<unknown>
22
+ inputs: Record<string, unknown>
23
23
  }
24
24
 
25
25
  @Component({
@@ -53,4 +53,8 @@ export class SortableListComponent {
53
53
  this.elements = this.elements.filter((_, i) => i !== index)
54
54
  this.elementsChange.emit(this.elements)
55
55
  }
56
+
57
+ trackByFn(index: number) {
58
+ return index
59
+ }
56
60
  }
@@ -12,7 +12,7 @@
12
12
  </span>
13
13
  </div>
14
14
  </div>
15
- <div class="flex-1">
15
+ <div class="flex-1 overflow-y-auto">
16
16
  <ng-content></ng-content>
17
17
  </div>
18
18
  </div>