chore: add ids on features
This commit is contained in:
parent
76ed2200cf
commit
bcd650e844
4 changed files with 89 additions and 1 deletions
|
@ -1,10 +1,21 @@
|
||||||
import * as L from '../../vendors/leaflet/leaflet-src.esm.js'
|
import * as L from '../../vendors/leaflet/leaflet-src.esm.js'
|
||||||
import URLs from './urls.js'
|
import URLs from './urls.js'
|
||||||
import Browser from './browser.js'
|
import Browser from './browser.js'
|
||||||
|
import * as Utils from './utils.js'
|
||||||
import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
|
import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
|
||||||
|
|
||||||
// Import modules and export them to the global scope.
|
// Import modules and export them to the global scope.
|
||||||
// For the not yet module-compatible JS out there.
|
// For the not yet module-compatible JS out there.
|
||||||
|
|
||||||
// Copy the leaflet module, it's expected by leaflet plugins to be writeable.
|
// Copy the leaflet module, it's expected by leaflet plugins to be writeable.
|
||||||
window.L = { ...L }
|
window.L = { ...L }
|
||||||
window.U = { URLs, Request, ServerRequest, RequestError, HTTPError, NOKError, Browser }
|
window.U = {
|
||||||
|
URLs,
|
||||||
|
Request,
|
||||||
|
ServerRequest,
|
||||||
|
RequestError,
|
||||||
|
HTTPError,
|
||||||
|
NOKError,
|
||||||
|
Browser,
|
||||||
|
Utils,
|
||||||
|
}
|
||||||
|
|
13
umap/static/umap/js/modules/utils.js
Normal file
13
umap/static/umap/js/modules/utils.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
* Generate a pseudo-unique identifier (4 chars long)
|
||||||
|
*
|
||||||
|
* Using uppercase + lowercase + digits, here's the collision risk:
|
||||||
|
* - for 6 chars, 1 in 100 000
|
||||||
|
* - for 5 chars, 5 in 100 000
|
||||||
|
* - for 4 chars, 500 in 100 000
|
||||||
|
*
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
export function generateId() {
|
||||||
|
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
|
||||||
|
}
|
|
@ -9,8 +9,17 @@ U.FeatureMixin = {
|
||||||
// DataLayer the marker belongs to
|
// DataLayer the marker belongs to
|
||||||
this.datalayer = options.datalayer || null
|
this.datalayer = options.datalayer || null
|
||||||
this.properties = { _umap_options: {} }
|
this.properties = { _umap_options: {} }
|
||||||
|
let geojson_id
|
||||||
if (options.geojson) {
|
if (options.geojson) {
|
||||||
this.populate(options.geojson)
|
this.populate(options.geojson)
|
||||||
|
geojson_id = options.geojson.id
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each feature needs an unique identifier
|
||||||
|
if (this._checkId(geojson_id)) {
|
||||||
|
this.id = geojson_id
|
||||||
|
} else {
|
||||||
|
this.id = U.Utils.generateId()
|
||||||
}
|
}
|
||||||
let isDirty = false
|
let isDirty = false
|
||||||
const self = this
|
const self = this
|
||||||
|
@ -36,6 +45,9 @@ U.FeatureMixin = {
|
||||||
this.addInteractions()
|
this.addInteractions()
|
||||||
this.parentClass.prototype.initialize.call(this, latlng, options)
|
this.parentClass.prototype.initialize.call(this, latlng, options)
|
||||||
},
|
},
|
||||||
|
_checkId: function () {
|
||||||
|
return typeof string !== 'undefined'
|
||||||
|
},
|
||||||
|
|
||||||
preInit: function () {},
|
preInit: function () {},
|
||||||
|
|
||||||
|
@ -344,6 +356,7 @@ U.FeatureMixin = {
|
||||||
toGeoJSON: function () {
|
toGeoJSON: function () {
|
||||||
const geojson = this.parentClass.prototype.toGeoJSON.call(this)
|
const geojson = this.parentClass.prototype.toGeoJSON.call(this)
|
||||||
geojson.properties = this.cloneProperties()
|
geojson.properties = this.cloneProperties()
|
||||||
|
geojson.id = this.id
|
||||||
delete geojson.properties._storage_options
|
delete geojson.properties._storage_options
|
||||||
return geojson
|
return geojson
|
||||||
},
|
},
|
||||||
|
|
51
umap/tests/integration/test_features_id_generation.py
Normal file
51
umap/tests/integration/test_features_id_generation.py
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def test_ids_generation(page, live_server, tilelayer):
|
||||||
|
page.goto(f"{live_server.url}/en/map/new/")
|
||||||
|
|
||||||
|
# Click on the Draw a line button on a new map.
|
||||||
|
create_polyline = page.locator(".leaflet-control-toolbar ").get_by_title(
|
||||||
|
"Draw a polyline"
|
||||||
|
)
|
||||||
|
create_polyline.click()
|
||||||
|
|
||||||
|
map = page.locator("#map")
|
||||||
|
map.click(position={"x": 200, "y": 200})
|
||||||
|
map.click(position={"x": 100, "y": 100})
|
||||||
|
# Click again to finish
|
||||||
|
map.click(position={"x": 100, "y": 100})
|
||||||
|
|
||||||
|
# Click on the Draw a polygon button on a new map.
|
||||||
|
create_polygon = page.locator(".leaflet-control-toolbar ").get_by_title(
|
||||||
|
"Draw a polygon"
|
||||||
|
)
|
||||||
|
create_polygon.click()
|
||||||
|
|
||||||
|
map = page.locator("#map")
|
||||||
|
map.click(position={"x": 300, "y": 300})
|
||||||
|
map.click(position={"x": 300, "y": 400})
|
||||||
|
map.click(position={"x": 350, "y": 450})
|
||||||
|
# Click again to finish
|
||||||
|
map.click(position={"x": 350, "y": 450})
|
||||||
|
|
||||||
|
download_panel = page.get_by_title("Share and download")
|
||||||
|
download_panel.click()
|
||||||
|
|
||||||
|
button = page.get_by_role("button", name="geojson")
|
||||||
|
|
||||||
|
with page.expect_download() as download_info:
|
||||||
|
button.click()
|
||||||
|
|
||||||
|
download = download_info.value
|
||||||
|
|
||||||
|
path = Path("/tmp/") / download.suggested_filename
|
||||||
|
download.save_as(path)
|
||||||
|
downloaded = json.loads(path.read_text())
|
||||||
|
|
||||||
|
assert "features" in downloaded
|
||||||
|
features = downloaded["features"]
|
||||||
|
assert len(features) == 2
|
||||||
|
assert "id" in features[0]
|
||||||
|
assert "id" in features[1]
|
Loading…
Reference in a new issue