umap-project 3.4.0b3__py3-none-any.whl → 3.6.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.
Files changed (222) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/br/LC_MESSAGES/django.po +71 -57
  4. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/da/LC_MESSAGES/django.po +18 -14
  6. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/de/LC_MESSAGES/django.po +20 -16
  8. umap/locale/en/LC_MESSAGES/django.po +18 -14
  9. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/es/LC_MESSAGES/django.po +20 -16
  11. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/fr/LC_MESSAGES/django.po +18 -14
  13. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  14. umap/locale/hu/LC_MESSAGES/django.po +20 -16
  15. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  16. umap/locale/pl/LC_MESSAGES/django.po +101 -95
  17. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/zh_TW/LC_MESSAGES/django.po +20 -16
  19. umap/management/commands/clean_tilelayer.py +0 -1
  20. umap/management/commands/search_maps.py +95 -0
  21. umap/settings/__init__.py +9 -1
  22. umap/settings/base.py +7 -6
  23. umap/static/umap/content.css +0 -3
  24. umap/static/umap/css/bar.css +9 -6
  25. umap/static/umap/css/form.css +25 -9
  26. umap/static/umap/css/icon.css +8 -0
  27. umap/static/umap/css/popup.css +1 -0
  28. umap/static/umap/img/16-white.svg +5 -2
  29. umap/static/umap/img/16.svg +1 -1
  30. umap/static/umap/img/source/16-white.svg +7 -4
  31. umap/static/umap/img/source/16.svg +1 -1
  32. umap/static/umap/js/components/copiable.js +47 -0
  33. umap/static/umap/js/modules/autocomplete.js +32 -67
  34. umap/static/umap/js/modules/browser.js +31 -14
  35. umap/static/umap/js/modules/data/features.js +34 -36
  36. umap/static/umap/js/modules/data/fields.js +199 -23
  37. umap/static/umap/js/modules/data/layer.js +85 -96
  38. umap/static/umap/js/modules/domutils.js +25 -1
  39. umap/static/umap/js/modules/filters.js +24 -50
  40. umap/static/umap/js/modules/form/builder.js +17 -16
  41. umap/static/umap/js/modules/form/fields.js +20 -20
  42. umap/static/umap/js/modules/formatter.js +9 -1
  43. umap/static/umap/js/modules/help.js +12 -13
  44. umap/static/umap/js/modules/importer.js +17 -26
  45. umap/static/umap/js/modules/importers/banfr.js +0 -1
  46. umap/static/umap/js/modules/importers/cadastrefr.js +19 -19
  47. umap/static/umap/js/modules/importers/communesfr.js +7 -8
  48. umap/static/umap/js/modules/importers/datasets.js +14 -14
  49. umap/static/umap/js/modules/importers/geodatamine.js +20 -22
  50. umap/static/umap/js/modules/importers/opendata.js +10 -0
  51. umap/static/umap/js/modules/importers/overpass.js +19 -18
  52. umap/static/umap/js/modules/managers.js +1 -1
  53. umap/static/umap/js/modules/permissions.js +15 -5
  54. umap/static/umap/js/modules/rendering/controls.js +203 -10
  55. umap/static/umap/js/modules/rendering/icon.js +5 -9
  56. umap/static/umap/js/modules/rendering/layers/base.js +1 -1
  57. umap/static/umap/js/modules/rendering/layers/classified.js +16 -11
  58. umap/static/umap/js/modules/rendering/layers/heat.js +1 -0
  59. umap/static/umap/js/modules/rendering/map.js +67 -57
  60. umap/static/umap/js/modules/rendering/popup.js +6 -3
  61. umap/static/umap/js/modules/rendering/template.js +40 -40
  62. umap/static/umap/js/modules/rendering/ui.js +1 -2
  63. umap/static/umap/js/modules/rules.js +34 -41
  64. umap/static/umap/js/modules/schema.js +0 -7
  65. umap/static/umap/js/modules/share.js +36 -69
  66. umap/static/umap/js/modules/slideshow.js +3 -3
  67. umap/static/umap/js/modules/tableeditor.js +0 -1
  68. umap/static/umap/js/modules/ui/bar.js +53 -33
  69. umap/static/umap/js/modules/ui/hash.js +36 -0
  70. umap/static/umap/js/modules/ui/loader.js +26 -0
  71. umap/static/umap/js/modules/ui/panel.js +33 -21
  72. umap/static/umap/js/modules/ui/tooltip.js +1 -1
  73. umap/static/umap/js/modules/umap.js +81 -80
  74. umap/static/umap/js/modules/utils.js +13 -3
  75. umap/static/umap/js/umap.controls.js +16 -179
  76. umap/static/umap/locale/am_ET.js +7 -8
  77. umap/static/umap/locale/am_ET.json +7 -8
  78. umap/static/umap/locale/ar.js +7 -8
  79. umap/static/umap/locale/ar.json +7 -8
  80. umap/static/umap/locale/ast.js +7 -8
  81. umap/static/umap/locale/ast.json +7 -8
  82. umap/static/umap/locale/bg.js +7 -8
  83. umap/static/umap/locale/bg.json +7 -8
  84. umap/static/umap/locale/br.js +44 -36
  85. umap/static/umap/locale/br.json +44 -36
  86. umap/static/umap/locale/ca.js +7 -8
  87. umap/static/umap/locale/ca.json +7 -8
  88. umap/static/umap/locale/cs_CZ.js +7 -8
  89. umap/static/umap/locale/cs_CZ.json +7 -8
  90. umap/static/umap/locale/da.js +8 -9
  91. umap/static/umap/locale/da.json +8 -9
  92. umap/static/umap/locale/de.js +62 -63
  93. umap/static/umap/locale/de.json +62 -63
  94. umap/static/umap/locale/el.js +7 -8
  95. umap/static/umap/locale/el.json +7 -8
  96. umap/static/umap/locale/en.js +7 -8
  97. umap/static/umap/locale/en.json +7 -8
  98. umap/static/umap/locale/en_US.json +7 -8
  99. umap/static/umap/locale/es.js +19 -20
  100. umap/static/umap/locale/es.json +19 -20
  101. umap/static/umap/locale/et.js +7 -8
  102. umap/static/umap/locale/et.json +7 -8
  103. umap/static/umap/locale/eu.js +23 -24
  104. umap/static/umap/locale/eu.json +23 -24
  105. umap/static/umap/locale/fa_IR.js +7 -8
  106. umap/static/umap/locale/fa_IR.json +7 -8
  107. umap/static/umap/locale/fi.js +7 -8
  108. umap/static/umap/locale/fi.json +7 -8
  109. umap/static/umap/locale/fr.js +11 -12
  110. umap/static/umap/locale/fr.json +11 -12
  111. umap/static/umap/locale/gl.js +147 -148
  112. umap/static/umap/locale/gl.json +147 -148
  113. umap/static/umap/locale/he.js +7 -8
  114. umap/static/umap/locale/he.json +7 -8
  115. umap/static/umap/locale/hr.js +7 -8
  116. umap/static/umap/locale/hr.json +7 -8
  117. umap/static/umap/locale/hu.js +8 -9
  118. umap/static/umap/locale/hu.json +8 -9
  119. umap/static/umap/locale/id.js +7 -8
  120. umap/static/umap/locale/id.json +7 -8
  121. umap/static/umap/locale/is.js +7 -8
  122. umap/static/umap/locale/is.json +7 -8
  123. umap/static/umap/locale/it.js +7 -8
  124. umap/static/umap/locale/it.json +7 -8
  125. umap/static/umap/locale/ja.js +7 -8
  126. umap/static/umap/locale/ja.json +7 -8
  127. umap/static/umap/locale/ko.js +7 -8
  128. umap/static/umap/locale/ko.json +7 -8
  129. umap/static/umap/locale/lt.js +7 -8
  130. umap/static/umap/locale/lt.json +7 -8
  131. umap/static/umap/locale/ms.js +7 -8
  132. umap/static/umap/locale/ms.json +7 -8
  133. umap/static/umap/locale/nl.js +7 -8
  134. umap/static/umap/locale/nl.json +7 -8
  135. umap/static/umap/locale/no.js +7 -8
  136. umap/static/umap/locale/no.json +7 -8
  137. umap/static/umap/locale/pl.js +53 -54
  138. umap/static/umap/locale/pl.json +53 -54
  139. umap/static/umap/locale/pl_PL.json +7 -8
  140. umap/static/umap/locale/pt.js +7 -8
  141. umap/static/umap/locale/pt.json +7 -8
  142. umap/static/umap/locale/pt_BR.js +7 -8
  143. umap/static/umap/locale/pt_BR.json +7 -8
  144. umap/static/umap/locale/pt_PT.js +7 -8
  145. umap/static/umap/locale/pt_PT.json +7 -8
  146. umap/static/umap/locale/ro.js +7 -8
  147. umap/static/umap/locale/ro.json +7 -8
  148. umap/static/umap/locale/ru.js +7 -8
  149. umap/static/umap/locale/ru.json +7 -8
  150. umap/static/umap/locale/sk_SK.js +7 -8
  151. umap/static/umap/locale/sk_SK.json +7 -8
  152. umap/static/umap/locale/sl.js +7 -8
  153. umap/static/umap/locale/sl.json +7 -8
  154. umap/static/umap/locale/sr.js +7 -8
  155. umap/static/umap/locale/sr.json +7 -8
  156. umap/static/umap/locale/sv.js +7 -8
  157. umap/static/umap/locale/sv.json +7 -8
  158. umap/static/umap/locale/th_TH.js +7 -8
  159. umap/static/umap/locale/th_TH.json +7 -8
  160. umap/static/umap/locale/tr.js +7 -8
  161. umap/static/umap/locale/tr.json +7 -8
  162. umap/static/umap/locale/uk_UA.js +7 -8
  163. umap/static/umap/locale/uk_UA.json +7 -8
  164. umap/static/umap/locale/vi.js +7 -8
  165. umap/static/umap/locale/vi.json +7 -8
  166. umap/static/umap/locale/vi_VN.json +7 -8
  167. umap/static/umap/locale/zh.js +7 -8
  168. umap/static/umap/locale/zh.json +7 -8
  169. umap/static/umap/locale/zh_CN.json +7 -8
  170. umap/static/umap/locale/zh_TW.Big5.json +7 -8
  171. umap/static/umap/locale/zh_TW.js +20 -21
  172. umap/static/umap/locale/zh_TW.json +20 -21
  173. umap/static/umap/map.css +6 -21
  174. umap/static/umap/unittests/utils.js +7 -7
  175. umap/static/umap/vendors/locatecontrol/L.Control.Locate.esm.js +942 -0
  176. umap/static/umap/vendors/photon/leaflet.photon.esm.js +472 -0
  177. umap/sync/app.py +4 -1
  178. umap/templates/umap/content_footer.html +1 -0
  179. umap/templates/umap/css.html +0 -4
  180. umap/templates/umap/js.html +1 -8
  181. umap/templates/umap/team_form.html +2 -1
  182. umap/tests/integration/conftest.py +3 -2
  183. umap/tests/integration/test_anonymous_owned_map.py +1 -1
  184. umap/tests/integration/test_conditional_rules.py +106 -51
  185. umap/tests/integration/test_draw_polygon.py +4 -0
  186. umap/tests/integration/test_draw_polyline.py +11 -0
  187. umap/tests/integration/test_edit_datalayer.py +1 -1
  188. umap/tests/integration/test_edit_map.py +2 -0
  189. umap/tests/integration/test_fields.py +19 -0
  190. umap/tests/integration/test_filters.py +24 -0
  191. umap/tests/integration/test_iframe.py +1 -1
  192. umap/tests/integration/test_import.py +26 -0
  193. umap/tests/integration/test_map.py +3 -3
  194. umap/tests/integration/test_optimistic_merge.py +7 -1
  195. umap/tests/integration/test_owned_map.py +2 -2
  196. umap/tests/integration/test_popup.py +31 -0
  197. umap/tests/integration/test_remote_data.py +5 -5
  198. umap/tests/integration/test_search.py +41 -0
  199. umap/tests/integration/test_share.py +2 -2
  200. umap/tests/integration/test_team.py +1 -1
  201. umap/tests/integration/test_websocket_sync.py +6 -1
  202. umap/tests/test_search_maps_command.py +44 -0
  203. umap/tests/test_utils.py +4 -1
  204. umap/utils.py +10 -3
  205. umap/views.py +17 -4
  206. {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/METADATA +29 -23
  207. {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/RECORD +210 -214
  208. {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/WHEEL +1 -1
  209. umap/static/umap/js/umap.core.js +0 -93
  210. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.css +0 -46
  211. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.js +0 -240
  212. umap/static/umap/vendors/editinosm/edit-in-osm.png +0 -0
  213. umap/static/umap/vendors/hash/leaflet-hash.js +0 -162
  214. umap/static/umap/vendors/loading/Control.Loading.css +0 -26
  215. umap/static/umap/vendors/loading/Control.Loading.js +0 -351
  216. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css +0 -1
  217. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css.map +0 -1
  218. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +0 -4
  219. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +0 -1
  220. umap/static/umap/vendors/photon/leaflet.photon.js +0 -487
  221. {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/entry_points.txt +0 -0
  222. {umap_project-3.4.0b3.dist-info → umap_project-3.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,47 @@
1
+ import Umap from '../modules/umap.js'
2
+ import * as DOMUtils from '../modules/domutils.js'
3
+ import * as Utils from '../modules/utils.js'
4
+ import { translate } from '../modules/i18n.js'
5
+
6
+ class CopiableInput extends HTMLElement {
7
+ connectedCallback() {
8
+ DOMUtils.copiableInput(this, this.dataset.label, this.dataset.value || '')
9
+ }
10
+ }
11
+
12
+ class CopiableTextarea extends HTMLElement {
13
+ static get observedAttributes() {
14
+ return ['value']
15
+ }
16
+
17
+ constructor() {
18
+ super()
19
+ const id = `copiable-${Utils.generateId()}`
20
+ this.innerHTML = `
21
+ <div class="copiable-textarea">
22
+ <label for="${id}">${this.dataset.label}</label>
23
+ <div>
24
+ <textarea type="text" id="${id}" readOnly>${this.value}</textarea>
25
+ <button type="button" class="icon icon-24 icon-copy" title="${translate('copy')}" data-ref=button></button>
26
+ </div>
27
+ </div>
28
+ `
29
+ this.textarea = this.querySelector('textarea')
30
+ this.button = this.querySelector('button')
31
+ this.button.addEventListener('click', () =>
32
+ DOMUtils.copyToClipboard(this.textarea.textContent)
33
+ )
34
+ }
35
+ attributeChangedCallback(name, oldValue, newValue) {
36
+ this.textarea.textContent = newValue
37
+ }
38
+ }
39
+
40
+ function register(Class, tagName) {
41
+ if ('customElements' in window && !customElements.get(tagName)) {
42
+ customElements.define(tagName, Class)
43
+ }
44
+ }
45
+
46
+ register(CopiableInput, 'copiable-input')
47
+ register(CopiableTextarea, 'copiable-textarea')
@@ -1,13 +1,9 @@
1
- import {
2
- DomEvent,
3
- DomUtil,
4
- Util,
5
- setOptions,
6
- } from '../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { DomEvent, Util, setOptions } from '../../vendors/leaflet/leaflet-src.esm.js'
7
2
  import { translate } from './i18n.js'
8
3
  import { Request, ServerRequest } from './request.js'
9
4
  import { escapeHTML, generateId } from './utils.js'
10
5
  import * as Utils from './utils.js'
6
+ import * as DOMUtils from './domutils.js'
11
7
 
12
8
  export class BaseAutocomplete {
13
9
  constructor(parent, options) {
@@ -41,26 +37,18 @@ export class BaseAutocomplete {
41
37
  }
42
38
 
43
39
  createInput() {
44
- this.input = DomUtil.element({
45
- tagName: 'input',
46
- type: 'text',
47
- parent: this.parent,
48
- placeholder: this.options.placeholder,
49
- autocomplete: 'off',
50
- className: this.options.className,
51
- name: this.options.name || 'autocomplete',
52
- })
53
- DomEvent.on(this.input, 'keydown', this.onKeyDown, this)
54
- DomEvent.on(this.input, 'keyup', this.onKeyUp, this)
55
- DomEvent.on(this.input, 'blur', this.onBlur, this)
40
+ this.input = DOMUtils.loadTemplate(`
41
+ <input type="text" placeholder="${this.options.placeholder}" autocomplete="off" class="${this.options.className}" name="${this.options.name || 'autocomplete'}">
42
+ `)
43
+ this.parent.appendChild(this.input)
44
+ this.input.addEventListener('keydown', (event) => this.onKeyDown(event))
45
+ this.input.addEventListener('keyup', (event) => this.onKeyUp(event))
46
+ this.input.addEventListener('blur', (event) => this.onBlur(event))
56
47
  }
57
48
 
58
49
  createContainer() {
59
- this.container = DomUtil.element({
60
- tagName: 'ul',
61
- parent: document.body,
62
- className: 'umap-autocomplete',
63
- })
50
+ this.container = DOMUtils.loadTemplate('<ul class="umap-autocomplete"></ul>')
51
+ document.body.appendChild(this.container)
64
52
  }
65
53
 
66
54
  resizeContainer() {
@@ -167,20 +155,17 @@ export class BaseAutocomplete {
167
155
  }
168
156
 
169
157
  createResult(item) {
170
- const el = DomUtil.element({
171
- tagName: 'li',
172
- parent: this.container,
173
- textContent: item.label,
174
- })
158
+ const li = DOMUtils.loadTemplate(`<li>${item.label}</li>`)
159
+ this.container.appendChild(li)
175
160
  const result = {
176
161
  item: item,
177
- el: el,
162
+ el: li,
178
163
  }
179
- DomEvent.on(el, 'mouseover', () => {
164
+ li.addEventListener('mouseover', () => {
180
165
  this.current = result
181
166
  this.highlight()
182
167
  })
183
- DomEvent.on(el, 'mousedown', () => this.setChoice())
168
+ li.addEventListener('mousedown', () => this.setChoice())
184
169
  return result
185
170
  }
186
171
 
@@ -202,8 +187,7 @@ export class BaseAutocomplete {
202
187
 
203
188
  highlight() {
204
189
  this.results.forEach((result, index) => {
205
- if (index === this.current) DomUtil.addClass(result.el, 'on')
206
- else DomUtil.removeClass(result.el, 'on')
190
+ result.el.classList.toggle('on', index === this.current)
207
191
  })
208
192
  }
209
193
 
@@ -231,14 +215,10 @@ export class BaseAutocomplete {
231
215
  export class BaseAjax extends BaseAutocomplete {
232
216
  constructor(el, options) {
233
217
  super(el, options)
234
- this.setUrl()
218
+ this.url = this.options.url
235
219
  this.initRequest()
236
220
  }
237
221
 
238
- setUrl() {
239
- this.url = this.options?.url
240
- }
241
-
242
222
  initRequest() {
243
223
  this.request = new Request()
244
224
  }
@@ -276,10 +256,6 @@ export class BaseAjax extends BaseAutocomplete {
276
256
  }
277
257
 
278
258
  class BaseServerAjax extends BaseAjax {
279
- setUrl() {
280
- this.url = '/agnocomplete/AutocompleteUser/?q={q}'
281
- }
282
-
283
259
  initRequest() {
284
260
  this.server = new ServerRequest()
285
261
  }
@@ -298,19 +274,15 @@ export const SingleMixin = (Base) =>
298
274
  }
299
275
 
300
276
  displaySelected(result) {
301
- const result_el = DomUtil.element({
302
- tagName: 'div',
303
- parent: this.selectedContainer,
304
- })
305
- result_el.textContent = result.item.label
306
- const close = DomUtil.element({
307
- tagName: 'span',
308
- parent: result_el,
309
- className: 'close',
310
- textContent: '×',
311
- })
277
+ const [root, { close }] = DOMUtils.loadTemplateWithRefs(`
278
+ <div class="with-toolbox">
279
+ ${result.item.label}
280
+ <button type="button" class="icon icon-16 icon-close" title="${translate('Close')}" data-ref="close"></button>
281
+ </div>
282
+ `)
283
+ this.selectedContainer.appendChild(root)
312
284
  this.input.style.display = 'none'
313
- DomEvent.on(close, 'click', () => {
285
+ close.addEventListener('click', () => {
314
286
  this.selectedContainer.innerHTML = ''
315
287
  this.input.style.display = 'block'
316
288
  this.options.on_unselect?.(result)
@@ -328,19 +300,12 @@ export const MultipleMixin = (Base) =>
328
300
  }
329
301
 
330
302
  displaySelected(result) {
331
- const result_el = DomUtil.element({
332
- tagName: 'li',
333
- parent: this.selectedContainer,
334
- })
335
- result_el.textContent = result.item.label
336
- const close = DomUtil.element({
337
- tagName: 'span',
338
- parent: result_el,
339
- className: 'close',
340
- textContent: '×',
341
- })
342
- DomEvent.on(close, 'click', () => {
343
- this.selectedContainer.removeChild(result_el)
303
+ const [li, { close }] = DOMUtils.loadTemplateWithRefs(`
304
+ <li class="with-toolbox">${result.item.label} <button class="icon icon-16 icon-close" type="button" data-ref="close"></button></li>
305
+ `)
306
+ this.selectedContainer.appendChild(li)
307
+ close.addEventListener('click', () => {
308
+ this.selectedContainer.removeChild(li)
344
309
  this.options.on_unselect?.(result)
345
310
  })
346
311
  this.hide()
@@ -1,4 +1,4 @@
1
- import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { DomEvent, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
2
2
  import { Form } from './form/builder.js'
3
3
  import { EXPORT_FORMATS } from './formatter.js'
4
4
  import { translate } from './i18n.js'
@@ -57,18 +57,23 @@ export default class Browser {
57
57
 
58
58
  addDataLayer(datalayer, parent) {
59
59
  const open = this.mode !== 'layers' ? ' open' : ''
60
- const [container, { headline, toolbox, label }] = Utils.loadTemplateWithRefs(`
61
- <details class="datalayer ${datalayer.cssId}" id="${this.datalayerId(datalayer)}"${open}>
62
- <summary data-ref=headline class="with-toolbox">
60
+ const [container, { details, toolbox, label, ul }] = Utils.loadTemplateWithRefs(`
61
+ <details data-ref=details class="datalayer ${datalayer.cssId}" id="${datalayer.cssId}"${open}>
62
+ <summary class="with-toolbox">
63
63
  <span>
64
64
  <span class="datalayer-name truncate" data-id="${datalayer.id}" data-ref=label></span>
65
65
  <span class="datalayer-counter"></span>
66
66
  </span>
67
67
  <span data-ref=toolbox></span>
68
68
  </summary>
69
- <ul></ul>
69
+ <ul data-ref=ul></ul>
70
70
  </details>
71
71
  `)
72
+ details.addEventListener('toggle', () => {
73
+ if (details.open && !ul.innerHTML.trim()) {
74
+ this._appendFeaturesDOM(datalayer, ul)
75
+ }
76
+ })
72
77
  datalayer.renderToolbox(toolbox)
73
78
  parent.appendChild(container)
74
79
  this.updateFeaturesList(datalayer)
@@ -77,25 +82,31 @@ export default class Browser {
77
82
  updateFeaturesList(datalayer) {
78
83
  // Compute once, but use it for each feature later.
79
84
  this.bounds = this._leafletMap.getBounds()
80
- const id = this.datalayerId(datalayer)
81
- const parent = document.getElementById(id)
82
- // Panel is not open
85
+ const parent = document.getElementById(datalayer.cssId)
86
+ // Browser is not open
83
87
  if (!parent) return
84
88
  parent.classList.toggle('off', !datalayer.isVisible())
85
89
  const label = parent.querySelector('.datalayer-name')
86
90
  const container = parent.querySelector('ul')
87
91
  container.innerHTML = ''
88
- datalayer.features.forEach((feature) => this.addFeature(feature, container))
92
+ const isOpen = container.parentNode.open
93
+ if (isOpen || this.hasActiveFilters()) {
94
+ this._appendFeaturesDOM(datalayer, container)
95
+ }
89
96
  datalayer.propagate(['properties.name'])
90
97
  const total = datalayer.count()
91
98
  if (!total) return
92
99
  const current = container.querySelectorAll('li').length
93
- const count = total === current ? total : `${current}/${total}`
100
+ const count = !this.hasActiveFilters() ? total : `${current}/${total}`
94
101
  const counter = parent.querySelector('.datalayer-counter')
95
102
  counter.textContent = `(${count})`
96
103
  counter.title = translate(`Features in this layer: ${count}`)
97
104
  }
98
105
 
106
+ _appendFeaturesDOM(datalayer, container) {
107
+ datalayer.features.forEach((feature) => this.addFeature(feature, container))
108
+ }
109
+
99
110
  toggleBadge() {
100
111
  Utils.toggleBadge(this.filtersTitle, this.hasActiveFilters())
101
112
  Utils.toggleBadge('.umap-control-browse', this.hasActiveFilters())
@@ -133,12 +144,13 @@ export default class Browser {
133
144
  update() {
134
145
  if (!this.isOpen()) return
135
146
  this.dataContainer.innerHTML = ''
136
- this._umap.datalayers.browsable().map((datalayer) => {
147
+ for (const datalayer of this._umap.datalayers.browsable()) {
137
148
  this.addDataLayer(datalayer, this.dataContainer)
138
- })
149
+ }
139
150
  }
140
151
 
141
152
  open(mode) {
153
+ // TODO add loader
142
154
  // Force only if mode is known, otherwise keep current mode.
143
155
  if (mode) this.mode = mode
144
156
  const template = `
@@ -200,11 +212,16 @@ export default class Browser {
200
212
  content: container,
201
213
  className: 'umap-browser',
202
214
  })
203
-
215
+ details.addEventListener('toggle', () => {
216
+ if (details.open && !formContainer.innerHTML.trim()) {
217
+ this.buildFilters()
218
+ }
219
+ })
204
220
  this.update()
205
221
  }
206
222
 
207
223
  buildFilters() {
224
+ if (!this.filtersTitle.parentNode.open) return
208
225
  this.formContainer.innerHTML = ''
209
226
  const fields = [
210
227
  [
@@ -260,7 +277,7 @@ export default class Browser {
260
277
  if (datalayer.isVisible()) allHidden = false
261
278
  })
262
279
  this._umap.datalayers.browsable().map((datalayer) => {
263
- datalayer.autoLoaded = false
280
+ datalayer.autoVisibility = false
264
281
  if (allHidden) {
265
282
  datalayer.show()
266
283
  } else {
@@ -1,12 +1,7 @@
1
- import {
2
- DomEvent,
3
- DomUtil,
4
- GeoJSON,
5
- LineUtil,
6
- } from '../../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { GeoJSON, LineUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
7
2
  import { uMapAlert as Alert } from '../../components/alerts/alert.js'
8
3
  import { MutatingForm } from '../form/builder.js'
9
- import { translate } from '../i18n.js'
4
+ import { translate, getLocale } from '../i18n.js'
10
5
  import {
11
6
  PREFERENCES as ORS_PREFERENCES,
12
7
  PROFILES as ORS_PROFILES,
@@ -243,15 +238,16 @@ class Feature {
243
238
  if (this._umap.editedFeature === this && !event?.force) return
244
239
  // If this feature is active (popup open), let's close it.
245
240
  this.deactivate()
246
- const container = DomUtil.create('div', 'umap-feature-container')
247
- DomUtil.createTitle(
248
- container,
249
- translate('Feature properties'),
250
- `icon-${this.getClassName()}`
251
- )
241
+ const container = DOMUtils.loadTemplate(`
242
+ <div class="umap-feature-container">
243
+ <h3><i class="icon icon-16 icon-${this.getClassName()}"></i> ${translate('Feature properties')}</h3>
244
+ </div>
245
+ `)
252
246
 
247
+ // No need to sync the datalayer key, given we already do a delete/upsert when
248
+ // it changes.
253
249
  let builder = new MutatingForm(this, [
254
- ['datalayer', { handler: 'EditableDataLayerSwitcher' }],
250
+ ['datalayer', { handler: 'EditableDataLayerSwitcher', sync: false }],
255
251
  ])
256
252
  // removeLayer step will close the edit panel, let's reopen it
257
253
  builder.on('set', () => this.edit(event))
@@ -260,17 +256,19 @@ class Feature {
260
256
  const properties = []
261
257
  for (const field of this.fields) {
262
258
  const options = { handler: 'Input', label: field.key }
263
- if (field.key === 'description' || field.type === 'Text') {
259
+ if (field.key === 'description' || field.TYPE === 'Text') {
264
260
  options.handler = 'Textarea'
265
261
  options.helpEntries = ['textFormatting']
266
- } else if (field.type === 'Number') {
262
+ } else if (field.TYPE === 'Number') {
267
263
  options.handler = 'FloatInput'
268
- } else if (field.type === 'Date') {
264
+ } else if (field.TYPE === 'Date') {
269
265
  options.handler = 'DateInput'
270
- } else if (field.type === 'Datetime') {
266
+ } else if (field.TYPE === 'Datetime') {
271
267
  options.handler = 'DateTimeInput'
272
- } else if (field.type === 'Boolean') {
268
+ } else if (field.TYPE === 'Boolean') {
273
269
  options.handler = 'Switch'
270
+ } else if (field.TYPE === 'Enum') {
271
+ options.helpText = translate('Comma separated list of values')
274
272
  }
275
273
  properties.push([`properties.${field.key}`, options])
276
274
  }
@@ -331,7 +329,7 @@ class Feature {
331
329
  let builder = new MutatingForm(this, optionsFields, {
332
330
  id: 'umap-feature-shape-properties',
333
331
  })
334
- const shapeProperties = DomUtil.createFieldset(
332
+ const shapeProperties = DOMUtils.createFieldset(
335
333
  container,
336
334
  translate('Shape properties')
337
335
  )
@@ -343,7 +341,7 @@ class Feature {
343
341
  builder = new MutatingForm(this, advancedOptions, {
344
342
  id: 'umap-feature-advanced-properties',
345
343
  })
346
- const advancedProperties = DomUtil.createFieldset(
344
+ const advancedProperties = DOMUtils.createFieldset(
347
345
  container,
348
346
  translate('Advanced properties')
349
347
  )
@@ -351,7 +349,7 @@ class Feature {
351
349
 
352
350
  const interactionOptions = this.getInteractionOptions()
353
351
  builder = new MutatingForm(this, interactionOptions)
354
- const popupFieldset = DomUtil.createFieldset(
352
+ const popupFieldset = DOMUtils.createFieldset(
355
353
  container,
356
354
  translate('Interaction options')
357
355
  )
@@ -442,7 +440,7 @@ class Feature {
442
440
  this.properties = Object.fromEntries(
443
441
  Object.entries(geojson.properties || {}).map(this.cleanProperty)
444
442
  )
445
- this.properties._umap_options = L.extend(
443
+ this.properties._umap_options = Object.assign(
446
444
  {},
447
445
  this.properties._storage_options,
448
446
  this.properties._umap_options
@@ -514,8 +512,8 @@ class Feature {
514
512
  }
515
513
 
516
514
  cloneProperties() {
517
- const properties = L.extend({}, this.properties)
518
- properties._umap_options = L.extend({}, properties._umap_options)
515
+ const properties = Object.assign({}, this.properties)
516
+ properties._umap_options = Object.assign({}, properties._umap_options)
519
517
  if (Object.keys && Object.keys(properties._umap_options).length === 0) {
520
518
  delete properties._umap_options // It can make a difference on big data sets
521
519
  }
@@ -593,7 +591,7 @@ class Feature {
593
591
  extendedProperties() {
594
592
  // Include context properties
595
593
  const properties = this._umap.getGeoContext()
596
- const locale = L.getLocale()
594
+ const locale = getLocale()
597
595
  if (locale) properties.locale = locale
598
596
  if (U.lang) properties.lang = U.lang
599
597
  properties.rank = this.getRank() + 1
@@ -788,7 +786,7 @@ export class Point extends Feature {
788
786
  ]
789
787
  const builder = new MutatingForm(this, coordinatesOptions)
790
788
  builder.on('set', () => {
791
- if (!this.ui._latlng.isValid()) {
789
+ if (!Utils.LatLngIsValid(this.ui._latlng)) {
792
790
  Alert.error(translate('Invalid latitude or longitude'))
793
791
  builder.restoreField('ui._latlng.lat')
794
792
  builder.restoreField('ui._latlng.lng')
@@ -796,7 +794,7 @@ export class Point extends Feature {
796
794
  this.pullGeometry()
797
795
  this.zoomTo({ easing: false })
798
796
  })
799
- const fieldset = DomUtil.createFieldset(container, translate('Coordinates'))
797
+ const fieldset = DOMUtils.createFieldset(container, translate('Coordinates'))
800
798
  fieldset.appendChild(builder.build())
801
799
  }
802
800
 
@@ -964,7 +962,7 @@ class Path extends Feature {
964
962
  const builder = new MutatingForm(this, options, {
965
963
  id: 'umap-feature-line-decoration',
966
964
  })
967
- const fieldset = DomUtil.createFieldset(container, translate('Line decoration'))
965
+ const fieldset = DOMUtils.createFieldset(container, translate('Line decoration'))
968
966
  fieldset.appendChild(builder.build())
969
967
  }
970
968
  }
@@ -1077,7 +1075,7 @@ export class LineString extends Path {
1077
1075
  getAdvancedEditActions(container) {
1078
1076
  super.getAdvancedEditActions(container)
1079
1077
  const button = Utils.loadTemplate(`
1080
- <button class="button" type="button"><i class="icon icon-24 icon-polygon"></i>${translate('Transform to polygon')}</button>
1078
+ <button type="button"><i class="icon icon-24 icon-polygon"></i>${translate('Transform to polygon')}</button>
1081
1079
  `)
1082
1080
  container.appendChild(button)
1083
1081
  button.addEventListener('click', () => this.toPolygon())
@@ -1383,13 +1381,13 @@ export class Polygon extends Path {
1383
1381
 
1384
1382
  getAdvancedEditActions(container) {
1385
1383
  super.getAdvancedEditActions(container)
1386
- const toLineString = DomUtil.createButton(
1387
- 'button umap-to-polyline',
1388
- container,
1389
- translate('Transform to lines'),
1390
- this.toLineString,
1391
- this
1384
+ const toLineString = DOMUtils.loadTemplate(
1385
+ `<button type="button" class="umap-to-polyline">
1386
+ <i class="icon icon-24 icon-polyline"></i>${translate('Transform to lines')}
1387
+ </button>`
1392
1388
  )
1389
+ container.appendChild(toLineString)
1390
+ toLineString.addEventListener('click', () => this.toLineString())
1393
1391
  }
1394
1392
 
1395
1393
  isMulti() {