geonetwork-ui 2.2.0-dev.2a6e8d6d → 2.2.0-dev.3ee8e2c9

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 (57) hide show
  1. package/esm2022/libs/api/metadata-converter/src/lib/gn4/atomic-operations.mjs +2 -1
  2. package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +36 -2
  3. package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
  4. package/esm2022/libs/feature/editor/src/lib/record-form/record-form.component.mjs +5 -3
  5. package/esm2022/libs/feature/map/src/index.mjs +2 -1
  6. package/esm2022/libs/feature/map/src/lib/constant/index.mjs +2 -1
  7. package/esm2022/libs/feature/map/src/lib/constant/projections.mjs +2 -0
  8. package/esm2022/libs/feature/map/src/lib/utils/index.mjs +1 -3
  9. package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +60 -29
  10. package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +29 -20
  11. package/esm2022/libs/ui/inputs/src/lib/editable-label/editable-label.directive.mjs +45 -0
  12. package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +8 -3
  13. package/esm2022/libs/ui/search/src/lib/record-table/record-table.component.mjs +3 -3
  14. package/fesm2022/geonetwork-ui.mjs +159 -84
  15. package/fesm2022/geonetwork-ui.mjs.map +1 -1
  16. package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts +1 -0
  17. package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts.map +1 -1
  18. package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
  19. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +9 -5
  20. package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
  21. package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts.map +1 -1
  22. package/libs/feature/map/src/index.d.ts +1 -0
  23. package/libs/feature/map/src/index.d.ts.map +1 -1
  24. package/libs/feature/map/src/lib/constant/index.d.ts +1 -0
  25. package/libs/feature/map/src/lib/constant/index.d.ts.map +1 -1
  26. package/libs/feature/map/src/lib/constant/projections.d.ts.map +1 -0
  27. package/libs/feature/map/src/lib/utils/index.d.ts +0 -2
  28. package/libs/feature/map/src/lib/utils/index.d.ts.map +1 -1
  29. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts +13 -11
  30. package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
  31. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +1 -3
  32. package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
  33. package/libs/ui/inputs/src/lib/editable-label/editable-label.directive.d.ts +13 -0
  34. package/libs/ui/inputs/src/lib/editable-label/editable-label.directive.d.ts.map +1 -0
  35. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +18 -17
  36. package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts.map +1 -1
  37. package/package.json +2 -1
  38. package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +3 -0
  39. package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +43 -0
  40. package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +11 -7
  41. package/src/libs/feature/editor/src/lib/record-form/record-form.component.ts +2 -1
  42. package/src/libs/feature/map/src/index.ts +1 -0
  43. package/src/libs/feature/map/src/lib/constant/index.ts +1 -0
  44. package/src/libs/feature/map/src/lib/utils/index.ts +0 -2
  45. package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +85 -50
  46. package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +18 -3
  47. package/src/libs/ui/inputs/src/lib/editable-label/editable-label.directive.ts +47 -0
  48. package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +3 -0
  49. package/src/libs/ui/search/src/lib/record-table/record-table.component.html +2 -2
  50. package/esm2022/libs/feature/map/src/lib/utils/map-utils-wms.service.mjs +0 -55
  51. package/esm2022/libs/feature/map/src/lib/utils/projections.mjs +0 -2
  52. package/libs/feature/map/src/lib/utils/map-utils-wms.service.d.ts +0 -17
  53. package/libs/feature/map/src/lib/utils/map-utils-wms.service.d.ts.map +0 -1
  54. package/libs/feature/map/src/lib/utils/projections.d.ts.map +0 -1
  55. package/src/libs/feature/map/src/lib/utils/map-utils-wms.service.ts +0 -58
  56. /package/libs/feature/map/src/lib/{utils → constant}/projections.d.ts +0 -0
  57. /package/src/libs/feature/map/src/lib/{utils → constant}/projections.ts +0 -0
@@ -2,18 +2,18 @@ import { HttpClient } from '@angular/common/http'
2
2
  import { Injectable } from '@angular/core'
3
3
  import type { FeatureCollection } from 'geojson'
4
4
  import { extend, Extent, isEmpty } from 'ol/extent'
5
- import OlFeature, { FeatureLike } from 'ol/Feature'
5
+ import Feature from 'ol/Feature'
6
6
  import GeoJSON from 'ol/format/GeoJSON'
7
7
  import { Geometry } from 'ol/geom'
8
8
  import Layer from 'ol/layer/Layer'
9
9
  import Map from 'ol/Map'
10
- import { fromLonLat } from 'ol/proj'
10
+ import { transformExtent } from 'ol/proj'
11
11
  import Source from 'ol/source/Source'
12
12
  import ImageWMS from 'ol/source/ImageWMS'
13
13
  import TileWMS from 'ol/source/TileWMS'
14
14
  import VectorSource from 'ol/source/Vector'
