umap-project 3.4.0b1__py3-none-any.whl → 3.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. umap/__init__.py +1 -1
  2. umap/context_processors.py +1 -1
  3. umap/locale/da/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/da/LC_MESSAGES/django.po +20 -16
  5. umap/locale/en/LC_MESSAGES/django.po +18 -14
  6. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/es/LC_MESSAGES/django.po +20 -16
  8. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  9. umap/locale/fr/LC_MESSAGES/django.po +18 -14
  10. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/pl/LC_MESSAGES/django.po +72 -71
  12. umap/migrations/0018_datalayer_uuid.py +1 -1
  13. umap/models.py +7 -3
  14. umap/settings/local.py.sample +1 -1
  15. umap/static/umap/content.css +0 -3
  16. umap/static/umap/css/bar.css +9 -6
  17. umap/static/umap/css/form.css +27 -11
  18. umap/static/umap/css/popup.css +1 -0
  19. umap/static/umap/js/components/base.js +1 -1
  20. umap/static/umap/js/components/copiable.js +47 -0
  21. umap/static/umap/js/modules/autocomplete.js +31 -58
  22. umap/static/umap/js/modules/browser.js +8 -8
  23. umap/static/umap/js/modules/data/features.js +33 -36
  24. umap/static/umap/js/modules/data/fields.js +446 -0
  25. umap/static/umap/js/modules/data/layer.js +76 -93
  26. umap/static/umap/js/modules/domutils.js +24 -4
  27. umap/static/umap/js/modules/filters.js +20 -47
  28. umap/static/umap/js/modules/form/fields.js +4 -4
  29. umap/static/umap/js/modules/formatter.js +9 -1
  30. umap/static/umap/js/modules/help.js +13 -14
  31. umap/static/umap/js/modules/i18n.js +1 -1
  32. umap/static/umap/js/modules/importer.js +18 -27
  33. umap/static/umap/js/modules/importers/banfr.js +0 -1
  34. umap/static/umap/js/modules/importers/cadastrefr.js +19 -19
  35. umap/static/umap/js/modules/importers/communesfr.js +7 -8
  36. umap/static/umap/js/modules/importers/datasets.js +14 -14
  37. umap/static/umap/js/modules/importers/geodatamine.js +20 -22
  38. umap/static/umap/js/modules/importers/opendata.js +10 -0
  39. umap/static/umap/js/modules/importers/overpass.js +19 -18
  40. umap/static/umap/js/modules/managers.js +1 -265
  41. umap/static/umap/js/modules/permissions.js +5 -3
  42. umap/static/umap/js/modules/rendering/controls.js +6 -4
  43. umap/static/umap/js/modules/rendering/icon.js +5 -9
  44. umap/static/umap/js/modules/rendering/layers/base.js +1 -1
  45. umap/static/umap/js/modules/rendering/layers/classified.js +16 -11
  46. umap/static/umap/js/modules/rendering/layers/heat.js +27 -21
  47. umap/static/umap/js/modules/rendering/map.js +22 -22
  48. umap/static/umap/js/modules/rendering/popup.js +6 -3
  49. umap/static/umap/js/modules/rendering/template.js +31 -37
  50. umap/static/umap/js/modules/rendering/ui.js +1 -2
  51. umap/static/umap/js/modules/rules.js +34 -41
  52. umap/static/umap/js/modules/schema.js +0 -7
  53. umap/static/umap/js/modules/share.js +36 -69
  54. umap/static/umap/js/modules/slideshow.js +3 -3
  55. umap/static/umap/js/modules/tableeditor.js +0 -1
  56. umap/static/umap/js/modules/ui/bar.js +51 -32
  57. umap/static/umap/js/modules/ui/dialog.js +10 -1
  58. umap/static/umap/js/modules/ui/panel.js +28 -23
  59. umap/static/umap/js/modules/ui/tooltip.js +1 -1
  60. umap/static/umap/js/modules/umap.js +84 -84
  61. umap/static/umap/js/modules/utils.js +13 -4
  62. umap/static/umap/js/umap.controls.js +33 -14
  63. umap/static/umap/locale/am_ET.js +19 -8
  64. umap/static/umap/locale/am_ET.json +19 -8
  65. umap/static/umap/locale/ar.js +19 -8
  66. umap/static/umap/locale/ar.json +19 -8
  67. umap/static/umap/locale/ast.js +19 -8
  68. umap/static/umap/locale/ast.json +19 -8
  69. umap/static/umap/locale/bg.js +19 -8
  70. umap/static/umap/locale/bg.json +19 -8
  71. umap/static/umap/locale/br.js +20 -9
  72. umap/static/umap/locale/br.json +20 -9
  73. umap/static/umap/locale/ca.js +19 -8
  74. umap/static/umap/locale/ca.json +19 -8
  75. umap/static/umap/locale/cs_CZ.js +20 -9
  76. umap/static/umap/locale/cs_CZ.json +20 -9
  77. umap/static/umap/locale/da.js +54 -43
  78. umap/static/umap/locale/da.json +54 -43
  79. umap/static/umap/locale/de.js +44 -33
  80. umap/static/umap/locale/de.json +44 -33
  81. umap/static/umap/locale/el.js +20 -9
  82. umap/static/umap/locale/el.json +20 -9
  83. umap/static/umap/locale/en.js +20 -9
  84. umap/static/umap/locale/en.json +20 -9
  85. umap/static/umap/locale/en_US.json +19 -8
  86. umap/static/umap/locale/es.js +55 -44
  87. umap/static/umap/locale/es.json +55 -44
  88. umap/static/umap/locale/et.js +20 -9
  89. umap/static/umap/locale/et.json +20 -9
  90. umap/static/umap/locale/eu.js +25 -14
  91. umap/static/umap/locale/eu.json +25 -14
  92. umap/static/umap/locale/fa_IR.js +20 -9
  93. umap/static/umap/locale/fa_IR.json +20 -9
  94. umap/static/umap/locale/fi.js +19 -8
  95. umap/static/umap/locale/fi.json +19 -8
  96. umap/static/umap/locale/fr.js +21 -10
  97. umap/static/umap/locale/fr.json +21 -10
  98. umap/static/umap/locale/gl.js +147 -136
  99. umap/static/umap/locale/gl.json +147 -136
  100. umap/static/umap/locale/he.js +19 -8
  101. umap/static/umap/locale/he.json +19 -8
  102. umap/static/umap/locale/hr.js +19 -8
  103. umap/static/umap/locale/hr.json +19 -8
  104. umap/static/umap/locale/hu.js +62 -51
  105. umap/static/umap/locale/hu.json +62 -51
  106. umap/static/umap/locale/id.js +19 -8
  107. umap/static/umap/locale/id.json +19 -8
  108. umap/static/umap/locale/is.js +20 -9
  109. umap/static/umap/locale/is.json +20 -9
  110. umap/static/umap/locale/it.js +20 -9
  111. umap/static/umap/locale/it.json +20 -9
  112. umap/static/umap/locale/ja.js +19 -8
  113. umap/static/umap/locale/ja.json +19 -8
  114. umap/static/umap/locale/ko.js +19 -8
  115. umap/static/umap/locale/ko.json +19 -8
  116. umap/static/umap/locale/lt.js +19 -8
  117. umap/static/umap/locale/lt.json +19 -8
  118. umap/static/umap/locale/ms.js +20 -9
  119. umap/static/umap/locale/ms.json +20 -9
  120. umap/static/umap/locale/nl.js +20 -9
  121. umap/static/umap/locale/nl.json +20 -9
  122. umap/static/umap/locale/no.js +19 -8
  123. umap/static/umap/locale/no.json +19 -8
  124. umap/static/umap/locale/pl.js +56 -45
  125. umap/static/umap/locale/pl.json +56 -45
  126. umap/static/umap/locale/pl_PL.json +19 -8
  127. umap/static/umap/locale/pt.js +20 -9
  128. umap/static/umap/locale/pt.json +20 -9
  129. umap/static/umap/locale/pt_BR.js +19 -8
  130. umap/static/umap/locale/pt_BR.json +19 -8
  131. umap/static/umap/locale/pt_PT.js +19 -8
  132. umap/static/umap/locale/pt_PT.json +19 -8
  133. umap/static/umap/locale/ro.js +19 -8
  134. umap/static/umap/locale/ro.json +19 -8
  135. umap/static/umap/locale/ru.js +19 -8
  136. umap/static/umap/locale/ru.json +19 -8
  137. umap/static/umap/locale/si.js +1 -1
  138. umap/static/umap/locale/si.json +1 -1
  139. umap/static/umap/locale/sk_SK.js +19 -8
  140. umap/static/umap/locale/sk_SK.json +19 -8
  141. umap/static/umap/locale/sl.js +19 -8
  142. umap/static/umap/locale/sl.json +19 -8
  143. umap/static/umap/locale/sr.js +19 -8
  144. umap/static/umap/locale/sr.json +19 -8
  145. umap/static/umap/locale/sv.js +19 -8
  146. umap/static/umap/locale/sv.json +19 -8
  147. umap/static/umap/locale/th_TH.js +19 -8
  148. umap/static/umap/locale/th_TH.json +19 -8
  149. umap/static/umap/locale/tr.js +19 -8
  150. umap/static/umap/locale/tr.json +19 -8
  151. umap/static/umap/locale/uk_UA.js +19 -8
  152. umap/static/umap/locale/uk_UA.json +19 -8
  153. umap/static/umap/locale/vi.js +19 -8
  154. umap/static/umap/locale/vi.json +19 -8
  155. umap/static/umap/locale/vi_VN.json +19 -8
  156. umap/static/umap/locale/zh.js +19 -8
  157. umap/static/umap/locale/zh.json +19 -8
  158. umap/static/umap/locale/zh_CN.json +19 -8
  159. umap/static/umap/locale/zh_TW.Big5.json +19 -8
  160. umap/static/umap/locale/zh_TW.js +53 -42
  161. umap/static/umap/locale/zh_TW.json +53 -42
  162. umap/static/umap/map.css +8 -7
  163. umap/static/umap/unittests/utils.js +7 -7
  164. umap/templates/umap/content_footer.html +1 -0
  165. umap/templates/umap/css.html +0 -2
  166. umap/templates/umap/js.html +1 -3
  167. umap/templates/umap/login_popup_end.html +2 -2
  168. umap/tests/integration/conftest.py +11 -2
  169. umap/tests/integration/test_anonymous_owned_map.py +2 -2
  170. umap/tests/integration/test_conditional_rules.py +107 -52
  171. umap/tests/integration/test_draw_polygon.py +4 -0
  172. umap/tests/integration/test_draw_polyline.py +11 -0
  173. umap/tests/integration/test_edit_datalayer.py +1 -1
  174. umap/tests/integration/test_fields.py +19 -0
  175. umap/tests/integration/test_filters.py +6 -7
  176. umap/tests/integration/test_iframe.py +1 -1
  177. umap/tests/integration/test_import.py +23 -0
  178. umap/tests/integration/test_map.py +2 -2
  179. umap/tests/integration/test_map_preview.py +1 -1
  180. umap/tests/integration/test_owned_map.py +2 -2
  181. umap/tests/integration/test_picto.py +1 -1
  182. umap/tests/integration/test_popup.py +31 -0
  183. umap/tests/integration/test_remote_data.py +4 -4
  184. umap/tests/integration/test_save.py +1 -1
  185. umap/tests/integration/test_search.py +41 -0
  186. umap/tests/integration/test_share.py +2 -2
  187. umap/tests/integration/test_team.py +1 -1
  188. umap/tests/integration/test_websocket_sync.py +69 -20
  189. umap/tests/test_dashboard.py +1 -1
  190. umap/tests/test_statics.py +2 -2
  191. umap/tests/test_utils.py +4 -1
  192. umap/tests/test_views.py +1 -1
  193. umap/utils.py +3 -2
  194. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/METADATA +17 -17
  195. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/RECORD +198 -199
  196. umap/static/umap/js/umap.core.js +0 -93
  197. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.css +0 -46
  198. umap/static/umap/vendors/editinosm/Leaflet.EditInOSM.js +0 -240
  199. umap/static/umap/vendors/editinosm/edit-in-osm.png +0 -0
  200. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/WHEEL +0 -0
  201. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/entry_points.txt +0 -0
  202. {umap_project-3.4.0b1.dist-info → umap_project-3.4.2.dist-info}/licenses/LICENSE +0 -0
