umap-project 3.4.2__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 (168) 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/de/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/de/LC_MESSAGES/django.po +20 -16
  6. umap/locale/en/LC_MESSAGES/django.po +14 -14
  7. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/hu/LC_MESSAGES/django.po +20 -16
  9. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/pl/LC_MESSAGES/django.po +32 -27
  11. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/zh_TW/LC_MESSAGES/django.po +20 -16
  13. umap/management/commands/clean_tilelayer.py +0 -1
  14. umap/management/commands/search_maps.py +95 -0
  15. umap/settings/__init__.py +9 -1
  16. umap/settings/base.py +7 -6
  17. umap/static/umap/css/icon.css +8 -0
  18. umap/static/umap/img/16-white.svg +5 -2
  19. umap/static/umap/img/16.svg +1 -1
  20. umap/static/umap/img/source/16-white.svg +7 -4
  21. umap/static/umap/img/source/16.svg +1 -1
  22. umap/static/umap/js/modules/autocomplete.js +1 -9
  23. umap/static/umap/js/modules/browser.js +27 -10
  24. umap/static/umap/js/modules/data/features.js +3 -2
  25. umap/static/umap/js/modules/data/fields.js +12 -2
  26. umap/static/umap/js/modules/data/layer.js +13 -9
  27. umap/static/umap/js/modules/domutils.js +4 -0
  28. umap/static/umap/js/modules/filters.js +11 -10
  29. umap/static/umap/js/modules/form/builder.js +17 -16
  30. umap/static/umap/js/modules/form/fields.js +16 -16
  31. umap/static/umap/js/modules/permissions.js +10 -2
  32. umap/static/umap/js/modules/rendering/controls.js +202 -9
  33. umap/static/umap/js/modules/rendering/layers/classified.js +1 -1
  34. umap/static/umap/js/modules/rendering/map.js +45 -35
  35. umap/static/umap/js/modules/rendering/template.js +12 -6
  36. umap/static/umap/js/modules/ui/bar.js +2 -1
  37. umap/static/umap/js/modules/ui/hash.js +36 -0
  38. umap/static/umap/js/modules/ui/loader.js +26 -0
  39. umap/static/umap/js/modules/ui/panel.js +7 -0
  40. umap/static/umap/js/modules/umap.js +6 -0
  41. umap/static/umap/js/modules/utils.js +5 -4
  42. umap/static/umap/js/umap.controls.js +0 -182
  43. umap/static/umap/locale/am_ET.js +2 -5
  44. umap/static/umap/locale/am_ET.json +2 -5
  45. umap/static/umap/locale/ar.js +2 -5
  46. umap/static/umap/locale/ar.json +2 -5
  47. umap/static/umap/locale/ast.js +2 -5
  48. umap/static/umap/locale/ast.json +2 -5
  49. umap/static/umap/locale/bg.js +2 -5
  50. umap/static/umap/locale/bg.json +2 -5
  51. umap/static/umap/locale/br.js +40 -43
  52. umap/static/umap/locale/br.json +40 -43
  53. umap/static/umap/locale/ca.js +2 -5
  54. umap/static/umap/locale/ca.json +2 -5
  55. umap/static/umap/locale/cs_CZ.js +0 -3
  56. umap/static/umap/locale/cs_CZ.json +0 -3
  57. umap/static/umap/locale/da.js +1 -4
  58. umap/static/umap/locale/da.json +1 -4
  59. umap/static/umap/locale/de.js +27 -30
  60. umap/static/umap/locale/de.json +27 -30
  61. umap/static/umap/locale/el.js +0 -3
  62. umap/static/umap/locale/el.json +0 -3
  63. umap/static/umap/locale/en.js +0 -3
  64. umap/static/umap/locale/en.json +0 -3
  65. umap/static/umap/locale/en_US.json +2 -5
  66. umap/static/umap/locale/es.js +0 -3
  67. umap/static/umap/locale/es.json +0 -3
  68. umap/static/umap/locale/et.js +0 -3
  69. umap/static/umap/locale/et.json +0 -3
  70. umap/static/umap/locale/eu.js +0 -3
  71. umap/static/umap/locale/eu.json +0 -3
  72. umap/static/umap/locale/fa_IR.js +0 -3
  73. umap/static/umap/locale/fa_IR.json +0 -3
  74. umap/static/umap/locale/fi.js +2 -5
  75. umap/static/umap/locale/fi.json +2 -5
  76. umap/static/umap/locale/fr.js +3 -6
  77. umap/static/umap/locale/fr.json +3 -6
  78. umap/static/umap/locale/gl.js +0 -3
  79. umap/static/umap/locale/gl.json +0 -3
  80. umap/static/umap/locale/he.js +2 -5
  81. umap/static/umap/locale/he.json +2 -5
  82. umap/static/umap/locale/hr.js +2 -5
  83. umap/static/umap/locale/hr.json +2 -5
  84. umap/static/umap/locale/hu.js +7 -10
  85. umap/static/umap/locale/hu.json +7 -10
  86. umap/static/umap/locale/id.js +2 -5
  87. umap/static/umap/locale/id.json +2 -5
  88. umap/static/umap/locale/is.js +0 -3
  89. umap/static/umap/locale/is.json +0 -3
  90. umap/static/umap/locale/it.js +0 -3
  91. umap/static/umap/locale/it.json +0 -3
  92. umap/static/umap/locale/ja.js +2 -5
  93. umap/static/umap/locale/ja.json +2 -5
  94. umap/static/umap/locale/ko.js +2 -5
  95. umap/static/umap/locale/ko.json +2 -5
  96. umap/static/umap/locale/lt.js +2 -5
  97. umap/static/umap/locale/lt.json +2 -5
  98. umap/static/umap/locale/ms.js +0 -3
  99. umap/static/umap/locale/ms.json +0 -3
  100. umap/static/umap/locale/nl.js +0 -3
  101. umap/static/umap/locale/nl.json +0 -3
  102. umap/static/umap/locale/no.js +2 -5
  103. umap/static/umap/locale/no.json +2 -5
  104. umap/static/umap/locale/pl.js +2 -5
  105. umap/static/umap/locale/pl.json +2 -5
  106. umap/static/umap/locale/pl_PL.json +2 -5
  107. umap/static/umap/locale/pt.js +0 -3
  108. umap/static/umap/locale/pt.json +0 -3
  109. umap/static/umap/locale/pt_BR.js +2 -5
  110. umap/static/umap/locale/pt_BR.json +2 -5
  111. umap/static/umap/locale/pt_PT.js +2 -5
  112. umap/static/umap/locale/pt_PT.json +2 -5
  113. umap/static/umap/locale/ro.js +2 -5
  114. umap/static/umap/locale/ro.json +2 -5
  115. umap/static/umap/locale/ru.js +2 -5
  116. umap/static/umap/locale/ru.json +2 -5
  117. umap/static/umap/locale/sk_SK.js +2 -5
  118. umap/static/umap/locale/sk_SK.json +2 -5
  119. umap/static/umap/locale/sl.js +2 -5
  120. umap/static/umap/locale/sl.json +2 -5
  121. umap/static/umap/locale/sr.js +2 -5
  122. umap/static/umap/locale/sr.json +2 -5
  123. umap/static/umap/locale/sv.js +2 -5
  124. umap/static/umap/locale/sv.json +2 -5
  125. umap/static/umap/locale/th_TH.js +2 -5
  126. umap/static/umap/locale/th_TH.json +2 -5
  127. umap/static/umap/locale/tr.js +2 -5
  128. umap/static/umap/locale/tr.json +2 -5
  129. umap/static/umap/locale/uk_UA.js +2 -5
  130. umap/static/umap/locale/uk_UA.json +2 -5
  131. umap/static/umap/locale/vi.js +2 -5
  132. umap/static/umap/locale/vi.json +2 -5
  133. umap/static/umap/locale/vi_VN.json +2 -5
  134. umap/static/umap/locale/zh.js +2 -5
  135. umap/static/umap/locale/zh.json +2 -5
  136. umap/static/umap/locale/zh_CN.json +2 -5
  137. umap/static/umap/locale/zh_TW.Big5.json +2 -5
  138. umap/static/umap/locale/zh_TW.js +1 -4
  139. umap/static/umap/locale/zh_TW.json +1 -4
  140. umap/static/umap/map.css +1 -17
  141. umap/static/umap/vendors/locatecontrol/L.Control.Locate.esm.js +942 -0
  142. umap/static/umap/vendors/photon/leaflet.photon.esm.js +472 -0
  143. umap/sync/app.py +4 -1
  144. umap/templates/umap/css.html +0 -2
  145. umap/templates/umap/js.html +0 -5
  146. umap/templates/umap/team_form.html +2 -1
  147. umap/tests/integration/test_edit_map.py +2 -0
  148. umap/tests/integration/test_filters.py +24 -0
  149. umap/tests/integration/test_import.py +26 -23
  150. umap/tests/integration/test_map.py +1 -1
  151. umap/tests/integration/test_optimistic_merge.py +7 -1
  152. umap/tests/integration/test_remote_data.py +1 -1
  153. umap/tests/test_search_maps_command.py +44 -0
  154. umap/utils.py +9 -3
  155. umap/views.py +17 -4
  156. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/METADATA +24 -18
  157. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/RECORD +160 -162
  158. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/WHEEL +1 -1
  159. umap/static/umap/vendors/hash/leaflet-hash.js +0 -162
  160. umap/static/umap/vendors/loading/Control.Loading.css +0 -26
  161. umap/static/umap/vendors/loading/Control.Loading.js +0 -351
  162. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css +0 -1
  163. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.css.map +0 -1
  164. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js +0 -4
  165. umap/static/umap/vendors/locatecontrol/L.Control.Locate.min.js.map +0 -1
  166. umap/static/umap/vendors/photon/leaflet.photon.js +0 -487
  167. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/entry_points.txt +0 -0
  168. {umap_project-3.4.2.dist-info → umap_project-3.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,472 @@
1
+ import {
2
+ Control,
3
+ DomUtil,
4
+ DomEvent,
5
+ Evented,
6
+ latLng,
7
+ Util,
8
+ } from '../leaflet/leaflet-src.esm.js'
9
+
10
+ const PhotonBase = Evented.extend({
11
+ forEach: (els, callback) => {
12
+ Array.prototype.forEach.call(els, callback)
13
+ },
14
+
15
+ ajax: function () {
16
+ const url = this.options.url + this.buildQueryString(this.getParams())
17
+ this.fire('ajax:send')
18
+ return new Promise((resolve) => {
19
+ fetch(url).then(async (resp) => {
20
+ if (resp.ok) {
21
+ resolve(await resp.json())
22
+ }
23
+ this.fire('ajax:return')
24
+ })
25
+ })
26
+ },
27
+
28
+ buildQueryString: (params) => {
29
+ const queryString = []
30
+ for (const [key, param] of Object.entries(params)) {
31
+ if (param) {
32
+ queryString.push(`${encodeURIComponent(key)}=${encodeURIComponent(param)}`)
33
+ }
34
+ }
35
+ return queryString.join('&')
36
+ },
37
+
38
+ featureToPopupContent: (feature) => {
39
+ const container = DomUtil.create('div', 'leaflet-photon-popup')
40
+ const title = DomUtil.create('h3', '', container)
41
+ title.innerHTML = feature.properties.label
42
+ return container
43
+ },
44
+ })
45
+
46
+ const PhotonBaseSearch = PhotonBase.extend({
47
+ options: {
48
+ url: 'https://photon.komoot.io/api/?',
49
+ placeholder: 'Start typing...',
50
+ minChar: 3,
51
+ limit: 5,
52
+ submitDelay: 300,
53
+ includePosition: true,
54
+ bbox: null,
55
+ noResultLabel: 'No result',
56
+ feedbackEmail: 'photon@komoot.de', // Set to null to remove feedback box
57
+ feedbackLabel: 'Feedback',
58
+ },
59
+
60
+ CACHE: '',
61
+ RESULTS: [],
62
+ KEYS: {
63
+ LEFT: 37,
64
+ UP: 38,
65
+ RIGHT: 39,
66
+ DOWN: 40,
67
+ TAB: 9,
68
+ RETURN: 13,
69
+ ESC: 27,
70
+ APPLE: 91,
71
+ SHIFT: 16,
72
+ ALT: 17,
73
+ CTRL: 18,
74
+ },
75
+
76
+ initialize: function (input, options) {
77
+ this.input = input
78
+ Util.setOptions(this, options)
79
+ let CURRENT = null
80
+
81
+ Object.defineProperty(this, 'CURRENT', {
82
+ get: () => CURRENT,
83
+ set: function (index) {
84
+ if (typeof index === 'object') {
85
+ index = this.resultToIndex(index)
86
+ }
87
+ CURRENT = index
88
+ },
89
+ })
90
+
91
+ this.input.type = 'search'
92
+ this.input.placeholder = this.options.placeholder
93
+ this.input.autocomplete = 'off'
94
+ this.input.autocorrect = 'off'
95
+ DomEvent.disableClickPropagation(this.input)
96
+
97
+ DomEvent.on(this.input, 'keydown', this.onKeyDown, this)
98
+ DomEvent.on(this.input, 'input', this.onInput, this)
99
+ DomEvent.on(this.input, 'blur', this.onBlur, this)
100
+ DomEvent.on(this.input, 'focus', this.onFocus, this)
101
+ this.createResultsContainer()
102
+ },
103
+
104
+ createResultsContainer: function () {
105
+ this.resultsContainer =
106
+ this.options.resultsContainer ||
107
+ DomUtil.create('ul', 'photon-autocomplete', document.querySelector('body'))
108
+ },
109
+
110
+ resizeContainer: function () {
111
+ const l = this.getLeft(this.input)
112
+ const t = this.getTop(this.input) + this.input.offsetHeight
113
+ this.resultsContainer.style.left = `${l}px`
114
+ this.resultsContainer.style.top = `${t}px`
115
+ const width = this.options.width ? this.options.width : this.input.offsetWidth - 2
116
+ this.resultsContainer.style.width = `${width}px`
117
+ },
118
+
119
+ onKeyDown: function (e) {
120
+ switch (e.keyCode) {
121
+ case this.KEYS.TAB:
122
+ if (this.CURRENT !== null) {
123
+ this.setChoice()
124
+ }
125
+ DomEvent.stop(e)
126
+ break
127
+ case this.KEYS.RETURN:
128
+ DomEvent.stop(e)
129
+ this.setChoice()
130
+ break
131
+ case this.KEYS.ESC:
132
+ DomEvent.stop(e)
133
+ this.hide()
134
+ this.input.blur()
135
+ break
136
+ case this.KEYS.DOWN:
137
+ if (this.RESULTS.length > 0) {
138
+ if (this.CURRENT !== null && this.CURRENT < this.RESULTS.length - 1) {
139
+ // what if one resutl?
140
+ this.CURRENT++
141
+ this.highlight()
142
+ } else if (this.CURRENT === null) {
143
+ this.CURRENT = 0
144
+ this.highlight()
145
+ }
146
+ }
147
+ break
148
+ case this.KEYS.UP:
149
+ if (this.CURRENT !== null) {
150
+ DomEvent.stop(e)
151
+ }
152
+ if (this.RESULTS.length > 0) {
153
+ if (this.CURRENT > 0) {
154
+ this.CURRENT--
155
+ this.highlight()
156
+ } else if (this.CURRENT === 0) {
157
+ this.CURRENT = null
158
+ this.highlight()
159
+ }
160
+ }
161
+ break
162
+ }
163
+ },
164
+
165
+ onInput: function (_e) {
166
+ if (typeof this.submitDelay === 'number') {
167
+ window.clearTimeout(this.submitDelay)
168
+ delete this.submitDelay
169
+ }
170
+ this.submitDelay = window.setTimeout(
171
+ Util.bind(this.search, this),
172
+ this.options.submitDelay
173
+ )
174
+ },
175
+
176
+ onBlur: function (_e) {
177
+ this.fire('blur')
178
+ setTimeout(() => {
179
+ this.hide()
180
+ }, 100)
181
+ },
182
+
183
+ onFocus: function (_e) {
184
+ this.fire('focus')
185
+ this.input.select()
186
+ this.search() // In case we have a value from a previous search.
187
+ },
188
+
189
+ clear: function () {
190
+ this.RESULTS = []
191
+ this.CURRENT = null
192
+ this.CACHE = ''
193
+ this.resultsContainer.innerHTML = ''
194
+ },
195
+
196
+ hide: function () {
197
+ this.fire('hide')
198
+ this.clear()
199
+ this.resultsContainer.style.display = 'none'
200
+ },
201
+
202
+ setChoice: function (choice) {
203
+ choice = choice || this.RESULTS[this.CURRENT]
204
+ if (choice) {
205
+ this.hide()
206
+ this.fire('selected', { choice: choice.feature })
207
+ this.onSelected(choice.feature)
208
+ this.input.value = ''
209
+ }
210
+ },
211
+
212
+ search: function () {
213
+ const val = this.input.value
214
+ const minChar =
215
+ typeof this.options.minChar === 'function'
216
+ ? this.options.minChar(val)
217
+ : val.length >= this.options.minChar
218
+ if (!val || !minChar) return this.clear()
219
+ if (`${val}` === `${this.CACHE}`) return
220
+ this.CACHE = val
221
+ this._doSearch()
222
+ },
223
+
224
+ _doSearch: function () {
225
+ this.ajax().then((data) => this.handleResults(data))
226
+ },
227
+
228
+ _onSelected: (_feature) => {},
229
+
230
+ onSelected: function (choice) {
231
+ return (this.options.onSelected || this._onSelected).call(this, choice)
232
+ },
233
+
234
+ _formatResult: function (feature, el) {
235
+ const title = DomUtil.create('strong', '', el)
236
+ const detailsContainer = DomUtil.create('small', '', el)
237
+ const details = []
238
+ const type = this.formatType(feature)
239
+ if (feature.properties.name) {
240
+ title.innerHTML = feature.properties.name
241
+ } else if (feature.properties.housenumber) {
242
+ title.innerHTML = feature.properties.housenumber
243
+ if (feature.properties.street) {
244
+ title.innerHTML += ` ${feature.properties.street}`
245
+ }
246
+ }
247
+ if (type) details.push(type)
248
+ if (
249
+ feature.properties.city &&
250
+ feature.properties.city !== feature.properties.name
251
+ ) {
252
+ details.push(feature.properties.city)
253
+ }
254
+ if (
255
+ feature.properties.state &&
256
+ feature.properties.state !== feature.properties.name
257
+ ) {
258
+ details.push(feature.properties.state)
259
+ }
260
+ if (feature.properties.country) details.push(feature.properties.country)
261
+ detailsContainer.innerHTML = details.join(', ')
262
+ },
263
+
264
+ formatResult: function (feature, el) {
265
+ return (this.options.formatResult || this._formatResult).call(this, feature, el)
266
+ },
267
+
268
+ formatType: function (feature) {
269
+ return (this.options.formatType || this._formatType).call(this, feature)
270
+ },
271
+
272
+ _formatType: (feature) =>
273
+ feature.properties.osm_value === 'yes'
274
+ ? feature.properties.osm_key
275
+ : feature.properties.osm_value,
276
+
277
+ createResult: function (feature) {
278
+ const el = DomUtil.create('li', '', this.resultsContainer)
279
+ this.formatResult(feature, el)
280
+ const result = {
281
+ feature: feature,
282
+ el: el,
283
+ }
284
+ // Touch handling needed
285
+ DomEvent.on(
286
+ el,
287
+ 'mouseover',
288
+ function (_e) {
289
+ this.CURRENT = result
290
+ this.highlight()
291
+ },
292
+ this
293
+ )
294
+ DomEvent.on(
295
+ el,
296
+ 'mousedown',
297
+ function (_e) {
298
+ this.setChoice()
299
+ },
300
+ this
301
+ )
302
+ return result
303
+ },
304
+
305
+ resultToIndex: function (result) {
306
+ let out = null
307
+ this.forEach(this.RESULTS, (item, index) => {
308
+ if (item === result) {
309
+ out = index
310
+ return
311
+ }
312
+ })
313
+ return out
314
+ },
315
+
316
+ handleResults: function (geojson) {
317
+ this.clear()
318
+ this.resultsContainer.style.display = 'block'
319
+ this.resizeContainer()
320
+ this.forEach(geojson.features, (feature) => {
321
+ this.RESULTS.push(this.createResult(feature))
322
+ })
323
+ if (geojson.features.length === 0) {
324
+ const noresult = DomUtil.create('li', 'photon-no-result', this.resultsContainer)
325
+ noresult.innerHTML = this.options.noResultLabel
326
+ }
327
+ if (this.options.feedbackEmail) {
328
+ const feedback = DomUtil.create('a', 'photon-feedback', this.resultsContainer)
329
+ feedback.href = `mailto:${this.options.feedbackEmail}`
330
+ feedback.innerHTML = this.options.feedbackLabel
331
+ }
332
+ this.CURRENT = 0
333
+ this.highlight()
334
+ if (this.options.resultsHandler) {
335
+ this.options.resultsHandler(geojson)
336
+ }
337
+ },
338
+
339
+ highlight: function () {
340
+ this.forEach(this.RESULTS, (item, index) => {
341
+ if (index === this.CURRENT) {
342
+ DomUtil.addClass(item.el, 'on')
343
+ } else {
344
+ DomUtil.removeClass(item.el, 'on')
345
+ }
346
+ })
347
+ },
348
+
349
+ getLeft: (el) => {
350
+ let tmp = el.offsetLeft
351
+ el = el.offsetParent
352
+ while (el) {
353
+ tmp += el.offsetLeft
354
+ el = el.offsetParent
355
+ }
356
+ return tmp
357
+ },
358
+
359
+ getTop: (el) => {
360
+ let tmp = el.offsetTop
361
+ el = el.offsetParent
362
+ while (el) {
363
+ tmp += el.offsetTop
364
+ el = el.offsetParent
365
+ }
366
+ return tmp
367
+ },
368
+
369
+ getParams: function () {
370
+ return {
371
+ q: this.CACHE,
372
+ lang: this.options.lang,
373
+ limit: this.options.limit,
374
+ osm_tag: this.options.osm_tag,
375
+ }
376
+ },
377
+ })
378
+
379
+ export const PhotonSearch = PhotonBaseSearch.extend({
380
+ initialize: function (map, input, options) {
381
+ this.map = map
382
+ PhotonBaseSearch.prototype.initialize.call(this, input, options)
383
+ },
384
+
385
+ _onSelected: function (feature) {
386
+ this.map.setView(
387
+ [feature.geometry.coordinates[1], feature.geometry.coordinates[0]],
388
+ 16
389
+ )
390
+ },
391
+
392
+ getParams: function () {
393
+ const params = PhotonBaseSearch.prototype.getParams.call(this)
394
+ if (this.options.includePosition) {
395
+ params.lat = this.map.getCenter().lat
396
+ params.lon = this.map.getCenter().lng
397
+ if (this.options.location_bias_scale) {
398
+ params.location_bias_scale = this.options.location_bias_scale
399
+ }
400
+ }
401
+ if (this.options.bbox && this.options.bbox.length === 4) {
402
+ params.bbox = this.options.bbox.join(',')
403
+ }
404
+ return params
405
+ },
406
+ })
407
+
408
+ Control.Photon = Control.extend({
409
+ includes: Evented.prototype,
410
+
411
+ onAdd: function (map, options) {
412
+ this.map = map
413
+ this.container = DomUtil.create('div', 'leaflet-photon')
414
+
415
+ this.options = Util.extend(this.options, options)
416
+
417
+ this.input = DomUtil.create('input', 'photon-input', this.container)
418
+ this.search = new PhotonSearch(map, this.input, this.options)
419
+ this.search.on('blur', this.forwardEvent, this)
420
+ this.search.on('focus', this.forwardEvent, this)
421
+ this.search.on('hide', this.forwardEvent, this)
422
+ this.search.on('selected', this.forwardEvent, this)
423
+ this.search.on('ajax:send', this.forwardEvent, this)
424
+ this.search.on('ajax:return', this.forwardEvent, this)
425
+ return this.container
426
+ },
427
+
428
+ // TODO onRemove
429
+
430
+ forwardEvent: function (e) {
431
+ this.fire(e.type, e)
432
+ },
433
+ })
434
+
435
+ export const PhotonReverse = PhotonBase.extend({
436
+ options: {
437
+ url: 'https://photon.komoot.io/reverse/?',
438
+ limit: 1,
439
+ handleResults: null,
440
+ },
441
+
442
+ initialize: function (options) {
443
+ Util.setOptions(this, options)
444
+ },
445
+
446
+ doReverse: function (latlng) {
447
+ latlng = latLng(latlng)
448
+ this.fire('reverse', { latlng: latlng })
449
+ this.latlng = latlng
450
+ this.ajax().then((data) => this.handleResults(data))
451
+ },
452
+
453
+ _handleResults: (data) => {
454
+ /*eslint-disable no-console */
455
+ console.log(data)
456
+ /*eslint-enable no-alert */
457
+ },
458
+
459
+ handleResults: function (data) {
460
+ return (this.options.handleResults || this._handleResults).call(this, data)
461
+ },
462
+
463
+ getParams: function () {
464
+ return {
465
+ lang: this.options.lang,
466
+ limit: this.options.limit,
467
+ lat: this.latlng.lat,
468
+ lon: this.latlng.lng,
469
+ osm_tag: this.options.osm_tag,
470
+ }
471
+ },
472
+ })
umap/sync/app.py CHANGED
@@ -184,4 +184,7 @@ class Peer:
184
184
  logging.debug(err)
185
185
 
186
186
 
187
- urlpatterns = [path("ws/sync/<str:map_id>", name="ws_sync", view=sync)]
187
+ script_name = ""
188
+ if settings.FORCE_SCRIPT_NAME:
189
+ script_name = f"{settings.FORCE_SCRIPT_NAME.strip('/')}/"
190
+ urlpatterns = [path(f"{script_name}ws/sync/<str:map_id>", name="ws_sync", view=sync)]
@@ -10,8 +10,6 @@
10
10
  href="{% static 'umap/vendors/measurable/Leaflet.Measurable.css' %}" />
11
11
  <link rel="stylesheet"
12
12
  href="{% static 'umap/vendors/fullscreen/leaflet.fullscreen.css' %}" />
13
- <link rel="stylesheet"
14
- href="{% static 'umap/vendors/locatecontrol/L.Control.Locate.min.css' %}" />
15
13
  <link rel="stylesheet"
16
14
  href="{% static 'umap/vendors/iconlayers/iconLayers.css' %}" />
17
15
  <link rel="stylesheet" href="{% static 'umap/vars.css' %}" />
@@ -16,20 +16,15 @@
16
16
  <script src="{% static 'umap/vendors/editable/Path.Drag.js' %}" defer></script>
17
17
  <script src="{% static 'umap/vendors/editable/Leaflet.Editable.js' %}" defer></script>
18
18
  <script type="module" src="{% static 'umap/js/modules/global.js' %}" defer></script>
19
- <script src="{% static 'umap/vendors/hash/leaflet-hash.js' %}" defer></script>
20
19
  <script src="{% static 'umap/vendors/minimap/Control.MiniMap.min.js' %}"
21
20
  defer></script>
22
21
  <script src="{% static 'umap/vendors/csv2geojson/csv2geojson.js' %}" defer></script>
23
22
  <script src="{% static 'umap/vendors/osmtogeojson/osmtogeojson.js' %}" defer></script>
24
- <script src="{% static 'umap/vendors/loading/Control.Loading.js' %}" defer></script>
25
- <script src="{% static 'umap/vendors/photon/leaflet.photon.js' %}" defer></script>
26
23
  <script src="{% static 'umap/vendors/fullscreen/Leaflet.fullscreen.min.js' %}"
27
24
  defer></script>
28
25
  <script src="{% static 'umap/vendors/measurable/Leaflet.Measurable.js' %}"
29
26
  defer></script>
30
27
  <script src="{% static 'umap/vendors/iconlayers/iconLayers.js' %}" defer></script>
31
- <script src="{% static 'umap/vendors/locatecontrol/L.Control.Locate.min.js' %}"
32
- defer></script>
33
28
  <script src="{% static 'umap/vendors/textpath/leaflet.textpath.js' %}"
34
29
  defer></script>
35
30
  <script src="{% static 'umap/vendors/simple-statistics/simple-statistics.min.js' %}"
@@ -48,7 +48,8 @@
48
48
  className: 'edit-team-members',
49
49
  on_select: onSelect,
50
50
  on_unselect: onUnselect,
51
- placeholder: "{% trans "Add user" %}"
51
+ placeholder: "{% trans "Add user" %}",
52
+ url: "{% url 'agnocomplete:agnocomplete' 'AutocompleteUser' %}?q={q}"
52
53
  }
