umap-project 2.4.1__py3-none-any.whl → 2.5.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 (199) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  3. umap/locale/el/LC_MESSAGES/django.po +145 -90
  4. umap/locale/en/LC_MESSAGES/django.po +13 -13
  5. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/eu/LC_MESSAGES/django.po +145 -89
  7. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/hu/LC_MESSAGES/django.po +100 -50
  9. umap/static/umap/base.css +5 -2
  10. umap/static/umap/content.css +2 -2
  11. umap/static/umap/css/contextmenu.css +11 -0
  12. umap/static/umap/css/dialog.css +25 -4
  13. umap/static/umap/css/importers.css +2 -0
  14. umap/static/umap/css/panel.css +6 -4
  15. umap/static/umap/css/slideshow.css +69 -0
  16. umap/static/umap/css/tableeditor.css +69 -0
  17. umap/static/umap/css/tooltip.css +3 -3
  18. umap/static/umap/img/16-white.svg +4 -0
  19. umap/static/umap/img/source/16-white.svg +5 -1
  20. umap/static/umap/js/components/alerts/alert.css +11 -11
  21. umap/static/umap/js/components/alerts/alert.js +1 -1
  22. umap/static/umap/js/modules/autocomplete.js +27 -5
  23. umap/static/umap/js/modules/browser.js +20 -14
  24. umap/static/umap/js/modules/caption.js +4 -4
  25. umap/static/umap/js/modules/dompurify.js +2 -3
  26. umap/static/umap/js/modules/facets.js +53 -17
  27. umap/static/umap/js/modules/formatter.js +153 -0
  28. umap/static/umap/js/modules/global.js +25 -16
  29. umap/static/umap/js/modules/help.js +26 -26
  30. umap/static/umap/js/modules/importer.js +10 -10
  31. umap/static/umap/js/modules/importers/communesfr.js +3 -1
  32. umap/static/umap/js/modules/importers/datasets.js +8 -6
  33. umap/static/umap/js/modules/importers/geodatamine.js +14 -14
  34. umap/static/umap/js/modules/importers/overpass.js +19 -15
  35. umap/static/umap/js/modules/orderable.js +2 -2
  36. umap/static/umap/js/modules/request.js +1 -1
  37. umap/static/umap/js/modules/rules.js +26 -11
  38. umap/static/umap/js/modules/schema.js +16 -12
  39. umap/static/umap/js/{umap.share.js → modules/share.js} +58 -103
  40. umap/static/umap/js/modules/slideshow.js +141 -0
  41. umap/static/umap/js/modules/sync/engine.js +3 -3
  42. umap/static/umap/js/modules/sync/updaters.js +10 -11
  43. umap/static/umap/js/modules/sync/websocket.js +1 -1
  44. umap/static/umap/js/modules/tableeditor.js +329 -0
  45. umap/static/umap/js/modules/ui/base.js +93 -0
  46. umap/static/umap/js/modules/ui/contextmenu.js +50 -0
  47. umap/static/umap/js/modules/ui/dialog.js +169 -31
  48. umap/static/umap/js/modules/ui/panel.js +7 -5
  49. umap/static/umap/js/modules/ui/tooltip.js +7 -77
  50. umap/static/umap/js/modules/urls.js +1 -2
  51. umap/static/umap/js/modules/utils.js +36 -16
  52. umap/static/umap/js/umap.controls.js +27 -29
  53. umap/static/umap/js/umap.core.js +19 -15
  54. umap/static/umap/js/umap.datalayer.permissions.js +15 -18
  55. umap/static/umap/js/umap.features.js +113 -131
  56. umap/static/umap/js/umap.forms.js +203 -228
  57. umap/static/umap/js/umap.icon.js +17 -22
  58. umap/static/umap/js/umap.js +117 -107
  59. umap/static/umap/js/umap.layer.js +374 -324
  60. umap/static/umap/js/umap.permissions.js +7 -10
  61. umap/static/umap/js/umap.popup.js +20 -20
  62. umap/static/umap/locale/am_ET.js +22 -5
  63. umap/static/umap/locale/am_ET.json +22 -5
  64. umap/static/umap/locale/ar.js +22 -5
  65. umap/static/umap/locale/ar.json +22 -5
  66. umap/static/umap/locale/ast.js +22 -5
  67. umap/static/umap/locale/ast.json +22 -5
  68. umap/static/umap/locale/bg.js +22 -5
  69. umap/static/umap/locale/bg.json +22 -5
  70. umap/static/umap/locale/br.js +22 -5
  71. umap/static/umap/locale/br.json +22 -5
  72. umap/static/umap/locale/ca.js +56 -39
  73. umap/static/umap/locale/ca.json +56 -39
  74. umap/static/umap/locale/cs_CZ.js +22 -5
  75. umap/static/umap/locale/cs_CZ.json +22 -5
  76. umap/static/umap/locale/da.js +22 -5
  77. umap/static/umap/locale/da.json +22 -5
  78. umap/static/umap/locale/de.js +22 -5
  79. umap/static/umap/locale/de.json +22 -5
  80. umap/static/umap/locale/el.js +27 -10
  81. umap/static/umap/locale/el.json +27 -10
  82. umap/static/umap/locale/en.js +22 -6
  83. umap/static/umap/locale/en.json +22 -6
  84. umap/static/umap/locale/en_US.json +22 -5
  85. umap/static/umap/locale/es.js +22 -6
  86. umap/static/umap/locale/es.json +22 -6
  87. umap/static/umap/locale/et.js +22 -5
  88. umap/static/umap/locale/et.json +22 -5
  89. umap/static/umap/locale/eu.js +167 -150
  90. umap/static/umap/locale/eu.json +167 -150
  91. umap/static/umap/locale/fa_IR.js +22 -5
  92. umap/static/umap/locale/fa_IR.json +22 -5
  93. umap/static/umap/locale/fi.js +22 -5
  94. umap/static/umap/locale/fi.json +22 -5
  95. umap/static/umap/locale/fr.js +22 -6
  96. umap/static/umap/locale/fr.json +22 -6
  97. umap/static/umap/locale/gl.js +22 -5
  98. umap/static/umap/locale/gl.json +22 -5
  99. umap/static/umap/locale/he.js +22 -5
  100. umap/static/umap/locale/he.json +22 -5
  101. umap/static/umap/locale/hr.js +22 -5
  102. umap/static/umap/locale/hr.json +22 -5
  103. umap/static/umap/locale/hu.js +89 -72
  104. umap/static/umap/locale/hu.json +89 -72
  105. umap/static/umap/locale/id.js +22 -5
  106. umap/static/umap/locale/id.json +22 -5
  107. umap/static/umap/locale/is.js +22 -5
  108. umap/static/umap/locale/is.json +22 -5
  109. umap/static/umap/locale/it.js +22 -5
  110. umap/static/umap/locale/it.json +22 -5
  111. umap/static/umap/locale/ja.js +22 -5
  112. umap/static/umap/locale/ja.json +22 -5
  113. umap/static/umap/locale/ko.js +22 -5
  114. umap/static/umap/locale/ko.json +22 -5
  115. umap/static/umap/locale/lt.js +22 -5
  116. umap/static/umap/locale/lt.json +22 -5
  117. umap/static/umap/locale/ms.js +22 -5
  118. umap/static/umap/locale/ms.json +22 -5
  119. umap/static/umap/locale/nl.js +22 -5
  120. umap/static/umap/locale/nl.json +22 -5
  121. umap/static/umap/locale/no.js +22 -5
  122. umap/static/umap/locale/no.json +22 -5
  123. umap/static/umap/locale/pl.js +22 -5
  124. umap/static/umap/locale/pl.json +22 -5
  125. umap/static/umap/locale/pl_PL.json +22 -5
  126. umap/static/umap/locale/pt.js +22 -6
  127. umap/static/umap/locale/pt.json +22 -6
  128. umap/static/umap/locale/pt_BR.js +22 -5
  129. umap/static/umap/locale/pt_BR.json +22 -5
  130. umap/static/umap/locale/pt_PT.js +22 -5
  131. umap/static/umap/locale/pt_PT.json +22 -5
  132. umap/static/umap/locale/ro.js +22 -5
  133. umap/static/umap/locale/ro.json +22 -5
  134. umap/static/umap/locale/ru.js +22 -5
  135. umap/static/umap/locale/ru.json +22 -5
  136. umap/static/umap/locale/sk_SK.js +22 -5
  137. umap/static/umap/locale/sk_SK.json +22 -5
  138. umap/static/umap/locale/sl.js +22 -5
  139. umap/static/umap/locale/sl.json +22 -5
  140. umap/static/umap/locale/sr.js +22 -5
  141. umap/static/umap/locale/sr.json +22 -5
  142. umap/static/umap/locale/sv.js +22 -5
  143. umap/static/umap/locale/sv.json +22 -5
  144. umap/static/umap/locale/th_TH.js +22 -5
  145. umap/static/umap/locale/th_TH.json +22 -5
  146. umap/static/umap/locale/tr.js +22 -5
  147. umap/static/umap/locale/tr.json +22 -5
  148. umap/static/umap/locale/uk_UA.js +22 -5
  149. umap/static/umap/locale/uk_UA.json +22 -5
  150. umap/static/umap/locale/vi.js +22 -5
  151. umap/static/umap/locale/vi.json +22 -5
  152. umap/static/umap/locale/vi_VN.json +22 -5
  153. umap/static/umap/locale/zh.js +22 -5
  154. umap/static/umap/locale/zh.json +22 -5
  155. umap/static/umap/locale/zh_CN.json +22 -5
  156. umap/static/umap/locale/zh_TW.Big5.json +22 -5
  157. umap/static/umap/locale/zh_TW.js +22 -5
  158. umap/static/umap/locale/zh_TW.json +22 -5
  159. umap/static/umap/map.css +9 -153
  160. umap/static/umap/vars.css +15 -0
  161. umap/static/umap/vendors/dompurify/purify.es.js +5 -59
  162. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  163. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +410 -428
  164. umap/static/umap/vendors/geojson-to-gpx/index.js +155 -0
  165. umap/static/umap/vendors/osmtogeojson/osmtogeojson.js +1 -2
  166. umap/static/umap/vendors/togeojson/togeojson.es.js +1109 -0
  167. umap/static/umap/vendors/togeojson/{togeojson.umd.js.map → togeojson.es.mjs.map} +1 -1
  168. umap/static/umap/vendors/tokml/tokml.es.js +895 -0
  169. umap/static/umap/vendors/tokml/tokml.es.mjs.map +1 -0
  170. umap/storage.py +6 -2
  171. umap/templates/umap/components/alerts/alert.html +3 -3
  172. umap/templates/umap/css.html +3 -0
  173. umap/templates/umap/js.html +0 -6
  174. umap/tests/fixtures/categorized_highway.geojson +1 -0
  175. umap/tests/fixtures/test_import_osm_relation.json +130 -0
  176. umap/tests/integration/conftest.py +8 -1
  177. umap/tests/integration/test_browser.py +3 -2
  178. umap/tests/integration/test_categorized_layer.py +141 -0
  179. umap/tests/integration/test_conditional_rules.py +21 -0
  180. umap/tests/integration/test_datalayer.py +9 -4
  181. umap/tests/integration/test_edit_datalayer.py +1 -0
  182. umap/tests/integration/test_edit_polygon.py +1 -1
  183. umap/tests/integration/test_export_map.py +2 -3
  184. umap/tests/integration/test_import.py +22 -0
  185. umap/tests/integration/test_map_preview.py +36 -2
  186. umap/tests/integration/test_tableeditor.py +158 -4
  187. umap/tests/integration/test_websocket_sync.py +2 -2
  188. umap/tests/test_views.py +2 -2
  189. umap/views.py +3 -2
  190. {umap_project-2.4.1.dist-info → umap_project-2.5.0.dist-info}/METADATA +8 -8
  191. {umap_project-2.4.1.dist-info → umap_project-2.5.0.dist-info}/RECORD +194 -184
  192. umap/static/umap/js/umap.slideshow.js +0 -165
  193. umap/static/umap/js/umap.tableeditor.js +0 -118
  194. umap/static/umap/vendors/togeojson/togeojson.umd.js +0 -2
  195. umap/static/umap/vendors/togpx/togpx.js +0 -547
  196. umap/static/umap/vendors/tokml/tokml.js +0 -343
  197. {umap_project-2.4.1.dist-info → umap_project-2.5.0.dist-info}/WHEEL +0 -0
  198. {umap_project-2.4.1.dist-info → umap_project-2.5.0.dist-info}/entry_points.txt +0 -0
  199. {umap_project-2.4.1.dist-info → umap_project-2.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,24 +1,28 @@
1
- import URLs from './urls.js'
1
+ import {
2
+ uMapAlert as Alert,
3
+ uMapAlertConflict as AlertConflict,
4
+ uMapAlertCreation as AlertCreation,
5
+ } from '../components/alerts/alert.js'
6
+ import { AjaxAutocomplete, AjaxAutocompleteMultiple, AutocompleteDatalist } from './autocomplete.js'
2
7
  import Browser from './browser.js'
3
- import Facets from './facets.js'
4
8
  import Caption from './caption.js'
5
- import { Panel, EditPanel, FullPanel } from './ui/panel.js'
6
- import Dialog from './ui/dialog.js'
7
- import Tooltip from './ui/tooltip.js'
9
+ import Facets from './facets.js'
10
+ import { Formatter } from './formatter.js'
11
+ import Help from './help.js'
12
+ import Importer from './importer.js'
13
+ import Orderable from './orderable.js'
14
+ import { HTTPError, NOKError, Request, RequestError, ServerRequest } from './request.js'
8
15
  import Rules from './rules.js'
9
- import * as Utils from './utils.js'
10
16
  import { SCHEMA } from './schema.js'
11
- import { Request, ServerRequest, RequestError, HTTPError, NOKError } from './request.js'
12
- import { AjaxAutocomplete, AjaxAutocompleteMultiple } from './autocomplete.js'
13
- import Orderable from './orderable.js'
14
- import Importer from './importer.js'
15
- import Help from './help.js'
17
+ import Share from './share.js'
18
+ import Slideshow from './slideshow.js'
16
19
  import { SyncEngine } from './sync/engine.js'
17
- import {
18
- uMapAlert as Alert,
19
- uMapAlertCreation as AlertCreation,
20
- uMapAlertConflict as AlertConflict,
21
- } from '../components/alerts/alert.js'
20
+ import Dialog from './ui/dialog.js'
21
+ import { EditPanel, FullPanel, Panel } from './ui/panel.js'
22
+ import TableEditor from './tableeditor.js'
23
+ import Tooltip from './ui/tooltip.js'
24
+ import URLs from './urls.js'
25
+ import * as Utils from './utils.js'
22
26
 
23
27
  // Import modules and export them to the global scope.
24
28
  // For the not yet module-compatible JS out there.
@@ -30,11 +34,13 @@ window.U = {
30
34
  AlertConflict,
31
35
  AjaxAutocomplete,
32
36
  AjaxAutocompleteMultiple,
37
+ AutocompleteDatalist,
33
38
  Browser,
34
39
  Caption,
35
40
  Dialog,
36
41
  EditPanel,
37
42
  Facets,
43
+ Formatter,
38
44
  FullPanel,
39
45
  Help,
40
46
  HTTPError,
@@ -47,7 +53,10 @@ window.U = {
47
53
  Rules,
48
54
  SCHEMA,
49
55
  ServerRequest,
56
+ Share,
57
+ Slideshow,
50
58
  SyncEngine,
59
+ TableEditor,
51
60
  Tooltip,
52
61
  URLs,
53
62
  Utils,
@@ -1,4 +1,4 @@
1
- import { DomUtil, DomEvent } from '../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
2
2
  import { translate } from './i18n.js'
3
3
 
4
4
  const SHORTCUTS = {
@@ -165,6 +165,7 @@ const ENTRIES = {
165
165
  export default class Help {
166
166
  constructor(map) {
167
167
  this.map = map
168
+ this.dialog = new U.Dialog()
168
169
  this.isMacOS = /mac/i.test(
169
170
  // eslint-disable-next-line compat/compat -- Fallback available.
170
171
  navigator.userAgentData ? navigator.userAgentData.platform : navigator.platform
@@ -190,42 +191,43 @@ export default class Help {
190
191
  show(entries) {
191
192
  const container = DomUtil.add('div')
192
193
  DomUtil.createTitle(container, translate('Help'))
193
- // Special dynamic case. Do we still think this dialog is usefull ?
194
- if (entries == 'edit') {
194
+ for (const name of entries) {
195
195
  DomUtil.element({
196
196
  tagName: 'div',
197
197
  className: 'umap-help-entry',
198
198
  parent: container,
199
- }).appendChild(this._buildEditEntry())
200
- } else {
201
- for (const name of entries) {
202
- DomUtil.element({
203
- tagName: 'div',
204
- className: 'umap-help-entry',
205
- parent: container,
206
- innerHTML: ENTRIES[name],
207
- })
208
- }
199
+ innerHTML: ENTRIES[name],
200
+ })
209
201
  }
202
+ this.dialog.open({ template: container, className: 'dark', cancel: false, accept: false })
203
+ }
204
+
205
+ // Special dynamic case. Do we still think this dialog is useful?
206
+ showGetStarted() {
207
+ const container = DomUtil.add('div')
208
+ DomUtil.createTitle(container, translate('Where do we go from here?'))
209
+ DomUtil.element({
210
+ tagName: 'div',
211
+ className: 'umap-help-entry',
212
+ parent: container,
213
+ }).appendChild(this._buildEditEntry())
210
214
  this.map.dialog.open({ content: container, className: 'dark' })
211
215
  }
212
216
 
213
- button(container, entries, classname) {
217
+ button(container, entries) {
214
218
  const button = DomUtil.createButton(
215
- classname || 'umap-help-button',
219
+ 'umap-help-button',
216
220
  container,
217
221
  translate('Help')
218
222
  )
219
- entries = typeof entries === 'string' ? [entries] : entries
220
- DomEvent.on(button, 'click', DomEvent.stop).on(button, 'click', () =>
221
- this.show(entries)
222
- )
223
+ button.addEventListener('click', () => this.show(entries))
223
224
  return button
224
225
  }
225
226
 
226
- link(container, entries) {
227
- const button = this.button(container, entries, 'umap-help-link')
227
+ getStartedLink(container) {
228
+ const button = DomUtil.createButton('umap-help-link', container, translate('Help'))
228
229
  button.textContent = translate('Help')
230
+ button.addEventListener('click', () => this.showGetStarted())
229
231
  return button
230
232
  }
231
233
 
@@ -237,16 +239,14 @@ export default class Help {
237
239
 
238
240
  _buildEditEntry() {
239
241
  const container = DomUtil.create('div', '')
240
- const title = DomUtil.create('h4', '', container)
241
242
  const actionsContainer = DomUtil.create('ul', 'umap-edit-actions', container)
242
243
  const addAction = (action) => {
243
244
  const actionContainer = DomUtil.add('li', '', actionsContainer)
244
- DomUtil.add('i', action.options.className, actionContainer),
245
- DomUtil.add('span', '', actionContainer, action.options.tooltip)
245
+ DomUtil.add('i', action.options.className, actionContainer)
246
+ DomUtil.add('span', '', actionContainer, action.options.tooltip)
246
247
  DomEvent.on(actionContainer, 'click', action.addHooks, action)
247
- DomEvent.on(actionContainer, 'click', this.map.dialog.close, this.map.dialog)
248
+ DomEvent.on(actionContainer, 'click', this.dialog.close, this.dialog)
248
249
  }
249
- title.textContent = translate('Where do we go from here?')
250
250
  for (const id in this.map.helpMenuActions) {
251
251
  addAction(this.map.helpMenuActions[id])
252
252
  }
@@ -1,8 +1,8 @@
1
- import { DomUtil, DomEvent } from '../../vendors/leaflet/leaflet-src.esm.js'
2
- import { translate } from './i18n.js'
1
+ import { DomEvent, DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
3
2
  import { uMapAlert as Alert } from '../components/alerts/alert.js'
4
- import Dialog from './ui/dialog.js'
3
+ import { translate } from './i18n.js'
5
4
  import { SCHEMA } from './schema.js'
5
+ import Dialog from './ui/dialog.js'
6
6
  import * as Utils from './utils.js'
7
7
 
8
8
  const TEMPLATE = `
@@ -53,7 +53,7 @@ export default class Importer {
53
53
  this.TYPES = ['geojson', 'csv', 'gpx', 'kml', 'osm', 'georss', 'umap']
54
54
  this.IMPORTERS = []
55
55
  this.loadImporters()
56
- this.dialog = new Dialog(this.map._controlContainer)
56
+ this.dialog = new Dialog()
57
57
  }
58
58
 
59
59
  loadImporters() {
@@ -114,7 +114,7 @@ export default class Importer {
114
114
  }
115
115
 
116
116
  get action() {
117
- return this.qs('[name=action]:checked').value
117
+ return this.qs('[name=action]:checked')?.value
118
118
  }
119
119
 
120
120
  get layerId() {
@@ -179,12 +179,12 @@ export default class Importer {
179
179
  this.format === 'umap' || !this.url
180
180
  )
181
181
  this.qs('[name=layer-name]').toggleAttribute('hidden', Boolean(this.layerId))
182
- this.qs('#clear').toggleAttribute('hidden', !Boolean(this.layerId))
182
+ this.qs('#clear').toggleAttribute('hidden', !this.layerId)
183
183
  }
184
184
 
185
185
  onFileChange(e) {
186
- let type = '',
187
- newType
186
+ let type = ''
187
+ let newType
188
188
  for (const file of e.target.files) {
189
189
  newType = U.Utils.detectFileType(file)
190
190
  if (!type && newType) type = newType
@@ -234,7 +234,7 @@ export default class Importer {
234
234
  }
235
235
 
236
236
  submit() {
237
- let hasErrors = false
237
+ let hasErrors
238
238
  if (this.format === 'umap') {
239
239
  hasErrors = !this.full()
240
240
  } else if (!this.url) {
@@ -242,7 +242,7 @@ export default class Importer {
242
242
  } else if (this.action) {
243
243
  hasErrors = !this[this.action]()
244
244
  }
245
- if (!hasErrors) {
245
+ if (hasErrors === false) {
246
246
  Alert.info(translate('Data successfully imported!'))
247
247
  }
248
248
  }
@@ -37,8 +37,10 @@ export class Importer {
37
37
  this.autocomplete = new Autocomplete(container, options)
38
38
 
39
39
  importer.dialog.open({
40
- content: container,
40
+ template: container,
41
41
  className: `${this.id} importer dark`,
42
+ cancel: false,
43
+ accept: false,
42
44
  })
43
45
  }
44
46
  }
@@ -30,13 +30,15 @@ export class Importer {
30
30
  importer.format = select.options[select.selectedIndex].dataset.format
31
31
  importer.layerName = select.options[select.selectedIndex].textContent
32
32
  }
33
- importer.dialog.close()
34
33
  }
35
- L.DomUtil.createButton('', container, translate('Choose this dataset'), confirm)
36
34
 
37
- importer.dialog.open({
38
- content: container,
39
- className: `${this.id} importer dark`,
40
- })
35
+ importer.dialog
36
+ .open({
37
+ template: container,
38
+ className: `${this.id} importer dark`,
39
+ accept: translate('Choose this dataset'),
40
+ cancel: false,
41
+ })
42
+ .then(confirm)
41
43
  }
42
44
  }
@@ -1,8 +1,8 @@
1
- import { DomUtil, DomEvent } from '../../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { DomEvent, DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
+ import { uMapAlert as Alert } from '../../components/alerts/alert.js'
2
3
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
3
4
  import { translate } from '../i18n.js'
4
5
  import * as Utils from '../utils.js'
5
- import { uMapAlert as Alert } from '../../components/alerts/alert.js'
6
6
 
7
7
  const BOUNDARY_TYPES = {
8
8
  admin_6: 'département',
@@ -25,7 +25,6 @@ const TEMPLATE = `
25
25
  </label>
26
26
  <label id="boundary">
27
27
  </label>
28
- <button class="button">${translate('Choose this data')}</button>
29
28
  `
30
29
 
31
30
  class Autocomplete extends SingleMixin(BaseAjax) {
@@ -52,9 +51,9 @@ export class Importer {
52
51
  container.innerHTML = TEMPLATE
53
52
  const response = await importer.map.request.get(`${this.baseUrl}/themes`)
54
53
  const select = container.querySelector('select')
55
- if (response && response.ok) {
54
+ if (response?.ok) {
56
55
  const { themes } = await response.json()
57
- themes.sort((a, b) => Utils.naturalSort(a['name:fr'], b ['name:fr']))
56
+ themes.sort((a, b) => Utils.naturalSort(a['name:fr'], b['name:fr']))
58
57
  for (const theme of themes) {
59
58
  DomUtil.element({
60
59
  tagName: 'option',
@@ -66,7 +65,6 @@ export class Importer {
66
65
  } else {
67
66
  console.error(response)
68
67
  }
69
- const asPoint = container.querySelector('[name=aspoint]')
70
68
  this.autocomplete = new Autocomplete(container.querySelector('#boundary'), {
71
69
  placeholder: translate('Search admin boundary'),
72
70
  url: `${this.baseUrl}/boundaries/search?text={q}`,
@@ -75,21 +73,23 @@ export class Importer {
75
73
  boundaryName = choice.item.label
76
74
  },
77
75
  })
78
- const confirm = () => {
76
+ const confirm = (form) => {
79
77
  if (!boundary || !select.value) {
80
78
  Alert.error(translate('Please choose a theme and a boundary first.'))
81
79
  return
82
80
  }
83
- importer.url = `${this.baseUrl}/data/${select.value}/${boundary}?format=geojson&aspoint=${asPoint.checked}`
81
+ importer.url = `${this.baseUrl}/data/${form.theme}/${boundary}?format=geojson&aspoint=${Boolean(form.aspoint)}`
84
82
  importer.format = 'geojson'
85
83
  importer.layerName = `${boundaryName} — ${select.options[select.selectedIndex].textContent}`
86
- importer.dialog.close()
87
84
  }
88
- DomEvent.on(container.querySelector('button'), 'click', confirm)
89
85
 
90
- importer.dialog.open({
91
- content: container,
92
- className: `${this.id} importer dark`,
93
- })
86
+ importer.dialog
87
+ .open({
88
+ template: container,
89
+ className: `${this.id} importer dark`,
90
+ accept: translate('Choose this data'),
91
+ cancel: false,
92
+ })
93
+ .then(confirm)
94
94
  }
95
95
  }
@@ -1,7 +1,7 @@
1
1
  import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
+ import { uMapAlert as Alert } from '../../components/alerts/alert.js'
2
3
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
3
4
  import { translate } from '../i18n.js'
4
- import { uMapAlert as Alert } from '../../components/alerts/alert.js'
5
5
 
6
6
  const TEMPLATE = `
7
7
  <h3>Overpass</h3>
@@ -11,7 +11,7 @@ const TEMPLATE = `
11
11
  </label>
12
12
  <label>
13
13
  ${translate('Geometry mode')}
14
- <select name="out-mode">
14
+ <select name="out">
15
15
  <option value="geom" selected>${translate('Default')}</option>
16
16
  <option value="center">${translate('Only geometry centers')}</option>
17
17
  </select>
@@ -38,6 +38,9 @@ export class Importer {
38
38
  this.map = map
39
39
  this.name = options.name || 'Overpass'
40
40
  this.baseUrl = options?.url || 'https://overpass-api.de/api/interpreter'
41
+ this.searchUrl =
42
+ options?.searchUrl ||
43
+ 'https://photon.komoot.io/api?q={q}&layer=county&layer=city&layer=state'
41
44
  this.id = 'overpass'
42
45
  }
43
46
 
@@ -47,7 +50,7 @@ export class Importer {
47
50
  const container = DomUtil.create('div')
48
51
  container.innerHTML = TEMPLATE
49
52
  this.autocomplete = new Autocomplete(container.querySelector('#area'), {
50
- url: 'https://photon.komoot.io/api?q={q}&osm_tag=place',
53
+ url: this.searchUrl,
51
54
  placeholder: translate(
52
55
  'Type area name, or let empty to load data in current map view'
53
56
  ),
@@ -58,27 +61,28 @@ export class Importer {
58
61
  })
59
62
  this.map.help.parse(container)
60
63
 
61
- const confirm = () => {
62
- let tags = container.querySelector('[name=tags]').value
63
- if (!tags) {
64
- Alert.error(translate('Please define an expression for the query first'))
64
+ const confirm = (form) => {
65
+ if (!form.tags) {
66
+ Alert.error(translate('Expression is empty'))
65
67
  return
66
68
  }
67
- const outMode = container.querySelector('[name=out-mode]').value
69
+ let tags = form.tags
68
70
  if (!tags.startsWith('[')) tags = `[${tags}]`
69
71
  let area = '{south},{west},{north},{east}'
70
72
  if (boundary) area = `area:${boundary}`
71
- let query = `[out:json];nwr${tags}(${area});out ${outMode};`
73
+ const query = `[out:json];nwr${tags}(${area});out ${form.out};`
72
74
  importer.url = `${this.baseUrl}?data=${query}`
73
75
  if (boundary) importer.layerName = boundaryName
74
76
  importer.format = 'osm'
75
- importer.dialog.close()
76
77
  }
77
- L.DomUtil.createButton('', container, translate('Choose this data'), confirm)
78
78
 
79
- importer.dialog.open({
80
- content: container,
81
- className: `${this.id} importer dark`,
82
- })
79
+ importer.dialog
80
+ .open({
81
+ template: container,
82
+ className: `${this.id} importer dark`,
83
+ accept: translate('Choose this data'),
84
+ cancel: false
85
+ })
86
+ .then(confirm)
83
87
  }
84
88
  }
@@ -59,8 +59,8 @@ export default class Orderable {
59
59
  const dst = this.findTarget(e.target)
60
60
  if (!dst || dst === this.src) return
61
61
  this.dst = dst
62
- const targetIndex = this.nodeIndex(this.dst),
63
- srcIndex = this.nodeIndex(this.src)
62
+ const targetIndex = this.nodeIndex(this.dst)
63
+ const srcIndex = this.nodeIndex(this.src)
64
64
  if (targetIndex > srcIndex) this.parent.insertBefore(this.dst, this.src)
65
65
  else this.parent.insertBefore(this.src, this.dst)
66
66
  }
@@ -1,5 +1,5 @@
1
- import { translate } from './i18n.js'
2
1
  import { uMapAlert as Alert } from '../components/alerts/alert.js'
2
+ import { translate } from './i18n.js'
3
3
 
4
4
  export class RequestError extends Error {}
5
5
 
@@ -1,9 +1,9 @@
1
- import { DomUtil, DomEvent, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
2
- import * as Utils from './utils.js'
1
+ import { DomEvent, DomUtil, stamp } from '../../vendors/leaflet/leaflet-src.esm.js'
3
2
  import { translate } from './i18n.js'
3
+ import * as Utils from './utils.js'
4
+ import { AutocompleteDatalist } from './autocomplete.js'
4
5
 
5
6
  class Rule {
6
-
7
7
  get condition() {
8
8
  return this._condition
9
9
  }
@@ -13,7 +13,6 @@ class Rule {
13
13
  this.parse()
14
14
  }
15
15
 
16
-
17
16
  get isDirty() {
18
17
  return this._isDirty
19
18
  }
@@ -51,7 +50,7 @@ class Rule {
51
50
  }
52
51
 
53
52
  not_equal(other) {
54
- return this.expected != other
53
+ return this.expected !== other
55
54
  }
56
55
 
57
56
  gt(other) {
@@ -73,10 +72,15 @@ class Rule {
73
72
  break
74
73
  }
75
74
  }
76
- if (vars.length != 2) return
75
+ if (vars.length !== 2) return
77
76
  this.key = vars[0]
78
77
  this.expected = vars[1]
79
- if (!isNaN(this.expected)) this.cast = parseFloat
78
+ // Special cases where we want to be lousy when checking isNaN without
79
+ // coercing to a Number first because we handle multiple types.
80
+ // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/
81
+ // Reference/Global_Objects/Number/isNaN
82
+ // biome-ignore lint/suspicious/noGlobalIsNan: expected might not be a number.
83
+ if (!isNaN(this.expected)) this.cast = Number.parseFloat
80
84
  else if (['true', 'false'].includes(this.expected)) this.cast = (v) => !!v
81
85
  this.expected = this.cast(this.expected)
82
86
  }
@@ -120,7 +124,18 @@ class Rule {
120
124
  const builder = new U.FormBuilder(this, options)
121
125
  const defaultShapeProperties = DomUtil.add('div', '', container)
122
126
  defaultShapeProperties.appendChild(builder.build())
123
-
127
+ const autocomplete = new AutocompleteDatalist(builder.helpers.condition.input)
128
+ const properties = this.map.allProperties()
129
+ autocomplete.suggestions = properties
130
+ autocomplete.input.addEventListener('input', (event) => {
131
+ const value = event.target.value
132
+ if (properties.includes(value)) {
133
+ autocomplete.suggestions = [`${value}=`, `${value}!=`, `${value}>`, `${value}<`]
134
+ } else if (value.endsWith('=')) {
135
+ const key = value.split('!')[0].split('=')[0]
136
+ autocomplete.suggestions = this.map.sortedValues(key).map((str) => `${value}${str || ''}`)
137
+ }
138
+ })
124
139
  this.map.editPanel.open({ content: container })
125
140
  }
126
141
 
@@ -163,7 +178,7 @@ class Rule {
163
178
  }
164
179
 
165
180
  _delete() {
166
- this.map.rules.rules = this.map.rules.rules.filter((rule) => rule != this)
181
+ this.map.rules.rules = this.map.rules.rules.filter((rule) => rule !== this)
167
182
  }
168
183
  }
169
184
 
@@ -183,8 +198,8 @@ export default class Rules {
183
198
  }
184
199
 
185
200
  onReorder(src, dst, initialIndex, finalIndex) {
186
- const moved = this.rules.find((rule) => stamp(rule) == src.dataset.id)
187
- const reference = this.rules.find((rule) => stamp(rule) == dst.dataset.id)
201
+ const moved = this.rules.find((rule) => stamp(rule) === src.dataset.id)
202
+ const reference = this.rules.find((rule) => stamp(rule) === dst.dataset.id)
188
203
  const movedIdx = this.rules.indexOf(moved)
189
204
  let referenceIdx = this.rules.indexOf(reference)
190
205
  const minIndex = Math.min(movedIdx, referenceIdx)
@@ -40,12 +40,16 @@ export const SCHEMA = {
40
40
  label: translate('Do you want to display caption menus?'),
41
41
  default: true,
42
42
  },
43
+ categorized: {
44
+ type: Object,
45
+ impacts: ['data'],
46
+ },
43
47
  color: {
44
48
  type: String,
45
49
  impacts: ['data'],
46
50
  handler: 'ColorPicker',
47
51
  label: translate('color'),
48
- helpEntries: 'colorValue',
52
+ helpEntries: ['colorValue'],
49
53
  inheritable: true,
50
54
  default: 'DarkBlue',
51
55
  },
@@ -65,7 +69,7 @@ export const SCHEMA = {
65
69
  type: String,
66
70
  impacts: ['data'],
67
71
  label: translate('dash array'),
68
- helpEntries: 'dashArray',
72
+ helpEntries: ['dashArray'],
69
73
  inheritable: true,
70
74
  },
71
75
  datalayersControl: {
@@ -92,7 +96,7 @@ export const SCHEMA = {
92
96
  type: 'Text',
93
97
  impacts: ['ui'],
94
98
  label: translate('description'),
95
- helpEntries: 'textFormatting',
99
+ helpEntries: ['textFormatting'],
96
100
  },
97
101
  displayOnLoad: {
98
102
  type: Boolean,
@@ -131,7 +135,7 @@ export const SCHEMA = {
131
135
  type: Boolean,
132
136
  impacts: ['data'],
133
137
  label: translate('fill'),
134
- helpEntries: 'fill',
138
+ helpEntries: ['fill'],
135
139
  inheritable: true,
136
140
  default: true,
137
141
  },
@@ -140,7 +144,7 @@ export const SCHEMA = {
140
144
  impacts: ['data'],
141
145
  handler: 'ColorPicker',
142
146
  label: translate('fill color'),
143
- helpEntries: 'fillColor',
147
+ helpEntries: ['fillColor'],
144
148
  inheritable: true,
145
149
  },
146
150
  fillOpacity: {
@@ -216,7 +220,7 @@ export const SCHEMA = {
216
220
  type: Boolean,
217
221
  impacts: ['data'],
218
222
  label: translate('Allow interactions'),
219
- helpEntries: 'interactive',
223
+ helpEntries: ['interactive'],
220
224
  inheritable: true,
221
225
  default: true,
222
226
  },
@@ -243,7 +247,7 @@ export const SCHEMA = {
243
247
  labelKey: {
244
248
  type: String,
245
249
  impacts: ['data'],
246
- helpEntries: 'labelKey',
250
+ helpEntries: ['labelKey'],
247
251
  placeholder: translate('Default: name'),
248
252
  label: translate('Label key'),
249
253
  inheritable: true,
@@ -319,7 +323,7 @@ export const SCHEMA = {
319
323
  type: String,
320
324
  impacts: [],
321
325
  label: translate('Link to…'),
322
- helpEntries: 'outlink',
326
+ helpEntries: ['outlink'],
323
327
  placeholder: 'http://...',
324
328
  inheritable: true,
325
329
  },
@@ -441,7 +445,7 @@ export const SCHEMA = {
441
445
  max: 10,
442
446
  step: 0.5,
443
447
  label: translate('Simplify'),
444
- helpEntries: 'smoothFactor',
448
+ helpEntries: ['smoothFactor'],
445
449
  inheritable: true,
446
450
  default: 1.0,
447
451
  },
@@ -459,7 +463,7 @@ export const SCHEMA = {
459
463
  type: Boolean,
460
464
  impacts: ['data'],
461
465
  label: translate('stroke'),
462
- helpEntries: 'stroke',
466
+ helpEntries: ['stroke'],
463
467
  inheritable: true,
464
468
  default: true,
465
469
  },
@@ -467,7 +471,7 @@ export const SCHEMA = {
467
471
  type: Boolean,
468
472
  impacts: ['sync', 'ui'],
469
473
  label: translate('Enable real-time collaboration'),
470
- helpEntries: 'sync',
474
+ helpEntries: ['sync'],
471
475
  default: false,
472
476
  },
473
477
  tilelayer: {
@@ -526,7 +530,7 @@ export const SCHEMA = {
526
530
  type: Number,
527
531
  impacts: [], // not need to update the view
528
532
  placeholder: translate('Inherit'),
529
- helpEntries: 'zoomTo',
533
+ helpEntries: ['zoomTo'],
530
534
  label: translate('Default zoom level'),
531
535
  inheritable: true,
532
536
  },