@@ -25,7 +25,7 @@ export function getLocale() {
25
25
  }
26
26
 
27
27
  // @function translate(string: String, data?: Object): String
28
- // Actually try to translate the `string`, with optionnal variable passed in `data`.
28
+ // Actually try to translate the `string`, with optional variable passed in `data`.
29
29
  export function translate(string, data = {}) {
30
30
  if (locale && locales[locale] && locales[locale][string] !== undefined) {
31
31
  string = locales[locale][string]
@@ -1,13 +1,10 @@
1
- import {
2
- DomEvent,
3
- DomUtil,
4
- LatLngBounds,
5
- } from '../../vendors/leaflet/leaflet-src.esm.js'
1
+ import { LatLngBounds } from '../../vendors/leaflet/leaflet-src.esm.js'
6
2
  import { uMapAlert as Alert } from '../components/alerts/alert.js'
7
3
  import { translate } from './i18n.js'
8
4
  import { SCHEMA } from './schema.js'
9
5
  import Dialog from './ui/dialog.js'
10
6
  import * as Utils from './utils.js'
7
+ import * as DOMUtils from './domutils.js'
11
8
 
12
9
  const TEMPLATE = `
13
10
  <div class="umap-import">
@@ -203,18 +200,15 @@ export default class Importer extends Utils.WithTemplate {
203
200
  button.toggleAttribute('hidden', false)
204
201
  }
205
202
  for (const type of this.TYPES) {
206
- DomUtil.element({
207
- tagName: 'option',
208
- parent: this.qs('[name=format]'),
209
- value: type,
210
- textContent: type,
211
- })
203
+ this.qs('[name=format]').appendChild(
204
+ DOMUtils.loadTemplate(`<option value="${type}">${type}</option>`)
205
+ )
212
206
  }
213
207
  this._umap.help.parse(this.container)
214
208
  this.qs('[name=submit]').addEventListener('click', () => this.submit())
215
- DomEvent.on(this.qs('[type=file]'), 'change', this.onFileChange, this)
209
+ this.qs('[type=file]').addEventListener('change', () => this.onFileChange())
216
210
  for (const element of this.container.querySelectorAll('[onchange]')) {
217
- DomEvent.on(element, 'change', this.onChange, this)
211
+ element.addEventListener('change', () => this.onChange())
218
212
  }
219
213
  }
220
214
 
@@ -253,21 +247,18 @@ export default class Importer extends Utils.WithTemplate {
253
247
  layerSelect.innerHTML = ''
254
248
  this._umap.datalayers.reverse().map((datalayer) => {
255
249
  if (datalayer.isLoaded() && !datalayer.isRemoteLayer()) {
256
- DomUtil.element({
257
- tagName: 'option',
258
- parent: layerSelect,
259
- textContent: datalayer.getName(),
260
- value: datalayer.id,
261
- })
250
+ layerSelect.appendChild(
251
+ DOMUtils.loadTemplate(
252
+ `<option value="${datalayer.id}">${datalayer.getName()}</option>`
253
+ )
254
+ )
262
255
  }
263
256
  })
264
- DomUtil.element({
265
- tagName: 'option',
266
- value: '',
267
- textContent: translate('Import in a new layer'),
268
- parent: layerSelect,
269
- selected: true,
270
- })
257
+ layerSelect.appendChild(
258
+ DOMUtils.loadTemplate(
259
+ `<option value="" selected>${translate('Import in a new layer')}</option>`
260
+ )
261
+ )
271
262
  }
272
263
 
273
264
  open() {
@@ -353,7 +344,7 @@ export default class Importer extends Utils.WithTemplate {
353
344
 
354
345
  async copy() {
355
346
  // Format may be guessed from file later.
356
- // Usefull in case of multiple files with different formats.
347
+ // Useful in case of multiple files with different formats.
357
348
  if (!this.format && !this.files.length) {
358
349
  this.onError(translate('Please choose a format'))
359
350
  return false
@@ -1,4 +1,3 @@
1
- import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { uMapAlert as Alert } from '../../components/alerts/alert.js'
3
2
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
4
3
  import { translate } from '../i18n.js'
@@ -1,26 +1,28 @@
1
- import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { uMapAlert as Alert } from '../../components/alerts/alert.js'
3
2
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
4
3
  import { translate } from '../i18n.js'
5
4
  import * as Util from '../utils.js'
5
+ import * as DOMUtils from '../domutils.js'
6
6
  import { AutocompleteCommunes } from './communesfr.js'
7
7
 
8
8
  const TEMPLATE = `
9
- <h3>Cadastre</h3>
10
- <p>Importer les données cadastrales d’une commune française.</p>
11
- <div class="formbox">
12
- <select name="theme">
13
- <option value="batiments">Bâtiments</option>
14
- <option value="communes">Communes</option>
15
- <option value="feuilles">Feuilles</option>
16
- <option value="lieux_dits">Lieux dits</option>
17
- <option value="parcelles" selected>Parcelles</option>
18
- <option value="prefixes_sections">Préfixes sections</option>
19
- <option value="sections">Sections</option>
20
- <option value="subdivisions_fiscales">Subdivisions fiscales</option>
21
- </select>
22
- <label id="boundary">
23
- </label>
9
+ <div>
10
+ <h3>Cadastre</h3>
11
+ <p>Importer les données cadastrales d’une commune française.</p>
12
+ <div class="formbox">
13
+ <select name="theme" data-ref="select">
14
+ <option value="batiments">Bâtiments</option>
15
+ <option value="communes">Communes</option>
16
+ <option value="feuilles">Feuilles</option>
17
+ <option value="lieux_dits">Lieux dits</option>
18
+ <option value="parcelles" selected>Parcelles</option>
19
+ <option value="prefixes_sections">Préfixes sections</option>
20
+ <option value="sections">Sections</option>
21
+ <option value="subdivisions_fiscales">Subdivisions fiscales</option>
22
+ </select>
23
+ <label id="boundary">
24
+ </label>
25
+ </div>
24
26
  </div>
25
27
  `
26
28
 
@@ -33,9 +35,7 @@ export class Importer {
33
35
  async open(importer) {
34
36
  let boundary = null
35
37
  let boundaryName = null
36
- const container = DomUtil.create('div')
37
- container.innerHTML = TEMPLATE
38
- const select = container.querySelector('select')
38
+ const [container, { select }] = DOMUtils.loadTemplateWithRefs(TEMPLATE)
39
39
  const options = {
40
40
  placeholder: 'Nom ou code INSEE…',
41
41
  url: 'https://geo.api.gouv.fr/communes?nom={q}&limit=5',
@@ -1,6 +1,6 @@
1
- import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
3
2
  import * as Util from '../utils.js'
3
+ import * as DOMUtils from '../domutils.js'
4
4
 
5
5
  export class AutocompleteCommunes extends SingleMixin(BaseAjax) {
6
6
  createResult(item) {
@@ -29,13 +29,12 @@ export class Importer {
29
29
  }
30
30
 
31
31
  async open(importer) {
32
- const container = DomUtil.create('div')
33
- DomUtil.createTitle(container, this.name)
34
- DomUtil.element({
35
- tagName: 'p',
36
- parent: container,
37
- textContent: "Importer les contours d'une commune française.",
38
- })
32
+ const container = DOMUtils.loadTemplate(`
33
+ <div>
34
+ <h3>${this.name}</h3>
35
+ <p>Importer les contours d'une commune française.</p>
36
+ </div>
37
+ `)
39
38
  const options = {
40
39
  placeholder: 'Nom ou code INSEE…',
41
40
  url: 'https://geo.api.gouv.fr/communes?nom={q}&limit=5',
@@ -1,5 +1,5 @@
1
- import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { translate } from '../i18n.js'
2
+ import * as DOMUtils from '../domutils.js'
3
3
 
4
4
  export class Importer {
5
5
  constructor(map, options) {
@@ -9,20 +9,20 @@ export class Importer {
9
9
  }
10
10
 
11
11
  async open(importer) {
12
- const container = DomUtil.create('div', 'formbox')
13
- DomUtil.element({ tagName: 'h3', textContent: this.name, parent: container })
14
- const select = DomUtil.create('select', '', container)
15
- const noPreset = DomUtil.element({
16
- tagName: 'option',
17
- parent: select,
18
- value: '',
19
- textContent: translate('Choose a dataset'),
20
- })
12
+ const [container, { select }] = DOMUtils.loadTemplateWithRefs(`
13
+ <div class="formbox">
14
+ <h3>${this.name}</h3>
15
+ <select data-ref="select">
16
+ <option value="">${translate('Choose a dataset')}</option>
17
+ </select>
18
+ </div>
19
+ `)
20
+
21
21
  for (const dataset of this.choices) {
22
- const option = DomUtil.create('option', '', select)
23
- option.value = dataset.url
24
- option.textContent = dataset.label
25
- option.dataset.format = dataset.format || 'geojson'
22
+ const option = DOMUtils.loadTemplate(
23
+ `<option value="${dataset.url}" data-format="${dataset.format || 'geojson'}">${dataset.label}</option>`
24
+ )
25
+ select.appendChild(option)
26
26
  }
27
27
  const confirm = () => {
28
28
  if (select.value) {
@@ -1,8 +1,8 @@
1
- import { DomEvent, DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { uMapAlert as Alert } from '../../components/alerts/alert.js'
3
2
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
4
3
  import { translate } from '../i18n.js'
5
4
  import * as Utils from '../utils.js'
5
+ import * as DOMUtils from '../domutils.js'
6
6
 
7
7
  const BOUNDARY_TYPES = {
8
8
  admin_6: 'département',
@@ -14,18 +14,20 @@ const BOUNDARY_TYPES = {
14
14
  }
15
15
 
16
16
  const TEMPLATE = `
17
- <h3>GeoDataMine</h3>
18
- <p>${translate('GeoDataMine: thematic data from OpenStreetMap')}.</p>
19
- <div class="formbox">
20
- <select name="theme">
21
- <option value="">${translate('Choose a theme')}</option>
22
- </select>
23
- <label>
24
- <input type="checkbox" name="aspoint" />
25
- ${translate('Simplify all geometries to points')}
26
- </label>
27
- <label id="boundary">
28
- </label>
17
+ <div>
18
+ <h3>GeoDataMine</h3>
19
+ <p>${translate('GeoDataMine: thematic data from OpenStreetMap')}.</p>
20
+ <div class="formbox">
21
+ <select name="theme" data-ref="select">
22
+ <option value="">${translate('Choose a theme')}</option>
23
+ </select>
24
+ <label>
25
+ <input type="checkbox" name="aspoint" />
26
+ ${translate('Simplify all geometries to points')}
27
+ </label>
28
+ <label id="boundary">
29
+ </label>
30
+ </div>
29
31
  </div>
30
32
  `
31
33
 
@@ -49,20 +51,16 @@ export class Importer {
49
51
  async open(importer) {
50
52
  let boundary = null
51
53
  let boundaryName = null
52
- const container = DomUtil.create('div')
53
- container.innerHTML = TEMPLATE
54
+ const [container, { select }] = DOMUtils.loadTemplateWithRefs(TEMPLATE)
54
55
  const response = await this.umap.request.get(`${this.baseUrl}/themes`)
55
- const select = container.querySelector('select')
56
56
  if (response?.ok) {
57
57
  const { themes } = await response.json()
58
58
  themes.sort((a, b) => Utils.naturalSort(a['name:fr'], b['name:fr']))
59
59
  for (const theme of themes) {
60
- DomUtil.element({
61
- tagName: 'option',
62
- value: theme.id,
63
- textContent: theme['name:fr'],
64
- parent: select,
65
- })
60
+ const option = DOMUtils.loadTemplate(
61
+ `<option value="${theme.id}">${theme['name:fr']}</option>`
62
+ )
63
+ select.appendChild(option)
66
64
  }
67
65
  } else {
68
66
  console.error(response)
@@ -63,6 +63,16 @@ const PORTALS = [
63
63
  url: 'https://admin.geospm.com',
64
64
  platform: 'prodige',
65
65
  },
66
+ {
67
+ name: 'SNCF',
68
+ url: 'https://ressources.data.sncf.com',
69
+ platform: 'opendatasoft',
70
+ },
71
+ {
72
+ name: 'Réseau STAR Rennes',
73
+ url: 'https://data.explore.star.fr',
74
+ platform: 'opendatasoft',
75
+ },
66
76
  {
67
77
  name: 'Toulouse Métropole',
68
78
  url: 'https://data.toulouse-metropole.fr',
@@ -1,22 +1,24 @@
1
- import { DomUtil } from '../../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { uMapAlert as Alert } from '../../components/alerts/alert.js'
3
2
  import { BaseAjax, SingleMixin } from '../autocomplete.js'
4
3
  import { translate } from '../i18n.js'
4
+ import * as DOMUtils from '../domutils.js'
5
5
 
6
6
  const TEMPLATE = `
7
- <h3>Overpass</h3>
8
- <label>
9
- <span data-help="overpassImporter">${translate('Expression')}</span>
10
- <input type="text" placeholder="amenity=drinking_water" name="tags" />
11
- </label>
12
- <label>
13
- ${translate('Geometry mode')}
14
- <select name="out">
15
- <option value="geom" selected>${translate('Default')}</option>
16
- <option value="center">${translate('Only geometry centers')}</option>
17
- </select>
18
- </label>
19
- <label id="area"><span>${translate('Search area')}</span></label>
7
+ <div>
8
+ <h3>Overpass</h3>
9
+ <label>
10
+ <span data-help="overpassImporter">${translate('Expression')}</span>
11
+ <input type="text" placeholder="amenity=drinking_water" name="tags" data-ref="tags" />
12
+ </label>
13
+ <label>
14
+ ${translate('Geometry mode')}
15
+ <select name="out">
16
+ <option value="geom" selected>${translate('Default')}</option>
17
+ <option value="center">${translate('Only geometry centers')}</option>
18
+ </select>
19
+ </label>
20
+ <label data-ref="area" id="area"><span>${translate('Search area')}</span></label>
21
+ </div>
20
22
  `
21
23
 
22
24
  class Autocomplete extends SingleMixin(BaseAjax) {
@@ -57,12 +59,11 @@ export class Importer {
57
59
  }
58
60
 
59
61
  async open(importer) {
60
- const container = DomUtil.create('div')
61
- container.innerHTML = TEMPLATE
62
+ const [container, { area, tags }] = DOMUtils.loadTemplateWithRefs(TEMPLATE)
62
63
  if (this.expression) {
63
- container.querySelector('[name=tags]').value = this.expression
64
+ tags.value = this.expression
64
65
  }
65
- this.autocomplete = new Autocomplete(container.querySelector('#area'), {
66
+ this.autocomplete = new Autocomplete(area, {
66
67
  url: this.searchUrl,
67
68
  placeholder: translate(
68
69
  'Type area name, or let empty to load data in current map view'
@@ -1,8 +1,4 @@
1
1
  import * as Utils from './utils.js'
2
- import { translate } from './i18n.js'
3
- import Orderable from './orderable.js'
4
- import { uMapAlert as Alert } from '../components/alerts/alert.js'
5
- import { Form } from './form/builder.js'
6
2
 
7
3
  export class DataLayerManager extends Object {
8
4
  add(datalayer) {
@@ -11,7 +7,7 @@ export class DataLayerManager extends Object {
11
7
  active() {
12
8
  return Object.values(this)
13
9
  .filter((datalayer) => !datalayer.isDeleted)
14
- .sort((a, b) => a.rank > b.rank)
10
+ .sort((a, b) => a.rank - b.rank)
15
11
  }
16
12
  reverse() {
17
13
  return this.active().reverse()
@@ -116,263 +112,3 @@ export class FeatureManager extends Map {
116
112
  return this.all()[index - 1]
117
113
  }
118
114
  }
119
-
120
- export class FieldManager extends Map {
121
- constructor(parent, dialog) {
122
- super()
123
- this.parent = parent
124
- this.dialog = dialog
125
- this.parent.properties.fields ??= []
126
- this.pull()
127
- }
128
-
129
- pull() {
130
- this.clear()
131
- for (const field of this.parent.properties.fields) {
132
- this.add(field)
133
- }
134
- }
135
-
136
- push() {
137
- this.parent.properties.fields = this.all().map((field) => {
138
- // We don't want to keep the reference, otherwise editing
139
- // it will also change the old value
140
- return { ...field }
141
- })
142
- }
143
-
144
- async commit() {
145
- return new Promise((resolve) => {
146
- const oldFields = Utils.CopyJSON(this.parent.properties.fields)
147
- resolve()
148
- this.push()
149
- this.parent.sync.update(
150
- 'properties.fields',
151
- this.parent.properties.fields,
152
- oldFields
153
- )
154
- })
155
- }
156
-
157
- add(field) {
158
- if (!field?.key) {
159
- console.error('Invalid field', field)
160
- return
161
- }
162
- field.type ??= 'String'
163
- // Copy object, so not to affect original
164
- // when edited.
165
- this.set(field.key, { ...field })
166
- this.push()
167
- }
168
-
169
- delete(key) {
170
- super.delete(key)
171
- this.push()
172
- }
173
-
174
- all() {
175
- return Array.from(this.values())
176
- }
177
-
178
- edit(container) {
179
- const [root, { ul, add, manageFilters }] = Utils.loadTemplateWithRefs(`
180
- <details id="fields-management">
181
- <summary><h4>${translate('Manage Fields')}</h4></summary>
182
- <fieldset>
183
- <ul data-ref=ul></ul>
184
- <div class="button-bar half">
185
- <button type="button" data-ref=add>${translate('Add a new field')}</button>
186
- <button type="button" data-ref="manageFilters">${translate('Manage filters')}</button>
187
- </div>
188
- </fieldset>
189
- </details>
190
- `)
191
- container.appendChild(root)
192
- add.hidden = this.parent.isRemoteLayer?.()
193
- add.addEventListener('click', () => {
194
- this.editField().then(() => {
195
- this.parent.edit().then((panel) => {
196
- panel.scrollTo('details#fields-management')
197
- })
198
- })
199
- })
200
- manageFilters.addEventListener('click', () => this.parent.filters.edit())
201
- for (const field of this.all()) {
202
- const [row, { edit, del, addFilter, editFilter }] = Utils.loadTemplateWithRefs(
203
- `<li class="orderable with-toolbox" data-key="${field.key}">
204
- <span>
205
- <i class="icon icon-16 icon-field-${field.type}" title="${field.type}"></i>
206
- ${field.key}
207
- </span>
208
- <span>
209
- <button class="icon icon-16 icon-edit" title="${translate('Edit this field')}" data-ref=edit></button>
210
- <button class="icon icon-16 icon-filters" title="${translate('Edit filter')}" data-ref=editFilter></button>
211
- <button class="icon icon-16 icon-filters-empty" title="${translate('Add a filter for this field')}" data-ref=addFilter></button>
212
- <button class="icon icon-16 icon-delete" title="${translate('Delete this field')}" data-ref=del></button>
213
- <i class="icon icon-16 icon-drag" title="${translate('Drag to reorder')}"></i>
214
- </span>
215
- </li>`
216
- )
217
- editFilter.hidden = !this.parent.filters.has(field.key)
218
- addFilter.hidden = this.parent.filters.has(field.key)
219
- del.hidden = this.parent.isRemoteLayer?.()
220
- editFilter.addEventListener('click', () =>
221
- this.parent.filters.createFilterForm(field.key)
222
- )
223
- addFilter.addEventListener('click', () =>
224
- this.parent.filters.createFilterForm(field.key)
225
- )
226
- ul.appendChild(row)
227
- edit.addEventListener('click', () => {
228
- this.editField(field.key).then(() => {
229
- this.parent.edit().then((panel) => {
230
- panel.scrollTo('details#fields-management')
231
- })
232
- })
233
- })
234
- del.addEventListener('click', () => {
235
- this.confirmDelete(field.key).then(() => {
236
- this.parent.edit().then((panel) => {
237
- panel.scrollTo('details#fields-management')
238
- })
239
- })
240
- })
241
- }
242
- const onReorder = (src, dst, initialIndex, finalIndex) => {
243
- const orderedKeys = Array.from(ul.querySelectorAll('li')).map(
244
- (el) => el.dataset.key
245
- )
246
- const oldFields = Utils.CopyJSON(this.parent.properties.fields)
247
- const copy = Object.fromEntries(this)
248
- this.clear()
249
- for (const key of orderedKeys) {
250
- this.add(copy[key])
251
- }
252
- this.parent.sync.update(
253
- 'properties.fields',
254
- this.parent.properties.fields,
255
- oldFields
256
- )
257
- }
258
- const orderable = new Orderable(ul, onReorder)
259
- }
260
-
261
- async editField(name) {
262
- if (!name && this.parent.isRemoteLayer?.()) return
263
- const FIELD_TYPES = [
264
- 'String',
265
- 'Text',
266
- 'Number',
267
- 'Date',
268
- 'Datetime',
269
- 'Enum',
270
- 'Boolean',
271
- ]
272
- const field = this.get(name) || {}
273
- const metadatas = [
274
- [
275
- 'key',
276
- {
277
- handler: 'BlurInput',
278
- label: translate('Field Name'),
279
- disabled: this.parent.isRemoteLayer?.(),
280
- },
281
- ],
282
- [
283
- 'type',
284
- {
285
- handler: 'Select',
286
- selectOptions: FIELD_TYPES,
287
- label: translate('Field Type'),
288
- },
289
- ],
290
- ]
291
- const form = new Form(field, metadatas)
292
-
293
- const [container, { body, addFilter }] = Utils.loadTemplateWithRefs(`
294
- <div>
295
- <h3>${translate('Manage field')}</h3>
296
- <div data-ref=body></div>
297
- <button type="button" data-ref=addFilter hidden><i class="icon icon-16 icon-filters"></i>${translate('Add filter for this field')}</button>
298
- </div>
299
- `)
300
- body.appendChild(form.build())
301
- if (this.parent.filters) {
302
- addFilter.addEventListener('click', () => {
303
- this.dialog.accept()
304
- this.parent.filters.createFilterForm(field.key)
305
- })
306
- addFilter.hidden = false
307
- }
308
-
309
- return this.dialog.open({ template: container }).then(() => {
310
- if (!this.validateName(field.key, field.key !== name)) {
311
- this.pull()
312
- return
313
- }
314
- this.parent.sync.startBatch()
315
- const oldFields = Utils.CopyJSON(this.parent.properties.fields)
316
- if (!name) {
317
- this.add(field)
318
- } else if (name !== field.key) {
319
- this.clear()
320
- // Keep order on rename
321
- for (const old of oldFields) {
322
- if (old.key === name) {
323
- this.add(field)
324
- } else {
325
- this.add(old)
326
- }
327
- }
328
- this.parent.renameField(name, field.key)
329
- } else {
330
- this.push()
331
- }
332
- this.parent.sync.update(
333
- 'properties.fields',
334
- this.parent.properties.fields,
335
- oldFields
336
- )
337
- this.parent.sync.commitBatch()
338
- this.parent.render(['properties.fields'])
339
- })
340
- }
341
-
342
- validateName(name, isNew = false) {
343
- if (!name) {
344
- Alert.error(translate('Name cannot be empty.'))
345
- return false
346
- }
347
- if (name.includes('.')) {
348
- Alert.error(translate('Name “{name}” should not contain a dot.', { name }))
349
- return false
350
- }
351
- if (isNew && this.has(name)) {
352
- Alert.error(translate('This name already exists: “{name}”', { name }))
353
- return false
354
- }
355
- return true
356
- }
357
-
358
- async confirmDelete(name) {
359
- return this.dialog
360
- .confirm(translate('Are you sure you want to delete this field on all the data?'))
361
- .then(() => {
362
- this.parent.sync.startBatch()
363
- const oldFields = Utils.CopyJSON(this.parent.properties.fields)
364
- this.delete(name)
365
- this.push()
366
- if (this.parent.filters.has(name)) {
367
- this.parent.filters.remove(name)
368
- }
369
- this.parent.deleteField(name)
370
- this.parent.sync.update(
371
- 'properties.fields',
372
- this.parent.properties.fields,
373
- oldFields
374
- )
375
- this.parent.sync.commitBatch()
376
- })
377
- }
378
- }
@@ -1,4 +1,3 @@
1
- import { DomUtil } from '../../vendors/leaflet/leaflet-src.esm.js'
2
1
  import { uMapAlert as Alert } from '../components/alerts/alert.js'
3
2
  import { MutatingForm } from './form/builder.js'
4
3
  import { translate } from './i18n.js'
@@ -177,8 +176,11 @@ export class MapPermissions {
177
176
  Alert.info(translate('Please save the map first'))
178
177
  return
179
178
  }
180
- const container = DomUtil.create('div', 'umap-edit-permissions')
181
- DomUtil.createTitle(container, translate('Update permissions'), 'icon-key')
179
+ const container = DOMUtils.loadTemplate(`
180
+ <div class="umap-edit-permissions">
181
+ <h3><i class="icon icon-16 icon-key"></i> ${translate('Update permissions')}</h3>
182
+ </div>
183
+ `)
182
184
  if (this.isAnonymousMap()) this._editAnonymous(container)
183
185
  else this._editWithOwner(container)
184
186
  this._editDatalayers(container)