umap-project 3.2.0__py3-none-any.whl → 3.3.1__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.

Files changed (179) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/el/LC_MESSAGES/django.po +42 -38
  4. umap/locale/en/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/en/LC_MESSAGES/django.po +15 -15
  6. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/hu/LC_MESSAGES/django.po +39 -35
  8. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  9. umap/locale/nl/LC_MESSAGES/django.po +31 -27
  10. umap/settings/base.py +2 -0
  11. umap/static/umap/css/contextmenu.css +58 -2
  12. umap/static/umap/css/form.css +175 -45
  13. umap/static/umap/css/icon.css +20 -0
  14. umap/static/umap/img/16-white.svg +21 -40
  15. umap/static/umap/img/16.svg +1 -1
  16. umap/static/umap/img/24-white.svg +9 -9
  17. umap/static/umap/img/24.svg +23 -10
  18. umap/static/umap/img/source/16-white.svg +23 -41
  19. umap/static/umap/img/source/16.svg +1 -1
  20. umap/static/umap/img/source/24-white.svg +11 -11
  21. umap/static/umap/img/source/24.svg +25 -12
  22. umap/static/umap/js/modules/caption.js +8 -0
  23. umap/static/umap/js/modules/data/features.js +318 -174
  24. umap/static/umap/js/modules/data/layer.js +27 -20
  25. umap/static/umap/js/modules/form/builder.js +11 -7
  26. umap/static/umap/js/modules/form/fields.js +10 -7
  27. umap/static/umap/js/modules/formatter.js +42 -20
  28. umap/static/umap/js/modules/importer.js +6 -1
  29. umap/static/umap/js/modules/importers/opendata.js +125 -37
  30. umap/static/umap/js/modules/importers/openrouteservice.js +140 -0
  31. umap/static/umap/js/modules/managers.js +12 -4
  32. umap/static/umap/js/modules/printer.js +107 -0
  33. umap/static/umap/js/modules/rendering/controls.js +78 -2
  34. umap/static/umap/js/modules/rendering/icon.js +113 -82
  35. umap/static/umap/js/modules/rendering/layers/cluster.js +220 -64
  36. umap/static/umap/js/modules/rendering/map.js +5 -1
  37. umap/static/umap/js/modules/rendering/template.js +71 -1
  38. umap/static/umap/js/modules/rendering/ui.js +101 -34
  39. umap/static/umap/js/modules/schema.js +24 -0
  40. umap/static/umap/js/modules/share.js +19 -12
  41. umap/static/umap/js/modules/ui/bar.js +6 -1
  42. umap/static/umap/js/modules/ui/base.js +24 -9
  43. umap/static/umap/js/modules/ui/contextmenu.js +17 -7
  44. umap/static/umap/js/modules/ui/dialog.js +7 -4
  45. umap/static/umap/js/modules/umap.js +68 -62
  46. umap/static/umap/js/umap.controls.js +22 -57
  47. umap/static/umap/locale/am_ET.js +39 -4
  48. umap/static/umap/locale/am_ET.json +39 -4
  49. umap/static/umap/locale/ar.js +39 -4
  50. umap/static/umap/locale/ar.json +39 -4
  51. umap/static/umap/locale/ast.js +39 -4
  52. umap/static/umap/locale/ast.json +39 -4
  53. umap/static/umap/locale/bg.js +39 -4
  54. umap/static/umap/locale/bg.json +39 -4
  55. umap/static/umap/locale/br.js +39 -4
  56. umap/static/umap/locale/br.json +39 -4
  57. umap/static/umap/locale/ca.js +39 -4
  58. umap/static/umap/locale/ca.json +39 -4
  59. umap/static/umap/locale/cs_CZ.js +39 -4
  60. umap/static/umap/locale/cs_CZ.json +39 -4
  61. umap/static/umap/locale/da.js +47 -12
  62. umap/static/umap/locale/da.json +47 -12
  63. umap/static/umap/locale/de.js +39 -4
  64. umap/static/umap/locale/de.json +39 -4
  65. umap/static/umap/locale/el.js +81 -46
  66. umap/static/umap/locale/el.json +81 -46
  67. umap/static/umap/locale/en.js +38 -4
  68. umap/static/umap/locale/en.json +38 -4
  69. umap/static/umap/locale/en_US.json +39 -4
  70. umap/static/umap/locale/es.js +47 -12
  71. umap/static/umap/locale/es.json +47 -12
  72. umap/static/umap/locale/et.js +39 -4
  73. umap/static/umap/locale/et.json +39 -4
  74. umap/static/umap/locale/eu.js +80 -45
  75. umap/static/umap/locale/eu.json +80 -45
  76. umap/static/umap/locale/fa_IR.js +39 -4
  77. umap/static/umap/locale/fa_IR.json +39 -4
  78. umap/static/umap/locale/fi.js +39 -4
  79. umap/static/umap/locale/fi.json +39 -4
  80. umap/static/umap/locale/fr.js +39 -4
  81. umap/static/umap/locale/fr.json +39 -4
  82. umap/static/umap/locale/gl.js +39 -4
  83. umap/static/umap/locale/gl.json +39 -4
  84. umap/static/umap/locale/he.js +39 -4
  85. umap/static/umap/locale/he.json +39 -4
  86. umap/static/umap/locale/hr.js +39 -4
  87. umap/static/umap/locale/hr.json +39 -4
  88. umap/static/umap/locale/hu.js +55 -20
  89. umap/static/umap/locale/hu.json +55 -20
  90. umap/static/umap/locale/id.js +39 -4
  91. umap/static/umap/locale/id.json +39 -4
  92. umap/static/umap/locale/is.js +39 -4
  93. umap/static/umap/locale/is.json +39 -4
  94. umap/static/umap/locale/it.js +39 -4
  95. umap/static/umap/locale/it.json +39 -4
  96. umap/static/umap/locale/ja.js +39 -4
  97. umap/static/umap/locale/ja.json +39 -4
  98. umap/static/umap/locale/ko.js +39 -4
  99. umap/static/umap/locale/ko.json +39 -4
  100. umap/static/umap/locale/lt.js +39 -4
  101. umap/static/umap/locale/lt.json +39 -4
  102. umap/static/umap/locale/ms.js +52 -17
  103. umap/static/umap/locale/ms.json +52 -17
  104. umap/static/umap/locale/nl.js +58 -23
  105. umap/static/umap/locale/nl.json +58 -23
  106. umap/static/umap/locale/no.js +39 -4
  107. umap/static/umap/locale/no.json +39 -4
  108. umap/static/umap/locale/pl.js +39 -4
  109. umap/static/umap/locale/pl.json +39 -4
  110. umap/static/umap/locale/pl_PL.json +39 -4
  111. umap/static/umap/locale/pt.js +39 -4
  112. umap/static/umap/locale/pt.json +39 -4
  113. umap/static/umap/locale/pt_BR.js +39 -4
  114. umap/static/umap/locale/pt_BR.json +39 -4
  115. umap/static/umap/locale/pt_PT.js +39 -4
  116. umap/static/umap/locale/pt_PT.json +39 -4
  117. umap/static/umap/locale/ro.js +39 -4
  118. umap/static/umap/locale/ro.json +39 -4
  119. umap/static/umap/locale/ru.js +39 -4
  120. umap/static/umap/locale/ru.json +39 -4
  121. umap/static/umap/locale/sk_SK.js +39 -4
  122. umap/static/umap/locale/sk_SK.json +39 -4
  123. umap/static/umap/locale/sl.js +39 -4
  124. umap/static/umap/locale/sl.json +39 -4
  125. umap/static/umap/locale/sr.js +39 -4
  126. umap/static/umap/locale/sr.json +39 -4
  127. umap/static/umap/locale/sv.js +39 -4
  128. umap/static/umap/locale/sv.json +39 -4
  129. umap/static/umap/locale/th_TH.js +39 -4
  130. umap/static/umap/locale/th_TH.json +39 -4
  131. umap/static/umap/locale/tr.js +39 -4
  132. umap/static/umap/locale/tr.json +39 -4
  133. umap/static/umap/locale/uk_UA.js +39 -4
  134. umap/static/umap/locale/uk_UA.json +39 -4
  135. umap/static/umap/locale/vi.js +39 -4
  136. umap/static/umap/locale/vi.json +39 -4
  137. umap/static/umap/locale/vi_VN.json +39 -4
  138. umap/static/umap/locale/zh.js +39 -4
  139. umap/static/umap/locale/zh.json +39 -4
  140. umap/static/umap/locale/zh_CN.json +39 -4
  141. umap/static/umap/locale/zh_TW.Big5.json +39 -4
  142. umap/static/umap/locale/zh_TW.js +98 -63
  143. umap/static/umap/locale/zh_TW.json +98 -63
  144. umap/static/umap/map.css +90 -41
  145. umap/static/umap/vars.css +1 -0
  146. umap/static/umap/vendors/editable/Leaflet.Editable.js +3 -1
  147. umap/static/umap/vendors/openrouteservice/ors-js-client.js +521 -0
  148. umap/static/umap/vendors/openrouteservice/ors-js-client.js.map +1 -0
  149. umap/static/umap/vendors/simple-elevation-chart/elevation.js +63 -0
  150. umap/static/umap/vendors/simple-elevation-chart/elevation.svg +8 -0
  151. umap/static/umap/vendors/snapdom/snapdom.min.mjs +3 -0
  152. umap/storage/staticfiles.py +12 -0
  153. umap/templates/umap/css.html +0 -4
  154. umap/templates/umap/js.html +1 -3
  155. umap/tests/integration/test_basics.py +2 -0
  156. umap/tests/integration/test_conditional_rules.py +17 -17
  157. umap/tests/integration/test_datalayer.py +1 -1
  158. umap/tests/integration/test_draw_polygon.py +3 -5
  159. umap/tests/integration/test_draw_polyline.py +4 -6
  160. umap/tests/integration/test_draw_route.py +178 -0
  161. umap/tests/integration/test_edit_map.py +1 -1
  162. umap/tests/integration/test_edit_marker.py +7 -7
  163. umap/tests/integration/test_edit_polygon.py +2 -2
  164. umap/tests/integration/test_export_map.py +74 -10
  165. umap/tests/integration/test_map_preview.py +1 -1
  166. umap/tests/integration/test_share.py +1 -1
  167. umap/tests/integration/test_tableeditor.py +4 -4
  168. umap/tests/integration/test_websocket_sync.py +4 -4
  169. umap/utils.py +5 -1
  170. umap/views.py +2 -0
  171. {umap_project-3.2.0.dist-info → umap_project-3.3.1.dist-info}/METADATA +9 -9
  172. {umap_project-3.2.0.dist-info → umap_project-3.3.1.dist-info}/RECORD +175 -171
  173. umap/static/umap/vendors/markercluster/MarkerCluster.Default.css +0 -60
  174. umap/static/umap/vendors/markercluster/MarkerCluster.css +0 -14
  175. umap/static/umap/vendors/markercluster/leaflet.markercluster.js +0 -2
  176. umap/static/umap/vendors/markercluster/leaflet.markercluster.js.map +0 -1
  177. {umap_project-3.2.0.dist-info → umap_project-3.3.1.dist-info}/WHEEL +0 -0
  178. {umap_project-3.2.0.dist-info → umap_project-3.3.1.dist-info}/entry_points.txt +0 -0
  179. {umap_project-3.2.0.dist-info → umap_project-3.3.1.dist-info}/licenses/LICENSE +0 -0