15
- import { Options, optionsFromCapabilities } from 'ol/source/WMTS'
16
- import { DragPan, MouseWheelZoom, defaults, Interaction } from 'ol/interaction'
15
+ import { optionsFromCapabilities } from 'ol/source/WMTS'
16
+ import { defaults, DragPan, Interaction, MouseWheelZoom } from 'ol/interaction'
17
17
  import {
18
18
  mouseOnly,
19
19
  noModifierKeys,
@@ -21,45 +21,53 @@ import {
21
21
  primaryAction,
22
22
  } from 'ol/events/condition'
23
23
  import WMTSCapabilities from 'ol/format/WMTSCapabilities'
24
- import { from, Observable, of } from 'rxjs'
24
+ import { from, Observable } from 'rxjs'
25
25
  import { map } from 'rxjs/operators'
26
26
  import {
27
27
  MapContextLayerModel,
28
28
  MapContextLayerTypeEnum,
29
+ MapContextLayerWmsModel,
29
30
  MapContextLayerWmtsModel,
30
31
  } from '../map-context/map-context.model'
31
- import { MapUtilsWMSService } from './map-utils-wms.service'
32
32
  import Collection from 'ol/Collection'
33
33
  import MapBrowserEvent from 'ol/MapBrowserEvent'
34
- import { DatasetDistribution } from '../../../../../../libs/common/domain/src/lib/model/record'
34
+ import {
35
+ CatalogRecord,
36
+ DatasetDistribution,
37
+ } from '../../../../../../libs/common/domain/src/lib/model/record'
38
+ import { ProxyService } from '../../../../../../libs/util/shared/src'
39
+ import { WmsEndpoint } from '@camptocamp/ogc-client'
40
+ import { LONLAT_CRS_CODES } from '../constant/projections'
41
+ import { fromEPSGCode, register } from 'ol/proj/proj4'
42
+ import proj4 from 'proj4/dist/proj4'
35
43
 
36
44
  const FEATURE_PROJECTION = 'EPSG:3857'
37
45
  const DATA_PROJECTION = 'EPSG:4326'
38
46
 
47
+ const GEOJSON = new GeoJSON()
48
+
39
49
  @Injectable({
40
50
  providedIn: 'root',
41
51
  })
42
52
  export class MapUtilsService {
43
- constructor(private http: HttpClient, private wmsUtils: MapUtilsWMSService) {}
53
+ constructor(private http: HttpClient, private proxy: ProxyService) {}
44
54
 
45
55
  createEmptyMap(): Map {
46
- const map = new Map({
56
+ return new Map({
47
57
  controls: [],
48
58
  pixelRatio: 1,
49
59
  })
50
- return map
51
60
  }
52
61
 
53
62
  readFeatureCollection = (
54
63
  featureCollection: FeatureCollection,
55
64
  featureProjection = FEATURE_PROJECTION,
56
65
  dataProjection = DATA_PROJECTION
57
- ): FeatureLike[] => {
58
- const olFeatures = new GeoJSON().readFeatures(featureCollection, {
66
+ ): Feature<Geometry>[] => {
67
+ return GEOJSON.readFeatures(featureCollection, {
59
68
  featureProjection,
60
69
  dataProjection,
61
- })
62
- return olFeatures
70
+ }) as Feature<Geometry>[]
63
71
  }
64
72
 
65
73
  isWMSLayer(layer: Layer<Source>): boolean {
@@ -78,20 +86,14 @@ export class MapUtilsService {
78
86
  ...source.getParams(),
79
87
  INFO_FORMAT: 'application/json',
80
88
  }
81
- const url = source.getFeatureInfoUrl(
82
- coordinate,
83
- resolution,
84
- projection,
85
- params
86
- )
87
- return url
89
+ return source.getFeatureInfoUrl(coordinate, resolution, projection, params)
88
90
  }
89
91
 
90
- getVectorFeaturesFromClick(olMap, event): OlFeature<Geometry>[] {
92
+ getVectorFeaturesFromClick(olMap, event): Feature<Geometry>[] {
91
93
  const features = []
92
94
  const hit = olMap.forEachFeatureAtPixel(
93
95
  event.pixel,
94
- (feature: OlFeature<Geometry>) => {
96
+ (feature: Feature<Geometry>) => {
95
97
  return feature
96
98
  },
97
99
  { layerFilter: (layer) => layer.getSource() instanceof VectorSource }
@@ -103,9 +105,9 @@ export class MapUtilsService {
103
105
  }
104
106
 
105
107
  getGFIFeaturesObservablesFromClick(
106
- olMap,
107
- event
108
- ): Observable<OlFeature<Geometry>[]>[] {
108
+ olMap: Map,
109
+ event: MapBrowserEvent<PointerEvent>
110
+ ): Observable<Feature<Geometry>[]>[] {
109
111
  const wmsLayers = olMap.getLayers().getArray().filter(this.isWMSLayer)
110
112
 
111
113
  if (wmsLayers.length > 0) {
@@ -128,8 +130,8 @@ export class MapUtilsService {
128
130
  /**
129
131
  * Will emit `null` if no extent could be computed
130
132
  */
131
- getLayerExtent(layer: MapContextLayerModel): Observable<Extent | null> {
132
- let geographicExtent: Observable<Extent>
133
+ async getLayerExtent(layer: MapContextLayerModel): Promise<Extent | null> {
134
+ let latLonExtent: Extent
133
135
  if (
134
136
  layer &&
135
137
  layer.type === 'geojson' &&
@@ -138,37 +140,55 @@ export class MapUtilsService {
138
140
  layer.data.features[0] &&
139
141
  layer.data.features[0].geometry
140
142
  ) {
141
- geographicExtent = of(layer.data).pipe(
142
- map((layerData) =>
143
- new GeoJSON()
144
- .readFeatures(layerData)
145
- .map((feature) => feature.getGeometry())
146
- .filter((geom) => !!geom)
147
- .reduce(
148
- (prev, curr) =>
149
- prev ? extend(prev, curr.getExtent()) : curr.getExtent(),
150
- null as Extent
151
- )
143
+ latLonExtent = new GeoJSON()
144
+ .readFeatures(layer.data)
145
+ .map((feature) => feature.getGeometry())
146
+ .filter((geom) => !!geom)
147
+ .reduce(
148
+ (prev, curr) =>
149
+ prev ? extend(prev, curr.getExtent()) : curr.getExtent(),
150
+ null as Extent
152
151
  )
153
- )
154
152
  } else if (layer && layer.type === 'wms') {
155
- geographicExtent = this.wmsUtils.getLayerLonLatBBox(layer)
153
+ latLonExtent = await this.getWmsLayerExtent(layer)
156
154
  } else if (layer && layer.type === 'wmts') {
157
155
  if (layer.extent) {
158
- geographicExtent = of(layer.extent)
156
+ latLonExtent = layer.extent
159
157
  } else {
160
- return of(layer.options.tileGrid.getExtent())
158
+ return layer.options.tileGrid.getExtent()
161
159
  }
162
160
  } else {
163
- return of(null)
161
+ return null
162
+ }
163
+ if (!latLonExtent || isEmpty(latLonExtent)) {
164
+ return null
164
165
  }
165
- return geographicExtent.pipe(
166
- map((extent) => [
167
- ...fromLonLat([extent[0], extent[1]], 'EPSG:3857'),
168
- ...fromLonLat([extent[2], extent[3]], 'EPSG:3857'),
169
- ]),
170
- map((extent) => (isEmpty(extent) ? null : extent))
166
+ return transformExtent(latLonExtent, 'EPSG:4326', 'EPSG:3857')
167
+ }
168
+
169
+ async getWmsLayerExtent(
170
+ layer: MapContextLayerWmsModel
171
+ ): Promise<Extent | null> {
172
+ const endpoint = await new WmsEndpoint(
173
+ this.proxy.getProxiedUrl(layer.url)
174
+ ).isReady()
175
+ const { boundingBoxes } = endpoint.getLayerByName(layer.name)
176
+ if (!Object.keys(boundingBoxes).length) {
177
+ return null
178
+ }
179
+ const lonLatCRS = Object.keys(boundingBoxes)?.find((crs) =>
180
+ LONLAT_CRS_CODES.includes(crs)
171
181
  )
182
+ if (lonLatCRS) {
183
+ return boundingBoxes[lonLatCRS].map(parseFloat)
184
+ } else {
185
+ const availableEPSGCode = Object.keys(boundingBoxes)[0]
186
+ register(proj4)
187
+ const proj = await fromEPSGCode(availableEPSGCode)
188
+ const bboxWithFiniteNumbers =
189
+ boundingBoxes[availableEPSGCode].map(parseFloat)
190
+ return transformExtent(bboxWithFiniteNumbers, proj, 'EPSG:4326')
191
+ }
172
192
  }
173
193
 
174
194
  getWmtsLayerFromCapabilities(
@@ -235,6 +255,21 @@ ${e.stack || e.message || e}`)
235
255
  .getArray()
236
256
  )
237
257
  }
258
+
259
+ getRecordExtent(record: Partial<CatalogRecord>): Extent {
260
+ if (!('spatialExtents' in record)) {
261
+ return null
262
+ }
263
+ // transform an array of geojson geometries into a bbox
264
+ const totalExtent = record.spatialExtents.reduce(
265
+ (prev, curr) => {
266
+ const geom = GEOJSON.readGeometry(curr.geometry)
267
+ return extend(prev, geom.getExtent())
268
+ },
269
+ [Infinity, Infinity, -Infinity, -Infinity]
270
+ )
271
+ return transformExtent(totalExtent, 'EPSG:4326', 'EPSG:3857')
272
+ }
238
273
  }
239
274
 
240
275
  export function dragPanCondition(
@@ -22,10 +22,14 @@ import { StyleLike } from 'ol/style/Style'
22
22
  import {
23
23
  BehaviorSubject,
24
24
  combineLatest,
25
+ from,
26
+ lastValueFrom,
25
27
  Observable,
26
28
  of,
29
+ startWith,
27
30
  Subscription,
28
31
  throwError,
32
+ withLatestFrom,
29
33
  } from 'rxjs'
30
34
  import {
31
35
  catchError,
@@ -99,7 +103,7 @@ export class MapViewComponent implements OnInit, OnDestroy {
99
103
 
100
104
  mapContext$ = this.currentLayers$.pipe(
101
105
  switchMap((layers) =>
102
- this.mapUtils.getLayerExtent(layers[0]).pipe(
106
+ from(this.mapUtils.getLayerExtent(layers[0])).pipe(
103
107
  catchError((error) => {
104
108
  console.warn(error) // FIXME: report this to the user somehow
105
109
  return of(undefined)
@@ -115,7 +119,19 @@ export class MapViewComponent implements OnInit, OnDestroy {
115
119
  ),
116
120
  tap(() => this.resetSelection())
117
121
  )
118
- )
122
+ ),
123
+ withLatestFrom(this.mdViewFacade.metadata$),
124
+ map(([context, metadata]) => {
125
+ if (context.view.extent) return context
126
+ const extent = this.mapUtils.getRecordExtent(metadata)
127
+ return {
128
+ ...context,
129
+ view: {
130
+ ...context.view,
131
+ extent,
132
+ },
133
+ }
134
+ })
119
135
  )
120
136
 
121
137
  constructor(
@@ -123,7 +139,6 @@ export class MapViewComponent implements OnInit, OnDestroy {
123
139
  private mapManager: MapManagerService,
124
140
  private mapUtils: MapUtilsService,
125
141
  private dataService: DataService,
126
- private proxy: ProxyService,
127
142
  private featureInfo: FeatureInfoService,
128
143
  private changeRef: ChangeDetectorRef,
129
144
  private styleService: MapStyleService
@@ -0,0 +1,47 @@
1
+ import {
2
+ Directive,
3
+ ElementRef,
4
+ Renderer2,
5
+ AfterViewInit,
6
+ EventEmitter,
7
+ Output,
8
+ Input,
9
+ } from '@angular/core'
10
+
11
+ @Directive({
12
+ selector: '[gnUiEditableLabel]',
13
+ })
14
+ export class EditableLabelDirective implements AfterViewInit {
15
+ @Output() editableLabelChanged = new EventEmitter<string>()
16
+ @Input() gnUiEditableLabel?: boolean
17
+
18
+ constructor(private el: ElementRef, private renderer: Renderer2) {}
19
+
20
+ ngAfterViewInit() {
21
+ if (this.gnUiEditableLabel !== false) {
22
+ const appendedInput = this.renderer.createElement('input')
23
+
24
+ this.renderer.setStyle(appendedInput, 'background', 'inherit')
25
+ this.renderer.setStyle(appendedInput, 'color', 'inherit')
26
+ this.renderer.setStyle(appendedInput, 'font', 'inherit')
27
+ this.renderer.setStyle(appendedInput, 'border', 'inherit')
28
+ this.renderer.setStyle(appendedInput, 'width', '100%')
29
+ this.renderer.setStyle(appendedInput, 'padding', 'inherit')
30
+ this.renderer.setStyle(appendedInput, 'margin', '0')
31
+ this.renderer.setStyle(appendedInput, 'height', 'inherit')
32
+ this.renderer.setStyle(appendedInput, 'line-height', 'inherit')
33
+ this.renderer.setStyle(appendedInput, 'text-decoration', 'inherit')
34
+
35
+ const hostContent = this.el.nativeElement.textContent || ''
36
+ const formattedContent = hostContent.replace(/\s+/g, ' ').trim()
37
+ this.renderer.setProperty(appendedInput, 'value', formattedContent)
38
+ this.renderer.setProperty(this.el.nativeElement, 'innerHTML', '')
39
+
40
+ this.renderer.listen(appendedInput, 'input', (event) => {
41
+ this.editableLabelChanged.emit(event.target.value)
42
+ })
43
+
44
+ this.renderer.appendChild(this.el.nativeElement, appendedInput)
45
+ }
46
+ }
47
+ }
@@ -41,6 +41,7 @@ import { MatFormFieldModule } from '@angular/material/form-field'
41
41
  import { MatInputModule } from '@angular/material/input'
42
42
  import { MatDatepickerModule } from '@angular/material/datepicker'
43
43
  import { MatNativeDateModule } from '@angular/material/core'
44
+ import { EditableLabelDirective } from './editable-label/editable-label.directive'
44
45
 
45
46
  @NgModule({
46
47
  declarations: [
@@ -68,6 +69,7 @@ import { MatNativeDateModule } from '@angular/material/core'
68
69
  CheckboxComponent,
69
70
  SearchInputComponent,
70
71
  DateRangePickerComponent,
72
+ EditableLabelDirective,
71
73
  ],
72
74
  imports: [
73
75
  CommonModule,
@@ -106,6 +108,7 @@ import { MatNativeDateModule } from '@angular/material/core'
106
108
  CheckboxComponent,
107
109
  SearchInputComponent,
108
110
  DateRangePickerComponent,
111
+ EditableLabelDirective,
109
112
  ],
110
113
  })
111
114
  export class UiInputsModule {}
@@ -38,7 +38,7 @@
38
38
  </div>
39
39
  <div
40
40
  class="contents hover:text-gray-900 text-gray-800 cursor-pointer"
41
- (click)="recordSelect.emit(record)"
41
+ (click)="recordsSelect.emit([record])"
42
42
  *ngFor="let record of records"
43
43
  >
44
44
  <div class="record-table-col text-16">
@@ -157,7 +157,7 @@
157
157
  </div>
158
158
  <div
159
159
  class="contents hover:text-gray-900 text-gray-800 cursor-pointer"
160
- (click)="recordSelect.emit(record)"
160
+ (click)="recordsSelect.emit([record])"
161
161
  *ngFor="let record of records"
162
162
  >
163
163
  <div class="record-table-col">
@@ -1,55 +0,0 @@
1
- import { Injectable } from '@angular/core';
2
- import { WmsEndpoint } from '@camptocamp/ogc-client';
3
- import { ProxyService } from '../../../../../../libs/util/shared/src';
4
- import { from } from 'rxjs';
5
- import { map, switchMap } from 'rxjs/operators';
6
- import { LONLAT_CRS_CODES } from './projections';
7
- import { fromEPSGCode, register } from 'ol/proj/proj4';
8
- import proj4 from 'proj4/dist/proj4';
9
- import { transformExtent } from 'ol/proj';
10
- import * as i0 from "@angular/core";
11
- import * as i1 from "../../../../../../libs/util/shared/src";
12
- export class MapUtilsWMSService {
13
- constructor(proxy) {
14
- this.proxy = proxy;
15
- }
16
- getCapabilities(layer) {
17
- return from(new WmsEndpoint(this.proxy.getProxiedUrl(layer.url)).isReady());
18
- }
19
- getLayerFull(layer) {
20
- return this.getCapabilities(layer).pipe(map((endpoint) => endpoint.getLayerByName(layer.name)));
21
- }
22
- getLayerLonLatBBox(layer) {
23
- return this.getLayerFull(layer).pipe(switchMap((wmsLayerFull) => from(this.getLonLatBBox(wmsLayerFull))));
24
- }
25
- async getLonLatBBox(wmsLayerFull) {
26
- const { boundingBoxes } = wmsLayerFull;
27
- const lonLatCRS = Object.keys(boundingBoxes)?.find((crs) => LONLAT_CRS_CODES.includes(crs));
28
- if (lonLatCRS) {
29
- return boundingBoxes[lonLatCRS];
30
- }
31
- else {
32
- const availableEPSGCode = Object.keys(boundingBoxes)[0];
33
- register(proj4);
34
- const proj = await fromEPSGCode(availableEPSGCode);
35
- proj4.defs(availableEPSGCode, proj);
36
- const bboxWithFiniteNumbers = [
37
- parseFloat(boundingBoxes[availableEPSGCode][0]),
38
- parseFloat(boundingBoxes[availableEPSGCode][1]),
39
- parseFloat(boundingBoxes[availableEPSGCode][2]),
40
- parseFloat(boundingBoxes[availableEPSGCode][3]),
41
- ];
42
- const extent = transformExtent(bboxWithFiniteNumbers, proj, 'EPSG:4326');
43
- return extent;
44
- }
45
- }
46
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: MapUtilsWMSService, deps: [{ token: i1.ProxyService }], target: i0.ɵɵFactoryTarget.Injectable }); }
47
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: MapUtilsWMSService, providedIn: 'root' }); }
48
- }
49
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.1.7", ngImport: i0, type: MapUtilsWMSService, decorators: [{
50
- type: Injectable,
51
- args: [{
52
- providedIn: 'root',
53
- }]
54
- }], ctorParameters: function () { return [{ type: i1.ProxyService }]; } });
55
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLXV0aWxzLXdtcy5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy9mZWF0dXJlL21hcC9zcmMvbGliL3V0aWxzL21hcC11dGlscy13bXMuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFBO0FBQzFDLE9BQU8sRUFBRSxXQUFXLEVBQWdCLE1BQU0sd0JBQXdCLENBQUE7QUFFbEUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHdDQUF3QyxDQUFBO0FBQ3JFLE9BQU8sRUFBRSxJQUFJLEVBQWMsTUFBTSxNQUFNLENBQUE7QUFDdkMsT0FBTyxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQTtBQUMvQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDaEQsT0FBTyxFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFFdEQsT0FBTyxLQUFLLE1BQU0sa0JBQWtCLENBQUE7QUFDcEMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLFNBQVMsQ0FBQTs7O0FBS3pDLE1BQU0sT0FBTyxrQkFBa0I7SUFDN0IsWUFBb0IsS0FBbUI7UUFBbkIsVUFBSyxHQUFMLEtBQUssQ0FBYztJQUFHLENBQUM7SUFFM0MsZUFBZSxDQUFDLEtBQThCO1FBQzVDLE9BQU8sSUFBSSxDQUFDLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7SUFDN0UsQ0FBQztJQUVELFlBQVksQ0FBQyxLQUE4QjtRQUN6QyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUNyQyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQ3ZELENBQUE7SUFDSCxDQUFDO0lBRUQsa0JBQWtCLENBQUMsS0FBOEI7UUFDL0MsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksQ0FDbEMsU0FBUyxDQUFDLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQ3BFLENBQUE7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLGFBQWEsQ0FBQyxZQUEwQjtRQUM1QyxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsWUFBWSxDQUFBO1FBQ3RDLE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsR0FBRyxFQUFFLEVBQUUsQ0FDekQsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUMvQixDQUFBO1FBQ0QsSUFBSSxTQUFTLEVBQUU7WUFDYixPQUFPLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQTtTQUNoQzthQUFNO1lBQ0wsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3ZELFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQTtZQUNmLE1BQU0sSUFBSSxHQUFHLE1BQU0sWUFBWSxDQUFDLGlCQUFpQixDQUFDLENBQUE7WUFDbEQsS0FBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxJQUFJLENBQUMsQ0FBQTtZQUVuQyxNQUFNLHFCQUFxQixHQUFHO2dCQUM1QixVQUFVLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9DLFVBQVUsQ0FBQyxhQUFhLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDL0MsVUFBVSxDQUFDLGFBQWEsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMvQyxVQUFVLENBQUMsYUFBYSxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDaEQsQ0FBQTtZQUNELE1BQU0sTUFBTSxHQUFHLGVBQWUsQ0FBQyxxQkFBcUIsRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUE7WUFDeEUsT0FBTyxNQUFNLENBQUE7U0FDZDtJQUNILENBQUM7OEdBekNVLGtCQUFrQjtrSEFBbEIsa0JBQWtCLGNBRmpCLE1BQU07OzJGQUVQLGtCQUFrQjtrQkFIOUIsVUFBVTttQkFBQztvQkFDVixVQUFVLEVBQUUsTUFBTTtpQkFDbkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSdcbmltcG9ydCB7IFdtc0VuZHBvaW50LCBXbXNMYXllckZ1bGwgfSBmcm9tICdAY2FtcHRvY2FtcC9vZ2MtY2xpZW50J1xuaW1wb3J0IHsgTWFwQ29udGV4dExheWVyV21zTW9kZWwgfSBmcm9tICcuLi9tYXAtY29udGV4dC9tYXAtY29udGV4dC5tb2RlbCdcbmltcG9ydCB7IFByb3h5U2VydmljZSB9IGZyb20gJy4uLy4uLy4uLy4uLy4uLy4uL2xpYnMvdXRpbC9zaGFyZWQvc3JjJ1xuaW1wb3J0IHsgZnJvbSwgT2JzZXJ2YWJsZSB9IGZyb20gJ3J4anMnXG5pbXBvcnQgeyBtYXAsIHN3aXRjaE1hcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJ1xuaW1wb3J0IHsgTE9OTEFUX0NSU19DT0RFUyB9IGZyb20gJy4vcHJvamVjdGlvbnMnXG5pbXBvcnQgeyBmcm9tRVBTR0NvZGUsIHJlZ2lzdGVyIH0gZnJvbSAnb2wvcHJvai9wcm9qNCdcbmltcG9ydCB7IEV4dGVudCB9IGZyb20gJ29sL2V4dGVudCdcbmltcG9ydCBwcm9qNCBmcm9tICdwcm9qNC9kaXN0L3Byb2o0J1xuaW1wb3J0IHsgdHJhbnNmb3JtRXh0ZW50IH0gZnJvbSAnb2wvcHJvaidcblxuQEluamVjdGFibGUoe1xuICBwcm92aWRlZEluOiAncm9vdCcsXG59KVxuZXhwb3J0IGNsYXNzIE1hcFV0aWxzV01TU2VydmljZSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcHJveHk6IFByb3h5U2VydmljZSkge31cblxuICBnZXRDYXBhYmlsaXRpZXMobGF5ZXI6IE1hcENvbnRleHRMYXllcldtc01vZGVsKTogT2JzZXJ2YWJsZTxXbXNFbmRwb2ludD4ge1xuICAgIHJldHVybiBmcm9tKG5ldyBXbXNFbmRwb2ludCh0aGlzLnByb3h5LmdldFByb3hpZWRVcmwobGF5ZXIudXJsKSkuaXNSZWFkeSgpKVxuICB9XG5cbiAgZ2V0TGF5ZXJGdWxsKGxheWVyOiBNYXBDb250ZXh0TGF5ZXJXbXNNb2RlbCk6IE9ic2VydmFibGU8V21zTGF5ZXJGdWxsPiB7XG4gICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKGxheWVyKS5waXBlKFxuICAgICAgbWFwKChlbmRwb2ludCkgPT4gZW5kcG9pbnQuZ2V0TGF5ZXJCeU5hbWUobGF5ZXIubmFtZSkpXG4gICAgKVxuICB9XG5cbiAgZ2V0TGF5ZXJMb25MYXRCQm94KGxheWVyOiBNYXBDb250ZXh0TGF5ZXJXbXNNb2RlbCkge1xuICAgIHJldHVybiB0aGlzLmdldExheWVyRnVsbChsYXllcikucGlwZShcbiAgICAgIHN3aXRjaE1hcCgod21zTGF5ZXJGdWxsKSA9PiBmcm9tKHRoaXMuZ2V0TG9uTGF0QkJveCh3bXNMYXllckZ1bGwpKSlcbiAgICApXG4gIH1cblxuICBhc3luYyBnZXRMb25MYXRCQm94KHdtc0xheWVyRnVsbDogV21zTGF5ZXJGdWxsKTogUHJvbWlzZTxFeHRlbnQ+IHtcbiAgICBjb25zdCB7IGJvdW5kaW5nQm94ZXMgfSA9IHdtc0xheWVyRnVsbFxuICAgIGNvbnN0IGxvbkxhdENSUyA9IE9iamVjdC5rZXlzKGJvdW5kaW5nQm94ZXMpPy5maW5kKChjcnMpID0+XG4gICAgICBMT05MQVRfQ1JTX0NPREVTLmluY2x1ZGVzKGNycylcbiAgICApXG4gICAgaWYgKGxvbkxhdENSUykge1xuICAgICAgcmV0dXJuIGJvdW5kaW5nQm94ZXNbbG9uTGF0Q1JTXVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBhdmFpbGFibGVFUFNHQ29kZSA9IE9iamVjdC5rZXlzKGJvdW5kaW5nQm94ZXMpWzBdXG4gICAgICByZWdpc3Rlcihwcm9qNClcbiAgICAgIGNvbnN0IHByb2ogPSBhd2FpdCBmcm9tRVBTR0NvZGUoYXZhaWxhYmxlRVBTR0NvZGUpXG4gICAgICBwcm9qNC5kZWZzKGF2YWlsYWJsZUVQU0dDb2RlLCBwcm9qKVxuXG4gICAgICBjb25zdCBiYm94V2l0aEZpbml0ZU51bWJlcnMgPSBbXG4gICAgICAgIHBhcnNlRmxvYXQoYm91bmRpbmdCb3hlc1thdmFpbGFibGVFUFNHQ29kZV1bMF0pLFxuICAgICAgICBwYXJzZUZsb2F0KGJvdW5kaW5nQm94ZXNbYXZhaWxhYmxlRVBTR0NvZGVdWzFdKSxcbiAgICAgICAgcGFyc2VGbG9hdChib3VuZGluZ0JveGVzW2F2YWlsYWJsZUVQU0dDb2RlXVsyXSksXG4gICAgICAgIHBhcnNlRmxvYXQoYm91bmRpbmdCb3hlc1thdmFpbGFibGVFUFNHQ29kZV1bM10pLFxuICAgICAgXVxuICAgICAgY29uc3QgZXh0ZW50ID0gdHJhbnNmb3JtRXh0ZW50KGJib3hXaXRoRmluaXRlTnVtYmVycywgcHJvaiwgJ0VQU0c6NDMyNicpXG4gICAgICByZXR1cm4gZXh0ZW50XG4gICAgfVxuICB9XG59XG4iXX0=
@@ -1,2 +0,0 @@
1
- export const LONLAT_CRS_CODES = ['EPSG:4326', 'CRS:84'];
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvamVjdGlvbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL2ZlYXR1cmUvbWFwL3NyYy9saWIvdXRpbHMvcHJvamVjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsQ0FBQyxXQUFXLEVBQUUsUUFBUSxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgY29uc3QgTE9OTEFUX0NSU19DT0RFUyA9IFsnRVBTRzo0MzI2JywgJ0NSUzo4NCddXG4iXX0=
@@ -1,17 +0,0 @@
1
- import { WmsEndpoint, WmsLayerFull } from '@camptocamp/ogc-client';
2
- import { MapContextLayerWmsModel } from '../map-context/map-context.model';
3
- import { ProxyService } from '../../../../../../libs/util/shared/src';
4
- import { Observable } from 'rxjs';
5
- import { Extent } from 'ol/extent';
6
- import * as i0 from "@angular/core";
7
- export declare class MapUtilsWMSService {
8
- private proxy;
9
- constructor(proxy: ProxyService);
10
- getCapabilities(layer: MapContextLayerWmsModel): Observable<WmsEndpoint>;
11
- getLayerFull(layer: MapContextLayerWmsModel): Observable<WmsLayerFull>;
12
- getLayerLonLatBBox(layer: MapContextLayerWmsModel): Observable<Extent>;
13
- getLonLatBBox(wmsLayerFull: WmsLayerFull): Promise<Extent>;
14
- static ɵfac: i0.ɵɵFactoryDeclaration<MapUtilsWMSService, never>;
15
- static ɵprov: i0.ɵɵInjectableDeclaration<MapUtilsWMSService>;
16
- }
17
- //# sourceMappingURL=map-utils-wms.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"map-utils-wms.service.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/feature/map/src/lib/utils/map-utils-wms.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAClE,OAAO,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAA;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,wCAAwC,CAAA;AACrE,OAAO,EAAQ,UAAU,EAAE,MAAM,MAAM,CAAA;AAIvC,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;;AAIlC,qBAGa,kBAAkB;IACjB,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAEvC,eAAe,CAAC,KAAK,EAAE,uBAAuB,GAAG,UAAU,CAAC,WAAW,CAAC;IAIxE,YAAY,CAAC,KAAK,EAAE,uBAAuB,GAAG,UAAU,CAAC,YAAY,CAAC;IAMtE,kBAAkB,CAAC,KAAK,EAAE,uBAAuB;IAM3C,aAAa,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;yCAnBrD,kBAAkB;6CAAlB,kBAAkB;CA0C9B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"projections.d.ts","sourceRoot":"","sources":["../../../../../../src/libs/feature/map/src/lib/utils/projections.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,UAA0B,CAAA"}
@@ -1,58 +0,0 @@
1
- import { Injectable } from '@angular/core'
2
- import { WmsEndpoint, WmsLayerFull } from '@camptocamp/ogc-client'
3
- import { MapContextLayerWmsModel } from '../map-context/map-context.model'
4
- import { ProxyService } from '../../../../../../libs/util/shared/src'
5
- import { from, Observable } from 'rxjs'
6
- import { map, switchMap } from 'rxjs/operators'
7
- import { LONLAT_CRS_CODES } from './projections'
8
- import { fromEPSGCode, register } from 'ol/proj/proj4'
9
- import { Extent } from 'ol/extent'
10
- import proj4 from 'proj4/dist/proj4'
11
- import { transformExtent } from 'ol/proj'
12
-
13
- @Injectable({
14
- providedIn: 'root',
15
- })
16
- export class MapUtilsWMSService {
17
- constructor(private proxy: ProxyService) {}
18
-
19
- getCapabilities(layer: MapContextLayerWmsModel): Observable<WmsEndpoint> {
20
- return from(new WmsEndpoint(this.proxy.getProxiedUrl(layer.url)).isReady())
21
- }
22
-
23
- getLayerFull(layer: MapContextLayerWmsModel): Observable<WmsLayerFull> {
24
- return this.getCapabilities(layer).pipe(
25
- map((endpoint) => endpoint.getLayerByName(layer.name))
26
- )
27
- }
28
-
29
- getLayerLonLatBBox(layer: MapContextLayerWmsModel) {
30
- return this.getLayerFull(layer).pipe(
31
- switchMap((wmsLayerFull) => from(this.getLonLatBBox(wmsLayerFull)))
32
- )
33
- }
34
-
35
- async getLonLatBBox(wmsLayerFull: WmsLayerFull): Promise<Extent> {
36
- const { boundingBoxes } = wmsLayerFull
37
- const lonLatCRS = Object.keys(boundingBoxes)?.find((crs) =>
38
- LONLAT_CRS_CODES.includes(crs)
39
- )
40
- if (lonLatCRS) {
41
- return boundingBoxes[lonLatCRS]
42
- } else {
43
- const availableEPSGCode = Object.keys(boundingBoxes)[0]
44
- register(proj4)
45
- const proj = await fromEPSGCode(availableEPSGCode)
46
- proj4.defs(availableEPSGCode, proj)
47
-
48
- const bboxWithFiniteNumbers = [
49
- parseFloat(boundingBoxes[availableEPSGCode][0]),
50
- parseFloat(boundingBoxes[availableEPSGCode][1]),
51
- parseFloat(boundingBoxes[availableEPSGCode][2]),
52
- parseFloat(boundingBoxes[availableEPSGCode][3]),
53
- ]
54
- const extent = transformExtent(bboxWithFiniteNumbers, proj, 'EPSG:4326')
55
- return extent
56
- }
57
- }
58
- }