mirror of
https://github.com/umap-project/umap.git
synced 2025-05-06 06:21:49 +02:00
feat: simple implementation of ids
This commit is contained in:
parent
b271dde93e
commit
fb8ee1fc38
7 changed files with 101 additions and 4 deletions
|
@ -1,8 +1,9 @@
|
|||
import * as L from '../../vendors/leaflet/leaflet-src.esm.js'
|
||||
import URLs from './urls.js'
|
||||
import * as utils from './utils.js'
|
||||
// Import modules and export them to the global scope.
|
||||
// For the not yet module-compatible JS out there.
|
||||
|
||||
// Copy the leaflet module, it's expected by leaflet plugins to be writeable.
|
||||
window.L = { ...L }
|
||||
window.umap = { URLs }
|
||||
window.umap = { URLs, utils }
|
||||
|
|
8
umap/static/umap/js/modules/utils.js
Normal file
8
umap/static/umap/js/modules/utils.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
export function generateId() {
|
||||
// A real implementation would benefit from another id type.
|
||||
// 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
|
||||
return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
|
||||
}
|
|
@ -1065,7 +1065,10 @@ L.U.TileLayerControl = L.Control.IconLayers.extend({
|
|||
// when the tilelayer is actually added to the map (needs this._tileZoom
|
||||
// to be defined)
|
||||
// Fixme when https://github.com/Leaflet/Leaflet/pull/9201 is released
|
||||
const icon = L.Util.template(layer.options.url_template, this.map.demoTileInfos)
|
||||
const icon = L.Util.template(
|
||||
layer.options.url_template,
|
||||
this.map.demoTileInfos
|
||||
)
|
||||
layers.push({
|
||||
title: layer.options.name,
|
||||
layer: layer,
|
||||
|
@ -1431,10 +1434,12 @@ L.U.Editable = L.Editable.extend({
|
|||
if (e.layer instanceof L.U.Marker) e.layer.del()
|
||||
})
|
||||
this.on('editable:drawing:commit', function (e) {
|
||||
console.log('sync: polyline ready', e.layer)
|
||||
e.layer.isDirty = true
|
||||
if (this.map.editedFeature !== e.layer) e.layer.edit(e)
|
||||
})
|
||||
this.on('editable:editing', (e) => {
|
||||
console.log('sync: polyline moved', e.layer)
|
||||
const layer = e.layer
|
||||
layer.isDirty = true
|
||||
if (layer._tooltip && layer.isTooltipOpen()) {
|
||||
|
@ -1462,6 +1467,7 @@ L.U.Editable = L.Editable.extend({
|
|||
},
|
||||
|
||||
createMarker: function (latlng) {
|
||||
console.log('sync: create marker', latlng)
|
||||
return new L.U.Marker(this.map, latlng, this._getDefaultProperties())
|
||||
},
|
||||
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
const generateId = window.umap.utils.generateId
|
||||
|
||||
L.U.FeatureMixin = {
|
||||
staticOptions: { mainColor: 'color' },
|
||||
|
||||
|
@ -9,9 +11,21 @@ L.U.FeatureMixin = {
|
|||
// DataLayer the marker belongs to
|
||||
this.datalayer = options.datalayer || null
|
||||
this.properties = { _umap_options: {} }
|
||||
let geojson_id
|
||||
if (options.geojson) {
|
||||
this.populate(options.geojson)
|
||||
geojson_id = options.geojson.id
|
||||
}
|
||||
|
||||
// Each feature needs an unique ID
|
||||
if (this._checkId(geojson_id)) {
|
||||
this.id = geojson_id
|
||||
} else {
|
||||
this.id = generateId()
|
||||
}
|
||||
|
||||
console.log('id', this.id)
|
||||
|
||||
let isDirty = false
|
||||
const self = this
|
||||
try {
|
||||
|
@ -222,6 +236,7 @@ L.U.FeatureMixin = {
|
|||
},
|
||||
|
||||
del: function () {
|
||||
console.log('sync: feature deleted', this)
|
||||
this.isDirty = true
|
||||
this.map.closePopup()
|
||||
if (this.datalayer) {
|
||||
|
@ -248,6 +263,11 @@ L.U.FeatureMixin = {
|
|||
return [key, value]
|
||||
},
|
||||
|
||||
// Ensures the id meets our requirements
|
||||
_checkId: function (string) {
|
||||
return typeof string !== 'undefined'
|
||||
},
|
||||
|
||||
populate: function (feature) {
|
||||
this.properties = Object.fromEntries(
|
||||
Object.entries(feature.properties || {}).map(this.cleanProperty)
|
||||
|
@ -344,7 +364,9 @@ L.U.FeatureMixin = {
|
|||
toGeoJSON: function () {
|
||||
const geojson = this.parentClass.prototype.toGeoJSON.call(this)
|
||||
geojson.properties = this.cloneProperties()
|
||||
geojson.id = this.id
|
||||
delete geojson.properties._storage_options
|
||||
console.log(geojson)
|
||||
return geojson
|
||||
},
|
||||
|
||||
|
@ -510,6 +532,7 @@ L.U.FeatureMixin = {
|
|||
},
|
||||
|
||||
clone: function () {
|
||||
console.log('sync: clone feature')
|
||||
const layer = this.datalayer.geojsonToFeatures(this.toGeoJSON())
|
||||
layer.isDirty = true
|
||||
layer.edit()
|
||||
|
@ -560,6 +583,7 @@ L.U.Marker = L.Marker.extend({
|
|||
this.on(
|
||||
'dragend',
|
||||
function (e) {
|
||||
console.log('sync: marker latlng updated', this._latlng)
|
||||
this.isDirty = true
|
||||
this.edit(e)
|
||||
},
|
||||
|
|
|
@ -34,7 +34,7 @@ L.Map.mergeOptions({
|
|||
// we cannot rely on this because of the y is overriden by Leaflet
|
||||
// See https://github.com/Leaflet/Leaflet/pull/9201
|
||||
// And let's remove this -y when this PR is merged and released.
|
||||
demoTileInfos: { s: 'a', z: 9, x: 265, y: 181, '-y': 181, r: '' },
|
||||
demoTileInfos: { 's': 'a', 'z': 9, 'x': 265, 'y': 181, '-y': 181, 'r': '' },
|
||||
licences: [],
|
||||
licence: '',
|
||||
enableMarkerDraw: true,
|
||||
|
@ -830,7 +830,10 @@ L.U.Map.include({
|
|||
self.isDirty = true
|
||||
}
|
||||
if (this._controls.tilelayersChooser)
|
||||
this._controls.tilelayersChooser.openSwitcher({ callback: callback, className: 'dark' })
|
||||
this._controls.tilelayersChooser.openSwitcher({
|
||||
callback: callback,
|
||||
className: 'dark',
|
||||
})
|
||||
},
|
||||
|
||||
manageDatalayers: function () {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
// Rendering only
|
||||
|
||||
L.U.Layer = {
|
||||
canBrowse: true,
|
||||
|
||||
|
|
53
umap/tests/integration/test_ids_generation.py
Normal file
53
umap/tests/integration/test_ids_generation.py
Normal file
|
@ -0,0 +1,53 @@
|
|||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from playwright.sync_api import expect
|
||||
|
||||
|
||||
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