geonetwork-ui 2.4.2-dev.ff0aab388 → 2.4.2

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 (103) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/read-parts.mjs +2 -3
  2. package/esm2022/libs/api/metadata-converter/src/lib/iso19139/write-parts.mjs +4 -1
  3. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  4. package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +4 -14
  5. package/esm2022/libs/feature/editor/src/lib/components/contact-card/contact-card.component.mjs +3 -3
  6. package/esm2022/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.mjs +3 -3
  7. package/esm2022/libs/feature/editor/src/lib/components/import-record/import-record.component.mjs +3 -4
  8. package/esm2022/libs/feature/editor/src/lib/components/online-resource-card/online-resource-card.component.mjs +3 -3
  9. package/esm2022/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.mjs +31 -40
  10. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.mjs +3 -3
  11. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.mjs +3 -3
  12. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-keywords/form-field-keywords.component.mjs +3 -3
  13. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.mjs +8 -9
  14. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.mjs +5 -25
  15. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-spatial-extent/form-field-spatial-extent.component.mjs +5 -4
  16. package/esm2022/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.mjs +3 -3
  17. package/esm2022/libs/feature/editor/src/lib/fields.config.mjs +10 -2
  18. package/esm2022/libs/feature/record/src/lib/data-view/data-view.component.mjs +6 -3
  19. package/esm2022/libs/feature/record/src/lib/data-view-share/data-view-share.component.mjs +3 -3
  20. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +6 -3
  21. package/esm2022/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.mjs +3 -1
  22. package/esm2022/libs/ui/search/src/lib/results-table/results-table.component.mjs +3 -3
  23. package/esm2022/libs/util/data-fetcher/src/lib/data-fetcher.mjs +5 -1
  24. package/esm2022/libs/util/data-fetcher/src/lib/headers.mjs +3 -2
  25. package/esm2022/libs/util/data-fetcher/src/lib/model.mjs +2 -1
  26. package/esm2022/libs/util/data-fetcher/src/lib/readers/wfs.mjs +79 -0
  27. package/esm2022/translations/de.json +13 -5
  28. package/esm2022/translations/en.json +22 -14
  29. package/esm2022/translations/es.json +13 -5
  30. package/esm2022/translations/fr.json +23 -15
  31. package/esm2022/translations/it.json +32 -26
  32. package/esm2022/translations/nl.json +13 -5
  33. package/esm2022/translations/pt.json +13 -5
  34. package/fesm2022/geonetwork-ui.mjs +293 -182
  35. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  36. package/libs/api/metadata-converter/src/lib/iso19139/read-parts.d.ts.map +1 -1
  37. package/libs/api/metadata-converter/src/lib/iso19139/write-parts.d.ts.map +1 -1
  38. package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
  39. package/libs/feature/editor/src/lib/components/import-record/import-record.component.d.ts +0 -1
  40. package/libs/feature/editor/src/lib/components/import-record/import-record.component.d.ts.map +1 -1
  41. package/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.d.ts +7 -14
  42. package/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.d.ts.map +1 -1
  43. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.d.ts +2 -2
  44. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.d.ts.map +1 -1
  45. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.d.ts +1 -6
  46. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.d.ts.map +1 -1
  47. package/libs/feature/editor/src/lib/components/record-form/form-field/form-field-spatial-extent/form-field-spatial-extent.component.d.ts.map +1 -1
  48. package/libs/feature/editor/src/lib/fields.config.d.ts.map +1 -1
  49. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts +2 -1
  50. package/libs/feature/record/src/lib/data-view/data-view.component.d.ts.map +1 -1
  51. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +2 -1
  52. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  53. package/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.d.ts.map +1 -1
  54. package/libs/util/data-fetcher/src/lib/data-fetcher.d.ts +3 -2
  55. package/libs/util/data-fetcher/src/lib/data-fetcher.d.ts.map +1 -1
  56. package/libs/util/data-fetcher/src/lib/headers.d.ts.map +1 -1
  57. package/libs/util/data-fetcher/src/lib/model.d.ts +1 -1
  58. package/libs/util/data-fetcher/src/lib/model.d.ts.map +1 -1
  59. package/libs/util/data-fetcher/src/lib/readers/wfs.d.ts +21 -0
  60. package/libs/util/data-fetcher/src/lib/readers/wfs.d.ts.map +1 -0
  61. package/package.json +1 -1
  62. package/src/libs/api/metadata-converter/src/lib/fixtures/geocat-ch.records.ts +1 -0
  63. package/src/libs/api/metadata-converter/src/lib/iso19139/read-parts.ts +1 -2
  64. package/src/libs/api/metadata-converter/src/lib/iso19139/write-parts.ts +3 -0
  65. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +1 -1
  66. package/src/libs/feature/dataviz/src/lib/service/data.service.ts +4 -14
  67. package/src/libs/feature/editor/src/lib/components/contact-card/contact-card.component.html +1 -1
  68. package/src/libs/feature/editor/src/lib/components/generic-keywords/generic-keywords.component.html +1 -1
  69. package/src/libs/feature/editor/src/lib/components/import-record/import-record.component.html +4 -1
  70. package/src/libs/feature/editor/src/lib/components/import-record/import-record.component.ts +0 -4
  71. package/src/libs/feature/editor/src/lib/components/online-resource-card/online-resource-card.component.ts +2 -2
  72. package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.html +8 -8
  73. package/src/libs/feature/editor/src/lib/components/online-service-resource-input/online-service-resource-input.component.ts +32 -45
  74. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts/form-field-contacts.component.html +1 -1
  75. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-contacts-for-resource/form-field-contacts-for-resource.component.html +3 -1
  76. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-keywords/form-field-keywords.component.html +1 -1
  77. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.html +0 -1
  78. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-link-resources/form-field-online-link-resources.component.ts +6 -6
  79. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.html +24 -17
  80. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-online-resources/form-field-online-resources.component.ts +2 -27
  81. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-spatial-extent/form-field-spatial-extent.component.html +1 -1
  82. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-spatial-extent/form-field-spatial-extent.component.ts +2 -1
  83. package/src/libs/feature/editor/src/lib/components/record-form/form-field/form-field-update-frequency/form-field-update-frequency.component.html +1 -1
  84. package/src/libs/feature/editor/src/lib/fields.config.ts +9 -1
  85. package/src/libs/feature/record/src/lib/data-view/data-view.component.html +1 -0
  86. package/src/libs/feature/record/src/lib/data-view/data-view.component.ts +1 -0
  87. package/src/libs/feature/record/src/lib/data-view-share/data-view-share.component.html +1 -1
  88. package/src/libs/feature/record/src/lib/map-view/map-view.component.html +1 -0
  89. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +1 -0
  90. package/src/libs/ui/search/src/lib/record-preview-feed/record-preview-feed.component.ts +3 -0
  91. package/src/libs/ui/search/src/lib/results-table/results-table.component.html +1 -1
  92. package/src/libs/util/data-fetcher/src/lib/data-fetcher.ts +9 -1
  93. package/src/libs/util/data-fetcher/src/lib/headers.ts +4 -3
  94. package/src/libs/util/data-fetcher/src/lib/model.ts +1 -0
  95. package/src/libs/util/data-fetcher/src/lib/readers/wfs.ts +112 -0
  96. package/translations/de.json +13 -5
  97. package/translations/en.json +22 -14
  98. package/translations/es.json +13 -5
  99. package/translations/fr.json +23 -15
  100. package/translations/it.json +32 -26
  101. package/translations/nl.json +13 -5
  102. package/translations/pt.json +13 -5
  103. package/translations/sk.json +14 -6
