umap-project 2.8.2__py3-none-any.whl → 2.9.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.

Files changed (260) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +15 -2
  3. umap/asgi.py +12 -7
  4. umap/context_processors.py +1 -0
  5. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/br/LC_MESSAGES/django.po +111 -67
  7. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/cs_CZ/LC_MESSAGES/django.po +110 -66
  9. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/el/LC_MESSAGES/django.po +129 -85
  11. umap/locale/en/LC_MESSAGES/django.po +103 -60
  12. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/es/LC_MESSAGES/django.po +114 -69
  14. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/fr/LC_MESSAGES/django.po +105 -61
  16. umap/locale/gl/LC_MESSAGES/django.mo +0 -0
  17. umap/locale/gl/LC_MESSAGES/django.po +216 -171
  18. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  19. umap/locale/it/LC_MESSAGES/django.po +142 -98
  20. umap/locale/nl/LC_MESSAGES/django.mo +0 -0
  21. umap/locale/nl/LC_MESSAGES/django.po +196 -151
  22. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  23. umap/locale/pt/LC_MESSAGES/django.po +115 -71
  24. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  25. umap/locale/zh_TW/LC_MESSAGES/django.po +109 -65
  26. umap/management/commands/empty_trash.py +12 -1
  27. umap/migrations/0026_datalayer_modified_at_datalayer_share_status.py +26 -0
  28. umap/models.py +43 -13
  29. umap/settings/base.py +5 -2
  30. umap/static/umap/base.css +5 -2
  31. umap/static/umap/content.css +2 -22
  32. umap/static/umap/css/bar.css +39 -10
  33. umap/static/umap/css/contextmenu.css +14 -2
  34. umap/static/umap/css/form.css +33 -39
  35. umap/static/umap/css/icon.css +47 -5
  36. umap/static/umap/css/panel.css +20 -2
  37. umap/static/umap/css/popup.css +0 -1
  38. umap/static/umap/css/tooltip.css +33 -31
  39. umap/static/umap/img/16-white.svg +5 -3
  40. umap/static/umap/img/16.svg +1 -1
  41. umap/static/umap/img/24-white.svg +17 -16
  42. umap/static/umap/img/24.svg +29 -18
  43. umap/static/umap/img/providers/bitbucket.png +0 -0
  44. umap/static/umap/img/providers/github.png +0 -0
  45. umap/static/umap/img/providers/keycloak.png +0 -0
  46. umap/static/umap/img/providers/openstreetmap-oauth2.png +0 -0
  47. umap/static/umap/img/providers/twitter-oauth2.png +0 -0
  48. umap/static/umap/img/source/16-white.svg +6 -4
  49. umap/static/umap/img/source/16.svg +1 -1
  50. umap/static/umap/img/source/24-white.svg +20 -18
  51. umap/static/umap/img/source/24.svg +30 -19
  52. umap/static/umap/js/components/alerts/alert.js +4 -1
  53. umap/static/umap/js/modules/browser.js +8 -8
  54. umap/static/umap/js/modules/caption.js +30 -7
  55. umap/static/umap/js/modules/data/features.js +101 -56
  56. umap/static/umap/js/modules/data/layer.js +108 -83
  57. umap/static/umap/js/modules/form/builder.js +242 -0
  58. umap/static/umap/js/modules/form/fields.js +1346 -0
  59. umap/static/umap/js/modules/formatter.js +9 -8
  60. umap/static/umap/js/modules/help.js +20 -24
  61. umap/static/umap/js/modules/importer.js +6 -3
  62. umap/static/umap/js/modules/permissions.js +11 -6
  63. umap/static/umap/js/modules/rendering/icon.js +5 -1
  64. umap/static/umap/js/modules/rendering/layers/classified.js +12 -8
  65. umap/static/umap/js/modules/rendering/layers/cluster.js +11 -1
  66. umap/static/umap/js/modules/rendering/map.js +1 -23
  67. umap/static/umap/js/modules/rendering/ui.js +20 -38
  68. umap/static/umap/js/modules/rules.js +3 -2
  69. umap/static/umap/js/modules/saving.js +5 -0
  70. umap/static/umap/js/modules/schema.js +8 -6
  71. umap/static/umap/js/modules/share.js +3 -3
  72. umap/static/umap/js/modules/sync/engine.js +56 -26
  73. umap/static/umap/js/modules/sync/updaters.js +15 -6
  74. umap/static/umap/js/modules/sync/websocket.js +50 -37
  75. umap/static/umap/js/modules/tableeditor.js +3 -2
  76. umap/static/umap/js/modules/ui/bar.js +101 -9
  77. umap/static/umap/js/modules/ui/base.js +7 -24
  78. umap/static/umap/js/modules/ui/contextmenu.js +9 -2
  79. umap/static/umap/js/modules/ui/panel.js +5 -1
  80. umap/static/umap/js/modules/ui/tooltip.js +19 -11
  81. umap/static/umap/js/modules/umap.js +121 -68
  82. umap/static/umap/js/modules/utils.js +196 -12
  83. umap/static/umap/js/umap.controls.js +11 -353
  84. umap/static/umap/locale/am_ET.js +17 -5
  85. umap/static/umap/locale/am_ET.json +17 -5
  86. umap/static/umap/locale/ar.js +17 -5
  87. umap/static/umap/locale/ar.json +17 -5
  88. umap/static/umap/locale/ast.js +17 -5
  89. umap/static/umap/locale/ast.json +17 -5
  90. umap/static/umap/locale/bg.js +17 -5
  91. umap/static/umap/locale/bg.json +17 -5
  92. umap/static/umap/locale/br.js +33 -20
  93. umap/static/umap/locale/br.json +33 -20
  94. umap/static/umap/locale/ca.js +17 -5
  95. umap/static/umap/locale/ca.json +17 -5
  96. umap/static/umap/locale/cs_CZ.js +15 -5
  97. umap/static/umap/locale/cs_CZ.json +15 -5
  98. umap/static/umap/locale/da.js +17 -5
  99. umap/static/umap/locale/da.json +17 -5
  100. umap/static/umap/locale/de.js +17 -5
  101. umap/static/umap/locale/de.json +17 -5
  102. umap/static/umap/locale/el.js +63 -51
  103. umap/static/umap/locale/el.json +63 -51
  104. umap/static/umap/locale/en.js +15 -5
  105. umap/static/umap/locale/en.json +15 -5
  106. umap/static/umap/locale/en_US.json +17 -5
  107. umap/static/umap/locale/es.js +25 -13
  108. umap/static/umap/locale/es.json +25 -13
  109. umap/static/umap/locale/et.js +17 -5
  110. umap/static/umap/locale/et.json +17 -5
  111. umap/static/umap/locale/eu.js +17 -5
  112. umap/static/umap/locale/eu.json +17 -5
  113. umap/static/umap/locale/fa_IR.js +17 -5
  114. umap/static/umap/locale/fa_IR.json +17 -5
  115. umap/static/umap/locale/fi.js +17 -5
  116. umap/static/umap/locale/fi.json +17 -5
  117. umap/static/umap/locale/fr.js +16 -6
  118. umap/static/umap/locale/fr.json +16 -6
  119. umap/static/umap/locale/gl.js +357 -345
  120. umap/static/umap/locale/gl.json +357 -345
  121. umap/static/umap/locale/he.js +17 -5
  122. umap/static/umap/locale/he.json +17 -5
  123. umap/static/umap/locale/hr.js +17 -5
  124. umap/static/umap/locale/hr.json +17 -5
  125. umap/static/umap/locale/hu.js +14 -5
  126. umap/static/umap/locale/hu.json +14 -5
  127. umap/static/umap/locale/id.js +17 -5
  128. umap/static/umap/locale/id.json +17 -5
  129. umap/static/umap/locale/is.js +17 -5
  130. umap/static/umap/locale/is.json +17 -5
  131. umap/static/umap/locale/it.js +125 -113
  132. umap/static/umap/locale/it.json +125 -113
  133. umap/static/umap/locale/ja.js +17 -5
  134. umap/static/umap/locale/ja.json +17 -5
  135. umap/static/umap/locale/ko.js +17 -5
  136. umap/static/umap/locale/ko.json +17 -5
  137. umap/static/umap/locale/lt.js +17 -5
  138. umap/static/umap/locale/lt.json +17 -5
  139. umap/static/umap/locale/ms.js +17 -5
  140. umap/static/umap/locale/ms.json +17 -5
  141. umap/static/umap/locale/nl.js +132 -119
  142. umap/static/umap/locale/nl.json +132 -119
  143. umap/static/umap/locale/no.js +17 -5
  144. umap/static/umap/locale/no.json +17 -5
  145. umap/static/umap/locale/pl.js +17 -5
  146. umap/static/umap/locale/pl.json +17 -5
  147. umap/static/umap/locale/pl_PL.json +17 -5
  148. umap/static/umap/locale/pt.js +38 -25
  149. umap/static/umap/locale/pt.json +38 -25
  150. umap/static/umap/locale/pt_BR.js +17 -5
  151. umap/static/umap/locale/pt_BR.json +17 -5
  152. umap/static/umap/locale/pt_PT.js +17 -5
  153. umap/static/umap/locale/pt_PT.json +17 -5
  154. umap/static/umap/locale/ro.js +17 -5
  155. umap/static/umap/locale/ro.json +17 -5
  156. umap/static/umap/locale/ru.js +17 -5
  157. umap/static/umap/locale/ru.json +17 -5
  158. umap/static/umap/locale/sk_SK.js +17 -5
  159. umap/static/umap/locale/sk_SK.json +17 -5
  160. umap/static/umap/locale/sl.js +17 -5
  161. umap/static/umap/locale/sl.json +17 -5
  162. umap/static/umap/locale/sr.js +17 -5
  163. umap/static/umap/locale/sr.json +17 -5
  164. umap/static/umap/locale/sv.js +17 -5
  165. umap/static/umap/locale/sv.json +17 -5
  166. umap/static/umap/locale/th_TH.js +17 -5
  167. umap/static/umap/locale/th_TH.json +17 -5
  168. umap/static/umap/locale/tr.js +17 -5
  169. umap/static/umap/locale/tr.json +17 -5
  170. umap/static/umap/locale/uk_UA.js +17 -5
  171. umap/static/umap/locale/uk_UA.json +17 -5
  172. umap/static/umap/locale/vi.js +17 -5
  173. umap/static/umap/locale/vi.json +17 -5
  174. umap/static/umap/locale/vi_VN.json +17 -5
  175. umap/static/umap/locale/zh.js +17 -5
  176. umap/static/umap/locale/zh.json +17 -5
  177. umap/static/umap/locale/zh_CN.json +17 -5
  178. umap/static/umap/locale/zh_TW.Big5.json +17 -5
  179. umap/static/umap/locale/zh_TW.js +15 -5
  180. umap/static/umap/locale/zh_TW.json +15 -5
  181. umap/static/umap/map.css +29 -76
  182. umap/static/umap/nav.css +6 -3
  183. umap/static/umap/unittests/utils.js +14 -0
  184. umap/static/umap/vars.css +3 -0
  185. umap/static/umap/vendors/dompurify/purify.es.js +138 -354
  186. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  187. umap/static/umap/vendors/editable/Leaflet.Editable.js +1 -0
  188. umap/sync/__init__.py +0 -0
  189. umap/sync/app.py +187 -0
  190. umap/sync/payloads.py +56 -0
  191. umap/templates/auth/user_detail.html +4 -0
  192. umap/templates/auth/user_form.html +9 -6
  193. umap/templates/auth/user_stars.html +4 -0
  194. umap/templates/base.html +1 -1
  195. umap/templates/registration/login.html +2 -5
  196. umap/templates/umap/about.html +5 -0
  197. umap/templates/umap/about_summary.html +2 -2
  198. umap/templates/umap/components/provider.html +8 -0
  199. umap/templates/umap/content_footer.html +1 -1
  200. umap/templates/umap/css.html +0 -2
  201. umap/templates/umap/js.html +0 -4
  202. umap/templates/umap/map_detail.html +1 -1
  203. umap/templates/umap/password_change.html +4 -0
  204. umap/templates/umap/password_change_done.html +4 -0
  205. umap/templates/umap/search.html +4 -0
  206. umap/templates/umap/search_bar.html +1 -0
  207. umap/templates/umap/team_confirm_delete.html +4 -0
  208. umap/templates/umap/team_detail.html +4 -0
  209. umap/templates/umap/team_form.html +4 -0
  210. umap/templates/umap/user_dashboard.html +1 -1
  211. umap/templates/umap/user_teams.html +4 -0
  212. umap/tests/base.py +3 -1
  213. umap/tests/integration/conftest.py +16 -23
  214. umap/tests/integration/test_anonymous_owned_map.py +2 -2
  215. umap/tests/integration/test_basics.py +4 -7
  216. umap/tests/integration/test_caption.py +1 -0
  217. umap/tests/integration/test_categorized_layer.py +4 -8
  218. umap/tests/integration/test_choropleth.py +1 -1
  219. umap/tests/integration/test_conditional_rules.py +3 -3
  220. umap/tests/integration/test_draw_polygon.py +14 -22
  221. umap/tests/integration/test_draw_polyline.py +6 -14
  222. umap/tests/integration/test_edit_datalayer.py +11 -11
  223. umap/tests/integration/test_edit_map.py +30 -4
  224. umap/tests/integration/test_edit_marker.py +5 -5
  225. umap/tests/integration/test_edit_polygon.py +6 -6
  226. umap/tests/integration/test_features_id_generation.py +2 -6
  227. umap/tests/integration/test_import.py +115 -29
  228. umap/tests/integration/test_optimistic_merge.py +1 -0
  229. umap/tests/integration/test_owned_map.py +1 -1
  230. umap/tests/integration/test_picto.py +8 -8
  231. umap/tests/integration/test_save.py +3 -2
  232. umap/tests/integration/test_star.py +13 -9
  233. umap/tests/integration/test_tableeditor.py +8 -7
  234. umap/tests/integration/test_view_marker.py +10 -0
  235. umap/tests/integration/test_websocket_sync.py +239 -64
  236. umap/tests/settings.py +2 -0
  237. umap/tests/test_datalayer.py +2 -3
  238. umap/tests/test_datalayer_views.py +20 -1
  239. umap/tests/test_empty_trash.py +10 -3
  240. umap/tests/test_map_views.py +11 -0
  241. umap/utils.py +27 -11
  242. umap/views.py +37 -6
  243. {umap_project-2.8.2.dist-info → umap_project-2.9.0.dist-info}/METADATA +22 -22
  244. {umap_project-2.8.2.dist-info → umap_project-2.9.0.dist-info}/RECORD +247 -248
  245. {umap_project-2.8.2.dist-info → umap_project-2.9.0.dist-info}/WHEEL +1 -1
  246. umap/management/commands/run_websocket_server.py +0 -23
  247. umap/settings/local_s3.py +0 -45
  248. umap/static/umap/bitbucket.png +0 -0
  249. umap/static/umap/github.png +0 -0
  250. umap/static/umap/js/umap.forms.js +0 -1242
  251. umap/static/umap/keycloak.png +0 -0
  252. umap/static/umap/openstreetmap.png +0 -0
  253. umap/static/umap/twitter.png +0 -0
  254. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +0 -468
  255. umap/static/umap/vendors/toolbar/leaflet.toolbar.css +0 -1
  256. umap/static/umap/vendors/toolbar/leaflet.toolbar.js +0 -1
  257. umap/tests/test_websocket_server.py +0 -22
  258. umap/websocket_server.py +0 -202
  259. {umap_project-2.8.2.dist-info → umap_project-2.9.0.dist-info}/entry_points.txt +0 -0
  260. {umap_project-2.8.2.dist-info → umap_project-2.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,24 +1,32 @@
1
- import { DomEvent, DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { DomEvent } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
2
  import { translate } from '../i18n.js'
3
3
  import { Positioned } from './base.js'
4
+ import * as Utils from '../utils.js'
4
5
 
5
6
  export default class Tooltip extends Positioned {
6
7
  constructor(parent) {
7
8
  super()
8
9
  this.parent = parent
9
- this.container = DomUtil.create('div', 'with-transition', this.parent)
10
- this.container.id = 'umap-tooltip-container'
10
+ this.container = Utils.loadTemplate('<div class="umap-tooltip-container"></div>')
11
+ this.parent.appendChild(this.container)
11
12
  DomEvent.disableClickPropagation(this.container)
12
- DomEvent.on(this.container, 'contextmenu', DomEvent.stopPropagation) // Do not activate our custom context menu.
13
- DomEvent.on(this.container, 'wheel', DomEvent.stopPropagation)
14
- DomEvent.on(this.container, 'MozMousePixelScroll', DomEvent.stopPropagation)
13
+ this.container.addEventListener('contextmenu', (event) => event.stopPropagation()) // Do not activate our custom context menu.
14
+ this.container.addEventListener('wheel', (event) => event.stopPropagation())
15
+ this.container.addEventListener('MozMousePixelScroll', (event) =>
16
+ event.stopPropagation()
17
+ )
15
18
  }
16
19
 
17
20
  open(opts) {
21
+ this.container.classList.toggle('tooltip-accent', Boolean(opts.accent))
18
22
  const showIt = () => {
23
+ if (opts.content.nodeType === 1) {
24
+ this.container.appendChild(opts.content)
25
+ } else {
26
+ this.container.innerHTML = Utils.escapeHTML(opts.content)
27
+ }
28
+ this.parent.classList.add('umap-tooltip')
19
29
  this.openAt(opts)
20
- L.DomUtil.addClass(this.parent, 'umap-tooltip')
21
- this.container.innerHTML = U.Utils.escapeHTML(opts.content)
22
30
  }
23
31
  this.TOOLTIP_ID = window.setTimeout(L.bind(showIt, this), opts.delay || 0)
24
32
  const id = this.TOOLTIP_ID
@@ -26,7 +34,7 @@ export default class Tooltip extends Positioned {
26
34
  this.close(id)
27
35
  }
28
36
  if (opts.anchor) {
29
- L.DomEvent.once(opts.anchor, 'mouseout', closeIt)
37
+ opts.anchor.addEventListener('mouseout', closeIt, { once: true })
30
38
  }
31
39
  if (opts.duration !== Number.POSITIVE_INFINITY) {
32
40
  window.setTimeout(closeIt, opts.duration || 3000)
@@ -38,9 +46,9 @@ export default class Tooltip extends Positioned {
38
46
  // in the meantime. Eg. after a mouseout from the anchor.
39
47
  window.clearTimeout(id)
40
48
  if (id && id !== this.TOOLTIP_ID) return
41
- this.container.className = ''
49
+ this.toggleClassPosition()
42
50
  this.container.innerHTML = ''
43
51
  this.setPosition({})
44
- L.DomUtil.removeClass(this.parent, 'umap-tooltip')
52
+ this.parent.classList.remove('umap-tooltip')
45
53
  }
46
54
  }
@@ -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'
@@ -34,6 +34,7 @@ import {
34
34
  uMapAlert as Alert,
35
35
  } from '../components/alerts/alert.js'
36
36
  import Orderable from './orderable.js'
37
+ import { MutatingForm } from './form/builder.js'
37
38
 
38
39
  export default class Umap extends ServerStored {
39
40
  constructor(element, geojson) {
@@ -91,7 +92,8 @@ export default class Umap extends ServerStored {
91
92
  fullscreenControl !== undefined ? fullscreenControl : true
92
93
 
93
94
  if (center) {
94
- this._leafletMap.options.center = this._leafletMap.latLng(center)
95
+ this._leafletMap.options.center = this.properties.center =
96
+ this._leafletMap.latLng(center)
95
97
  }
96
98
 
97
99
  // Needed to render controls
@@ -111,8 +113,14 @@ export default class Umap extends ServerStored {
111
113
  this.slideshow,
112
114
  this._leafletMap._controlContainer
113
115
  )
116
+ this.editBar = new EditBar(
117
+ this,
118
+ this._leafletMap,
119
+ this._leafletMap._controlContainer
120
+ )
114
121
  this.tooltip = new Tooltip(this._leafletMap._controlContainer)
115
122
  this.contextmenu = new ContextMenu()
123
+ this.editContextmenu = new ContextMenu({ className: 'dark', orientation: 'rows' })
116
124
  this.server = new ServerRequest()
117
125
  this.request = new Request()
118
126
  this.facets = new Facets(this)
@@ -130,6 +138,7 @@ export default class Umap extends ServerStored {
130
138
  this.fullPanel = new FullPanel(this, this._leafletMap)
131
139
  this._leafletMap.initEditTools()
132
140
  this.topBar.setup()
141
+ this.editBar.setup()
133
142
  }
134
143
 
135
144
  this.datalayersFromQueryString = this.searchParams.get('datalayers')
@@ -540,7 +549,13 @@ export default class Umap extends ServerStored {
540
549
  if (SAVEMANAGER.isDirty) this.saveAll()
541
550
  break
542
551
  case 'z':
543
- if (SAVEMANAGER.isDirty) this.askForReset()
552
+ if (Utils.isWritable(event.target)) {
553
+ used = false
554
+ break
555
+ }
556
+ if (SAVEMANAGER.isDirty) {
557
+ this.askForReset()
558
+ }
544
559
  break
545
560
  case 'm':
546
561
  this._leafletMap.editTools.startMarker()
@@ -670,6 +685,7 @@ export default class Umap extends ServerStored {
670
685
  Alert.success(translate('Map has been saved!'))
671
686
  })
672
687
  }
688
+ this.sync.saved()
673
689
  this.fire('saved')
674
690
  }
675
691
 
@@ -730,11 +746,11 @@ export default class Umap extends ServerStored {
730
746
  editCaption() {
731
747
  if (!this.editEnabled) return
732
748
  if (this.properties.editMode !== 'advanced') return
733
- const container = DomUtil.create('div', 'umap-edit-container')
749
+ const container = DomUtil.create('div')
734
750
  const metadataFields = ['properties.name', 'properties.description']
735
751
 
736
752
  DomUtil.createTitle(container, translate('Edit map details'), 'icon-caption')
737
- const builder = new U.FormBuilder(this, metadataFields, {
753
+ const builder = new MutatingForm(this, metadataFields, {
738
754
  className: 'map-metadata',
739
755
  umap: this,
740
756
  })
@@ -749,9 +765,44 @@ export default class Umap extends ServerStored {
749
765
  'properties.permanentCredit',
750
766
  'properties.permanentCreditBackground',
751
767
  ]
752
- const creditsBuilder = new U.FormBuilder(this, creditsFields, { umap: this })
768
+ const creditsBuilder = new MutatingForm(this, creditsFields, { umap: this })
753
769
  credits.appendChild(creditsBuilder.build())
754
- 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' })
755
806
  }
756
807
 
757
808
  _editControls(container) {
@@ -765,12 +816,11 @@ export default class Umap extends ServerStored {
765
816
  'properties.miniMap',
766
817
  'properties.scaleControl',
767
818
  'properties.onLoadPanel',
768
- 'properties.defaultView',
769
819
  'properties.displayPopupFooter',
770
820
  'properties.captionBar',
771
821
  'properties.captionMenus',
772
822
  ])
773
- const builder = new U.FormBuilder(this, UIFields, { umap: this })
823
+ const builder = new MutatingForm(this, UIFields, { umap: this })
774
824
  const controlsOptions = DomUtil.createFieldset(
775
825
  container,
776
826
  translate('User interface options')
@@ -793,7 +843,7 @@ export default class Umap extends ServerStored {
793
843
  'properties.dashArray',
794
844
  ]
795
845
 
796
- const builder = new U.FormBuilder(this, shapeOptions, { umap: this })
846
+ const builder = new MutatingForm(this, shapeOptions, { umap: this })
797
847
  const defaultShapeProperties = DomUtil.createFieldset(
798
848
  container,
799
849
  translate('Default shape properties')
@@ -812,7 +862,7 @@ export default class Umap extends ServerStored {
812
862
  'properties.slugKey',
813
863
  ]
814
864
 
815
- const builder = new U.FormBuilder(this, optionsFields, { umap: this })
865
+ const builder = new MutatingForm(this, optionsFields, { umap: this })
816
866
  const defaultProperties = DomUtil.createFieldset(
817
867
  container,
818
868
  translate('Default properties')
@@ -830,7 +880,7 @@ export default class Umap extends ServerStored {
830
880
  'properties.labelInteractive',
831
881
  'properties.outlinkTarget',
832
882
  ]
833
- const builder = new U.FormBuilder(this, popupFields, { umap: this })
883
+ const builder = new MutatingForm(this, popupFields, { umap: this })
834
884
  const popupFieldset = DomUtil.createFieldset(
835
885
  container,
836
886
  translate('Default interaction options')
@@ -887,7 +937,7 @@ export default class Umap extends ServerStored {
887
937
  container,
888
938
  translate('Custom background')
889
939
  )
890
- const builder = new U.FormBuilder(this, tilelayerFields, { umap: this })
940
+ const builder = new MutatingForm(this, tilelayerFields, { umap: this })
891
941
  customTilelayer.appendChild(builder.build())
892
942
  }
893
943
 
@@ -935,7 +985,7 @@ export default class Umap extends ServerStored {
935
985
  ['properties.overlay.tms', { handler: 'Switch', label: translate('TMS format') }],
936
986
  ]
937
987
  const overlay = DomUtil.createFieldset(container, translate('Custom overlay'))
938
- const builder = new U.FormBuilder(this, overlayFields, { umap: this })
988
+ const builder = new MutatingForm(this, overlayFields, { umap: this })
939
989
  overlay.appendChild(builder.build())
940
990
  }
941
991
 
@@ -962,7 +1012,7 @@ export default class Umap extends ServerStored {
962
1012
  { handler: 'BlurFloatInput', placeholder: translate('max East') },
963
1013
  ],
964
1014
  ]
965
- const boundsBuilder = new U.FormBuilder(this, boundsFields, { umap: this })
1015
+ const boundsBuilder = new MutatingForm(this, boundsFields, { umap: this })
966
1016
  limitBounds.appendChild(boundsBuilder.build())
967
1017
  const boundsButtons = DomUtil.create('div', 'button-bar half', limitBounds)
968
1018
  DomUtil.createButton(
@@ -1027,14 +1077,7 @@ export default class Umap extends ServerStored {
1027
1077
  { handler: 'Switch', label: translate('Autostart when map is loaded') },
1028
1078
  ],
1029
1079
  ]
1030
- const slideshowBuilder = new U.FormBuilder(this, slideshowFields, {
1031
- callback: () => {
1032
- this.slideshow.load()
1033
- // FIXME when we refactor formbuilder: this callback is called in a 'postsync'
1034
- // event, which comes after the call of `setter` method, which will call the
1035
- // map.render method, which should do this redraw.
1036
- this.bottomBar.redraw()
1037
- },
1080
+ const slideshowBuilder = new MutatingForm(this, slideshowFields, {
1038
1081
  umap: this,
1039
1082
  })
1040
1083
  slideshow.appendChild(slideshowBuilder.build())
@@ -1042,7 +1085,9 @@ export default class Umap extends ServerStored {
1042
1085
 
1043
1086
  _editSync(container) {
1044
1087
  const sync = DomUtil.createFieldset(container, translate('Real-time collaboration'))
1045
- const builder = new U.FormBuilder(this, ['properties.syncEnabled'], { umap: this })
1088
+ const builder = new MutatingForm(this, ['properties.syncEnabled'], {
1089
+ umap: this,
1090
+ })
1046
1091
  sync.appendChild(builder.build())
1047
1092
  }
1048
1093
 
@@ -1051,44 +1096,38 @@ export default class Umap extends ServerStored {
1051
1096
  container,
1052
1097
  translate('Advanced actions')
1053
1098
  )
1054
- const advancedButtons = DomUtil.create('div', 'button-bar half', advancedActions)
1055
- if (this.permissions.isOwner()) {
1056
- const deleteButton = Utils.loadTemplate(`
1057
- <button class="button" type="button">
1099
+ const tpl = `
1100
+ <div class="button-bar half">
1101
+ <button class="button" type="button" data-ref=del hidden>
1058
1102
  <i class="icon icon-24 icon-delete"></i>${translate('Delete')}
1059
- </button>`)
1060
- deleteButton.addEventListener('click', () => this.del())
1061
- advancedButtons.appendChild(deleteButton)
1062
-
1063
- DomUtil.createButton(
1064
- 'button umap-empty',
1065
- advancedButtons,
1066
- translate('Clear data'),
1067
- this.emptyDataLayers,
1068
- this
1069
- )
1070
- DomUtil.createButton(
1071
- 'button umap-empty',
1072
- advancedButtons,
1073
- translate('Remove layers'),
1074
- this.removeDataLayers,
1075
- this
1076
- )
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())
1077
1128
  }
1078
- DomUtil.createButton(
1079
- 'button umap-clone',
1080
- advancedButtons,
1081
- translate('Clone this map'),
1082
- this.clone,
1083
- this
1084
- )
1085
- DomUtil.createButton(
1086
- 'button umap-download',
1087
- advancedButtons,
1088
- translate('Open share & download panel'),
1089
- this.share.open,
1090
- this.share
1091
- )
1129
+ clone.addEventListener('click', () => this.clone())
1130
+ download.addEventListener('click', () => this.share.open())
1092
1131
  }
1093
1132
 
1094
1133
  edit() {
@@ -1109,12 +1148,16 @@ export default class Umap extends ServerStored {
1109
1148
  this._editOverlay(container)
1110
1149
  this._editBounds(container)
1111
1150
  this._editSlideshow(container)
1112
- if (this.properties.websocketEnabled) {
1151
+ if (this.properties.websocketEnabled && this.id) {
1113
1152
  this._editSync(container)
1114
1153
  }
1115
1154
  this._advancedActions(container)
1116
1155
 
1117
- this.editPanel.open({ content: container, className: 'dark' })
1156
+ this.editPanel.open({
1157
+ content: container,
1158
+ className: 'dark',
1159
+ highlight: 'settings',
1160
+ })
1118
1161
  }
1119
1162
 
1120
1163
  reset() {
@@ -1234,6 +1277,7 @@ export default class Umap extends ServerStored {
1234
1277
  }
1235
1278
 
1236
1279
  enableEdit() {
1280
+ this.editBar.redraw()
1237
1281
  document.body.classList.add('umap-edit-enabled')
1238
1282
  this.editEnabled = true
1239
1283
  this.drop.enable()
@@ -1251,7 +1295,6 @@ export default class Umap extends ServerStored {
1251
1295
  this.editPanel.close()
1252
1296
  this.fullPanel.close()
1253
1297
  this.sync.stop()
1254
- this._leafletMap.closeInplaceToolbar()
1255
1298
  }
1256
1299
 
1257
1300
  fire(name) {
@@ -1259,6 +1302,7 @@ export default class Umap extends ServerStored {
1259
1302
  }
1260
1303
 
1261
1304
  askForReset(e) {
1305
+ if (this.getProperty('syncEnabled')) return
1262
1306
  this.dialog
1263
1307
  .confirm(translate('Are you sure you want to cancel your changes?'))
1264
1308
  .then(() => {
@@ -1347,10 +1391,14 @@ export default class Umap extends ServerStored {
1347
1391
  }
1348
1392
  this.topBar.redraw()
1349
1393
  },
1394
+ 'properties.slideshow.active': () => {
1395
+ this.slideshow.load()
1396
+ this.bottomBar.redraw()
1397
+ },
1350
1398
  numberOfConnectedPeers: () => {
1351
1399
  Utils.eachElement('.connected-peers span', (el) => {
1352
1400
  if (this.sync.websocketConnected) {
1353
- el.textContent = this.sync.getNumberOfConnectedPeers()
1401
+ el.textContent = Object.keys(this.sync.getPeers()).length
1354
1402
  } else {
1355
1403
  el.textContent = translate('Disconnected')
1356
1404
  }
@@ -1359,7 +1407,11 @@ export default class Umap extends ServerStored {
1359
1407
  },
1360
1408
  'properties.starred': () => {
1361
1409
  Utils.eachElement('.map-star', (el) => {
1362
- el.classList.toggle('starred', this.properties.starred)
1410
+ el.classList.toggle('icon-starred', this.properties.starred)
1411
+ el.classList.toggle('icon-star', !this.properties.starred)
1412
+ })
1413
+ Utils.eachElement('.map-stars', (el) => {
1414
+ el.textContent = this.properties.stars || 0
1363
1415
  })
1364
1416
  },
1365
1417
  }
@@ -1439,7 +1491,7 @@ export default class Umap extends ServerStored {
1439
1491
 
1440
1492
  removeDataLayers() {
1441
1493
  this.eachDataLayerReverse((datalayer) => {
1442
- datalayer._delete()
1494
+ datalayer.del()
1443
1495
  })
1444
1496
  }
1445
1497
 
@@ -1458,7 +1510,7 @@ export default class Umap extends ServerStored {
1458
1510
  const row = DomUtil.create('li', 'orderable', ul)
1459
1511
  DomUtil.createIcon(row, 'icon-drag', translate('Drag to reorder'))
1460
1512
  datalayer.renderToolbox(row)
1461
- const builder = new U.FormBuilder(
1513
+ const builder = new MutatingForm(
1462
1514
  datalayer,
1463
1515
  [['options.name', { handler: 'EditableText' }]],
1464
1516
  { className: 'umap-form-inline' }
@@ -1493,7 +1545,7 @@ export default class Umap extends ServerStored {
1493
1545
  this
1494
1546
  )
1495
1547
 
1496
- this.editPanel.open({ content: container })
1548
+ this.editPanel.open({ content: container, highlight: 'layers' })
1497
1549
  }
1498
1550
 
1499
1551
  getDataLayerByUmapId(id) {
@@ -1542,6 +1594,7 @@ export default class Umap extends ServerStored {
1542
1594
  return
1543
1595
  }
1544
1596
  this.properties.starred = data.starred
1597
+ this.properties.stars = data.stars
1545
1598
  Alert.success(
1546
1599
  data.starred
1547
1600
  ? translate('Map has been starred')