umap-project 2.9.0b0__py3-none-any.whl → 2.9.2__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 (205) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +15 -2
  3. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/br/LC_MESSAGES/django.po +111 -67
  5. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/cs_CZ/LC_MESSAGES/django.po +112 -67
  7. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/el/LC_MESSAGES/django.po +132 -87
  9. umap/locale/en/LC_MESSAGES/django.po +11 -10
  10. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/es/LC_MESSAGES/django.po +117 -71
  12. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/fr/LC_MESSAGES/django.po +11 -10
  14. umap/locale/gl/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/gl/LC_MESSAGES/django.po +219 -173
  16. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  17. umap/locale/it/LC_MESSAGES/django.po +145 -100
  18. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  19. umap/locale/nl/LC_MESSAGES/django.po +198 -152
  20. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  21. umap/locale/pt/LC_MESSAGES/django.po +118 -73
  22. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/zh_TW/LC_MESSAGES/django.po +112 -67
  24. umap/middleware.py +30 -1
  25. umap/models.py +20 -10
  26. umap/settings/base.py +2 -1
  27. umap/static/umap/base.css +4 -1
  28. umap/static/umap/css/bar.css +32 -0
  29. umap/static/umap/css/contextmenu.css +14 -2
  30. umap/static/umap/css/form.css +5 -10
  31. umap/static/umap/css/icon.css +39 -3
  32. umap/static/umap/css/panel.css +18 -1
  33. umap/static/umap/css/popup.css +0 -1
  34. umap/static/umap/img/16-white.svg +3 -3
  35. umap/static/umap/img/16.svg +1 -1
  36. umap/static/umap/img/24-white.svg +17 -16
  37. umap/static/umap/img/24.svg +29 -18
  38. umap/static/umap/img/providers/twitter-oauth2.png +0 -0
  39. umap/static/umap/img/source/16-white.svg +4 -4
  40. umap/static/umap/img/source/16.svg +1 -1
  41. umap/static/umap/img/source/24-white.svg +20 -18
  42. umap/static/umap/img/source/24.svg +30 -19
  43. umap/static/umap/js/modules/browser.js +2 -2
  44. umap/static/umap/js/modules/caption.js +4 -4
  45. umap/static/umap/js/modules/data/features.js +80 -32
  46. umap/static/umap/js/modules/data/layer.js +37 -50
  47. umap/static/umap/js/modules/form/builder.js +23 -22
  48. umap/static/umap/js/modules/form/fields.js +13 -5
  49. umap/static/umap/js/modules/formatter.js +6 -2
  50. umap/static/umap/js/modules/help.js +17 -23
  51. umap/static/umap/js/modules/importer.js +5 -2
  52. umap/static/umap/js/modules/permissions.js +6 -2
  53. umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
  54. umap/static/umap/js/modules/rendering/map.js +1 -21
  55. umap/static/umap/js/modules/rendering/ui.js +20 -38
  56. umap/static/umap/js/modules/rules.js +1 -1
  57. umap/static/umap/js/modules/saving.js +5 -0
  58. umap/static/umap/js/modules/schema.js +4 -1
  59. umap/static/umap/js/modules/sync/engine.js +39 -14
  60. umap/static/umap/js/modules/sync/updaters.js +7 -6
  61. umap/static/umap/js/modules/sync/websocket.js +48 -40
  62. umap/static/umap/js/modules/ui/bar.js +84 -0
  63. umap/static/umap/js/modules/ui/base.js +11 -0
  64. umap/static/umap/js/modules/ui/contextmenu.js +9 -2
  65. umap/static/umap/js/modules/ui/panel.js +5 -1
  66. umap/static/umap/js/modules/umap.js +85 -44
  67. umap/static/umap/js/umap.controls.js +11 -341
  68. umap/static/umap/locale/am_ET.js +17 -5
  69. umap/static/umap/locale/am_ET.json +17 -5
  70. umap/static/umap/locale/ar.js +17 -5
  71. umap/static/umap/locale/ar.json +17 -5
  72. umap/static/umap/locale/ast.js +17 -5
  73. umap/static/umap/locale/ast.json +17 -5
  74. umap/static/umap/locale/bg.js +17 -5
  75. umap/static/umap/locale/bg.json +17 -5
  76. umap/static/umap/locale/br.js +20 -15
  77. umap/static/umap/locale/br.json +20 -15
  78. umap/static/umap/locale/ca.js +8 -4
  79. umap/static/umap/locale/ca.json +8 -4
  80. umap/static/umap/locale/cs_CZ.js +8 -4
  81. umap/static/umap/locale/cs_CZ.json +8 -4
  82. umap/static/umap/locale/da.js +17 -5
  83. umap/static/umap/locale/da.json +17 -5
  84. umap/static/umap/locale/de.js +8 -4
  85. umap/static/umap/locale/de.json +8 -4
  86. umap/static/umap/locale/el.js +54 -50
  87. umap/static/umap/locale/el.json +54 -50
  88. umap/static/umap/locale/en.js +9 -4
  89. umap/static/umap/locale/en.json +9 -4
  90. umap/static/umap/locale/en_US.json +17 -5
  91. umap/static/umap/locale/es.js +13 -9
  92. umap/static/umap/locale/es.json +13 -9
  93. umap/static/umap/locale/et.js +17 -5
  94. umap/static/umap/locale/et.json +17 -5
  95. umap/static/umap/locale/eu.js +8 -4
  96. umap/static/umap/locale/eu.json +8 -4
  97. umap/static/umap/locale/fa_IR.js +8 -4
  98. umap/static/umap/locale/fa_IR.json +8 -4
  99. umap/static/umap/locale/fi.js +17 -5
  100. umap/static/umap/locale/fi.json +17 -5
  101. umap/static/umap/locale/fr.js +9 -4
  102. umap/static/umap/locale/fr.json +9 -4
  103. umap/static/umap/locale/gl.js +13 -9
  104. umap/static/umap/locale/gl.json +13 -9
  105. umap/static/umap/locale/he.js +17 -5
  106. umap/static/umap/locale/he.json +17 -5
  107. umap/static/umap/locale/hr.js +17 -5
  108. umap/static/umap/locale/hr.json +17 -5
  109. umap/static/umap/locale/hu.js +8 -4
  110. umap/static/umap/locale/hu.json +8 -4
  111. umap/static/umap/locale/id.js +17 -5
  112. umap/static/umap/locale/id.json +17 -5
  113. umap/static/umap/locale/is.js +17 -5
  114. umap/static/umap/locale/is.json +17 -5
  115. umap/static/umap/locale/it.js +31 -27
  116. umap/static/umap/locale/it.json +31 -27
  117. umap/static/umap/locale/ja.js +17 -5
  118. umap/static/umap/locale/ja.json +17 -5
  119. umap/static/umap/locale/ko.js +17 -5
  120. umap/static/umap/locale/ko.json +17 -5
  121. umap/static/umap/locale/lt.js +17 -5
  122. umap/static/umap/locale/lt.json +17 -5
  123. umap/static/umap/locale/ms.js +8 -4
  124. umap/static/umap/locale/ms.json +8 -4
  125. umap/static/umap/locale/nl.js +132 -127
  126. umap/static/umap/locale/nl.json +132 -127
  127. umap/static/umap/locale/no.js +17 -5
  128. umap/static/umap/locale/no.json +17 -5
  129. umap/static/umap/locale/pl.js +8 -4
  130. umap/static/umap/locale/pl.json +8 -4
  131. umap/static/umap/locale/pl_PL.json +17 -5
  132. umap/static/umap/locale/pt.js +38 -33
  133. umap/static/umap/locale/pt.json +38 -33
  134. umap/static/umap/locale/pt_BR.js +17 -5
  135. umap/static/umap/locale/pt_BR.json +17 -5
  136. umap/static/umap/locale/pt_PT.js +8 -4
  137. umap/static/umap/locale/pt_PT.json +8 -4
  138. umap/static/umap/locale/ro.js +17 -5
  139. umap/static/umap/locale/ro.json +17 -5
  140. umap/static/umap/locale/ru.js +17 -5
  141. umap/static/umap/locale/ru.json +17 -5
  142. umap/static/umap/locale/sk_SK.js +17 -5
  143. umap/static/umap/locale/sk_SK.json +17 -5
  144. umap/static/umap/locale/sl.js +17 -5
  145. umap/static/umap/locale/sl.json +17 -5
  146. umap/static/umap/locale/sr.js +17 -5
  147. umap/static/umap/locale/sr.json +17 -5
  148. umap/static/umap/locale/sv.js +17 -5
  149. umap/static/umap/locale/sv.json +17 -5
  150. umap/static/umap/locale/th_TH.js +8 -4
  151. umap/static/umap/locale/th_TH.json +8 -4
  152. umap/static/umap/locale/tr.js +17 -5
  153. umap/static/umap/locale/tr.json +17 -5
  154. umap/static/umap/locale/uk_UA.js +17 -5
  155. umap/static/umap/locale/uk_UA.json +17 -5
  156. umap/static/umap/locale/vi.js +17 -5
  157. umap/static/umap/locale/vi.json +17 -5
  158. umap/static/umap/locale/vi_VN.json +17 -5
  159. umap/static/umap/locale/zh.js +17 -5
  160. umap/static/umap/locale/zh.json +17 -5
  161. umap/static/umap/locale/zh_CN.json +17 -5
  162. umap/static/umap/locale/zh_TW.Big5.json +17 -5
  163. umap/static/umap/locale/zh_TW.js +14 -10
  164. umap/static/umap/locale/zh_TW.json +14 -10
  165. umap/static/umap/map.css +17 -68
  166. umap/static/umap/nav.css +4 -0
  167. umap/static/umap/vars.css +1 -0
  168. umap/static/umap/vendors/dompurify/purify.es.js +138 -354
  169. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  170. umap/static/umap/vendors/editable/Leaflet.Editable.js +1 -0
  171. umap/sync/app.py +19 -13
  172. umap/sync/payloads.py +8 -1
  173. umap/templates/auth/user_form.html +2 -2
  174. umap/templates/umap/content_footer.html +1 -1
  175. umap/templates/umap/css.html +0 -2
  176. umap/templates/umap/js.html +0 -1
  177. umap/templates/umap/messages.html +5 -1
  178. umap/templates/umap/search_bar.html +1 -0
  179. umap/tests/integration/test_anonymous_owned_map.py +2 -2
  180. umap/tests/integration/test_basics.py +2 -5
  181. umap/tests/integration/test_categorized_layer.py +4 -8
  182. umap/tests/integration/test_choropleth.py +1 -1
  183. umap/tests/integration/test_conditional_rules.py +3 -3
  184. umap/tests/integration/test_draw_polygon.py +11 -19
  185. umap/tests/integration/test_draw_polyline.py +6 -14
  186. umap/tests/integration/test_edit_datalayer.py +10 -10
  187. umap/tests/integration/test_edit_map.py +27 -1
  188. umap/tests/integration/test_edit_marker.py +5 -5
  189. umap/tests/integration/test_edit_polygon.py +5 -5
  190. umap/tests/integration/test_features_id_generation.py +2 -6
  191. umap/tests/integration/test_import.py +93 -29
  192. umap/tests/integration/test_owned_map.py +1 -1
  193. umap/tests/integration/test_save.py +2 -2
  194. umap/tests/integration/test_tableeditor.py +7 -7
  195. umap/tests/integration/test_view_marker.py +10 -0
  196. umap/tests/integration/test_websocket_sync.py +128 -32
  197. umap/utils.py +4 -1
  198. umap/views.py +1 -10
  199. {umap_project-2.9.0b0.dist-info → umap_project-2.9.2.dist-info}/METADATA +13 -13
  200. {umap_project-2.9.0b0.dist-info → umap_project-2.9.2.dist-info}/RECORD +203 -205
  201. umap/static/umap/vendors/toolbar/leaflet.toolbar.css +0 -1
  202. umap/static/umap/vendors/toolbar/leaflet.toolbar.js +0 -1
  203. {umap_project-2.9.0b0.dist-info → umap_project-2.9.2.dist-info}/WHEEL +0 -0
  204. {umap_project-2.9.0b0.dist-info → umap_project-2.9.2.dist-info}/entry_points.txt +0 -0
  205. {umap_project-2.9.0b0.dist-info → umap_project-2.9.2.dist-info}/licenses/LICENSE +0 -0