@@ -5,8 +5,6 @@ import {
5
5
  Component,
6
6
  EventEmitter,
7
7
  Input,
8
- OnChanges,
9
- OnInit,
10
8
  Output,
11
9
  } from '@angular/core'
12
10
  import { FormsModule } from '@angular/forms'
@@ -23,23 +21,27 @@ import {
23
21
  TextInputComponent,
24
22
  UrlInputComponent,
25
23
  } from '../../../../../../../libs/ui/inputs/src'
26
- import { TranslateModule } from '@ngx-translate/core'
24
+ import { createFuzzyFilter, getLayers } from '../../../../../../../libs/util/shared/src'
27
25
  import {
28
26
  NgIconComponent,
29
27
  provideIcons,
30
28
  provideNgIconsConfig,
31
29
  } from '@ng-icons/core'
32
- import { iconoirCloudUpload } from '@ng-icons/iconoir'
33
- import { createFuzzyFilter, getLayers } from '../../../../../../../libs/util/shared/src'
30
+ import { iconoirRefresh } from '@ng-icons/iconoir'
31
+ import { TranslateModule } from '@ngx-translate/core'
34
32
  import {
35
33
  BehaviorSubject,
36
34
  debounceTime,
37
35
  distinctUntilChanged,
38
- map,
39
36
  Observable,
40
37
  switchMap,
41
38
  } from 'rxjs'
