geonetwork-ui 2.2.0-dev.95201f8f → 2.2.0-dev.ae0a63ae
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.
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/atomic-operations.mjs +2 -1
- package/esm2022/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.mjs +36 -2
- package/esm2022/libs/api/repository/src/lib/gn4/index.mjs +3 -1
- package/esm2022/libs/common/domain/src/lib/model/record/metadata.model.mjs +1 -1
- package/esm2022/libs/feature/dataviz/src/lib/service/data.service.mjs +5 -4
- package/esm2022/libs/feature/editor/src/lib/record-form/record-form.component.mjs +5 -3
- package/esm2022/libs/feature/map/src/index.mjs +2 -1
- package/esm2022/libs/feature/map/src/lib/constant/index.mjs +2 -1
- package/esm2022/libs/feature/map/src/lib/constant/projections.mjs +2 -0
- package/esm2022/libs/feature/map/src/lib/feature-map.module.mjs +17 -3
- package/esm2022/libs/feature/map/src/lib/geocoding/geocoding.component.mjs +93 -0
- package/esm2022/libs/feature/map/src/lib/geocoding.service.mjs +40 -0
- package/esm2022/libs/feature/map/src/lib/utils/index.mjs +1 -3
- package/esm2022/libs/feature/map/src/lib/utils/map-utils.service.mjs +60 -29
- package/esm2022/libs/feature/record/src/lib/map-view/map-view.component.mjs +29 -20
- package/esm2022/libs/feature/search/src/lib/state/effects.mjs +5 -3
- package/esm2022/libs/ui/elements/src/index.mjs +2 -1
- package/esm2022/libs/ui/elements/src/lib/downloads-list/downloads-list.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.mjs +3 -3
- package/esm2022/libs/ui/elements/src/lib/ui-elements.module.mjs +3 -1
- package/esm2022/libs/ui/inputs/src/lib/editable-label/editable-label.directive.mjs +46 -0
- package/esm2022/libs/ui/inputs/src/lib/ui-inputs.module.mjs +8 -3
- package/esm2022/libs/ui/search/src/lib/record-table/record-table.component.mjs +3 -3
- package/esm2022/libs/util/shared/src/lib/links/link-utils.mjs +29 -13
- package/esm2022/translations/de.json +1 -0
- package/esm2022/translations/en.json +1 -0
- package/esm2022/translations/es.json +1 -0
- package/esm2022/translations/fr.json +1 -0
- package/esm2022/translations/it.json +1 -0
- package/esm2022/translations/nl.json +1 -0
- package/esm2022/translations/pt.json +1 -0
- package/fesm2022/geonetwork-ui.mjs +341 -108
- package/fesm2022/geonetwork-ui.mjs.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts +1 -0
- package/libs/api/metadata-converter/src/lib/gn4/atomic-operations.d.ts.map +1 -1
- package/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.d.ts.map +1 -1
- package/libs/api/repository/src/lib/gn4/index.d.ts +2 -0
- package/libs/api/repository/src/lib/gn4/index.d.ts.map +1 -1
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts +10 -5
- package/libs/common/domain/src/lib/model/record/metadata.model.d.ts.map +1 -1
- package/libs/feature/dataviz/src/lib/service/data.service.d.ts +15 -2
- package/libs/feature/dataviz/src/lib/service/data.service.d.ts.map +1 -1
- package/libs/feature/editor/src/lib/record-form/record-form.component.d.ts.map +1 -1
- package/libs/feature/map/src/index.d.ts +1 -0
- package/libs/feature/map/src/index.d.ts.map +1 -1
- package/libs/feature/map/src/lib/constant/index.d.ts +1 -0
- package/libs/feature/map/src/lib/constant/index.d.ts.map +1 -1
- package/libs/feature/map/src/lib/constant/projections.d.ts.map +1 -0
- package/libs/feature/map/src/lib/feature-map.module.d.ts +13 -12
- package/libs/feature/map/src/lib/feature-map.module.d.ts.map +1 -1
- package/libs/feature/map/src/lib/geocoding/geocoding.component.d.ts +25 -0
- package/libs/feature/map/src/lib/geocoding/geocoding.component.d.ts.map +1 -0
- package/libs/feature/map/src/lib/geocoding.service.d.ts +18 -0
- package/libs/feature/map/src/lib/geocoding.service.d.ts.map +1 -0
- package/libs/feature/map/src/lib/utils/index.d.ts +0 -2
- package/libs/feature/map/src/lib/utils/index.d.ts.map +1 -1
- package/libs/feature/map/src/lib/utils/map-utils.service.d.ts +13 -11
- package/libs/feature/map/src/lib/utils/map-utils.service.d.ts.map +1 -1
- package/libs/feature/record/src/lib/map-view/map-view.component.d.ts +1 -3
- package/libs/feature/record/src/lib/map-view/map-view.component.d.ts.map +1 -1
- package/libs/feature/search/src/lib/state/effects.d.ts.map +1 -1
- package/libs/ui/dataviz/src/lib/chart/chart.component.d.ts +1 -1
- package/libs/ui/elements/src/index.d.ts +1 -0
- package/libs/ui/elements/src/index.d.ts.map +1 -1
- package/libs/ui/elements/src/lib/downloads-list/downloads-list.component.d.ts +1 -1
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts +1 -1
- package/libs/ui/elements/src/lib/ui-elements.module.d.ts.map +1 -1
- package/libs/ui/inputs/src/lib/editable-label/editable-label.directive.d.ts +13 -0
- package/libs/ui/inputs/src/lib/editable-label/editable-label.directive.d.ts.map +1 -0
- package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts +2 -1
- package/libs/ui/inputs/src/lib/ui-inputs.module.d.ts.map +1 -1
- package/libs/util/shared/src/lib/links/link-utils.d.ts +19 -7
- package/libs/util/shared/src/lib/links/link-utils.d.ts.map +1 -1
- package/package.json +4 -1
- package/src/libs/api/metadata-converter/src/lib/gn4/atomic-operations.ts +3 -0
- package/src/libs/api/metadata-converter/src/lib/gn4/gn4.field.mapper.ts +43 -0
- package/src/libs/api/repository/src/lib/gn4/index.ts +2 -0
- package/src/libs/common/domain/src/lib/index.ts +2 -0
- package/src/libs/common/domain/src/lib/model/record/metadata.model.ts +12 -7
- package/src/libs/feature/dataviz/src/lib/service/data.service.ts +8 -5
- package/src/libs/feature/editor/src/lib/record-form/record-form.component.ts +2 -1
- package/src/libs/feature/map/src/index.ts +1 -0
- package/src/libs/feature/map/src/lib/constant/index.ts +1 -0
- package/src/libs/feature/map/src/lib/feature-map.module.ts +8 -0
- package/src/libs/feature/map/src/lib/geocoding/geocoding.component.css +0 -0
- package/src/libs/feature/map/src/lib/geocoding/geocoding.component.html +39 -0
- package/src/libs/feature/map/src/lib/geocoding/geocoding.component.ts +99 -0
- package/src/libs/feature/map/src/lib/geocoding.service.ts +59 -0
- package/src/libs/feature/map/src/lib/utils/index.ts +0 -2
- package/src/libs/feature/map/src/lib/utils/map-utils.service.ts +85 -50
- package/src/libs/feature/record/src/lib/map-view/map-view.component.ts +18 -3
- package/src/libs/feature/search/src/lib/state/effects.ts +4 -3
- package/src/libs/ui/elements/src/index.ts +1 -0
- package/src/libs/ui/elements/src/lib/downloads-list/downloads-list.component.html +4 -1
- package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.html +3 -2
- package/src/libs/ui/elements/src/lib/metadata-contact/metadata-contact.component.html +1 -1
- package/src/libs/ui/elements/src/lib/ui-elements.module.ts +1 -0
- package/src/libs/ui/inputs/src/lib/editable-label/editable-label.directive.ts +48 -0
- package/src/libs/ui/inputs/src/lib/ui-inputs.module.ts +3 -0
- package/src/libs/ui/search/src/lib/record-table/record-table.component.html +2 -2
- package/src/libs/util/shared/src/lib/links/link-utils.ts +34 -11
- package/translations/de.json +1 -0
- package/translations/en.json +1 -0
- package/translations/es.json +1 -0
- package/translations/fr.json +1 -0
- package/translations/it.json +1 -0
- package/translations/nl.json +1 -0
- package/translations/pt.json +1 -0
- package/translations/sk.json +1 -0
- package/esm2022/libs/feature/map/src/lib/utils/map-utils-wms.service.mjs +0 -55
- package/esm2022/libs/feature/map/src/lib/utils/projections.mjs +0 -2
- package/libs/feature/map/src/lib/utils/map-utils-wms.service.d.ts +0 -17
- package/libs/feature/map/src/lib/utils/map-utils-wms.service.d.ts.map +0 -1
- package/libs/feature/map/src/lib/utils/projections.d.ts.map +0 -1
- package/src/libs/feature/map/src/lib/utils/map-utils-wms.service.ts +0 -58
- /package/libs/feature/map/src/lib/{utils → constant}/projections.d.ts +0 -0
- /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
|
|
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 {
|
|
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 {
|
|
16
|
-
import {
|
|
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
|
|
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 {
|
|
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
|
|
53
|
+
constructor(private http: HttpClient, private proxy: ProxyService) {}
|
|
44
54
|
|
|
45
55
|
createEmptyMap(): Map {
|
|
46
|
-
|
|
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
|
-
):
|
|
58
|
-
|
|
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
|
-
|
|
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):
|
|
92
|
+
getVectorFeaturesFromClick(olMap, event): Feature<Geometry>[] {
|
|
91
93
|
const features = []
|
|
92
94
|
const hit = olMap.forEachFeatureAtPixel(
|
|
93
95
|
event.pixel,
|
|
94
|
-
(feature:
|
|
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<
|
|
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):
|
|
132
|
-
let
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
.
|
|
148
|
-
|
|
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
|
-
|
|
153
|
+
latLonExtent = await this.getWmsLayerExtent(layer)
|
|
156
154
|
} else if (layer && layer.type === 'wmts') {
|
|
157
155
|
if (layer.extent) {
|
|
158
|
-
|
|
156
|
+
latLonExtent = layer.extent
|
|
159
157
|
} else {
|
|
160
|
-
return
|
|
158
|
+
return layer.options.tileGrid.getExtent()
|
|
161
159
|
}
|
|
162
160
|
} else {
|
|
163
|
-
return
|
|
161
|
+
return null
|
|
162
|
+
}
|
|
163
|
+
if (!latLonExtent || isEmpty(latLonExtent)) {
|
|
164
|
+
return null
|
|
164
165
|
}
|
|
165
|
-
return
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
|
@@ -126,10 +126,11 @@ export class SearchEffects {
|
|
|
126
126
|
),
|
|
127
127
|
switchMap(([state, favorites]) => {
|
|
128
128
|
if (!state.params.useSpatialFilter || !this.filterGeometry$) {
|
|
129
|
-
return of([state, favorites,
|
|
129
|
+
return of([state, favorites, undefined])
|
|
130
130
|
}
|
|
131
131
|
return this.filterGeometry$.pipe(
|
|
132
132
|
tap((geom) => {
|
|
133
|
+
if (!geom) return
|
|
133
134
|
try {
|
|
134
135
|
const trace = validGeoJson(geom, true) as string[]
|
|
135
136
|
if (trace?.length > 0) {
|
|
@@ -145,7 +146,7 @@ export class SearchEffects {
|
|
|
145
146
|
}),
|
|
146
147
|
map((geom) => [state, favorites, geom]),
|
|
147
148
|
catchError((e) => {
|
|
148
|
-
return of([state, favorites,
|
|
149
|
+
return of([state, favorites, undefined])
|
|
149
150
|
})
|
|
150
151
|
)
|
|
151
152
|
}),
|
|
@@ -153,7 +154,7 @@ export class SearchEffects {
|
|
|
153
154
|
([state, favorites, geometry]: [
|
|
154
155
|
SearchStateSearch,
|
|
155
156
|
string[],
|
|
156
|
-
Geometry |
|
|
157
|
+
Geometry | undefined
|
|
157
158
|
]) => {
|
|
158
159
|
const { currentPage, pageSize, sort } = state.params
|
|
159
160
|
const filters = {
|
|
@@ -18,6 +18,7 @@ export * from './lib/pagination/pagination.component'
|
|
|
18
18
|
export * from './lib/related-record-card/related-record-card.component'
|
|
19
19
|
export * from './lib/search-results-error/search-results-error.component'
|
|
20
20
|
export * from './lib/user-preview/user-preview.component'
|
|
21
|
+
export * from './lib/max-lines/max-lines.component'
|
|
21
22
|
export * from './lib/record-api-form/record-api-form.component'
|
|
22
23
|
export * from './lib/markdown-parser/markdown-parser.component'
|
|
23
24
|
export * from './lib/image-overlay-preview/image-overlay-preview.component'
|
|
@@ -8,7 +8,10 @@
|
|
|
8
8
|
>
|
|
9
9
|
record.metadata.download
|
|
10
10
|
</p>
|
|
11
|
-
<div
|
|
11
|
+
<div
|
|
12
|
+
class="flex flex-wrap justify-start sm:justify-end sm:pb-4"
|
|
13
|
+
data-cy="download-format-filters"
|
|
14
|
+
>
|
|
12
15
|
<gn-ui-button
|
|
13
16
|
class="m-1 format-filter"
|
|
14
17
|
[extraClass]="
|
package/src/libs/ui/elements/src/lib/image-overlay-preview/image-overlay-preview.component.html
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
<gn-ui-content-ghost
|
|
2
2
|
[showContent]="imageUrl !== undefined"
|
|
3
|
-
ghostClass="h-
|
|
3
|
+
ghostClass="h-48 mb-3"
|
|
4
4
|
>
|
|
5
5
|
<div
|
|
6
6
|
*ngIf="imageUrl"
|
|
7
|
+
[showContent]="imageUrl !== undefined"
|
|
7
8
|
data-cy="record-thumbnail"
|
|
8
|
-
class="flex-shrink-0 bg-gray-100 rounded-lg overflow-hidden w-full border border-gray-300
|
|
9
|
+
class="flex-shrink-0 bg-gray-100 rounded-lg overflow-hidden w-full border border-gray-300 group-hover:shadow-xl group-hover:border-0 h-48 mb-3"
|
|
9
10
|
>
|
|
10
11
|
<gn-ui-thumbnail
|
|
11
12
|
class="relative h-full w-full"
|
|
@@ -88,6 +88,7 @@ import { ImageOverlayPreviewComponent } from './image-overlay-preview/image-over
|
|
|
88
88
|
AvatarComponent,
|
|
89
89
|
UserPreviewComponent,
|
|
90
90
|
PaginationButtonsComponent,
|
|
91
|
+
MaxLinesComponent,
|
|
91
92
|
RecordApiFormComponent,
|
|
92
93
|
MarkdownParserComponent,
|
|
93
94
|
ImageOverlayPreviewComponent,
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
standalone: true,
|
|
14
|
+
})
|
|
15
|
+
export class EditableLabelDirective implements AfterViewInit {
|
|
16
|
+
@Output() editableLabelChanged = new EventEmitter<string>()
|
|
17
|
+
@Input() gnUiEditableLabel?: boolean
|
|
18
|
+
|
|
19
|
+
constructor(private el: ElementRef, private renderer: Renderer2) {}
|
|
20
|
+
|
|
21
|
+
ngAfterViewInit() {
|
|
22
|
+
if (this.gnUiEditableLabel !== false) {
|
|
23
|
+
const appendedInput = this.renderer.createElement('input')
|
|
24
|
+
|
|
25
|
+
this.renderer.setStyle(appendedInput, 'background', 'inherit')
|
|
26
|
+
this.renderer.setStyle(appendedInput, 'color', 'inherit')
|
|
27
|
+
this.renderer.setStyle(appendedInput, 'font', 'inherit')
|
|
28
|
+
this.renderer.setStyle(appendedInput, 'border', 'inherit')
|
|
29
|
+
this.renderer.setStyle(appendedInput, 'width', '100%')
|
|
30
|
+
this.renderer.setStyle(appendedInput, 'padding', 'inherit')
|
|
31
|
+
this.renderer.setStyle(appendedInput, 'margin', '0')
|
|
32
|
+
this.renderer.setStyle(appendedInput, 'height', 'inherit')
|
|
33
|
+
this.renderer.setStyle(appendedInput, 'line-height', 'inherit')
|
|
34
|
+
this.renderer.setStyle(appendedInput, 'text-decoration', 'inherit')
|
|
35
|
+
|
|
36
|
+
const hostContent = this.el.nativeElement.textContent || ''
|
|
37
|
+
const formattedContent = hostContent.replace(/\s+/g, ' ').trim()
|
|
38
|
+
this.renderer.setProperty(appendedInput, 'value', formattedContent)
|
|
39
|
+
this.renderer.setProperty(this.el.nativeElement, 'innerHTML', '')
|
|
40
|
+
|
|
41
|
+
this.renderer.listen(appendedInput, 'input', (event) => {
|
|
42
|
+
this.editableLabelChanged.emit(event.target.value)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
this.renderer.appendChild(this.el.nativeElement, appendedInput)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -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: [
|
|
@@ -87,6 +88,7 @@ import { MatNativeDateModule } from '@angular/material/core'
|
|
|
87
88
|
MatInputModule,
|
|
88
89
|
MatDatepickerModule,
|
|
89
90
|
MatNativeDateModule,
|
|
91
|
+
EditableLabelDirective,
|
|
90
92
|
],
|
|
91
93
|
exports: [
|
|
92
94
|
DropdownSelectorComponent,
|
|
@@ -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)="
|
|
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)="
|
|
160
|
+
(click)="recordsSelect.emit([record])"
|
|
161
161
|
*ngFor="let record of records"
|
|
162
162
|
>
|
|
163
163
|
<div class="record-table-col">
|
|
@@ -43,9 +43,15 @@ export const FORMATS = {
|
|
|
43
43
|
color: '#328556',
|
|
44
44
|
mimeTypes: ['x-gis/x-shapefile'],
|
|
45
45
|
},
|
|
46
|
+
gml: {
|
|
47
|
+
extensions: ['gml'],
|
|
48
|
+
priority: 5,
|
|
49
|
+
color: '#c92bce',
|
|
50
|
+
mimeTypes: ['application/gml+xml', 'text/xml; subtype=gml'],
|
|
51
|
+
},
|
|
46
52
|
kml: {
|
|
47
53
|
extensions: ['kml', 'kmz'],
|
|
48
|
-
priority:
|
|
54
|
+
priority: 6,
|
|
49
55
|
color: '#348009',
|
|
50
56
|
mimeTypes: [
|
|
51
57
|
'application/vnd.google-earth.kml+xml',
|
|
@@ -54,34 +60,40 @@ export const FORMATS = {
|
|
|
54
60
|
},
|
|
55
61
|
gpkg: {
|
|
56
62
|
extensions: ['gpkg', 'geopackage'],
|
|
57
|
-
priority:
|
|
63
|
+
priority: 7,
|
|
58
64
|
color: '#ea79ba',
|
|
59
65
|
mimeTypes: ['application/geopackage+sqlite3'],
|
|
60
66
|
},
|
|
61
67
|
zip: {
|
|
62
68
|
extensions: ['zip', 'tar.gz'],
|
|
63
|
-
priority:
|
|
69
|
+
priority: 8,
|
|
64
70
|
color: '#f2bb3a',
|
|
65
71
|
mimeTypes: ['application/zip', 'application/x-zip'],
|
|
66
72
|
},
|
|
67
73
|
pdf: {
|
|
68
74
|
extensions: ['pdf'],
|
|
69
|
-
priority:
|
|
75
|
+
priority: 9,
|
|
70
76
|
color: '#db544a',
|
|
71
77
|
mimeTypes: ['application/pdf'],
|
|
72
78
|
},
|
|
73
79
|
jpg: {
|
|
74
80
|
extensions: ['jpg', 'jpeg', 'jfif', 'pjpeg', 'pjp'],
|
|
75
|
-
priority:
|
|
81
|
+
priority: 9,
|
|
76
82
|
color: '#673ab7',
|
|
77
83
|
mimeTypes: ['image/jpg'],
|
|
78
84
|
},
|
|
79
85
|
svg: {
|
|
80
86
|
extensions: ['svg'],
|
|
81
|
-
priority:
|
|
87
|
+
priority: 10,
|
|
82
88
|
color: '#d98294',
|
|
83
89
|
mimeTypes: ['image/svg+xml'],
|
|
84
90
|
},
|
|
91
|
+
dxf: {
|
|
92
|
+
extensions: ['dxf'],
|
|
93
|
+
priority: 11,
|
|
94
|
+
color: '#de630b',
|
|
95
|
+
mimeTypes: ['application/x-dxf', 'image/x-dxf'],
|
|
96
|
+
},
|
|
85
97
|
} as const
|
|
86
98
|
|
|
87
99
|
export type FileFormat = keyof typeof FORMATS
|
|
@@ -102,13 +114,24 @@ export function getLinkPriority(link: DatasetDistribution): number {
|
|
|
102
114
|
return getFormatPriority(getFileFormat(link))
|
|
103
115
|
}
|
|
104
116
|
|
|
105
|
-
export function
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
export function getFileFormatFromServiceOutput(
|
|
118
|
+
serviceOutput: string
|
|
119
|
+
): FileFormat | null {
|
|
120
|
+
function formatMatcher(format: typeof FORMATS[FileFormat]): boolean {
|
|
121
|
+
const output = serviceOutput.toLowerCase()
|
|
122
|
+
return (
|
|
123
|
+
format.extensions.some((extension: string) =>
|
|
124
|
+
output.includes(extension)
|
|
125
|
+
) ||
|
|
126
|
+
format.mimeTypes.some((mimeType: string) => output.includes(mimeType))
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
for (const formatName in FORMATS) {
|
|
130
|
+
if (formatMatcher(FORMATS[formatName])) {
|
|
131
|
+
return formatName as FileFormat
|
|
109
132
|
}
|
|
110
133
|
}
|
|
111
|
-
return
|
|
134
|
+
return null
|
|
112
135
|
}
|
|
113
136
|
|
|
114
137
|
export function getFileFormat(link: DatasetDistribution): FileFormat {
|
package/translations/de.json
CHANGED
|
@@ -177,6 +177,7 @@
|
|
|
177
177
|
"map.add.layer.wfs": "Aus WFS",
|
|
178
178
|
"map.add.layer.wms": "Aus WMS",
|
|
179
179
|
"map.addFromFile.placeholder": "Klicke hier oder ziehe eine Datei herein",
|
|
180
|
+
"map.geocoding.placeholder": "",
|
|
180
181
|
"map.help.addFromFile": "Klicke oder ziehe eine Datei herein um eine Karte hinzuzufügen (momentan wird nur das GeoJSON-Format unterstützt).",
|
|
181
182
|
"map.layer.add": "Hinzufügen",
|
|
182
183
|
"map.layers.available": "Verfügbare Layer",
|
package/translations/en.json
CHANGED
|
@@ -177,6 +177,7 @@
|
|
|
177
177
|
"map.add.layer.wfs": "From WFS",
|
|
178
178
|
"map.add.layer.wms": "From WMS",
|
|
179
179
|
"map.addFromFile.placeholder": "Click or drop a file here",
|
|
180
|
+
"map.geocoding.placeholder": "Search for a place",
|
|
180
181
|
"map.help.addFromFile": "Click or drag and drop a file to add to the map (currently supports GeoJSON format only).",
|
|
181
182
|
"map.layer.add": "Add",
|
|
182
183
|
"map.layers.available": "Available Layers",
|
package/translations/es.json
CHANGED
package/translations/fr.json
CHANGED
package/translations/it.json
CHANGED
package/translations/nl.json
CHANGED
package/translations/pt.json
CHANGED
package/translations/sk.json
CHANGED