@@ -3,53 +3,57 @@ const PING_INTERVAL = 30000
3
3
  const FIRST_CONNECTION_TIMEOUT = 2000
4
4
 
5
5
  export class WebSocketTransport {
6
- constructor(webSocketURI, authToken, messagesReceiver, peerId, username) {
6
+ constructor(messagesReceiver) {
7
7
  this.receiver = messagesReceiver
8
+ }
8
9
 
9
- this.websocket = new WebSocket(webSocketURI)
10
+ async connect(webSocketURI, authToken, peerId, username) {
11
+ return new Promise((resolve, reject) => {
12
+ this.websocket = new WebSocket(webSocketURI)
10
13
 
11
- this.websocket.onopen = () => {
12
- this.send('JoinRequest', { token: authToken, peer: peerId, username })
13
- this.receiver.onConnection()
14
- }
15
- this.websocket.addEventListener('message', this.onMessage.bind(this))
16
- this.websocket.onclose = () => {
17
- console.log('websocket closed')
18
- if (!this.receiver.closeRequested) {
19
- console.log('Not requested, reconnecting...')
20
- this.receiver.reconnect()
14
+ this.websocket.onopen = () => {
15
+ this.send('JoinRequest', { token: authToken, peer: peerId, username })
16
+ resolve(this.websocket)
21
17
  }
22
- }
23
-
24
- this.websocket.onerror = (error) => {
25
- console.log('WS ERROR', error)
26
- }
27
-
28
- this.ensureOpen = setInterval(() => {
29
- if (this.websocket.readyState !== WebSocket.OPEN) {
30
- this.websocket.close()
31
- clearInterval(this.ensureOpen)
18
+ this.websocket.addEventListener('message', this.onMessage.bind(this))
19
+ this.websocket.onclose = () => {
20
+ console.log('websocket closed')
21
+ if (!this.receiver.closeRequested) {
22
+ console.log('Not requested, reconnecting...')
23
+ this.receiver.reconnect()
24
+ }
32
25
  }
33
- }, FIRST_CONNECTION_TIMEOUT)
34
26
 
35
- // To ensure the connection is still alive, we send ping and expect pong back.
36
- // Websocket provides a `ping` method to keep the connection alive, but it's
37
- // unfortunately not possible to access it from the WebSocket object.
38
- // See https://making.close.com/posts/reliable-websockets/ for more details.
39
- this.pingInterval = setInterval(() => {
40
- if (this.websocket.readyState === WebSocket.OPEN) {
41
- console.log('sending ping')
42
- this.websocket.send('ping')
43
- this.pongReceived = false
44
- setTimeout(() => {
45
- if (!this.pongReceived) {
46
- console.warn('No pong received, reconnecting...')
47
- this.websocket.close()
48
- clearInterval(this.pingInterval)
49
- }
50
- }, PONG_TIMEOUT)
27
+ this.websocket.onerror = (error) => {
28
+ console.log('WS ERROR', error)
51
29
  }
52
- }, PING_INTERVAL)
30
+
31
+ this.ensureOpen = setInterval(() => {
32
+ if (this.websocket.readyState !== WebSocket.OPEN) {
33
+ this.websocket.close()
34
+ clearInterval(this.ensureOpen)
35
+ }
36
+ }, FIRST_CONNECTION_TIMEOUT)
37
+
38
+ // To ensure the connection is still alive, we send ping and expect pong back.
39
+ // Websocket provides a `ping` method to keep the connection alive, but it's
40
+ // unfortunately not possible to access it from the WebSocket object.
41
+ // See https://making.close.com/posts/reliable-websockets/ for more details.
42
+ this.pingInterval = setInterval(() => {
43
+ if (this.websocket.readyState === WebSocket.OPEN) {
44
+ console.log('sending ping')
45
+ this.websocket.send('ping')
46
+ this.pongReceived = false
47
+ setTimeout(() => {
48
+ if (!this.pongReceived) {
49
+ console.warn('No pong received, reconnecting...')
50
+ this.websocket.close()
51
+ clearInterval(this.pingInterval)
52
+ }
53
+ }, PONG_TIMEOUT)
54
+ }
55
+ }, PING_INTERVAL)
56
+ })
53
57
  }
54
58
 
55
59
  onMessage(wsMessage) {
@@ -72,4 +76,8 @@ export class WebSocketTransport {
72
76
  this.receiver.closeRequested = true
73
77
  this.websocket.close()
74
78
  }
79
+
80
+ get isOpen() {
81
+ return this.websocket?.readyState === WebSocket.OPEN
82
+ }
75
83
  }
@@ -3,6 +3,7 @@ import { translate } from '../i18n.js'
3
3
  import { WithTemplate } from '../utils.js'
4
4
  import ContextMenu from './contextmenu.js'
5
5
  import * as Utils from '../utils.js'
6
+ import { Point, LineString, Polygon } from '../data/features.js'
6
7
 
7
8
  const TOP_BAR_TEMPLATE = `
8
9
  <div class="umap-main-edit-toolbox with-transition dark">
@@ -202,3 +203,86 @@ export class BottomBar extends WithTemplate {
202
203
  this.elements.filter.hidden = !showMenus || !this._umap.properties.facetKey
203
204
  }
204
205
  }
206
+
207
+ const EDIT_BAR_TEMPLATE = `
208
+ <ul class="umap-edit-bar dark with-transition">
209
+ <li data-ref="marker"><button type="button" data-getstarted><i class="icon icon-24 icon-marker"></i></button></li>
210
+ <li data-ref="polyline"><button type="button" data-getstarted><i class="icon icon-24 icon-polyline"></i></button></li>
211
+ <li data-ref="multiline" hidden>
212
+ <button type="button" title="${translate('Add a line to the current multi')}"><i class="icon icon-24 icon-multiline"></i></button>
213
+ </li>
214
+ <li data-ref="polygon"><button type="button" data-getstarted><i class="icon icon-24 icon-polygon"></i></button></li>
215
+ <li data-ref="multipolygon" hidden>
216
+ <button type="button" title="${translate('Add a polygon to the current multi')}"><i class="icon icon-24 icon-multipolygon"></i></button>
217
+ </li>
218
+ <hr>
219
+ <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>
220
+ <li data-ref="import" hidden><button type="button"><i class="icon icon-24 icon-upload"></i></button></li>
221
+ <li data-ref="layers" hidden><button type="button" title="${translate('Manage layers')}"><i class="icon icon-24 icon-layers"></i></button></li>
222
+ <li data-ref="tilelayers" hidden><button type="button" title="${translate('Change tilelayers')}"><i class="icon icon-24 icon-tilelayer"></i></button></li>
223
+ <li data-ref="center" hidden><button type="button"><i class="icon icon-24 icon-center"></i></button></li>
224
+ <li data-ref="permissions" hidden><button type="button" title="${translate('Update permissions and editors')}"><i class="icon icon-24 icon-key"></i></button></li>
225
+ <li data-ref="settings" hidden><button data-getstarted type="button" title="${translate('Map advanced properties')}"><i class="icon icon-24 icon-settings"></i></button></li>
226
+ </ul>
227
+ `
228
+
229
+ export class EditBar extends WithTemplate {
230
+ constructor(umap, leafletMap, parent) {
231
+ super()
232
+ this._umap = umap
233
+ this._leafletMap = leafletMap
234
+ this.loadTemplate(EDIT_BAR_TEMPLATE)
235
+ this.parent = parent
236
+ }
237
+
238
+ setup() {
239
+ this.parent.appendChild(this.element)
240
+ DomEvent.disableClickPropagation(this.element)
241
+ this._onClick('marker', () => this._leafletMap.editTools.startMarker())
242
+ this._onClick('polyline', () => this._leafletMap.editTools.startPolyline())
243
+ this._onClick('multiline', () => {
244
+ console.log('click click')
245
+ this._umap.editedFeature.ui.editor.newShape()
246
+ })
247
+ this._onClick('polygon', () => this._leafletMap.editTools.startPolygon())
248
+ this._onClick('multipolygon', () => this._umap.editedFeature.ui.editor.newShape())
249
+ this._onClick('caption', () => this._umap.editCaption())
250
+ this._onClick('import', () => this._umap.importer.open())
251
+ this._onClick('layers', () => this._umap.editDatalayers())
252
+ this._onClick('tilelayers', () => this._leafletMap.editTileLayers())
253
+ this._onClick('center', () => this._umap.editCenter())
254
+ this._onClick('permissions', () => this._umap.permissions.edit())
255
+ this._onClick('settings', () => this._umap.edit())
256
+ this._addTitle('import', 'IMPORT_PANEL')
257
+ this._addTitle('marker', 'DRAW_MARKER')
258
+ this._addTitle('polyline', 'DRAW_LINE')
259
+ this._addTitle('polygon', 'DRAW_POLYGON')
260
+ this._leafletMap.on('seteditedfeature', () => this.redraw())
261
+ }
262
+
263
+ redraw() {
264
+ const editedFeature = this._umap.editedFeature
265
+ this.elements.multiline.hidden = !(editedFeature instanceof LineString)
266
+ this.elements.multipolygon.hidden = !(editedFeature instanceof Polygon)
267
+ this.elements.caption.hidden = this._umap.properties.editMode !== 'advanced'
268
+ this.elements.import.hidden = this._umap.properties.editMode !== 'advanced'
269
+ this.elements.layers.hidden = this._umap.properties.editMode !== 'advanced'
270
+ this.elements.tilelayers.hidden = this._umap.properties.editMode !== 'advanced'
271
+ this.elements.center.hidden = this._umap.properties.editMode !== 'advanced'
272
+ this.elements.permissions.hidden = this._umap.properties.editMode !== 'advanced'
273
+ this.elements.settings.hidden = this._umap.properties.editMode !== 'advanced'
274
+ }
275
+
276
+ _addTitle(ref, label) {
277
+ this.elements[ref].querySelector('button').title = this._umap.help.displayLabel(
278
+ label,
279
+ false
280
+ )
281
+ }
282
+
283
+ _onClick(ref, action) {
284
+ // Put the click on the button, not on the li, but keep the data-ref on the li
285
+ // so to hide/show it when needed.
286
+ this.elements[ref].querySelector('button').addEventListener('click', action)
287
+ }
288
+ }
@@ -4,6 +4,8 @@ export class Positioned {
4
4
  this.anchorTop(anchor)
5
5
  } else if (anchor && position === 'bottom') {
6
6
  this.anchorBottom(anchor)
7
+ } else {
8
+ this.anchorAbsolute()
7
9
  }
8
10
  }
9
11
 
@@ -31,6 +33,15 @@ export class Positioned {
31
33
  })
32
34
  }
33
35
 
36
+ anchorAbsolute() {
37
+ const left =
38
+ this.parent.offsetLeft +
39
+ this.parent.clientWidth / 2 -
40
+ this.container.clientWidth / 2
41
+ const top = this.parent.offsetTop + 75
42
+ this.setPosition({ top: top, left: left })
43
+ }
44
+
34
45
  getPosition(el) {
35
46
  return el.getBoundingClientRect()
36
47
  }
@@ -10,6 +10,9 @@ export default class ContextMenu extends Positioned {
10
10
  if (options.className) {
11
11
  this.container.classList.add(options.className)
12
12
  }
13
+ if (options.orientation === 'rows') {
14
+ this.container.classList.add('umap-contextmenu-rows')
15
+ }
13
16
  this.container.addEventListener('focusout', (event) => {
14
17
  if (!this.container.contains(event.relatedTarget)) this.close()
15
18
  })
@@ -37,10 +40,14 @@ export default class ContextMenu extends Positioned {
37
40
  )
38
41
  this.container.appendChild(li)
39
42
  } else {
43
+ let content = item.label || ''
44
+ if (item.icon) {
45
+ content = `<i class="icon icon-16 ${item.icon}"></i>${content}`
46
+ }
40
47
  const li = loadTemplate(
41
- `<li class="${item.className || ''}"><button tabindex="0" class="flat">${item.label}</button></li>`
48
+ `<li class="${item.className || ''}"><button tabindex="0" class="flat" title="${item.title || ''}">${content}</button></li>`
42
49
  )
43
- li.addEventListener('click', () => {
50
+ li.firstChild.addEventListener('click', () => {
44
51
  this.close()
45
52
  item.action()
46
53
  })
@@ -25,13 +25,16 @@ export class Panel {
25
25
  return this.container.classList.contains('on')
26
26
  }
27
27
 
28
- open({ content, className, actions = [] } = {}) {
28
+ open({ content, className, highlight, actions = [] } = {}) {
29
29
  if (this.isOpen()) {
30
30
  this.onClose()
31
31
  }
32
32
  this.container.className = `with-transition panel window ${this.className} ${
33
33
  this.mode || ''
34
34
  }`
35
+ if (highlight) {
36
+ this.container.dataset.highlight = highlight
37
+ }
35
38
  document.body.classList.add(`panel-${this.className.split(' ')[0]}-on`)
36
39
  this.container.innerHTML = ''
37
40
  const actionsContainer = DomUtil.create('ul', 'buttons', this.container)
@@ -75,6 +78,7 @@ export class Panel {
75
78
 
76
79
  close() {
77
80
  document.body.classList.remove(`panel-${this.className.split(' ')[0]}-on`)
81
+ this.container.dataset.highlight = null
78
82
  this.onClose()
79
83
  }
80
84
 
@@ -13,7 +13,7 @@ import { LeafletMap } from './rendering/map.js'
13
13
  import URLs from './urls.js'
14
14
  import { Panel, EditPanel, FullPanel } from './ui/panel.js'
15
15
  import Dialog from './ui/dialog.js'
16
- import { BottomBar, TopBar } from './ui/bar.js'
16
+ import { BottomBar, TopBar, EditBar } from './ui/bar.js'
17
17
  import Tooltip from './ui/tooltip.js'
18
18
  import ContextMenu from './ui/contextmenu.js'
19
19
  import { Request, ServerRequest } from './request.js'
@@ -92,7 +92,8 @@ export default class Umap extends ServerStored {
92
92
  fullscreenControl !== undefined ? fullscreenControl : true
93
93
 
94
94
  if (center) {
95
- this._leafletMap.options.center = this._leafletMap.latLng(center)
95
+ this._leafletMap.options.center = this.properties.center =
96
+ this._leafletMap.latLng(center)
96
97
  }
97
98
 
98
99
  // Needed to render controls
@@ -112,8 +113,14 @@ export default class Umap extends ServerStored {
112
113
  this.slideshow,
113
114
  this._leafletMap._controlContainer
114
115
  )
116
+ this.editBar = new EditBar(
117
+ this,
118
+ this._leafletMap,
119
+ this._leafletMap._controlContainer
120
+ )
115
121
  this.tooltip = new Tooltip(this._leafletMap._controlContainer)
116
122
  this.contextmenu = new ContextMenu()
123
+ this.editContextmenu = new ContextMenu({ className: 'dark', orientation: 'rows' })
117
124
  this.server = new ServerRequest()
118
125
  this.request = new Request()
119
126
  this.facets = new Facets(this)
@@ -131,6 +138,7 @@ export default class Umap extends ServerStored {
131
138
  this.fullPanel = new FullPanel(this, this._leafletMap)
132
139
  this._leafletMap.initEditTools()
133
140
  this.topBar.setup()
141
+ this.editBar.setup()
134
142
  }
135
143
 
136
144
  this.datalayersFromQueryString = this.searchParams.get('datalayers')
@@ -677,6 +685,7 @@ export default class Umap extends ServerStored {
677
685
  Alert.success(translate('Map has been saved!'))
678
686
  })
679
687
  }
688
+ this.sync.saved()
680
689
  this.fire('saved')
681
690
  }
682
691
 
@@ -737,7 +746,7 @@ export default class Umap extends ServerStored {
737
746
  editCaption() {
738
747
  if (!this.editEnabled) return
739
748
  if (this.properties.editMode !== 'advanced') return
740
- const container = DomUtil.create('div', 'umap-edit-container')
749
+ const container = DomUtil.create('div')
741
750
  const metadataFields = ['properties.name', 'properties.description']
742
751
 
743
752
  DomUtil.createTitle(container, translate('Edit map details'), 'icon-caption')
@@ -758,7 +767,42 @@ export default class Umap extends ServerStored {
758
767
  ]
759
768
  const creditsBuilder = new MutatingForm(this, creditsFields, { umap: this })
760
769
  credits.appendChild(creditsBuilder.build())
761
- this.editPanel.open({ content: container })
770
+ this.editPanel.open({ content: container, highlight: 'caption' })
771
+ }
772
+
773
+ editCenter() {
774
+ if (!this.editEnabled) return
775
+ if (this.properties.editMode !== 'advanced') return
776
+ const container = DomUtil.create('div')
777
+ const metadataFields = [
778
+ ['properties.zoom', { handler: 'IntInput', label: translate('Default zoom') }],
779
+ [
780
+ 'properties.center.lat',
781
+ { handler: 'FloatInput', label: translate('Default latitude') },
782
+ ],
783
+ [
784
+ 'properties.center.lng',
785
+ { handler: 'FloatInput', label: translate('Default longitude') },
786
+ ],
787
+ 'properties.defaultView',
788
+ ]
789
+
790
+ DomUtil.createTitle(container, translate('Edit map default view'), 'icon-zoom')
791
+ const builder = new MutatingForm(this, metadataFields, {
792
+ className: 'map-metadata',
793
+ umap: this,
794
+ })
795
+ const form = builder.build()
796
+ const button = Utils.loadTemplate(
797
+ `<button type="button">${translate('Use current center and zoom')}</button>`
798
+ )
799
+ button.addEventListener('click', () => {
800
+ this._setCenterAndZoom()
801
+ builder.fetchAll()
802
+ })
803
+ container.appendChild(form)
804
+ container.appendChild(button)
805
+ this.editPanel.open({ content: container, highlight: 'center' })
762
806
  }
763
807
 
764
808
  _editControls(container) {
@@ -772,7 +816,6 @@ export default class Umap extends ServerStored {
772
816
  'properties.miniMap',
773
817
  'properties.scaleControl',
774
818
  'properties.onLoadPanel',
775
- 'properties.defaultView',
776
819
  'properties.displayPopupFooter',
777
820
  'properties.captionBar',
778
821
  'properties.captionMenus',
@@ -1053,44 +1096,38 @@ export default class Umap extends ServerStored {
1053
1096
  container,
1054
1097
  translate('Advanced actions')
1055
1098
  )
1056
- const advancedButtons = DomUtil.create('div', 'button-bar half', advancedActions)
1057
- if (this.permissions.isOwner()) {
1058
- const deleteButton = Utils.loadTemplate(`
1059
- <button class="button" type="button">
1099
+ const tpl = `
1100
+ <div class="button-bar half">
1101
+ <button class="button" type="button" data-ref=del hidden>
1060
1102
  <i class="icon icon-24 icon-delete"></i>${translate('Delete')}
1061
- </button>`)
1062
- deleteButton.addEventListener('click', () => this.del())
1063
- advancedButtons.appendChild(deleteButton)
1064
-
1065
- DomUtil.createButton(
1066
- 'button umap-empty',
1067
- advancedButtons,
1068
- translate('Clear data'),
1069
- this.emptyDataLayers,
1070
- this
1071
- )
1072
- DomUtil.createButton(
1073
- 'button umap-empty',
1074
- advancedButtons,
1075
- translate('Remove layers'),
1076
- this.removeDataLayers,
1077
- this
1078
- )
1103
+ </button>
1104
+ <button class="button" type="button" data-ref=clear hidden>
1105
+ <i class="icon icon-24 icon-empty"></i>${translate('Clear data')}
1106
+ </button>
1107
+ <button class="button" type="button" data-ref=empty hidden>
1108
+ <i class="icon icon-24 icon-empty"></i>${translate('Remove layers')}
1109
+ </button>
1110
+ <button class="button" type="button" data-ref=clone>
1111
+ <i class="icon icon-24 icon-clone"></i>${translate('Clone this map')}
1112
+ </button>
1113
+ <button class="button" type="button" data-ref=download>
1114
+ <i class="icon icon-24 icon-download"></i>${translate('Open share & download panel')}
1115
+ </button>
1116
+ </div>
1117
+ `
1118
+ const [bar, { del, clear, empty, clone, download }] =
1119
+ Utils.loadTemplateWithRefs(tpl)
1120
+ advancedActions.appendChild(bar)
1121
+ if (this.permissions.isOwner()) {
1122
+ del.hidden = false
1123
+ del.addEventListener('click', () => this.del())
1124
+ clear.hidden = false
1125
+ clear.addEventListener('click', () => this.emptyDataLayers())
1126
+ empty.hidden = false
1127
+ empty.addEventListener('click', () => this.removeDataLayers())
1079
1128
  }
1080
- DomUtil.createButton(
1081
- 'button umap-clone',
1082
- advancedButtons,
1083
- translate('Clone this map'),
1084
- this.clone,
1085
- this
1086
- )
1087
- DomUtil.createButton(
1088
- 'button umap-download',
1089
- advancedButtons,
1090
- translate('Open share & download panel'),
1091
- this.share.open,
1092
- this.share
1093
- )
1129
+ clone.addEventListener('click', () => this.clone())
1130
+ download.addEventListener('click', () => this.share.open())
1094
1131
  }
1095
1132
 
1096
1133
  edit() {
@@ -1116,7 +1153,11 @@ export default class Umap extends ServerStored {
1116
1153
  }
1117
1154
  this._advancedActions(container)
1118
1155
 
1119
- this.editPanel.open({ content: container, className: 'dark' })
1156
+ this.editPanel.open({
1157
+ content: container,
1158
+ className: 'dark',
1159
+ highlight: 'settings',
1160
+ })
1120
1161
  }
1121
1162
 
1122
1163
  reset() {
@@ -1236,6 +1277,7 @@ export default class Umap extends ServerStored {
1236
1277
  }
1237
1278
 
1238
1279
  enableEdit() {
1280
+ this.editBar.redraw()
1239
1281
  document.body.classList.add('umap-edit-enabled')
1240
1282
  this.editEnabled = true
1241
1283
  this.drop.enable()
@@ -1253,7 +1295,6 @@ export default class Umap extends ServerStored {
1253
1295
  this.editPanel.close()
1254
1296
  this.fullPanel.close()
1255
1297
  this.sync.stop()
1256
- this._leafletMap.closeInplaceToolbar()
1257
1298
  }
1258
1299
 
1259
1300
  fire(name) {
@@ -1504,7 +1545,7 @@ export default class Umap extends ServerStored {
1504
1545
  this
1505
1546
  )
1506
1547
 
1507
- this.editPanel.open({ content: container })
1548
+ this.editPanel.open({ content: container, highlight: 'layers' })
1508
1549
  }
1509
1550
 
1510
1551
  getDataLayerByUmapId(id) {