53
54
  const autocomplete = new U.AjaxAutocompleteMultiple(form, options)
54
55
  for (const option of select.options) {
@@ -115,6 +115,7 @@ def test_limitbounds_impacts_ui(live_server, page, tilelayer):
115
115
  page.get_by_text("Limit bounds").click()
116
116
  default_zoom_url = f"{live_server.url}/en/map/new/#5/51.110/7.053"
117
117
  page.goto(default_zoom_url)
118
+ page.wait_for_timeout(300)
118
119
  page.get_by_role("button", name="Use current bounds").click()
119
120
 
120
121
  zoom_in = page.get_by_label("Zoom in")
@@ -198,6 +199,7 @@ def test_sortkey_impacts_datalayerindex(map, live_server, page):
198
199
  page.locator(".panel .umap-field-sortKey .blur-container button").click()
199
200
 
200
201
  # Features should be sorted by key (First, Second, Third)
202
+ page.locator(".umap-browser .datalayer-name").click()
201
203
  first_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(0)
202
204
  second_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(1)
203
205
  third_listed_feature = page.locator(".umap-browser .datalayer ul > li").nth(2)
@@ -219,6 +219,30 @@ def test_choice_with_empty_value(live_server, page, map):
219
219
  expect(markers).to_have_count(2)
220
220
 
221
221
 
222
+ def test_choice_with_numbers(live_server, page, map):
223
+ map.settings["properties"]["onLoadPanel"] = "datafilters"
224
+ map.settings["properties"]["fields"] = [{"key": "mynumber", "type": "Number"}]
225
+ map.settings["properties"]["filters"] = [
226
+ {"fieldKey": "mynumber", "label": "My Number"}
227
+ ]
228
+ map.save()
229
+ data = copy.deepcopy(DATALAYER_DATA1)
230
+ data["features"][0]["properties"]["mynumber"] = ""
231
+ del data["features"][1]["properties"]["mynumber"]
232
+ DataLayerFactory(map=map, data=data)
233
+ DataLayerFactory(map=map, data=DATALAYER_DATA2)
234
+ page.goto(f"{live_server.url}{map.get_absolute_url()}#6/47.5/-1.5")
235
+ expect(page.get_by_text("<empty value>")).to_be_visible()
236
+ expect(page.get_by_text("14")).to_be_visible()
237
+ markers = page.locator(".leaflet-marker-icon")
238
+ expect(markers).to_have_count(4)
239
+ page.get_by_text("14", exact=True).click()
240
+ expect(markers).to_have_count(1)
241
+ page.get_by_text("14", exact=True).click() # Unselect this filter.
242
+ page.get_by_text("<empty value>", exact=True).click()
243
+ expect(markers).to_have_count(2)
244
+
245
+
222
246
  def test_number_with_zero_value(live_server, page, map):
223
247
  map.settings["properties"]["onLoadPanel"] = "datafilters"
224
248
  map.settings["properties"]["filters"] = [