@@ -218,6 +218,7 @@ export const SCHEMA = {
218
218
  choices: [
219
219
  ['Default', translate('Default')],
220
220
  ['Circle', translate('Circle')],
221
+ ['LargeCircle', translate('Large Circle')],
221
222
  ['Drop', translate('Drop')],
222
223
  ['Ball', translate('Ball')],
223
224
  ['Raw', translate('None')],
@@ -234,6 +235,17 @@ export const SCHEMA = {
234
235
  inheritable: true,
235
236
  default: 1,
236
237
  },
238
+ iconSize: {
239
+ type: Number,
240
+ impacts: ['data'],
241
+ min: 12,
242
+ max: 64,
243
+ step: 4,
244
+ label: translate('Icon size'),
245
+ helpText: translate('Will only affect raw and large circle icons.'),
246
+ inheritable: true,
247
+ default: 24,
248
+ },
237
249
  iconUrl: {
238
250
  type: String,
239
251
  impacts: ['data'],
@@ -438,9 +450,17 @@ export const SCHEMA = {
438
450
  ['GeoRSSLink', translate('GeoRSS (only link)')],
439
451
  ['OSM', translate('OpenStreetMap')],
440
452
  ['Wikipedia', translate('Wikipedia')],
453
+ ['Route', translate('Route')],
441
454
  ],
442
455
  default: 'Default',
443
456
  },
457
+ printControl: {
458
+ type: Boolean,
459
+ impacts: ['ui'],
460
+ nullable: true,
461
+ label: translate('Display the print control'),
462
+ default: null,
463
+ },
444
464
  rank: {
445
465
  type: Number,
446
466
  impacts: ['datalayer-rank'],
@@ -453,6 +473,10 @@ export const SCHEMA = {
453
473
  type: Object,
454
474
  impacts: ['data'],
455
475
  },
476
+ route: {
477
+ type: Object,
478
+ impacts: ['data'],
479
+ },
456
480
  scaleControl: {
457
481
  type: Boolean,
458
482
  impacts: ['ui'],
@@ -43,7 +43,7 @@ export default class Share {
43
43
  const list = document.createElement('ul')
44
44
  list.classList.add('downloads')
45
45
  this.container.appendChild(list)
46
- for (const format of Object.keys(EXPORT_FORMATS)) {
46
+ for (const format of Object.keys(EXPORT_FORMATS).concat('jpg', 'png')) {
47
47
  const button = Utils.loadTemplate(`
48
48
  <li>
49
49
  <button class="flat" type="button">
@@ -142,22 +142,29 @@ export default class Share {
142
142
 
143
143
  async format(mode) {
144
144
  const type = EXPORT_FORMATS[mode]
145
- const content = await type.formatter(this._umap)
145
+ const features = this._umap.datalayers
146
+ .visible()
147
+ .reduce((acc, dl) => acc.concat(dl.features.visible()), [])
148
+ const content = await this._umap.formatter.stringify(features, mode)
146
149
  const filename = Utils.slugify(this._umap.properties.name) + type.ext
147
150
  return { content, filetype: type.filetype, filename }
148
151
  }
149
152
 
150
153
  async download(mode) {
151
- const { content, filetype, filename } = await this.format(mode)
152
- const blob = new Blob([content], { type: filetype })
153
- window.URL = window.URL || window.webkitURL
154
- const el = document.createElement('a')
155
- el.download = filename
156
- el.href = window.URL.createObjectURL(blob)
157
- el.style.display = 'none'
158
- document.body.appendChild(el)
159
- el.click()
160
- document.body.removeChild(el)
154
+ if (!(mode in EXPORT_FORMATS)) {
155
+ this._umap.openPrinter(mode)
156
+ } else {
157
+ const { content, filetype, filename } = await this.format(mode)
158
+ const blob = new Blob([content], { type: filetype })
159
+ window.URL = window.URL || window.webkitURL
160
+ const el = document.createElement('a')
161
+ el.download = filename
162
+ el.href = window.URL.createObjectURL(blob)
163
+ el.style.display = 'none'
164
+ document.body.appendChild(el)
165
+ el.click()
166
+ document.body.removeChild(el)
167
+ }
161
168
  }
162
169
  }
163
170
 
@@ -213,7 +213,9 @@ export class BottomBar extends WithTemplate {
213
213
  const selected = select.options[select.selectedIndex].value
214
214
  if (!selected) return
215
215
  this._umap.datalayers.active().map((datalayer) => {
216
- datalayer.toggle(datalayer.id === selected)
216
+ if (datalayer.properties.inCaption !== false) {
217
+ datalayer.toggle(datalayer.id === selected)
218
+ }
217
219
  })
218
220
  })
219
221
  this.redraw()
@@ -263,6 +265,7 @@ const EDIT_BAR_TEMPLATE = `
263
265
  <li data-ref="multipolygon" hidden>
264
266
  <button type="button" title="${translate('Add a polygon to the current multi')}"><i class="icon icon-24 icon-multipolygon"></i></button>
265
267
  </li>
268
+ <li data-ref="route" hidden><button type="button" data-getstarted title="${translate('Draw along routes')}"><i class="icon icon-24 icon-route"></i></button></li>
266
269
  <hr>
267
270
  <li data-ref="caption" hidden><button data-getstarted type="button" title="${translate('Edit map name and caption')}"><i class="icon icon-24 icon-caption"></i></button></li>
268
271
  <li data-ref="import" hidden><button type="button"><i class="icon icon-24 icon-upload"></i></button></li>
@@ -293,6 +296,7 @@ export class EditBar extends WithTemplate {
293
296
  this._onClick('multiline', () => this._umap.editedFeature.ui.editor.newShape())
294
297
  this._onClick('polygon', () => this._leafletMap.editTools.startPolygon())
295
298
  this._onClick('multipolygon', () => this._umap.editedFeature.ui.editor.newShape())
299
+ this._onClick('route', () => this._leafletMap.editTools.startRoute())
296
300
  this._onClick('caption', () => this._umap.editCaption())
297
301
  this._onClick('import', () => this._umap.importer.open())
298
302
  this._onClick('templates', () => this.templateIimporter.open())
@@ -321,6 +325,7 @@ export class EditBar extends WithTemplate {
321
325
  this.elements.center.hidden = this._umap.properties.editMode !== 'advanced'
322
326
  this.elements.permissions.hidden = this._umap.properties.editMode !== 'advanced'
323
327
  this.elements.settings.hidden = this._umap.properties.editMode !== 'advanced'
328
+ this.elements.route.hidden = !this._umap.properties.ORSAPIKey
324
329
  }
325
330
 
326
331
  _addTitle(ref, label) {
@@ -12,9 +12,19 @@ export class Positioned {
12
12
  }
13
13
 
14
14
  toggleClassPosition(position) {
15
- this.container.classList.toggle('tooltip-bottom', position === 'bottom')
16
- this.container.classList.toggle('tooltip-top', position === 'top')
17
- this.container.classList.toggle('tooltip-right', position === 'right')
15
+ const positions = [
16
+ 'bottom',
17
+ 'top',
18
+ 'left',
19
+ 'right',
20
+ 'bottom-right',
21
+ 'bottom-left',
22
+ 'top-right',
23
+ 'top-left',
24
+ ]
25
+ for (const known of positions) {
26
+ this.container.classList.toggle(`tooltip-${known}`, position === known)
27
+ }
18
28
  }
19
29
 
20
30
  anchorTop(el) {
@@ -39,7 +49,6 @@ export class Positioned {
39
49
  anchorRight(el) {
40
50
  this.toggleClassPosition('right')
41
51
  const coords = this.getPosition(el)
42
- console.log(coords)
43
52
  this.setPosition({
44
53
  left: coords.right + 11,
45
54
  top: coords.top,
@@ -71,18 +80,24 @@ export class Positioned {
71
80
  }
72
81
 
73
82
  computePosition([x, y]) {
83
+ let tooltip = ''
74
84
  let left
75
85
  let top
76
- if (x < window.innerWidth / 2) {
77
- left = x
78
- } else {
79
- left = x - this.container.offsetWidth
80
- }
81
86
  if (y < window.innerHeight / 2) {
82
87
  top = Math.min(y, window.innerHeight - this.container.offsetHeight)
88
+ tooltip += 'top'
83
89
  } else {
84
90
  top = Math.max(0, y - this.container.offsetHeight)
91
+ tooltip += 'bottom'
92
+ }
93
+ if (x < window.innerWidth / 2) {
94
+ left = x
95
+ tooltip += '-left'
96
+ } else {
97
+ left = x - this.container.offsetWidth
98
+ tooltip += '-right'
85
99
  }
100
+ this.toggleClassPosition(tooltip)
86
101
  this.setPosition({ left, top })
87
102
  }
88
103
 
@@ -1,4 +1,4 @@
1
- import { loadTemplate } from '../utils.js'
1
+ import { loadTemplate, loadTemplateWithRefs } from '../utils.js'
2
2
  import { Positioned } from './base.js'
3
3
 
4
4
  export default class ContextMenu extends Positioned {
@@ -29,16 +29,21 @@ export default class ContextMenu extends Positioned {
29
29
  this.openAt([coords.left, coords.bottom], items)
30
30
  }
31
31
 
32
- openAt([left, top], items) {
33
- this.container.innerHTML = ''
32
+ addItems(items, container) {
34
33
  for (const item of items) {
35
34
  if (item === '-') {
36
- this.container.appendChild(document.createElement('hr'))
35
+ container.appendChild(document.createElement('hr'))
36
+ } else if (item.items) {
37
+ const [li, { bar }] = loadTemplateWithRefs(
38
+ `<li class="dark"><ul data-ref=bar class="icon-bar"></ul></li>`
39
+ )
40
+ this.addItems(item.items, bar)
41
+ container.appendChild(li)
37
42
  } else if (typeof item.action === 'string') {
38
43
  const li = loadTemplate(
39
44
  `<li class="${item.className || ''}"><a tabindex="0" href="${item.action}">${item.label}</a></li>`
40
45
  )
41
- this.container.appendChild(li)
46
+ container.appendChild(li)
42
47
  } else {
43
48
  let content = item.label || ''
44
49
  if (item.icon) {
@@ -51,9 +56,14 @@ export default class ContextMenu extends Positioned {
51
56
  this.close()
52
57
  item.action()
53
58
  })
54
- this.container.appendChild(li)
59
+ container.appendChild(li)
55
60
  }
56
61
  }
62
+ }
63
+
64
+ openAt([left, top], items) {
65
+ this.container.innerHTML = ''
66
+ this.addItems(items, this.container)
57
67
  // When adding contextmenu below the map container, clicking on any link will send the
58
68
  // "focusout" element on link click, preventing to trigger the click action
59
69
  const parent = document
@@ -65,7 +75,7 @@ export default class ContextMenu extends Positioned {
65
75
  } else {
66
76
  this.computePosition([left, top])
67
77
  }
68
- this.container.querySelector('li > *').focus()
78
+ this.container.querySelector('button, a').focus()
69
79
  this.container.addEventListener(
70
80
  'keydown',
71
81
  (event) => {
@@ -37,7 +37,8 @@ export default class Dialog extends WithTemplate {
37
37
  this.init()
38
38
  }
39
39
 
40
- collectFormData(formData) {
40
+ collectFormData() {
41
+ const formData = new FormData(this.elements.form)
41
42
  const object = {}
42
43
  formData.forEach((value, key) => {
43
44
  if (!Reflect.has(object, key)) {
@@ -145,6 +146,10 @@ export default class Dialog extends WithTemplate {
145
146
  return this.waitForUser()
146
147
  }
147
148
 
149
+ on(...args) {
150
+ this.dialog.addEventListener(...args)
151
+ }
152
+
148
153
  close() {
149
154
  this.toggle(false)
150
155
  this.dialog.returnValue = undefined
@@ -171,9 +176,7 @@ export default class Dialog extends WithTemplate {
171
176
  'close',
172
177
  (event) => {
173
178
  if (this.dialog.returnValue === 'accept') {
174
- const value = this.hasFormData
175
- ? this.collectFormData(new FormData(this.elements.form))
176
- : true
179
+ const value = this.hasFormData ? this.collectFormData() : true
177
180
  resolve(value)
178
181
  }
179
182
  },
@@ -33,6 +33,7 @@ import Tooltip from './ui/tooltip.js'
33
33
  import URLs from './urls.js'
34
34
  import * as Utils from './utils.js'
35
35
  import { DataLayerManager } from './managers.js'
36
+ import { Importer as OpenRouteService } from './importers/openrouteservice.js'
36
37
 
37
38
  export default class Umap {
38
39
  constructor(element, geojson) {
@@ -128,7 +129,6 @@ export default class Umap {
128
129
  )
129
130
  this.tooltip = new Tooltip(this._leafletMap._controlContainer)
130
131
  this.contextmenu = new ContextMenu()
131
- this.editContextmenu = new ContextMenu({ className: 'dark', orientation: 'rows' })
132
132
  this.server = new ServerRequest()
133
133
  this.request = new Request()
134
134
  this.facets = new Facets(this)
@@ -210,7 +210,7 @@ export default class Umap {
210
210
 
211
211
  if (!this.properties.noControl) {
212
212
  this.initShortcuts()
213
- this._leafletMap.on('contextmenu', (e) => this.onContextMenu(e))
213
+ this._leafletMap.on('contextmenu', (event) => this.onContextMenu(event))
214
214
  this.onceDataLoaded(this.setViewFromQueryString)
215
215
  this.bottomBar.setup()
216
216
  this.propagate()
@@ -391,48 +391,28 @@ export default class Umap {
391
391
  }
392
392
  }
393
393
 
394
- getOwnContextMenuItems(event) {
394
+ getOwnContextMenu(event) {
395
395
  const items = []
396
- if (this.hasEditMode()) {
397
- if (this.editEnabled) {
398
- if (!this.isDirty) {
399
- items.push({
400
- label: this.help.displayLabel('STOP_EDIT'),
401
- action: () => this.disableEdit(),
402
- })
403
- }
404
- if (this.properties.enableMarkerDraw) {
405
- items.push({
406
- label: this.help.displayLabel('DRAW_MARKER'),
396
+ if (this.editEnabled) {
397
+ items.push({
398
+ items: [
399
+ {
400
+ title: this.help.displayLabel('DRAW_MARKER', false),
401
+ icon: 'icon-marker',
407
402
  action: () => this._leafletMap.editTools.startMarker(),
408
- })
409
- }
410
- if (this.properties.enablePolylineDraw) {
411
- items.push({
412
- label: this.help.displayLabel('DRAW_POLYGON'),
413
- action: () => this._leafletMap.editTools.startPolygon(),
414
- })
415
- }
416
- if (this.properties.enablePolygonDraw) {
417
- items.push({
418
- label: this.help.displayLabel('DRAW_LINE'),
403
+ },
404
+ {
405
+ title: this.help.displayLabel('DRAW_LINE', false),
406
+ icon: 'icon-polyline',
419
407
  action: () => this._leafletMap.editTools.startPolyline(),
420
- })
421
- }
422
- items.push('-')
423
- items.push({
424
- label: translate('Help'),
425
- action: () => this.help.show('edit'),
426
- })
427
- } else {
428
- items.push({
429
- label: this.help.displayLabel('TOGGLE_EDIT'),
430
- action: () => this.enableEdit(),
431
- })
432
- }
433
- }
434
- if (items.length) {
435
- items.push('-')
408
+ },
409
+ {
410
+ title: this.help.displayLabel('DRAW_POLYGON', false),
411
+ icon: 'icon-polygon',
412
+ action: () => this._leafletMap.editTools.startPolygon(),
413
+ },
414
+ ],
415
+ })
436
416
  }
437
417
  items.push(
438
418
  {
@@ -463,27 +443,32 @@ export default class Umap {
463
443
  return items
464
444
  }
465
445
 
466
- getSharedContextMenuItems(event) {
446
+ getSharedContextMenu(event) {
467
447
  const items = []
468
448
  if (this.properties.urls.routing) {
469
- items.push('-', {
449
+ items.push({
470
450
  label: translate('Directions from here'),
471
451
  action: () => this.openExternalRouting(event),
472
452
  })
473
453
  }
454
+ if (this.properties.ORSAPIKey) {
455
+ items.push({
456
+ label: translate('Compute isochrone from here'),
457
+ action: () => this.askForIsochrone(event),
458
+ })
459
+ }
474
460
  if (this.properties.urls.edit_in_osm) {
475
- items.push('-', {
461
+ items.push({
476
462
  label: translate('Edit in OpenStreetMap'),
477
463
  action: () => this.editInOSM(event),
478
464
  })
479
465
  }
466
+ if (items.length) items.unshift('-')
480
467
  return items
481
468
  }
482
469
 
483
470
  onContextMenu(event) {
484
- const items = this.getOwnContextMenuItems(event).concat(
485
- this.getSharedContextMenuItems(event)
486
- )
471
+ const items = this.getOwnContextMenu(event).concat(this.getSharedContextMenu(event))
487
472
  this.contextmenu.open(event.originalEvent, items)
488
473
  }
489
474
 
@@ -863,6 +848,7 @@ export default class Umap {
863
848
  const shapeOptions = [
864
849
  'properties.color',
865
850
  'properties.iconClass',
851
+ 'properties.iconSize',
866
852
  'properties.iconUrl',
867
853
  'properties.iconOpacity',
868
854
  'properties.opacity',
@@ -1276,20 +1262,6 @@ export default class Umap {
1276
1262
  }
1277
1263
  }
1278
1264
 
1279
- toGeoJSON() {
1280
- let features = []
1281
- this.datalayers.active().map((datalayer) => {
1282
- if (datalayer.isVisible()) {
1283
- features = features.concat(datalayer.featuresToGeoJSON())
1284
- }
1285
- })
1286
- const geojson = {
1287
- type: 'FeatureCollection',
1288
- features: features,
1289
- }
1290
- return geojson
1291
- }
1292
-
1293
1265
  enableEdit() {
1294
1266
  this.editBar.redraw()
1295
1267
  document.body.classList.add('umap-edit-enabled')
@@ -1637,8 +1609,8 @@ export default class Umap {
1637
1609
  for (const geojson of importedData.layers) {
1638
1610
  if (!geojson._umap_options && geojson._storage) {
1639
1611
  geojson._umap_options = geojson._storage
1640
- delete geojson._storage
1641
1612
  }
1613
+ delete geojson._storage
1642
1614
  delete geojson._umap_options?.id // Never trust an id at this stage
1643
1615
  if (geojson._umap_options?.iconUrl?.startsWith('/')) {
1644
1616
  geojson._umap_options.iconUrl = remoteOrigin + geojson._umap_options.iconUrl
@@ -1746,6 +1718,12 @@ export default class Umap {
1746
1718
  if (url) window.open(url)
1747
1719
  }
1748
1720
 
1721
+ async askForIsochrone(event) {
1722
+ if (!this.properties.ORSAPIKey) return
1723
+ const importer = new OpenRouteService(this)
1724
+ importer.isochrone(event.latlng)
1725
+ }
1726
+
1749
1727
  setCenterAndZoom() {
1750
1728
  this._setCenterAndZoom(true)
1751
1729
  Alert.success(translate('The zoom and center have been modified.'))
@@ -1776,4 +1754,32 @@ export default class Umap {
1776
1754
  redo() {
1777
1755
  this.sync._undoManager.redo()
1778
1756
  }
1757
+
1758
+ async screenshot() {
1759
+ const { snapdom, preCache } = await import('../../vendors/snapdom/snapdom.min.mjs')
1760
+ const el = document.querySelector('#map')
1761
+ await preCache(el)
1762
+ const result = await snapdom(el, {
1763
+ scale: 1,
1764
+ type: 'jpg',
1765
+ fast: false,
1766
+ exclude: [
1767
+ '.leaflet-control',
1768
+ '.umap-loader',
1769
+ '.panel',
1770
+ '.umap-caption-bar',
1771
+ '.umap-main-edit-toolbox',
1772
+ '.umap-edit-bar',
1773
+ ],
1774
+ })
1775
+ return result
1776
+ }
1777
+
1778
+ async openPrinter(action) {
1779
+ if (!this._printer) {
1780
+ const Printer = (await import('./printer.js')).default
1781
+ this._printer = new Printer(this)
1782
+ }
1783
+ this._printer.open(action)
1784
+ }
1779
1785
  }
@@ -210,57 +210,6 @@ U.Search = L.PhotonSearch.extend({
210
210
  },
211
211
  })
212
212
 
213
- U.SearchControl = L.Control.extend({
214
- options: {
215
- position: 'topleft',
216
- },
217
-
218
- onAdd: function (map) {
219
- this.map = map
220
- const container = L.DomUtil.create('div', 'leaflet-control-search umap-control')
221
- L.DomEvent.disableClickPropagation(container)
222
- L.DomUtil.createButton(
223
- '',
224
- container,
225
- L._('Search location'),
226
- (e) => {
227
- L.DomEvent.stop(e)
228
- this.open()
229
- },
230
- this
231
- )
232
- this.layer = L.layerGroup().addTo(map)
233
- return container
234
- },
235
-
236
- onRemove: function () {
237
- this.layer.remove()
238
- },
239
-
240
- open: function () {
241
- const options = {
242
- limit: 10,
243
- noResultLabel: L._('No results'),
244
- }
245
- if (this.map.options.photonUrl) options.url = this.map.options.photonUrl
246
- const container = L.DomUtil.create('div', '')
247
-
248
- L.DomUtil.createTitle(container, L._('Search location'), 'icon-search')
249
- const input = L.DomUtil.create('input', 'photon-input', container)
250
- const resultsContainer = L.DomUtil.create('div', 'photon-autocomplete', container)
251
- this.search = new U.Search(this.map, input, this.layer, options)
252
- const id = Math.random()
253
- this.search.on('ajax:send', () => {
254
- this.map.fire('dataloading', { id: id })
255
- })
256
- this.search.on('ajax:return', () => {
257
- this.map.fire('dataload', { id: id })
258
- })
259
- this.search.resultsContainer = resultsContainer
260
- this.map._umap.panel.open({ content: container }).then(input.focus())
261
- },
262
- })
263
-
264
213
  L.Control.MiniMap.include({
265
214
  initialize: function (layer, options) {
266
215
  L.Util.setOptions(this, options)
@@ -306,7 +255,14 @@ U.Editable = L.Editable.extend({
306
255
  if (event.layer instanceof U.LeafletMarker) event.layer.feature.del()
307
256
  })
308
257
  this.on('editable:drawing:commit', function (event) {
309
- if (this._umap.editedFeature !== event.layer) event.layer.feature.edit(event)
258
+ if (this._umap.editedFeature !== event.layer) {
259
+ const promise = event.layer.feature.edit(event)
260
+ if (event.layer.feature.isRoute?.()) {
261
+ promise.then((panel) => {
262
+ panel.scrollTo('details#edit-route')
263
+ })
264
+ }
265
+ }
310
266
  })
311
267
  this.on('editable:vertex:ctrlclick', (event) => {
312
268
  const index = event.vertex.getIndex()
@@ -322,13 +278,24 @@ U.Editable = L.Editable.extend({
322
278
  this.on('editable:vertex:rawclick', this.onVertexRawClick)
323
279
  },
324
280
 
325
- createPolyline: function (latlngs) {
281
+ startRoute: function (latlng) {
282
+ const feature = this.createLineString()
283
+ feature.askForRouteSettings().then(async () => {
284
+ feature.ui.enableEdit(this.map).newShape(latlng)
285
+ })
286
+ },
287
+
288
+ createLineString: function () {
326
289
  const datalayer = this._umap.defaultEditDataLayer()
327
290
  const line = new U.LineString(this._umap, datalayer, {
328
291
  geometry: { type: 'LineString', coordinates: [] },
329
292
  })
330
293
  line._needs_upsert = true
331
- return line.ui
294
+ return line
295
+ },
296
+
297
+ createPolyline: function (latlngs, properties = {}) {
298
+ return this.createLineString().ui
332
299
  },
333
300
 
334
301
  createPolygon: function (latlngs) {
@@ -372,7 +339,6 @@ U.Editable = L.Editable.extend({
372
339
  // only continue with Polylines and Polygons
373
340
  return
374
341
  }
375
-
376
342
  let content = L._('Drawing')
377
343
  let measure
378
344
  if (e.layer.editor._drawnLatLngs) {
@@ -422,8 +388,7 @@ U.Editable = L.Editable.extend({
422
388
  },
423
389
 
424
390
  onVertexRawClick: (e) => {
425
- e.layer.onVertexRawClick(e)
426
- L.DomEvent.stop(e)
391
+ // Do not delete the vertex on click (but on alt-click only)
427
392
  e.cancel()
428
393
  },
429
394