umap-project 2.3.1__py3-none-any.whl → 2.4.0__py3-none-any.whl
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.
Potentially problematic release.
This version of umap-project might be problematic. Click here for more details.
- umap/__init__.py +1 -1
- umap/locale/en/LC_MESSAGES/django.po +81 -31
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +117 -66
- umap/management/commands/run_websocket_server.py +23 -0
- umap/models.py +6 -1
- umap/settings/base.py +11 -3
- umap/static/umap/base.css +64 -184
- umap/static/umap/content.css +3 -2
- umap/static/umap/css/dialog.css +18 -0
- umap/static/umap/css/icon.css +8 -0
- umap/static/umap/css/importers.css +51 -0
- umap/static/umap/css/panel.css +18 -57
- umap/static/umap/css/tooltip.css +59 -0
- umap/static/umap/css/window.css +35 -0
- umap/static/umap/img/16-white.svg +1 -3
- umap/static/umap/img/alert-icon-error.svg +8 -0
- umap/static/umap/img/alert-icon-info.svg +4 -0
- umap/static/umap/img/alert-icon-success.svg +3 -0
- umap/static/umap/img/icon-external-link.svg +3 -0
- umap/static/umap/img/importers/communesfr.svg +5 -0
- umap/static/umap/img/importers/datasets.svg +13 -0
- umap/static/umap/img/importers/geodatamine.svg +10 -0
- umap/static/umap/img/importers/overpass.svg +7 -0
- umap/static/umap/img/importers/random.svg +18 -0
- umap/static/umap/img/importers/random1.svg +4 -0
- umap/static/umap/img/importers/random2.svg +4 -0
- umap/static/umap/img/source/16-white.svg +2 -4
- umap/static/umap/js/components/alerts/alert.css +160 -0
- umap/static/umap/js/components/alerts/alert.js +169 -0
- umap/static/umap/js/components/base.js +54 -0
- umap/static/umap/js/modules/autocomplete.js +347 -0
- umap/static/umap/js/modules/browser.js +6 -6
- umap/static/umap/js/modules/caption.js +5 -4
- umap/static/umap/js/modules/global.js +36 -12
- umap/static/umap/js/modules/help.js +255 -0
- umap/static/umap/js/modules/importer.js +308 -0
- umap/static/umap/js/modules/importers/communesfr.js +44 -0
- umap/static/umap/js/modules/importers/datasets.js +42 -0
- umap/static/umap/js/modules/importers/geodatamine.js +95 -0
- umap/static/umap/js/modules/importers/overpass.js +84 -0
- umap/static/umap/js/modules/request.js +12 -14
- umap/static/umap/js/modules/rules.js +241 -0
- umap/static/umap/js/modules/schema.js +63 -14
- umap/static/umap/js/modules/sync/engine.js +93 -0
- umap/static/umap/js/modules/sync/updaters.js +109 -0
- umap/static/umap/js/modules/sync/websocket.js +25 -0
- umap/static/umap/js/modules/ui/dialog.js +52 -0
- umap/static/umap/js/modules/{panel.js → ui/panel.js} +25 -14
- umap/static/umap/js/modules/ui/tooltip.js +116 -0
- umap/static/umap/js/modules/utils.js +25 -18
- umap/static/umap/js/umap.controls.js +13 -14
- umap/static/umap/js/umap.core.js +1 -324
- umap/static/umap/js/umap.features.js +77 -29
- umap/static/umap/js/umap.forms.js +9 -13
- umap/static/umap/js/umap.js +254 -215
- umap/static/umap/js/umap.layer.js +152 -74
- umap/static/umap/js/umap.permissions.js +5 -9
- umap/static/umap/js/umap.popup.js +1 -1
- umap/static/umap/js/umap.tableeditor.js +8 -8
- umap/static/umap/locale/am_ET.js +51 -16
- umap/static/umap/locale/am_ET.json +51 -16
- umap/static/umap/locale/ar.js +51 -16
- umap/static/umap/locale/ar.json +51 -16
- umap/static/umap/locale/ast.js +51 -16
- umap/static/umap/locale/ast.json +51 -16
- umap/static/umap/locale/bg.js +51 -16
- umap/static/umap/locale/bg.json +51 -16
- umap/static/umap/locale/br.js +55 -20
- umap/static/umap/locale/br.json +55 -20
- umap/static/umap/locale/ca.js +51 -16
- umap/static/umap/locale/ca.json +51 -16
- umap/static/umap/locale/cs_CZ.js +93 -58
- umap/static/umap/locale/cs_CZ.json +93 -58
- umap/static/umap/locale/da.js +51 -16
- umap/static/umap/locale/da.json +51 -16
- umap/static/umap/locale/de.js +56 -21
- umap/static/umap/locale/de.json +56 -21
- umap/static/umap/locale/el.js +51 -16
- umap/static/umap/locale/el.json +51 -16
- umap/static/umap/locale/en.js +52 -16
- umap/static/umap/locale/en.json +52 -16
- umap/static/umap/locale/en_US.json +51 -16
- umap/static/umap/locale/es.js +51 -16
- umap/static/umap/locale/es.json +51 -16
- umap/static/umap/locale/et.js +51 -16
- umap/static/umap/locale/et.json +51 -16
- umap/static/umap/locale/eu.js +51 -16
- umap/static/umap/locale/eu.json +51 -16
- umap/static/umap/locale/fa_IR.js +51 -16
- umap/static/umap/locale/fa_IR.json +51 -16
- umap/static/umap/locale/fi.js +51 -16
- umap/static/umap/locale/fi.json +51 -16
- umap/static/umap/locale/fr.js +61 -25
- umap/static/umap/locale/fr.json +61 -25
- umap/static/umap/locale/gl.js +51 -16
- umap/static/umap/locale/gl.json +51 -16
- umap/static/umap/locale/he.js +51 -16
- umap/static/umap/locale/he.json +51 -16
- umap/static/umap/locale/hr.js +51 -16
- umap/static/umap/locale/hr.json +51 -16
- umap/static/umap/locale/hu.js +51 -16
- umap/static/umap/locale/hu.json +51 -16
- umap/static/umap/locale/id.js +51 -16
- umap/static/umap/locale/id.json +51 -16
- umap/static/umap/locale/is.js +51 -16
- umap/static/umap/locale/is.json +51 -16
- umap/static/umap/locale/it.js +51 -16
- umap/static/umap/locale/it.json +51 -16
- umap/static/umap/locale/ja.js +51 -16
- umap/static/umap/locale/ja.json +51 -16
- umap/static/umap/locale/ko.js +51 -16
- umap/static/umap/locale/ko.json +51 -16
- umap/static/umap/locale/lt.js +51 -16
- umap/static/umap/locale/lt.json +51 -16
- umap/static/umap/locale/ms.js +51 -16
- umap/static/umap/locale/ms.json +51 -16
- umap/static/umap/locale/nl.js +51 -16
- umap/static/umap/locale/nl.json +51 -16
- umap/static/umap/locale/no.js +51 -16
- umap/static/umap/locale/no.json +51 -16
- umap/static/umap/locale/pl.js +93 -58
- umap/static/umap/locale/pl.json +93 -58
- umap/static/umap/locale/pl_PL.json +51 -16
- umap/static/umap/locale/pt.js +215 -180
- umap/static/umap/locale/pt.json +215 -180
- umap/static/umap/locale/pt_BR.js +51 -16
- umap/static/umap/locale/pt_BR.json +51 -16
- umap/static/umap/locale/pt_PT.js +51 -16
- umap/static/umap/locale/pt_PT.json +51 -16
- umap/static/umap/locale/ro.js +51 -16
- umap/static/umap/locale/ro.json +51 -16
- umap/static/umap/locale/ru.js +51 -16
- umap/static/umap/locale/ru.json +51 -16
- umap/static/umap/locale/si.js +51 -16
- umap/static/umap/locale/si.json +51 -16
- umap/static/umap/locale/sk_SK.js +51 -16
- umap/static/umap/locale/sk_SK.json +51 -16
- umap/static/umap/locale/sl.js +51 -16
- umap/static/umap/locale/sl.json +51 -16
- umap/static/umap/locale/sr.js +51 -16
- umap/static/umap/locale/sr.json +51 -16
- umap/static/umap/locale/sv.js +51 -16
- umap/static/umap/locale/sv.json +51 -16
- umap/static/umap/locale/th_TH.js +51 -16
- umap/static/umap/locale/th_TH.json +51 -16
- umap/static/umap/locale/tr.js +51 -16
- umap/static/umap/locale/tr.json +51 -16
- umap/static/umap/locale/uk_UA.js +51 -16
- umap/static/umap/locale/uk_UA.json +51 -16
- umap/static/umap/locale/vi.js +51 -16
- umap/static/umap/locale/vi.json +51 -16
- umap/static/umap/locale/vi_VN.json +51 -16
- umap/static/umap/locale/zh.js +51 -16
- umap/static/umap/locale/zh.json +51 -16
- umap/static/umap/locale/zh_CN.json +51 -16
- umap/static/umap/locale/zh_TW.Big5.json +51 -16
- umap/static/umap/locale/zh_TW.js +51 -16
- umap/static/umap/locale/zh_TW.json +51 -16
- umap/static/umap/map.css +40 -53
- umap/static/umap/unittests/sync.js +105 -0
- umap/static/umap/unittests/utils.js +78 -36
- umap/static/umap/vars.css +19 -1
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +2 -2
- umap/templates/umap/components/alerts/alert.html +89 -0
- umap/templates/umap/content.html +4 -3
- umap/templates/umap/css.html +4 -0
- umap/templates/umap/home.html +3 -0
- umap/templates/umap/js.html +0 -3
- umap/templates/umap/map_init.html +2 -8
- umap/templates/umap/messages.html +9 -11
- umap/templates/umap/search.html +3 -0
- umap/tests/base.py +2 -0
- umap/tests/integration/conftest.py +30 -0
- umap/tests/integration/test_anonymous_owned_map.py +8 -13
- umap/tests/integration/test_browser.py +77 -4
- umap/tests/integration/test_conditional_rules.py +201 -0
- umap/tests/integration/test_dashboard.py +1 -1
- umap/tests/integration/test_datalayer.py +2 -3
- umap/tests/integration/test_edit_datalayer.py +4 -4
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_facets_browser.py +3 -3
- umap/tests/integration/test_import.py +185 -49
- umap/tests/integration/test_map.py +31 -2
- umap/tests/integration/{test_collaborative_editing.py → test_optimistic_merge.py} +7 -7
- umap/tests/integration/test_owned_map.py +1 -1
- umap/tests/integration/test_picto.py +2 -2
- umap/tests/integration/test_statics.py +1 -1
- umap/tests/integration/test_view_marker.py +2 -2
- umap/tests/integration/test_websocket_sync.py +283 -0
- umap/tests/settings.py +5 -0
- umap/tests/test_datalayer_views.py +0 -1
- umap/tests/test_views.py +53 -0
- umap/urls.py +5 -0
- umap/views.py +40 -11
- umap/websocket_server.py +92 -0
- {umap_project-2.3.1.dist-info → umap_project-2.4.0.dist-info}/METADATA +10 -8
- {umap_project-2.3.1.dist-info → umap_project-2.4.0.dist-info}/RECORD +201 -167
- umap/static/umap/js/umap.autocomplete.js +0 -341
- umap/static/umap/js/umap.importer.js +0 -187
- umap/static/umap/js/umap.ui.js +0 -190
- {umap_project-2.3.1.dist-info → umap_project-2.4.0.dist-info}/WHEEL +0 -0
- {umap_project-2.3.1.dist-info → umap_project-2.4.0.dist-info}/entry_points.txt +0 -0
- {umap_project-2.3.1.dist-info → umap_project-2.4.0.dist-info}/licenses/LICENSE +0 -0
umap/static/umap/js/umap.core.js
CHANGED
|
@@ -139,7 +139,7 @@ L.DomUtil.createButtonIcon = (parent, className, title, size = 16) => {
|
|
|
139
139
|
|
|
140
140
|
L.DomUtil.createTitle = (parent, text, className, tag = 'h3') => {
|
|
141
141
|
const title = L.DomUtil.create(tag, '', parent)
|
|
142
|
-
L.DomUtil.createIcon(title, className)
|
|
142
|
+
if (className) L.DomUtil.createIcon(title, className)
|
|
143
143
|
L.DomUtil.add('span', '', title, text)
|
|
144
144
|
return title
|
|
145
145
|
}
|
|
@@ -245,329 +245,6 @@ L.DomEvent.once = (el, types, fn, context) => {
|
|
|
245
245
|
return L.DomEvent.on(el, types, fn, context).on(el, types, handler, context)
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
/*
|
|
249
|
-
* Global events
|
|
250
|
-
*/
|
|
251
|
-
U.Keys = {
|
|
252
|
-
LEFT: 37,
|
|
253
|
-
UP: 38,
|
|
254
|
-
RIGHT: 39,
|
|
255
|
-
DOWN: 40,
|
|
256
|
-
TAB: 9,
|
|
257
|
-
ENTER: 13,
|
|
258
|
-
ESC: 27,
|
|
259
|
-
APPLE: 91,
|
|
260
|
-
SHIFT: 16,
|
|
261
|
-
ALT: 17,
|
|
262
|
-
CTRL: 18,
|
|
263
|
-
E: 69,
|
|
264
|
-
F: 70,
|
|
265
|
-
H: 72,
|
|
266
|
-
I: 73,
|
|
267
|
-
L: 76,
|
|
268
|
-
M: 77,
|
|
269
|
-
O: 79,
|
|
270
|
-
P: 80,
|
|
271
|
-
S: 83,
|
|
272
|
-
Z: 90,
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
U.Help = L.Class.extend({
|
|
276
|
-
SHORTCUTS: {
|
|
277
|
-
DRAW_MARKER: {
|
|
278
|
-
shortcut: 'Modifier+M',
|
|
279
|
-
label: L._('Draw a marker'),
|
|
280
|
-
},
|
|
281
|
-
DRAW_LINE: {
|
|
282
|
-
shortcut: 'Modifier+L',
|
|
283
|
-
label: L._('Draw a polyline'),
|
|
284
|
-
},
|
|
285
|
-
DRAW_POLYGON: {
|
|
286
|
-
shortcut: 'Modifier+P',
|
|
287
|
-
label: L._('Draw a polygon'),
|
|
288
|
-
},
|
|
289
|
-
TOGGLE_EDIT: {
|
|
290
|
-
shortcut: 'Modifier+E',
|
|
291
|
-
label: L._('Toggle edit mode'),
|
|
292
|
-
},
|
|
293
|
-
STOP_EDIT: {
|
|
294
|
-
shortcut: 'Modifier+E',
|
|
295
|
-
label: L._('Stop editing'),
|
|
296
|
-
},
|
|
297
|
-
SAVE_MAP: {
|
|
298
|
-
shortcut: 'Modifier+S',
|
|
299
|
-
label: L._('Save map'),
|
|
300
|
-
},
|
|
301
|
-
IMPORT_PANEL: {
|
|
302
|
-
shortcut: 'Modifier+I',
|
|
303
|
-
label: L._('Import data'),
|
|
304
|
-
},
|
|
305
|
-
SEARCH: {
|
|
306
|
-
shortcut: 'Modifier+F',
|
|
307
|
-
label: L._('Search location'),
|
|
308
|
-
},
|
|
309
|
-
CANCEL: {
|
|
310
|
-
shortcut: 'Modifier+Z',
|
|
311
|
-
label: L._('Cancel edits'),
|
|
312
|
-
},
|
|
313
|
-
PREVIEW: {
|
|
314
|
-
shortcut: 'Modifier+E',
|
|
315
|
-
label: L._('Back to preview'),
|
|
316
|
-
},
|
|
317
|
-
SAVE: {
|
|
318
|
-
shortcut: 'Modifier+S',
|
|
319
|
-
label: L._('Save current edits'),
|
|
320
|
-
},
|
|
321
|
-
EDIT_FEATURE_LAYER: {
|
|
322
|
-
shortcut: 'Modifier+⇧+Click',
|
|
323
|
-
label: L._("Edit feature's layer"),
|
|
324
|
-
},
|
|
325
|
-
CONTINUE_LINE: {
|
|
326
|
-
shortcut: 'Modifier+Click',
|
|
327
|
-
label: L._('Continue line'),
|
|
328
|
-
},
|
|
329
|
-
},
|
|
330
|
-
|
|
331
|
-
displayLabel: function (action, withKbdTag = true) {
|
|
332
|
-
let { shortcut, label } = this.SHORTCUTS[action]
|
|
333
|
-
const modifier = this.isMacOS ? 'Cmd' : 'Ctrl'
|
|
334
|
-
shortcut = shortcut.replace('Modifier', modifier)
|
|
335
|
-
if (withKbdTag) {
|
|
336
|
-
shortcut = shortcut
|
|
337
|
-
.split('+')
|
|
338
|
-
.map((el) => `<kbd>${el}</kbd>`)
|
|
339
|
-
.join('+')
|
|
340
|
-
label += ` ${shortcut}`
|
|
341
|
-
} else {
|
|
342
|
-
label += ` (${shortcut})`
|
|
343
|
-
}
|
|
344
|
-
return label
|
|
345
|
-
},
|
|
346
|
-
|
|
347
|
-
initialize: function (map) {
|
|
348
|
-
this.map = map
|
|
349
|
-
this.box = L.DomUtil.create(
|
|
350
|
-
'div',
|
|
351
|
-
'umap-help-box with-transition dark',
|
|
352
|
-
document.body
|
|
353
|
-
)
|
|
354
|
-
const closeButton = L.DomUtil.createButton(
|
|
355
|
-
'umap-close-link',
|
|
356
|
-
this.box,
|
|
357
|
-
'',
|
|
358
|
-
this.hide,
|
|
359
|
-
this
|
|
360
|
-
)
|
|
361
|
-
L.DomUtil.add('i', 'umap-close-icon', closeButton)
|
|
362
|
-
const label = L.DomUtil.create('span', '', closeButton)
|
|
363
|
-
label.title = label.textContent = L._('Close')
|
|
364
|
-
this.content = L.DomUtil.create('div', 'umap-help-content', this.box)
|
|
365
|
-
this.isMacOS = /mac/i.test(
|
|
366
|
-
// eslint-disable-next-line compat/compat -- Fallback available.
|
|
367
|
-
navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform
|
|
368
|
-
)
|
|
369
|
-
},
|
|
370
|
-
|
|
371
|
-
onKeyDown: function (e) {
|
|
372
|
-
const key = e.keyCode,
|
|
373
|
-
ESC = 27
|
|
374
|
-
if (key === ESC) {
|
|
375
|
-
this.hide()
|
|
376
|
-
}
|
|
377
|
-
},
|
|
378
|
-
|
|
379
|
-
show: function () {
|
|
380
|
-
this.content.innerHTML = ''
|
|
381
|
-
for (let i = 0, name; i < arguments.length; i++) {
|
|
382
|
-
name = arguments[i]
|
|
383
|
-
L.DomUtil.add('div', 'umap-help-entry', this.content, this.resolve(name))
|
|
384
|
-
}
|
|
385
|
-
L.DomUtil.addClass(document.body, 'umap-help-on')
|
|
386
|
-
},
|
|
387
|
-
|
|
388
|
-
hide: function () {
|
|
389
|
-
L.DomUtil.removeClass(document.body, 'umap-help-on')
|
|
390
|
-
},
|
|
391
|
-
|
|
392
|
-
visible: function () {
|
|
393
|
-
return L.DomUtil.hasClass(document.body, 'umap-help-on')
|
|
394
|
-
},
|
|
395
|
-
|
|
396
|
-
resolve: function (name) {
|
|
397
|
-
return typeof this[name] === 'function' ? this[name]() : this[name]
|
|
398
|
-
},
|
|
399
|
-
|
|
400
|
-
button: function (container, entries, classname) {
|
|
401
|
-
const helpButton = L.DomUtil.createButton(
|
|
402
|
-
classname || 'umap-help-button',
|
|
403
|
-
container,
|
|
404
|
-
L._('Help')
|
|
405
|
-
)
|
|
406
|
-
if (entries) {
|
|
407
|
-
L.DomEvent.on(helpButton, 'click', L.DomEvent.stop).on(
|
|
408
|
-
helpButton,
|
|
409
|
-
'click',
|
|
410
|
-
function (e) {
|
|
411
|
-
const args = typeof entries === 'string' ? [entries] : entries
|
|
412
|
-
this.show.apply(this, args)
|
|
413
|
-
},
|
|
414
|
-
this
|
|
415
|
-
)
|
|
416
|
-
}
|
|
417
|
-
return helpButton
|
|
418
|
-
},
|
|
419
|
-
|
|
420
|
-
link: function (container, entries) {
|
|
421
|
-
const helpButton = this.button(container, entries, 'umap-help-link')
|
|
422
|
-
helpButton.textContent = L._('Help')
|
|
423
|
-
return helpButton
|
|
424
|
-
},
|
|
425
|
-
|
|
426
|
-
edit: function () {
|
|
427
|
-
const container = L.DomUtil.create('div', ''),
|
|
428
|
-
self = this,
|
|
429
|
-
title = L.DomUtil.create('h3', '', container),
|
|
430
|
-
actionsContainer = L.DomUtil.create('ul', 'umap-edit-actions', container)
|
|
431
|
-
const addAction = (action) => {
|
|
432
|
-
const actionContainer = L.DomUtil.add('li', '', actionsContainer)
|
|
433
|
-
L.DomUtil.add('i', action.options.className, actionContainer),
|
|
434
|
-
L.DomUtil.add('span', '', actionContainer, action.options.tooltip)
|
|
435
|
-
L.DomEvent.on(actionContainer, 'click', action.addHooks, action)
|
|
436
|
-
L.DomEvent.on(actionContainer, 'click', self.hide, self)
|
|
437
|
-
}
|
|
438
|
-
title.textContent = L._('Where do we go from here?')
|
|
439
|
-
for (const id in this.map.helpMenuActions) {
|
|
440
|
-
addAction(this.map.helpMenuActions[id])
|
|
441
|
-
}
|
|
442
|
-
return container
|
|
443
|
-
},
|
|
444
|
-
|
|
445
|
-
importFormats: function () {
|
|
446
|
-
const container = L.DomUtil.create('div')
|
|
447
|
-
L.DomUtil.add('h3', '', container, 'GeojSON')
|
|
448
|
-
L.DomUtil.add('p', '', container, L._('All properties are imported.'))
|
|
449
|
-
L.DomUtil.add('h3', '', container, 'GPX')
|
|
450
|
-
L.DomUtil.add('p', '', container, `${L._('Properties imported:')}name, desc`)
|
|
451
|
-
L.DomUtil.add('h3', '', container, 'KML')
|
|
452
|
-
L.DomUtil.add('p', '', container, `${L._('Properties imported:')}name, description`)
|
|
453
|
-
L.DomUtil.add('h3', '', container, 'CSV')
|
|
454
|
-
L.DomUtil.add(
|
|
455
|
-
'p',
|
|
456
|
-
'',
|
|
457
|
-
container,
|
|
458
|
-
L._(
|
|
459
|
-
'Comma, tab or semi-colon separated values. SRS WGS84 is implied. Only Point geometries are imported. The import will look at the column headers for any mention of «lat» and «lon» at the begining of the header, case insensitive. All other column are imported as properties.'
|
|
460
|
-
)
|
|
461
|
-
)
|
|
462
|
-
L.DomUtil.add('h3', '', container, 'uMap')
|
|
463
|
-
L.DomUtil.add(
|
|
464
|
-
'p',
|
|
465
|
-
'',
|
|
466
|
-
container,
|
|
467
|
-
L._('Imports all umap data, including layers and settings.')
|
|
468
|
-
)
|
|
469
|
-
return container
|
|
470
|
-
},
|
|
471
|
-
|
|
472
|
-
textFormatting: function () {
|
|
473
|
-
const container = L.DomUtil.create('div'),
|
|
474
|
-
title = L.DomUtil.add('h3', '', container, L._('Text formatting')),
|
|
475
|
-
elements = L.DomUtil.create('ul', '', container)
|
|
476
|
-
L.DomUtil.add('li', '', elements, L._('*single star for italic*'))
|
|
477
|
-
L.DomUtil.add('li', '', elements, L._('**double star for bold**'))
|
|
478
|
-
L.DomUtil.add('li', '', elements, L._('# one hash for main heading'))
|
|
479
|
-
L.DomUtil.add('li', '', elements, L._('## two hashes for second heading'))
|
|
480
|
-
L.DomUtil.add('li', '', elements, L._('### three hashes for third heading'))
|
|
481
|
-
L.DomUtil.add('li', '', elements, L._('Simple link: [[http://example.com]]'))
|
|
482
|
-
L.DomUtil.add(
|
|
483
|
-
'li',
|
|
484
|
-
'',
|
|
485
|
-
elements,
|
|
486
|
-
L._('Link with text: [[http://example.com|text of the link]]')
|
|
487
|
-
)
|
|
488
|
-
L.DomUtil.add('li', '', elements, L._('Image: {{http://image.url.com}}'))
|
|
489
|
-
L.DomUtil.add(
|
|
490
|
-
'li',
|
|
491
|
-
'',
|
|
492
|
-
elements,
|
|
493
|
-
L._('Image with custom width (in px): {{http://image.url.com|width}}')
|
|
494
|
-
)
|
|
495
|
-
L.DomUtil.add('li', '', elements, L._('Iframe: {{{http://iframe.url.com}}}'))
|
|
496
|
-
L.DomUtil.add(
|
|
497
|
-
'li',
|
|
498
|
-
'',
|
|
499
|
-
elements,
|
|
500
|
-
L._('Iframe with custom height (in px): {{{http://iframe.url.com|height}}}')
|
|
501
|
-
)
|
|
502
|
-
L.DomUtil.add(
|
|
503
|
-
'li',
|
|
504
|
-
'',
|
|
505
|
-
elements,
|
|
506
|
-
L._(
|
|
507
|
-
'Iframe with custom height and width (in px): {{{http://iframe.url.com|height*width}}}'
|
|
508
|
-
)
|
|
509
|
-
)
|
|
510
|
-
L.DomUtil.add('li', '', elements, L._('--- for a horizontal rule'))
|
|
511
|
-
return container
|
|
512
|
-
},
|
|
513
|
-
|
|
514
|
-
dynamicProperties: function () {
|
|
515
|
-
const container = L.DomUtil.create('div')
|
|
516
|
-
L.DomUtil.add('h3', '', container, L._('Dynamic properties'))
|
|
517
|
-
L.DomUtil.add(
|
|
518
|
-
'p',
|
|
519
|
-
'',
|
|
520
|
-
container,
|
|
521
|
-
L._(
|
|
522
|
-
'Use placeholders with feature properties between brackets, eg. {name}, they will be dynamically replaced by the corresponding values.'
|
|
523
|
-
)
|
|
524
|
-
)
|
|
525
|
-
return container
|
|
526
|
-
},
|
|
527
|
-
|
|
528
|
-
formatURL: `${L._(
|
|
529
|
-
'Supported variables that will be dynamically replaced'
|
|
530
|
-
)}: {bbox}, {lat}, {lng}, {zoom}, {east}, {north}..., {left}, {top}..., locale, lang`,
|
|
531
|
-
colorValue: L._('Must be a valid CSS value (eg.: DarkBlue or #123456)'),
|
|
532
|
-
smoothFactor: L._(
|
|
533
|
-
'How much to simplify the polyline on each zoom level (more = better performance and smoother look, less = more accurate)'
|
|
534
|
-
),
|
|
535
|
-
dashArray: L._(
|
|
536
|
-
'A comma separated list of numbers that defines the stroke dash pattern. Ex.: "5, 10, 15".'
|
|
537
|
-
),
|
|
538
|
-
zoomTo: L._('Zoom level for automatic zooms'),
|
|
539
|
-
labelKey: L._(
|
|
540
|
-
'The name of the property to use as feature label (eg.: "nom"). You can also use properties inside brackets to use more than one or mix with static content (eg.: "{name} in {place}")'
|
|
541
|
-
),
|
|
542
|
-
stroke: L._('Whether to display or not polygons paths.'),
|
|
543
|
-
fill: L._('Whether to fill polygons with color.'),
|
|
544
|
-
fillColor: L._('Optional. Same as color if not set.'),
|
|
545
|
-
shortCredit: L._('Will be displayed in the bottom right corner of the map'),
|
|
546
|
-
longCredit: L._('Will be visible in the caption of the map'),
|
|
547
|
-
permanentCredit: L._(
|
|
548
|
-
'Will be permanently visible in the bottom left corner of the map'
|
|
549
|
-
),
|
|
550
|
-
sortKey: L._(
|
|
551
|
-
'Comma separated list of properties to use for sorting features. To reverse the sort, put a minus sign (-) before. Eg. mykey,-otherkey.'
|
|
552
|
-
),
|
|
553
|
-
slugKey: L._('The name of the property to use as feature unique identifier.'),
|
|
554
|
-
filterKey: L._(
|
|
555
|
-
'Comma separated list of properties to use when filtering features by text input'
|
|
556
|
-
),
|
|
557
|
-
facetKey: L._(
|
|
558
|
-
'Comma separated list of properties to use for filters (eg.: mykey,otherkey). To control label, add it after a | (eg.: mykey|My Key,otherkey|Other Key). To control input field type, add it after another | (eg.: mykey|My Key|checkbox,otherkey|Other Key|datetime). Allowed values for the input field type are checkbox (default), radio, number, date and datetime.'
|
|
559
|
-
),
|
|
560
|
-
interactive: L._(
|
|
561
|
-
'If false, the polygon or line will act as a part of the underlying map.'
|
|
562
|
-
),
|
|
563
|
-
outlink: L._('Define link to open in a new window on polygon click.'),
|
|
564
|
-
dynamicRemoteData: L._('Fetch data each time map view changes.'),
|
|
565
|
-
proxyRemoteData: L._("To use if remote server doesn't allow cross domain (slower)"),
|
|
566
|
-
browsable: L._(
|
|
567
|
-
'Set it to false to hide this layer from the slideshow, the data browser, the popup navigation…'
|
|
568
|
-
),
|
|
569
|
-
})
|
|
570
|
-
|
|
571
248
|
L.LatLng.prototype.isValid = function () {
|
|
572
249
|
return (
|
|
573
250
|
isFinite(this.lat) &&
|
|
@@ -1,25 +1,61 @@
|
|
|
1
1
|
U.FeatureMixin = {
|
|
2
2
|
staticOptions: { mainColor: 'color' },
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
getSyncMetadata: function () {
|
|
5
|
+
return {
|
|
6
|
+
subject: 'feature',
|
|
7
|
+
metadata: {
|
|
8
|
+
id: this.id,
|
|
9
|
+
layerId: this.datalayer?.id || null,
|
|
10
|
+
featureType: this.getClassName(),
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
onCommit: function () {
|
|
16
|
+
// When the layer is a remote layer, we don't want to sync the creation of the
|
|
17
|
+
// points via the websocket, as the other peers will get them themselves.
|
|
18
|
+
if (this.datalayer.isRemoteLayer()) return
|
|
19
|
+
this.sync.upsert(this.toGeoJSON())
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
getGeometry: function () {
|
|
23
|
+
return this.toGeoJSON().geometry
|
|
24
|
+
},
|
|
25
|
+
|
|
26
|
+
syncDelete: function () {
|
|
27
|
+
this.sync.delete()
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
initialize: function (map, latlng, options, id) {
|
|
5
31
|
this.map = map
|
|
32
|
+
this.sync = map.sync_engine.proxy(this)
|
|
33
|
+
|
|
6
34
|
if (typeof options === 'undefined') {
|
|
7
35
|
options = {}
|
|
8
36
|
}
|
|
9
37
|
// DataLayer the marker belongs to
|
|
10
38
|
this.datalayer = options.datalayer || null
|
|
11
39
|
this.properties = { _umap_options: {} }
|
|
12
|
-
|
|
40
|
+
|
|
13
41
|
if (options.geojson) {
|
|
14
42
|
this.populate(options.geojson)
|
|
15
|
-
geojson_id = options.geojson.id
|
|
16
43
|
}
|
|
17
44
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.id = geojson_id
|
|
45
|
+
if (id) {
|
|
46
|
+
this.id = id
|
|
21
47
|
} else {
|
|
22
|
-
|
|
48
|
+
let geojson_id
|
|
49
|
+
if (options.geojson) {
|
|
50
|
+
geojson_id = options.geojson.id
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Each feature needs an unique identifier
|
|
54
|
+
if (U.Utils.checkId(geojson_id)) {
|
|
55
|
+
this.id = geojson_id
|
|
56
|
+
} else {
|
|
57
|
+
this.id = U.Utils.generateId()
|
|
58
|
+
}
|
|
23
59
|
}
|
|
24
60
|
let isDirty = false
|
|
25
61
|
const self = this
|
|
@@ -98,6 +134,7 @@ U.FeatureMixin = {
|
|
|
98
134
|
this.view()
|
|
99
135
|
}
|
|
100
136
|
}
|
|
137
|
+
this._redraw()
|
|
101
138
|
},
|
|
102
139
|
|
|
103
140
|
openPopup: function () {
|
|
@@ -107,7 +144,11 @@ U.FeatureMixin = {
|
|
|
107
144
|
edit: function (e) {
|
|
108
145
|
if (!this.map.editEnabled || this.isReadOnly()) return
|
|
109
146
|
const container = L.DomUtil.create('div', 'umap-feature-container')
|
|
110
|
-
L.DomUtil.createTitle(
|
|
147
|
+
L.DomUtil.createTitle(
|
|
148
|
+
container,
|
|
149
|
+
L._('Feature properties'),
|
|
150
|
+
`icon-${this.getClassName()}`
|
|
151
|
+
)
|
|
111
152
|
|
|
112
153
|
let builder = new U.FormBuilder(
|
|
113
154
|
this,
|
|
@@ -134,7 +175,6 @@ U.FeatureMixin = {
|
|
|
134
175
|
properties.unshift('properties.name')
|
|
135
176
|
builder = new U.FormBuilder(this, properties, {
|
|
136
177
|
id: 'umap-feature-properties',
|
|
137
|
-
callback: this._redraw, // In case we have dynamic options…
|
|
138
178
|
})
|
|
139
179
|
container.appendChild(builder.build())
|
|
140
180
|
this.appendEditFieldsets(container)
|
|
@@ -149,7 +189,7 @@ U.FeatureMixin = {
|
|
|
149
189
|
},
|
|
150
190
|
|
|
151
191
|
getAdvancedEditActions: function (container) {
|
|
152
|
-
|
|
192
|
+
L.DomUtil.createButton(
|
|
153
193
|
'button umap-delete',
|
|
154
194
|
container,
|
|
155
195
|
L._('Delete'),
|
|
@@ -165,7 +205,6 @@ U.FeatureMixin = {
|
|
|
165
205
|
const optionsFields = this.getShapeOptions()
|
|
166
206
|
let builder = new U.FormBuilder(this, optionsFields, {
|
|
167
207
|
id: 'umap-feature-shape-properties',
|
|
168
|
-
callback: this._redraw,
|
|
169
208
|
})
|
|
170
209
|
const shapeProperties = L.DomUtil.createFieldset(container, L._('Shape properties'))
|
|
171
210
|
shapeProperties.appendChild(builder.build())
|
|
@@ -173,7 +212,6 @@ U.FeatureMixin = {
|
|
|
173
212
|
const advancedOptions = this.getAdvancedOptions()
|
|
174
213
|
builder = new U.FormBuilder(this, advancedOptions, {
|
|
175
214
|
id: 'umap-feature-advanced-properties',
|
|
176
|
-
callback: this._redraw,
|
|
177
215
|
})
|
|
178
216
|
const advancedProperties = L.DomUtil.createFieldset(
|
|
179
217
|
container,
|
|
@@ -182,9 +220,7 @@ U.FeatureMixin = {
|
|
|
182
220
|
advancedProperties.appendChild(builder.build())
|
|
183
221
|
|
|
184
222
|
const interactionOptions = this.getInteractionOptions()
|
|
185
|
-
builder = new U.FormBuilder(this, interactionOptions
|
|
186
|
-
callback: this._redraw,
|
|
187
|
-
})
|
|
223
|
+
builder = new U.FormBuilder(this, interactionOptions)
|
|
188
224
|
const popupFieldset = L.DomUtil.createFieldset(
|
|
189
225
|
container,
|
|
190
226
|
L._('Interaction options')
|
|
@@ -240,13 +276,14 @@ U.FeatureMixin = {
|
|
|
240
276
|
}
|
|
241
277
|
return false
|
|
242
278
|
},
|
|
243
|
-
|
|
244
|
-
del: function () {
|
|
279
|
+
del: function (sync) {
|
|
245
280
|
this.isDirty = true
|
|
246
281
|
this.map.closePopup()
|
|
247
282
|
if (this.datalayer) {
|
|
248
283
|
this.datalayer.removeLayer(this)
|
|
249
284
|
this.disconnectFromDataLayer(this.datalayer)
|
|
285
|
+
|
|
286
|
+
if (sync !== false) this.syncDelete()
|
|
250
287
|
}
|
|
251
288
|
},
|
|
252
289
|
|
|
@@ -495,7 +532,7 @@ U.FeatureMixin = {
|
|
|
495
532
|
},
|
|
496
533
|
|
|
497
534
|
isFiltered: function () {
|
|
498
|
-
const filterKeys = this.
|
|
535
|
+
const filterKeys = this.datalayer.getFilterKeys()
|
|
499
536
|
const filter = this.map.browser.options.filter
|
|
500
537
|
if (filter && !this.matchFilter(filter, filterKeys)) return true
|
|
501
538
|
if (!this.matchFacets()) return true
|
|
@@ -504,6 +541,10 @@ U.FeatureMixin = {
|
|
|
504
541
|
|
|
505
542
|
matchFilter: function (filter, keys) {
|
|
506
543
|
filter = filter.toLowerCase()
|
|
544
|
+
if (U.Utils.hasVar(keys)) {
|
|
545
|
+
return this.getDisplayName().toLowerCase().indexOf(filter) !== -1
|
|
546
|
+
}
|
|
547
|
+
keys = keys.split(',')
|
|
507
548
|
for (let i = 0, value; i < keys.length; i++) {
|
|
508
549
|
value = (this.properties[keys[i]] || '') + ''
|
|
509
550
|
if (value.toLowerCase().indexOf(filter) !== -1) return true
|
|
@@ -549,7 +590,10 @@ U.FeatureMixin = {
|
|
|
549
590
|
},
|
|
550
591
|
|
|
551
592
|
clone: function () {
|
|
552
|
-
const
|
|
593
|
+
const geoJSON = this.toGeoJSON()
|
|
594
|
+
delete geoJSON.id
|
|
595
|
+
delete geoJSON.properties.id
|
|
596
|
+
const layer = this.datalayer.geojsonToFeatures(geoJSON)
|
|
553
597
|
layer.isDirty = true
|
|
554
598
|
layer.edit()
|
|
555
599
|
return layer
|
|
@@ -562,7 +606,7 @@ U.FeatureMixin = {
|
|
|
562
606
|
if (locale) properties.locale = locale
|
|
563
607
|
if (L.lang) properties.lang = L.lang
|
|
564
608
|
properties.rank = this.getRank() + 1
|
|
565
|
-
if (this.hasGeom()) {
|
|
609
|
+
if (this._map && this.hasGeom()) {
|
|
566
610
|
center = this.getCenter()
|
|
567
611
|
properties.lat = center.lat
|
|
568
612
|
properties.lon = center.lng
|
|
@@ -602,9 +646,11 @@ U.Marker = L.Marker.extend({
|
|
|
602
646
|
function (e) {
|
|
603
647
|
this.isDirty = true
|
|
604
648
|
this.edit(e)
|
|
649
|
+
this.sync.update('geometry', this.getGeometry())
|
|
605
650
|
},
|
|
606
651
|
this
|
|
607
652
|
)
|
|
653
|
+
this.on('editable:drawing:commit', this.onCommit)
|
|
608
654
|
if (!this.isReadOnly()) this.on('mouseover', this._enableDragging)
|
|
609
655
|
this.on('mouseout', this._onMouseOut)
|
|
610
656
|
this._popupHandlersAdded = true // prevent Leaflet from binding event on bindPopup
|
|
@@ -726,14 +772,10 @@ U.Marker = L.Marker.extend({
|
|
|
726
772
|
const builder = new U.FormBuilder(this, coordinatesOptions, {
|
|
727
773
|
callback: function () {
|
|
728
774
|
if (!this._latlng.isValid()) {
|
|
729
|
-
|
|
730
|
-
content: L._('Invalid latitude or longitude'),
|
|
731
|
-
level: 'error',
|
|
732
|
-
})
|
|
775
|
+
U.Alert.error(L._('Invalid latitude or longitude'))
|
|
733
776
|
builder.resetField('_latlng.lat')
|
|
734
777
|
builder.resetField('_latlng.lng')
|
|
735
778
|
}
|
|
736
|
-
this._redraw()
|
|
737
779
|
this.zoomTo({ easing: false })
|
|
738
780
|
},
|
|
739
781
|
callbackContext: this,
|
|
@@ -878,14 +920,15 @@ U.PathMixin = {
|
|
|
878
920
|
|
|
879
921
|
_onMouseOver: function () {
|
|
880
922
|
if (this.map.measureTools && this.map.measureTools.enabled()) {
|
|
881
|
-
this.map.
|
|
923
|
+
this.map.tooltip.open({ content: this.getMeasure(), anchor: this })
|
|
882
924
|
} else if (this.map.editEnabled && !this.map.editedFeature) {
|
|
883
|
-
this.map.
|
|
925
|
+
this.map.tooltip.open({ content: L._('Click to edit'), anchor: this })
|
|
884
926
|
}
|
|
885
927
|
},
|
|
886
928
|
|
|
887
929
|
addInteractions: function () {
|
|
888
930
|
U.FeatureMixin.addInteractions.call(this)
|
|
931
|
+
this.on('editable:disable', this.onCommit)
|
|
889
932
|
this.on('mouseover', this._onMouseOver)
|
|
890
933
|
this.on('edit', this.makeDirty)
|
|
891
934
|
this.on('drag editable:drag', this._onDrag)
|
|
@@ -928,7 +971,7 @@ U.PathMixin = {
|
|
|
928
971
|
items.push({
|
|
929
972
|
text: L._('Display measure'),
|
|
930
973
|
callback: function () {
|
|
931
|
-
|
|
974
|
+
U.Alert.info(this.getMeasure())
|
|
932
975
|
},
|
|
933
976
|
context: this,
|
|
934
977
|
})
|
|
@@ -1086,6 +1129,9 @@ U.Polyline = L.Polyline.extend({
|
|
|
1086
1129
|
geojson.geometry.coordinates = [
|
|
1087
1130
|
U.Utils.flattenCoordinates(geojson.geometry.coordinates),
|
|
1088
1131
|
]
|
|
1132
|
+
|
|
1133
|
+
delete geojson.id // delete the copied id, a new one will be generated.
|
|
1134
|
+
|
|
1089
1135
|
const polygon = this.datalayer.geojsonToFeatures(geojson)
|
|
1090
1136
|
polygon.edit()
|
|
1091
1137
|
this.del()
|
|
@@ -1093,7 +1139,7 @@ U.Polyline = L.Polyline.extend({
|
|
|
1093
1139
|
|
|
1094
1140
|
getAdvancedEditActions: function (container) {
|
|
1095
1141
|
U.FeatureMixin.getAdvancedEditActions.call(this, container)
|
|
1096
|
-
|
|
1142
|
+
L.DomUtil.createButton(
|
|
1097
1143
|
'button umap-to-polygon',
|
|
1098
1144
|
container,
|
|
1099
1145
|
L._('Transform to polygon'),
|
|
@@ -1223,6 +1269,8 @@ U.Polygon = L.Polygon.extend({
|
|
|
1223
1269
|
|
|
1224
1270
|
toPolyline: function () {
|
|
1225
1271
|
const geojson = this.toGeoJSON()
|
|
1272
|
+
delete geojson.id
|
|
1273
|
+
delete geojson.properties.id
|
|
1226
1274
|
geojson.geometry.type = 'LineString'
|
|
1227
1275
|
geojson.geometry.coordinates = U.Utils.flattenCoordinates(
|
|
1228
1276
|
geojson.geometry.coordinates
|
|
@@ -78,7 +78,7 @@ L.FormBuilder.Element.include({
|
|
|
78
78
|
info,
|
|
79
79
|
'mouseover',
|
|
80
80
|
function () {
|
|
81
|
-
this.builder.map.
|
|
81
|
+
this.builder.map.tooltip.open({
|
|
82
82
|
anchor: info,
|
|
83
83
|
content: this.options.helpTooltip,
|
|
84
84
|
position: 'top',
|
|
@@ -340,15 +340,6 @@ L.FormBuilder.TextColorPicker = L.FormBuilder.ColorPicker.extend({
|
|
|
340
340
|
],
|
|
341
341
|
})
|
|
342
342
|
|
|
343
|
-
L.FormBuilder.ProxyTTLSelect = L.FormBuilder.Select.extend({
|
|
344
|
-
selectOptions: [
|
|
345
|
-
[undefined, L._('No cache')],
|
|
346
|
-
['300', L._('5 min')],
|
|
347
|
-
['3600', L._('1 hour')],
|
|
348
|
-
['86400', L._('1 day')],
|
|
349
|
-
],
|
|
350
|
-
})
|
|
351
|
-
|
|
352
343
|
L.FormBuilder.LayerTypeChooser = L.FormBuilder.Select.extend({
|
|
353
344
|
getOptions: function () {
|
|
354
345
|
const layer_classes = [
|
|
@@ -1067,7 +1058,7 @@ L.FormBuilder.ManageOwner = L.FormBuilder.Element.extend({
|
|
|
1067
1058
|
className: 'edit-owner',
|
|
1068
1059
|
on_select: L.bind(this.onSelect, this),
|
|
1069
1060
|
}
|
|
1070
|
-
this.autocomplete = new U.
|
|
1061
|
+
this.autocomplete = new U.AjaxAutocomplete(this.parentNode, options)
|
|
1071
1062
|
const owner = this.toHTML()
|
|
1072
1063
|
if (owner)
|
|
1073
1064
|
this.autocomplete.displaySelected({
|
|
@@ -1096,7 +1087,7 @@ L.FormBuilder.ManageEditors = L.FormBuilder.Element.extend({
|
|
|
1096
1087
|
on_select: L.bind(this.onSelect, this),
|
|
1097
1088
|
on_unselect: L.bind(this.onUnselect, this),
|
|
1098
1089
|
}
|
|
1099
|
-
this.autocomplete = new U.
|
|
1090
|
+
this.autocomplete = new U.AjaxAutocompleteMultiple(this.parentNode, options)
|
|
1100
1091
|
this._values = this.toHTML()
|
|
1101
1092
|
if (this._values)
|
|
1102
1093
|
for (let i = 0; i < this._values.length; i++)
|
|
@@ -1185,7 +1176,12 @@ U.FormBuilder = L.FormBuilder.extend({
|
|
|
1185
1176
|
setter: function (field, value) {
|
|
1186
1177
|
L.FormBuilder.prototype.setter.call(this, field, value)
|
|
1187
1178
|
this.obj.isDirty = true
|
|
1188
|
-
if ('render' in this.obj)
|
|
1179
|
+
if ('render' in this.obj) {
|
|
1180
|
+
this.obj.render([field], this)
|
|
1181
|
+
}
|
|
1182
|
+
if ('sync' in this.obj) {
|
|
1183
|
+
this.obj.sync.update(field, value)
|
|
1184
|
+
}
|
|
1189
1185
|
},
|
|
1190
1186
|
|
|
1191
1187
|
finish: function () {
|