diff --git a/umap/static/umap/img/16.svg b/umap/static/umap/img/16.svg
index 3c1eb12c..6950d1f7 100644
--- a/umap/static/umap/img/16.svg
+++ b/umap/static/umap/img/16.svg
@@ -1 +1 @@
-
+
diff --git a/umap/static/umap/img/24.svg b/umap/static/umap/img/24.svg
index a1f6f6fd..8ae40765 100644
--- a/umap/static/umap/img/24.svg
+++ b/umap/static/umap/img/24.svg
@@ -13,10 +13,10 @@
1
-
-
+
+
-
+
@@ -47,7 +47,7 @@
-
+
diff --git a/umap/static/umap/img/source/16.svg b/umap/static/umap/img/source/16.svg
index fb7d31ef..aad5d758 100644
--- a/umap/static/umap/img/source/16.svg
+++ b/umap/static/umap/img/source/16.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/umap/static/umap/img/source/24.svg b/umap/static/umap/img/source/24.svg
index c6eaab05..72eddd1b 100644
--- a/umap/static/umap/img/source/24.svg
+++ b/umap/static/umap/img/source/24.svg
@@ -2,7 +2,7 @@
-
-
+
+
-
+
@@ -60,7 +60,7 @@
-
+
diff --git a/umap/static/umap/img/target.svg b/umap/static/umap/img/target.svg
new file mode 100644
index 00000000..d7b58538
--- /dev/null
+++ b/umap/static/umap/img/target.svg
@@ -0,0 +1 @@
+
diff --git a/umap/static/umap/js/modules/data/layer.js b/umap/static/umap/js/modules/data/layer.js
index 281c6e02..a7fb4603 100644
--- a/umap/static/umap/js/modules/data/layer.js
+++ b/umap/static/umap/js/modules/data/layer.js
@@ -332,6 +332,7 @@ export class DataLayer extends ServerStored {
.parse(raw, this.options.remoteData.format)
.then((geojson) => this.fromGeoJSON(geojson))
.catch((error) => {
+ console.debug(error)
Alert.error(
translate('Cannot parse remote data for layer "{layer}" with url "{url}"', {
layer: this.getName(),
@@ -532,6 +533,7 @@ export class DataLayer extends ServerStored {
return data
})
.catch((error) => {
+ console.debug(error)
Alert.error(translate('Import failed: invalid data'))
})
}
diff --git a/umap/static/umap/js/modules/global.js b/umap/static/umap/js/modules/global.js
index d6502b2f..4ef04502 100644
--- a/umap/static/umap/js/modules/global.js
+++ b/umap/static/umap/js/modules/global.js
@@ -1,5 +1,9 @@
import { uMapAlert as Alert } from '../components/alerts/alert.js'
-import { AjaxAutocomplete, AjaxAutocompleteMultiple, AutocompleteDatalist } from './autocomplete.js'
+import {
+ AjaxAutocomplete,
+ AjaxAutocompleteMultiple,
+ AutocompleteDatalist,
+} from './autocomplete.js'
import Help from './help.js'
import { ServerRequest } from './request.js'
import { SCHEMA } from './schema.js'
diff --git a/umap/static/umap/js/umap.controls.js b/umap/static/umap/js/umap.controls.js
index 287ca885..3aee1cf2 100644
--- a/umap/static/umap/js/umap.controls.js
+++ b/umap/static/umap/js/umap.controls.js
@@ -430,44 +430,70 @@ U.Search = L.PhotonSearch.extend({
},
formatResult: function (feature, el) {
- const tools = L.DomUtil.create('span', 'search-result-tools', el)
- const zoom = L.DomUtil.createButtonIcon(
- tools,
- 'icon-zoom',
- L._('Zoom to this place')
- )
- const edit = L.DomUtil.createButtonIcon(
- tools,
- 'icon-edit',
- L._('Save this location as new feature')
- )
- // We need to use "mousedown" because Leaflet.Photon listen to mousedown
- // on el.
- L.DomEvent.on(zoom, 'mousedown', (e) => {
- L.DomEvent.stop(e)
- this.zoomToFeature(feature)
- })
- L.DomEvent.on(edit, 'mousedown', (e) => {
- L.DomEvent.stop(e)
+ const [tools, { point, geom }] = U.Utils.loadTemplateWithRefs(`
+
+
+
+
+ `)
+ geom.hidden = !['R', 'W'].includes(feature.properties.osm_type)
+ point.addEventListener('mousedown', (event) => {
+ event.stopPropagation()
const datalayer = this.map._umap.defaultEditDataLayer()
- const layer = datalayer.makeFeature(feature)
- layer.isDirty = true
- layer.edit()
+ const marker = datalayer.makeFeature(feature)
+ marker.isDirty = true
+ marker.edit()
+ this.map._umap.panel.close()
})
+ geom.addEventListener('mousedown', async (event) => {
+ event.stopPropagation()
+ const osm_id = feature.properties.osm_id
+ const types = {
+ R: 'relation',
+ W: 'way',
+ N: 'node',
+ }
+ const osm_type = types[feature.properties.osm_type]
+ if (!osm_type || !osm_id) return
+ const url = `https://www.openstreetmap.org/api/0.6/${osm_type}/${osm_id}/full`
+ const response = await this.map._umap.request.get(url)
+ if (response?.ok) {
+ const importer = this.map._umap.importer
+ importer.build()
+ importer.format = 'osm'
+ importer.raw = await response.text()
+ importer.submit()
+ this.map._umap.panel.close()
+ }
+ })
+ el.appendChild(tools)
this._formatResult(feature, el)
+ const path = U.SCHEMA.iconUrl.default.replace('marker.svg', 'target.svg')
+ const icon = L.icon({
+ iconUrl: path,
+ iconSize: [24, 24],
+ iconAnchor: [12, 12],
+ })
+ const coords = feature.geometry.coordinates
+ const target = L.marker([coords[1], coords[0]], { icon })
+ el.addEventListener('mouseover', (event) => {
+ target.addTo(this.map)
+ })
+ el.addEventListener('mouseout', (event) => {
+ target.removeFrom(this.map)
+ })
},
- zoomToFeature: function (feature) {
- const zoom = Math.max(this.map.getZoom(), 16) // Never unzoom.
- this.map.setView(
- [feature.geometry.coordinates[1], feature.geometry.coordinates[0]],
- zoom
- )
- },
-
- onSelected: function (feature) {
- this.zoomToFeature(feature)
- this.map.panel.close()
+ setChoice: function (choice) {
+ choice = choice || this.RESULTS[this.CURRENT]
+ if (choice) {
+ const feature = choice.feature
+ const zoom = Math.max(this.map.getZoom(), 14) // Never unzoom.
+ this.map.setView(
+ [feature.geometry.coordinates[1], feature.geometry.coordinates[0]],
+ zoom
+ )
+ }
},
})
diff --git a/umap/static/umap/map.css b/umap/static/umap/map.css
index fd61b9b6..c78baa4d 100644
--- a/umap/static/umap/map.css
+++ b/umap/static/umap/map.css
@@ -263,18 +263,26 @@ ul.photon-autocomplete {
.photon-autocomplete li {
min-height: 40px;
line-height: 1em;
- padding: 5px 10px;
+ padding-inline-start: 10px;
overflow: hidden;
white-space: nowrap;
font-size: 1em;
- border-inline-start: 4px solid #efefef;
+ border-inline-start: 4px solid var(--color-lightGray);
}
.photon-autocomplete li strong {
display: block;
+ margin-top: 5px;
+}
+.photon-autocomplete button {
+ margin: 0;
+}
+.photon-autocomplete button:hover {
+ background-color: var(--color-brightCyan);
}
.photon-autocomplete li.on {
- border-inline-start: 4px solid #2980b9;
+ border-inline-start: 4px solid var(--color-brightCyan);
cursor: pointer;
+ background-color: var(--color-lightCyan);
}
.photon-autocomplete li.photon-no-result {
text-align: center;
@@ -292,7 +300,10 @@ ul.photon-autocomplete {
}
.search-result-tools {
float: inline-end;
- display: block;
+ display: none;
+}
+.photon-autocomplete li.on .search-result-tools {
+ display: flex;
}