42
39
 
40
+ marker('editor.record.form.field.onlineResource.edit.identifier.placeholder')
41
+ marker(
42
+ 'editor.record.form.field.onlineResource.edit.identifier.placeholder.wps'
43
+ )
44
+
43
45
  @Component({
44
46
  selector: 'gn-ui-online-service-resource-input',
45
47
  templateUrl: './online-service-resource-input.component.html',
@@ -59,26 +61,25 @@ import {
59
61
  UrlInputComponent,
60
62
  ],
61
63
  providers: [
62
- provideIcons({ iconoirCloudUpload }),
64
+ provideIcons({ iconoirRefresh }),
63
65
  provideNgIconsConfig({
64
66
  size: '1.5em',
65
67
  }),
66
68
  ],
67
69
  })
68
- export class OnlineServiceResourceInputComponent implements OnChanges, OnInit {
69
- @Input() service: DatasetServiceDistribution
70
+ export class OnlineServiceResourceInputComponent {
71
+ _service: DatasetServiceDistribution
72
+ @Input() set service(service: DatasetServiceDistribution) {
73
+ this._service = { ...service }
74
+ }
70
75
  @Input() protocolHint?: string
71
76
  @Input() disabled? = false
72
77
  @Input() modifyMode? = false
73
- @Output() urlChange: EventEmitter<string> = new EventEmitter()
74
- @Output() identifierSubmit: EventEmitter<{
75
- url: string
76
- identifier: string
77
- }> = new EventEmitter()
78
+ @Output() serviceChange: EventEmitter<DatasetServiceDistribution> =
79
+ new EventEmitter()
78
80
 
79
81
  errorMessage = false
80
- selectedProtocol: ServiceProtocol
81
- url = ''
82
+
82
83
  layersSubject = new BehaviorSubject<{ name: string; title: string }[]>([])
83
84
  layers$: Observable<{ name: string; title: string }[]> =
84
85
  this.layersSubject.asObservable()
@@ -121,35 +122,18 @@ export class OnlineServiceResourceInputComponent implements OnChanges, OnInit {
121
122
 
122
123
  get activeLayerSuggestion() {
123
124
  return !['wps', 'GPFDL', 'esriRest', 'other'].includes(
124
- this.service.accessServiceProtocol
125
+ this._service.accessServiceProtocol
125
126
  )
126
127
  }
127
128
 
128
- ngOnChanges() {
129
- this.selectedProtocol =
130
- this.protocolOptions.find(
131
- (option) => option.value === this.service.accessServiceProtocol
132
- )?.value ?? 'other'
133
- }
134
-
135
- ngOnInit() {
136
- if (this.service.url) {
137
- this.url = this.service.url.toString()
138
- }
139
- }
140
-
141
129
  handleUrlValueChange(url: string) {
142
- this.url = url
143
- this.service.url = url ? new URL(url) : undefined
130
+ this._service.url = url ? new URL(url) : undefined
144
131
  this.resetLayersSuggestion()
145
- this.urlChange.emit(this.url)
146
132
  }
147
133
 
148
134
  async handleUploadClick(url: string) {
149
- this.url = url
150
-
151
135
  try {
152
- const layers = await getLayers(url, this.service.accessServiceProtocol)
136
+ const layers = await getLayers(url, this._service.accessServiceProtocol)
153
137
 
154
138
  if (layers.length === 0) {
155
139
  throw new Error('No layers found')
@@ -165,27 +149,29 @@ export class OnlineServiceResourceInputComponent implements OnChanges, OnInit {
165
149
  }
166
150
 
167
151
  resetAllFormFields() {
168
- this.url = ''
169
- this.service.url = null
152
+ this._service.url = null
170
153
  this.resetLayersSuggestion()
171
154
  }
172
155
 
173
156
  resetLayersSuggestion() {
174
157
  this.errorMessage = false
175
158
  this.layersSubject.next([])
176
- this.service.identifierInService = null
159
+ this._service.identifierInService = null
177
160
  }
178
161
 
179
- submitIdentifier(identifier: string) {
180
- if (!identifier) return
181
- this.identifierSubmit.emit({ url: this.url, identifier })
182
- this.service.identifierInService = null
162
+ submit() {
163
+ this.serviceChange.emit({
164
+ ...this._service,
165
+ name: this._service.identifierInService, // should we keep the identifierInService? read-write duplicate with name
166
+ })
167
+ this._service.accessServiceProtocol = 'ogcFeatures'
168
+ this.resetAllFormFields()
183
169
  }
184
170
 
185
171
  getIdentifierPlaceholder(): string {
186
172
  const baseKey =
187
173
  'editor.record.form.field.onlineResource.edit.identifier.placeholder'
188
- return this.service.accessServiceProtocol === 'wps'
174
+ return this._service.accessServiceProtocol === 'wps'
189
175
  ? `${baseKey}.wps`
190
176
  : baseKey
191
177
  }
@@ -217,6 +203,7 @@ export class OnlineServiceResourceInputComponent implements OnChanges, OnInit {
217
203
  * gn-ui-autocomplete
218
204
  */
219
205
  handleSelectValue(val: { name: string; title: string }) {
220
- this.service.identifierInService = val.name
206
+ this._service.identifierInService = val.name // should we keep the identifierInService? read-write duplicate with name
207
+ this._service.description = val.title
221
208
  }
222
209
  }
@@ -1,6 +1,6 @@
1
1
  <div class="flex flex-col gap-3">
2
2
  <gn-ui-autocomplete
3
- [placeholder]="'Choose a contact'"
3
+ [placeholder]="'editor.record.form.field.contacts.placeholder' | translate"
4
4
  [action]="autoCompleteAction"
5
5
  (itemSelected)="addContact($event)"
6
6
  [displayWithFn]="displayWithFn"
@@ -31,7 +31,9 @@
31
31
  </div>
32
32
 
33
33
  <gn-ui-autocomplete
34
- [placeholder]="'Choose a contact'"
34
+ [placeholder]="
35
+ 'editor.record.form.field.contactsForResource.placeholder' | translate
36
+ "
35
37
  [action]="autoCompleteAction"
36
38
  (itemSelected)="addContact($event, role)"
37
39
  [displayWithFn]="displayWithFn"
@@ -2,7 +2,7 @@
2
2
  <gn-ui-generic-keywords
3
3
  [keywords]="filteredKeywords"
4
4
  [keywordTypes]="keywordTypes"
5
- [placeholder]="'editor.form.keywords.placeholder' | translate"
5
+ [placeholder]="'editor.record.form.keywords.placeholder' | translate"
6
6
  (changedKeywords)="handleKeywordsChange($event)"
7
7
  [allowSubmit]="false"
8
8
  >
@@ -41,7 +41,6 @@
41
41
  class="w-full"
42
42
  [disabled]="true"
43
43
  [value]="onlineResource.url"
44
- [disabled]="disabled$ | async"
45
44
  [showValidateButton]="false"
46
45
  ></gn-ui-url-input>
47
46
  </div>
@@ -1,3 +1,4 @@
1
+ import { CommonModule } from '@angular/common'
1
2
  import {
2
3
  ChangeDetectionStrategy,
3
4
  ChangeDetectorRef,
@@ -8,28 +9,27 @@ import {
8
9
  TemplateRef,
9
10
  ViewChild,
10
11
  } from '@angular/core'
12
+ import { MatDialog } from '@angular/material/dialog'
11
13
  import {
12
14
  OnlineLinkResource,
13
15
  OnlineResource,
14
16
  } from '../../../../../../../../../libs/common/domain/src/lib/model/record'
17
+ import { PlatformServiceInterface } from '../../../../../../../../../libs/common/domain/src/lib/platform.service.interface'
18
+ import { NotificationsService } from '../../../../../../../../../libs/feature/notifications/src'
15
19
  import {
16
20
  FileInputComponent,
17
21
  TextAreaComponent,
18
22
  TextInputComponent,
19
23
  UrlInputComponent,
20
24
  } from '../../../../../../../../../libs/ui/inputs/src'
21
- import { CommonModule } from '@angular/common'
22
- import { OnlineResourceCardComponent } from '../../../online-resource-card/online-resource-card.component'
23
25
  import {
24
26
  ModalDialogComponent,
25
27
  SortableListComponent,
26
28
  } from '../../../../../../../../../libs/ui/layout/src'
27
- import { NotificationsService } from '../../../../../../../../../libs/feature/notifications/src'
28
29
  import { TranslateModule, TranslateService } from '@ngx-translate/core'
29
- import { PlatformServiceInterface } from '../../../../../../../../../libs/common/domain/src/lib/platform.service.interface'
30
- import { map, Subscription } from 'rxjs'
31
- import { MatDialog } from '@angular/material/dialog'
30
+ import { Subscription } from 'rxjs'
32
31
  import { MAX_UPLOAD_SIZE_MB } from '../../../../fields.config'
32
+ import { OnlineResourceCardComponent } from '../../../online-resource-card/online-resource-card.component'
33
33
 
34
34
  @Component({
35
35
  selector: 'gn-ui-form-field-online-link-resources',
@@ -20,8 +20,7 @@
20
20
  >
21
21
  <gn-ui-online-service-resource-input
22
22
  [service]="newService"
23
- [disabled]="disabled$ | async"
24
- (identifierSubmit)="handleIdentifierSubmit($event)"
23
+ (serviceChange)="handleServiceChange($event)"
25
24
  ></gn-ui-online-service-resource-input>
26
25
  </div>
27
26
  <div class="h-[8px]"></div>
@@ -40,28 +39,36 @@
40
39
 
41
40
  <ng-template #dialogTemplate let-onlineResource>
42
41
  <div class="flex flex-col gap-[16px]">
43
- <div>
44
- <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
45
- editor.record.form.field.onlineResource.edit.title
46
- </h3>
47
- <gn-ui-text-input [(value)]="onlineResource.name"></gn-ui-text-input>
48
- </div>
49
- <div>
50
- <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
51
- editor.record.form.field.onlineResource.edit.description
52
- </h3>
53
- <gn-ui-text-area
54
- [(value)]="onlineResource.description"
55
- ></gn-ui-text-area>
56
- </div>
57
42
  <ng-container *ngIf="onlineResource.type === 'service'; else urlInput">
58
- <span class="w-full border-b border-gray-300"></span>
59
43
  <gn-ui-online-service-resource-input
60
44
  [service]="onlineResource"
61
45
  [modifyMode]="true"
46
+ [disabled]="true"
62
47
  ></gn-ui-online-service-resource-input>
48
+ <div>
49
+ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
50
+ editor.record.form.field.onlineResource.edit.description
51
+ </h3>
52
+ <gn-ui-text-area
53
+ [(value)]="onlineResource.description"
54
+ ></gn-ui-text-area>
55
+ </div>
63
56
  </ng-container>
64
57
  <ng-template #urlInput>
58
+ <div>
59
+ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
60
+ editor.record.form.field.onlineResource.edit.title
61
+ </h3>
62
+ <gn-ui-text-input [(value)]="onlineResource.name"></gn-ui-text-input>
63
+ </div>
64
+ <div>
65
+ <h3 class="text-[16px] font-bold text-main mb-[12px]" translate>
66
+ editor.record.form.field.onlineResource.edit.description
67
+ </h3>
68
+ <gn-ui-text-area
69
+ [(value)]="onlineResource.description"
70
+ ></gn-ui-text-area>
71
+ </div>
65
72
  <span class="w-full border-b border-gray-300"></span>
66
73
  <gn-ui-url-input
67
74
  class="w-full"
@@ -159,33 +159,8 @@ export class FormFieldOnlineResourcesComponent {
159
159
  }
160
160
  }
161
161
 
162
- handleServiceUrlChange(url: string) {
163
- this.valueChange.emit([
164
- ...this.allResources,
165
- {
166
- ...this.newService,
167
- url: new URL(url),
168
- },
169
- ])
170
- }
171
-
172
- handleIdentifierSubmit(payload: { url: string; identifier: string }) {
173
- this.valueChange.emit([
174
- ...this.allResources,
175
- {
176
- ...this.newService,
177
- url: new URL(payload.url),
178
- },
179
- ])
180
- }
181
-
182
- handleServiceModify(
183
- oldService: DatasetServiceDistribution,
184
- newService: DatasetServiceDistribution
185
- ) {
186
- oldService.accessServiceProtocol = newService.accessServiceProtocol
187
- oldService.identifierInService = newService.identifierInService
188
- oldService.url = newService.url
162
+ handleServiceChange(service: DatasetServiceDistribution) {
163
+ this.valueChange.emit([...this.allResources, service])
189
164
  }
190
165
 
191
166
  handleResourcesChange(items: unknown[]) {
@@ -1,6 +1,6 @@
1
1
  <div class="flex flex-col gap-3">
2
2
  <gn-ui-generic-keywords
3
- [placeholder]="'Search for place keywords'"
3
+ [placeholder]="'editor.record.form.keywords.place.placeholder' | translate"
4
4
  [keywords]="shownKeywords$ | async"
5
5
  [keywordTypes]="['place']"
6
6
  (deletedKeyword)="handleKeywordDelete($event)"
@@ -10,7 +10,7 @@ import { firstValueFrom, map, shareReplay } from 'rxjs'
10
10
  import { EditorFacade } from '../../../../+state/editor.facade'
11
11
  import { switchMap } from 'rxjs/operators'
12
12
  import { FormFieldMapContainerComponent } from '../form-field-map-container/form-field-map-container.component'
13
- import { TranslateService } from '@ngx-translate/core'
13
+ import { TranslateModule, TranslateService } from '@ngx-translate/core'
14
14
  import { SPATIAL_SCOPES } from '../../../../fields.config'
15
15
 
16
16
  // This intermediary type will let us keep track of which keyword is bound to
@@ -36,6 +36,7 @@ type KeywordWithExtent = Keyword & {
36
36
  CommonModule,
37
37
  GenericKeywordsComponent,
38
38
  FormFieldMapContainerComponent,
39
+ TranslateModule,
39
40
  ],
40
41
  })
41
42
  export class FormFieldSpatialExtentComponent {
@@ -5,7 +5,7 @@
5
5
  (toggled)="onPlannedToggled()"
6
6
  ></gn-ui-check-toggle>
7
7
  <gn-ui-dropdown-selector
8
- title="updateFrequency"
8
+ [title]="'editor.record.form.field.updateFrequency' | translate"
9
9
  [showTitle]="false"
10
10
  [choices]="choices"
11
11
  [selected]="selectedFrequency"
@@ -63,6 +63,8 @@ export const RECORD_KEYWORDS_FIELD: EditorField = {
63
63
  model: 'keywords',
64
64
  formFieldConfig: {},
65
65
  }
66
+ // keeping track of the label to not lose existing translation
67
+ marker('editor.record.form.field.keywords')
66
68
 
67
69
  export const RECORD_RESOURCE_CREATED_FIELD: EditorField = {
68
70
  model: 'resourceCreated',
@@ -156,18 +158,24 @@ export const RECORD_SPATIAL_EXTENTS_FIELD: EditorField = {
156
158
  model: 'spatialExtents',
157
159
  formFieldConfig: {},
158
160
  }
161
+ // keeping track of the label to not lose existing translation
162
+ marker('editor.record.form.field.spatialExtents')
159
163
 
160
164
  export const RECORD_ONLINE_RESOURCES: EditorField = {
161
165
  model: 'onlineResources',
162
166
  modelSpecifier: 'onlineResourceType:!link',
163
167
  formFieldConfig: {},
164
168
  }
169
+ // keeping track of the label to not lose existing translation
170
+ marker('editor.record.form.field.onlineResources')
165
171
 
166
172
  export const RECORD_ONLINE_LINK_RESOURCES: EditorField = {
167
173
  model: 'onlineResources',
168
174
  modelSpecifier: 'onlineResourceType:link',
169
175
  formFieldConfig: {},
170
176
  }
177
+ // keeping track of the label to not lose existing translation
178
+ marker('editor.record.form.field.onlineLinkResources')
171
179
 
172
180
  /************************************************************
173
181
  *************** SECTIONS *****************
@@ -273,7 +281,7 @@ export const DEFAULT_CONFIGURATION: EditorConfig = {
273
281
  ],
274
282
  },
275
283
  {
276
- labelKey: marker('editor.record.form.page.ressources'),
284
+ labelKey: marker('editor.record.form.page.resources'),
277
285
  sections: [ASSOCIATED_RESOURCES_SECTION, ANNEXES_SECTION],
278
286
  },
279
287
  {
@@ -1,6 +1,7 @@
1
1
  <div class="w-full h-full flex flex-col p-1">
2
2
  <gn-ui-dropdown-selector
3
3
  *ngIf="dropdownChoices$ | async as choices"
4
+ [ngClass]="{ hidden: !displaySource }"
4
5
  [title]="'table.select.data' | translate"
5
6
  class="truncate p-1 -mx-1 self-end mb-1"
6
7
  extraBtnClass="!text-primary font-sans font-medium"
@@ -34,6 +34,7 @@ import { TranslateModule } from '@ngx-translate/core'
34
34
  })
35
35
  export class DataViewComponent {
36
36
  @Input() mode: 'table' | 'chart'
37
+ @Input() displaySource = true
37
38
  @Output() chartConfig$ = new BehaviorSubject<DatavizConfigurationModel>(null)
38
39
  compatibleDataLinks$ = combineLatest([
39
40
  this.mdViewFacade.dataLinks$,
@@ -1,4 +1,4 @@
1
- <div class="container-lg px-5 my-1 lg:mx-auto">
1
+ <div class="px-5 my-1">
2
2
  <mat-tab-group
3
3
  [selectedIndex]="0"
4
4
  animationDuration="0ms"
@@ -1,6 +1,7 @@
1
1
  <div class="w-full h-full flex flex-col p-1">
2
2
  <div class="w-full flex justify-end">
3
3
  <gn-ui-dropdown-selector
4
+ [ngClass]="{ hidden: !displaySource }"
4
5
  class="truncate p-1 -mx-1 mb-1"
5
6
  extraBtnClass="!text-primary font-sans font-medium"
6
7
  [title]="'map.select.layer' | translate"
@@ -85,6 +85,7 @@ export class MapViewComponent implements AfterViewInit {
85
85
  @Input() set excludeWfs(value: boolean) {
86
86
  this.excludeWfs$.next(value)
87
87
  }
88
+ @Input() displaySource = true
88
89
  @ViewChild('mapContainer') mapContainer: MapContainerComponent
89
90
 
90
91
  excludeWfs$ = new BehaviorSubject(false)
@@ -2,6 +2,9 @@ import { ChangeDetectionStrategy, Component, ElementRef } from '@angular/core'
2
2
  import { RecordPreviewComponent } from '../record-preview/record-preview.component'
3
3
  import { TranslateService } from '@ngx-translate/core'
4
4
  import Duration from 'duration-relativetimeformat'
5
+ import { marker } from '@biesbjerg/ngx-translate-extract-marker'
6
+
7
+ marker('record.was.created.time')
5
8
 
6
9
  @Component({
7
10
  selector: 'gn-ui-record-preview-feed',
@@ -85,7 +85,7 @@
85
85
 
86
86
  <!-- OWNER COLUMN -->
87
87
  <gn-ui-interactive-table-column
88
- [width]="'9rem'"
88
+ [width]="'12rem'"
89
89
  [sortable]="true"
90
90
  [activeSort]="isSortedBy('recordOwner')"
91
91
  (sortChange)="setSortBy('recordOwner', $event)"
@@ -8,11 +8,16 @@ import { inferDatasetType } from './utils'
8
8
  import { BaseReader } from './readers/base'
9
9
  import { GmlReader } from './readers/gml'
10
10
  import { WfsVersion } from '@camptocamp/ogc-client'
11
+ import { WfsReader } from './readers/wfs'
11
12
 
12
13
  export async function openDataset(
13
14
  url: string,
14
15
  typeHint?: SupportedType,
15
- options?: { namespace: string; wfsVersion: WfsVersion }
16
+ options?: {
17
+ namespace?: string
18
+ wfsVersion?: WfsVersion
19
+ wfsFeatureType?: string
20
+ }
16
21
  ): Promise<BaseReader> {
17
22
  const fileType = await inferDatasetType(url, typeHint)
18
23
  let reader: BaseReader
@@ -33,6 +38,9 @@ export async function openDataset(
33
38
  case 'gml':
34
39
  reader = new GmlReader(url, options.namespace, options.wfsVersion)
35
40
  break
41
+ case 'wfs':
42
+ reader = await WfsReader.createReader(url, options.wfsFeatureType)
43
+ break
36
44
  }
37
45
  reader.load()
38
46
  return reader
@@ -5,9 +5,10 @@ export function parseHeaders(httpHeaders: Headers): DatasetHeaders {
5
5
  if (httpHeaders.has('Content-Type')) {
6
6
  result.mimeType = httpHeaders.get('Content-Type').split(';')[0]
7
7
  const supported =
8
- SupportedTypes.filter(
9
- (type) => AllMimeTypes[type].indexOf(result.mimeType as never) > -1
10
- )[0] || null
8
+ SupportedTypes.filter((type) => type !== 'wfs') // Ignore wfs type as it is not a file type
9
+ .filter(
10
+ (type) => AllMimeTypes[type].indexOf(result.mimeType as never) > -1
11
+ )[0] || null
11
12
  if (supported !== null) result.supportedType = supported
12
13
  }
13
14
  if (httpHeaders.has('Content-Length')) {
@@ -60,6 +60,7 @@ export const SupportedTypes = [
60
60
  'geojson',
61
61
  'excel',
62
62
  'gml',
63
+ 'wfs',
63
64
  ] as const
64
65
  export type SupportedType = (typeof SupportedTypes)[number]
65
66
 
@@ -0,0 +1,112 @@
1
+ import { WfsEndpoint, WfsVersion } from '@camptocamp/ogc-client'
2
+ import { DataItem, DatasetInfo, PropertyInfo } from '../model'
3
+ import { fetchDataAsText } from '../utils'
4
+ import { BaseReader } from './base'
5
+ import { GmlReader, parseGml } from './gml'
6
+ import { GeojsonReader, parseGeojson } from './geojson'
7
+
8
+ export class WfsReader extends BaseReader {
9
+ endpoint: WfsEndpoint
10
+ featureTypeName: string
11
+ version: WfsVersion
12
+
13
+ constructor(url: string, wfsEndpoint: WfsEndpoint, featureTypeName: string) {
14
+ super(url)
15
+ this.endpoint = wfsEndpoint
16
+ this.featureTypeName = featureTypeName
17
+ this.version = this.endpoint.getVersion()
18
+ }
19
+
20
+ get properties(): Promise<PropertyInfo[]> {
21
+ return this.getData().then((result) => result.properties)
22
+ }
23
+
24
+ get info(): Promise<DatasetInfo> {
25
+ return this.endpoint.getFeatureTypeFull(this.featureTypeName).then(
26
+ (result) =>
27
+ ({
28
+ itemsCount: result.objectCount,
29
+ }) as DatasetInfo
30
+ )
31
+ }
32
+
33
+ static async createReader(wfsUrlEndpoint: string, featureTypeName?: string) {
34
+ const wfsEndpoint = await new WfsEndpoint(wfsUrlEndpoint).isReady()
35
+ const featureTypes = wfsEndpoint.getFeatureTypes()
36
+ const featureType = wfsEndpoint.getFeatureTypeSummary(
37
+ featureTypes.length === 1 && !featureTypeName
38
+ ? featureTypes[0].name
39
+ : featureTypeName
40
+ )
41
+ if (!featureType) {
42
+ throw new Error('wfs.featuretype.notfound')
43
+ }
44
+
45
+ if (wfsEndpoint.supportsStartIndex()) {
46
+ return new WfsReader(wfsUrlEndpoint, wfsEndpoint, featureType.name)
47
+ } else if (wfsEndpoint.supportsJson(featureType.name)) {
48
+ return new GeojsonReader(
49
+ wfsEndpoint.getFeatureUrl(featureType.name, {
50
+ asJson: true,
51
+ outputCrs: 'EPSG:4326',
52
+ })
53
+ )
54
+ } else {
55
+ if (
56
+ featureType.outputFormats.find((f) =>
57
+ f.toLowerCase().includes('gml')
58
+ ) &&
59
+ (featureType.defaultCrs === 'EPSG:4326' ||
60
+ featureType.otherCrs?.includes('EPSG:4326'))
61
+ ) {
62
+ return new GmlReader(
63
+ wfsEndpoint.getFeatureUrl(featureType.name, {
64
+ outputFormat: featureType.outputFormats.find((f) =>
65
+ f.toLowerCase().includes('gml')
66
+ ),
67
+ outputCrs: 'EPSG:4326',
68
+ }),
69
+ featureType.name,
70
+ wfsEndpoint.getVersion()
71
+ )
72
+ }
73
+ throw new Error('wfs.geojsongml.notsupported')
74
+ }
75
+ }
76
+
77
+ protected getData() {
78
+ const asJson = this.endpoint.supportsJson(this.featureTypeName)
79
+ let url = this.endpoint.getFeatureUrl(this.featureTypeName, {
80
+ ...(this.startIndex !== null && { startIndex: this.startIndex }),
81
+ ...(this.count !== null && { maxFeatures: this.count }),
82
+ asJson,
83
+ outputCrs: 'EPSG:4326',
84
+ // sortBy: this.sort // TODO: no sort in ogc-client?
85
+ })
86
+
87
+ if (Array.isArray(this.sort) && this.sort.length > 0) {
88
+ const finalUrl = new URL(url)
89
+ const sorts = this.sort
90
+ .map(
91
+ (fieldSort) => `${fieldSort[1]}+${fieldSort[0] === 'asc' ? 'A' : 'D'}`
92
+ )
93
+ .join(',')
94
+ // Direct update on string url to prevent encoding of +A and +D
95
+ url = `${url}${finalUrl.search ? '&' : ''}SORTBY=${sorts}`
96
+ }
97
+
98
+ return fetchDataAsText(url).then((text) =>
99
+ asJson
100
+ ? parseGeojson(text)
101
+ : parseGml(text, this.featureTypeName, this.version)
102
+ )
103
+ }
104
+
105
+ load() {
106
+ // Nothing to load for Wfs
107
+ }
108
+
109
+ async read(): Promise<DataItem[]> {
110
+ return (await this.getData()).items
111
+ }
112
+ }