umap-project 1.12.2__py3-none-any.whl → 1.13.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 (158) 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 +82 -54
  4. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  5. umap/locale/cs_CZ/LC_MESSAGES/django.po +82 -54
  6. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/el/LC_MESSAGES/django.po +86 -58
  8. umap/locale/en/LC_MESSAGES/django.po +79 -51
  9. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  10. umap/locale/es/LC_MESSAGES/django.po +82 -54
  11. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  12. umap/locale/fr/LC_MESSAGES/django.po +84 -56
  13. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  14. umap/locale/hu/LC_MESSAGES/django.po +108 -80
  15. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  16. umap/locale/it/LC_MESSAGES/django.po +82 -54
  17. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/ms/LC_MESSAGES/django.po +82 -54
  19. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  20. umap/locale/pl/LC_MESSAGES/django.po +82 -54
  21. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  22. umap/locale/sv/LC_MESSAGES/django.po +82 -54
  23. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  24. umap/locale/zh_TW/LC_MESSAGES/django.po +86 -58
  25. umap/models.py +29 -0
  26. umap/static/umap/base.css +33 -5
  27. umap/static/umap/content.css +41 -2
  28. umap/static/umap/img/16.svg +12 -2
  29. umap/static/umap/img/source/16.svg +165 -820
  30. umap/static/umap/js/umap.browser.js +9 -3
  31. umap/static/umap/js/umap.controls.js +45 -217
  32. umap/static/umap/js/umap.core.js +66 -30
  33. umap/static/umap/js/umap.forms.js +18 -31
  34. umap/static/umap/js/umap.icon.js +44 -21
  35. umap/static/umap/js/umap.js +5 -26
  36. umap/static/umap/js/umap.layer.js +68 -25
  37. umap/static/umap/js/umap.popup.js +87 -0
  38. umap/static/umap/js/umap.share.js +254 -0
  39. umap/static/umap/js/umap.ui.js +4 -2
  40. umap/static/umap/locale/am_ET.js +19 -9
  41. umap/static/umap/locale/am_ET.json +19 -9
  42. umap/static/umap/locale/ar.js +19 -9
  43. umap/static/umap/locale/ar.json +19 -9
  44. umap/static/umap/locale/ast.js +19 -9
  45. umap/static/umap/locale/ast.json +19 -9
  46. umap/static/umap/locale/bg.js +19 -9
  47. umap/static/umap/locale/bg.json +19 -9
  48. umap/static/umap/locale/br.js +22 -12
  49. umap/static/umap/locale/br.json +22 -12
  50. umap/static/umap/locale/ca.js +19 -9
  51. umap/static/umap/locale/ca.json +19 -9
  52. umap/static/umap/locale/cs_CZ.js +19 -9
  53. umap/static/umap/locale/cs_CZ.json +19 -9
  54. umap/static/umap/locale/da.js +19 -9
  55. umap/static/umap/locale/da.json +19 -9
  56. umap/static/umap/locale/de.js +19 -9
  57. umap/static/umap/locale/de.json +19 -9
  58. umap/static/umap/locale/el.js +19 -9
  59. umap/static/umap/locale/el.json +19 -9
  60. umap/static/umap/locale/en.js +19 -9
  61. umap/static/umap/locale/en.json +19 -9
  62. umap/static/umap/locale/en_US.json +19 -9
  63. umap/static/umap/locale/es.js +19 -9
  64. umap/static/umap/locale/es.json +19 -9
  65. umap/static/umap/locale/et.js +19 -9
  66. umap/static/umap/locale/et.json +19 -9
  67. umap/static/umap/locale/fa_IR.js +19 -9
  68. umap/static/umap/locale/fa_IR.json +19 -9
  69. umap/static/umap/locale/fi.js +19 -9
  70. umap/static/umap/locale/fi.json +19 -9
  71. umap/static/umap/locale/fr.js +19 -9
  72. umap/static/umap/locale/fr.json +19 -9
  73. umap/static/umap/locale/gl.js +19 -9
  74. umap/static/umap/locale/gl.json +19 -9
  75. umap/static/umap/locale/he.js +19 -9
  76. umap/static/umap/locale/he.json +19 -9
  77. umap/static/umap/locale/hr.js +19 -9
  78. umap/static/umap/locale/hr.json +19 -9
  79. umap/static/umap/locale/hu.js +19 -9
  80. umap/static/umap/locale/hu.json +19 -9
  81. umap/static/umap/locale/id.js +19 -9
  82. umap/static/umap/locale/id.json +19 -9
  83. umap/static/umap/locale/is.js +19 -9
  84. umap/static/umap/locale/is.json +19 -9
  85. umap/static/umap/locale/it.js +19 -9
  86. umap/static/umap/locale/it.json +19 -9
  87. umap/static/umap/locale/ja.js +19 -9
  88. umap/static/umap/locale/ja.json +19 -9
  89. umap/static/umap/locale/ko.js +19 -9
  90. umap/static/umap/locale/ko.json +19 -9
  91. umap/static/umap/locale/lt.js +19 -9
  92. umap/static/umap/locale/lt.json +19 -9
  93. umap/static/umap/locale/ms.js +19 -9
  94. umap/static/umap/locale/ms.json +19 -9
  95. umap/static/umap/locale/nl.js +19 -9
  96. umap/static/umap/locale/nl.json +19 -9
  97. umap/static/umap/locale/no.js +19 -9
  98. umap/static/umap/locale/no.json +19 -9
  99. umap/static/umap/locale/pl.js +19 -9
  100. umap/static/umap/locale/pl.json +19 -9
  101. umap/static/umap/locale/pl_PL.json +19 -9
  102. umap/static/umap/locale/pt.js +19 -9
  103. umap/static/umap/locale/pt.json +19 -9
  104. umap/static/umap/locale/pt_BR.js +19 -9
  105. umap/static/umap/locale/pt_BR.json +19 -9
  106. umap/static/umap/locale/pt_PT.js +19 -9
  107. umap/static/umap/locale/pt_PT.json +19 -9
  108. umap/static/umap/locale/ro.js +19 -9
  109. umap/static/umap/locale/ro.json +19 -9
  110. umap/static/umap/locale/ru.js +19 -9
  111. umap/static/umap/locale/ru.json +19 -9
  112. umap/static/umap/locale/sk_SK.js +19 -9
  113. umap/static/umap/locale/sk_SK.json +19 -9
  114. umap/static/umap/locale/sl.js +19 -9
  115. umap/static/umap/locale/sl.json +19 -9
  116. umap/static/umap/locale/sr.js +19 -9
  117. umap/static/umap/locale/sr.json +19 -9
  118. umap/static/umap/locale/sv.js +19 -9
  119. umap/static/umap/locale/sv.json +19 -9
  120. umap/static/umap/locale/th_TH.js +19 -9
  121. umap/static/umap/locale/th_TH.json +19 -9
  122. umap/static/umap/locale/tr.js +19 -9
  123. umap/static/umap/locale/tr.json +19 -9
  124. umap/static/umap/locale/uk_UA.js +19 -9
  125. umap/static/umap/locale/uk_UA.json +19 -9
  126. umap/static/umap/locale/vi.js +19 -9
  127. umap/static/umap/locale/vi.json +19 -9
  128. umap/static/umap/locale/vi_VN.json +19 -9
  129. umap/static/umap/locale/zh.js +19 -9
  130. umap/static/umap/locale/zh.json +19 -9
  131. umap/static/umap/locale/zh_CN.json +19 -9
  132. umap/static/umap/locale/zh_TW.Big5.json +19 -9
  133. umap/static/umap/locale/zh_TW.js +55 -45
  134. umap/static/umap/locale/zh_TW.json +55 -45
  135. umap/static/umap/map.css +76 -9
  136. umap/static/umap/test/Map.Export.js +3 -3
  137. umap/static/umap/test/Polygon.js +2 -2
  138. umap/static/umap/test/Polyline.js +2 -0
  139. umap/static/umap/test/index.html +1 -0
  140. umap/static/umap/vendors/leaflet/leaflet-src.esm.js +7055 -7054
  141. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.js +1 -1
  142. umap/templates/auth/user_form.html +1 -1
  143. umap/templates/umap/content.html +1 -1
  144. umap/templates/umap/js.html +1 -0
  145. umap/templates/umap/map_list.html +1 -1
  146. umap/templates/umap/map_table.html +67 -35
  147. umap/templates/umap/user_dashboard.html +23 -1
  148. umap/templatetags/umap_tags.py +7 -27
  149. umap/tests/integration/test_edit_datalayer.py +45 -0
  150. umap/tests/integration/test_export_map.py +2 -3
  151. umap/tests/integration/test_facets_browser.py +86 -0
  152. umap/utils.py +17 -0
  153. umap/views.py +7 -18
  154. {umap_project-1.12.2.dist-info → umap_project-1.13.0.dist-info}/METADATA +4 -11
  155. {umap_project-1.12.2.dist-info → umap_project-1.13.0.dist-info}/RECORD +158 -155
  156. {umap_project-1.12.2.dist-info → umap_project-1.13.0.dist-info}/WHEEL +0 -0
  157. {umap_project-1.12.2.dist-info → umap_project-1.13.0.dist-info}/entry_points.txt +0 -0
  158. {umap_project-1.12.2.dist-info → umap_project-1.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -259,7 +259,7 @@ L.U.Map.include({
259
259
  }
260
260
  this.initShortcuts()
261
261
  this.onceDataLoaded(function () {
262
- if (L.Util.queryString('share')) this.renderShareBox()
262
+ if (L.Util.queryString('share')) this.share.open()
263
263
  else if (this.options.onLoadPanel === 'databrowser') this.openBrowser()
264
264
  else if (this.options.onLoadPanel === 'caption') this.displayCaption()
265
265
  else if (
@@ -352,6 +352,7 @@ L.U.Map.include({
352
352
  this.browser = new L.U.Browser(this)
353
353
  this.importer = new L.U.Importer(this)
354
354
  this.drop = new L.U.DropControl(this)
355
+ this.share = new L.U.Share(this)
355
356
  this._controls.tilelayers = new L.U.TileLayerControl(this)
356
357
  this._controls.tilelayers.setLayers()
357
358
 
@@ -853,28 +854,6 @@ L.U.Map.include({
853
854
  })
854
855
  },
855
856
 
856
- format: function (mode) {
857
- const type = this.EXPORT_TYPES[mode]
858
- const content = type.formatter(this)
859
- let name = this.options.name || 'data'
860
- name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
861
- const filename = name + type.ext
862
- return { content, filetype: type.filetype, filename }
863
- },
864
-
865
- download: function (mode) {
866
- const { content, filetype, filename } = this.format(mode)
867
- const blob = new Blob([content], { type: filetype })
868
- window.URL = window.URL || window.webkitURL
869
- const el = document.createElement('a')
870
- el.download = filename
871
- el.href = window.URL.createObjectURL(blob)
872
- el.style.display = 'none'
873
- document.body.appendChild(el)
874
- el.click()
875
- document.body.removeChild(el)
876
- },
877
-
878
857
  processFileToImport: function (file, layer, type) {
879
858
  type = type || L.Util.detectFileType(file)
880
859
  if (!type) {
@@ -1706,9 +1685,9 @@ L.U.Map.include({
1706
1685
  L.DomUtil.createButton(
1707
1686
  'button umap-download',
1708
1687
  advancedButtons,
1709
- L._('Open download panel'),
1710
- this.renderShareBox,
1711
- this
1688
+ L._('Open share & download panel'),
1689
+ this.share.open,
1690
+ this.share
1712
1691
  )
1713
1692
  },
1714
1693
 
@@ -1,6 +1,16 @@
1
1
  L.U.Layer = {
2
2
  canBrowse: true,
3
3
 
4
+ getType: function () {
5
+ const proto = Object.getPrototypeOf(this)
6
+ return proto.constructor.TYPE
7
+ },
8
+
9
+ getName: function () {
10
+ const proto = Object.getPrototypeOf(this)
11
+ return proto.constructor.NAME
12
+ },
13
+
4
14
  getFeatures: function () {
5
15
  return this._layers
6
16
  },
@@ -9,7 +19,7 @@ L.U.Layer = {
9
19
  return []
10
20
  },
11
21
 
12
- postUpdate: function () {},
22
+ onEdit: function () {},
13
23
 
14
24
  hasDataVisible: function () {
15
25
  return !!Object.keys(this._layers).length
@@ -17,7 +27,10 @@ L.U.Layer = {
17
27
  }
18
28
 
19
29
  L.U.Layer.Default = L.FeatureGroup.extend({
20
- _type: 'Default',
30
+ statics: {
31
+ NAME: L._('Default'),
32
+ TYPE: 'Default',
33
+ },
21
34
  includes: [L.U.Layer],
22
35
 
23
36
  initialize: function (datalayer) {
@@ -39,7 +52,10 @@ L.U.MarkerCluster = L.MarkerCluster.extend({
39
52
  })
40
53
 
41
54
  L.U.Layer.Cluster = L.MarkerClusterGroup.extend({
42
- _type: 'Cluster',
55
+ statics: {
56
+ NAME: L._('Clustered'),
57
+ TYPE: 'Cluster',
58
+ },
43
59
  includes: [L.U.Layer],
44
60
 
45
61
  initialize: function (datalayer) {
@@ -104,20 +120,23 @@ L.U.Layer.Cluster = L.MarkerClusterGroup.extend({
104
120
  ]
105
121
  },
106
122
 
107
- postUpdate: function (e) {
108
- if (e.helper.field === 'options.cluster.radius') {
123
+ onEdit: function (field, builder) {
124
+ if (field === 'options.cluster.radius') {
109
125
  // No way to reset radius of an already instanciated MarkerClusterGroup...
110
126
  this.datalayer.resetLayer(true)
111
127
  return
112
128
  }
113
- if (e.helper.field === 'options.color') {
129
+ if (field === 'options.color') {
114
130
  this.options.polygonOptions.color = this.datalayer.getColor()
115
131
  }
116
132
  },
117
133
  })
118
134
 
119
135
  L.U.Layer.Choropleth = L.FeatureGroup.extend({
120
- _type: 'Choropleth',
136
+ statics: {
137
+ NAME: L._('Choropleth'),
138
+ TYPE: 'Choropleth',
139
+ },
121
140
  includes: [L.U.Layer],
122
141
  canBrowse: true,
123
142
  // Have defaults that better suit the choropleth mode.
@@ -234,14 +253,17 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({
234
253
  L.FeatureGroup.prototype.onAdd.call(this, map)
235
254
  },
236
255
 
237
- postUpdate: function (e) {
238
- if (e.helper.field === 'options.choropleth.breaks') {
256
+ onEdit: function (field, builder) {
257
+ // If user touches the breaks, then force manual mode
258
+ if (field === 'options.choropleth.breaks') {
239
259
  this.datalayer.options.choropleth.mode = 'manual'
240
- e.helper.builder.helpers['options.choropleth.mode'].fetch()
260
+ builder.helpers['options.choropleth.mode'].fetch()
241
261
  }
242
262
  this.computeBreaks()
243
- if (e.helper.field !== 'options.choropleth.breaks') {
244
- e.helper.builder.helpers['options.choropleth.breaks'].fetch()
263
+ // If user changes the mode or the number of classes,
264
+ // then update the breaks input value
265
+ if (field === 'options.choropleth.mode' || field === 'options.choropleth.classes') {
266
+ builder.helpers['options.choropleth.breaks'].fetch()
245
267
  }
246
268
  },
247
269
 
@@ -317,7 +339,10 @@ L.U.Layer.Choropleth = L.FeatureGroup.extend({
317
339
  })
318
340
 
319
341
  L.U.Layer.Heat = L.HeatLayer.extend({
320
- _type: 'Heat',
342
+ statics: {
343
+ NAME: L._('Heatmap'),
344
+ TYPE: 'Heat',
345
+ },
321
346
  includes: [L.U.Layer],
322
347
  canBrowse: false,
323
348
 
@@ -382,12 +407,12 @@ L.U.Layer.Heat = L.HeatLayer.extend({
382
407
  ]
383
408
  },
384
409
 
385
- postUpdate: function (e) {
386
- if (e.helper.field === 'options.heat.intensityProperty') {
410
+ onEdit: function (field, builder) {
411
+ if (field === 'options.heat.intensityProperty') {
387
412
  this.datalayer.resetLayer(true) // We need to repopulate the latlngs
388
413
  return
389
414
  }
390
- if (e.helper.field === 'options.heat.radius') {
415
+ if (field === 'options.heat.radius') {
391
416
  this.options.radius = this.datalayer.options.heat.radius
392
417
  }
393
418
  this._updateOptions()
@@ -612,7 +637,7 @@ L.U.DataLayer = L.Evented.extend({
612
637
  // Only reset if type is defined (undefined is the default) and different from current type
613
638
  if (
614
639
  this.layer &&
615
- (!this.options.type || this.options.type === this.layer._type) &&
640
+ (!this.options.type || this.options.type === this.layer.getType()) &&
616
641
  !force
617
642
  ) {
618
643
  return
@@ -1185,6 +1210,28 @@ L.U.DataLayer = L.Evented.extend({
1185
1210
  })
1186
1211
  container.appendChild(builder.build())
1187
1212
 
1213
+ const redrawCallback = function (e) {
1214
+ const field = e.helper.field,
1215
+ builder = e.helper.builder
1216
+ this.hide()
1217
+ this.layer.onEdit(field, builder)
1218
+ this.show()
1219
+ }
1220
+
1221
+ const layerOptions = this.layer.getEditableOptions()
1222
+
1223
+ if (layerOptions.length) {
1224
+ builder = new L.U.FormBuilder(this, layerOptions, {
1225
+ id: 'datalayer-layer-properties',
1226
+ callback: redrawCallback,
1227
+ })
1228
+ const layerProperties = L.DomUtil.createFieldset(
1229
+ container,
1230
+ `${this.layer.getName()}: ${L._('settings')}`
1231
+ )
1232
+ layerProperties.appendChild(builder.build())
1233
+ }
1234
+
1188
1235
  let shapeOptions = [
1189
1236
  'options.color',
1190
1237
  'options.iconClass',
@@ -1198,12 +1245,6 @@ L.U.DataLayer = L.Evented.extend({
1198
1245
  'options.fillOpacity',
1199
1246
  ]
1200
1247
 
1201
- const redrawCallback = function (e) {
1202
- this.hide()
1203
- this.layer.postUpdate(e)
1204
- this.show()
1205
- }
1206
-
1207
1248
  builder = new L.U.FormBuilder(this, shapeOptions, {
1208
1249
  id: 'datalayer-advanced-properties',
1209
1250
  callback: redrawCallback,
@@ -1220,8 +1261,6 @@ L.U.DataLayer = L.Evented.extend({
1220
1261
  'options.labelKey',
1221
1262
  ]
1222
1263
 
1223
- optionsFields = optionsFields.concat(this.layer.getEditableOptions())
1224
-
1225
1264
  builder = new L.U.FormBuilder(this, optionsFields, {
1226
1265
  id: 'datalayer-advanced-properties',
1227
1266
  callback: redrawCallback,
@@ -1443,6 +1482,10 @@ L.U.DataLayer = L.Evented.extend({
1443
1482
  return !!this.options.browsable && this.canBrowse() && this.isVisible()
1444
1483
  },
1445
1484
 
1485
+ count: function () {
1486
+ return this._index.length
1487
+ },
1488
+
1446
1489
  hasData: function () {
1447
1490
  return !!this._index.length
1448
1491
  },
@@ -251,3 +251,90 @@ L.U.PopupTemplate.GeoRSSLink = L.U.PopupTemplate.Default.extend({
251
251
  return a
252
252
  },
253
253
  })
254
+
255
+ L.U.PopupTemplate.OSM = L.U.PopupTemplate.Default.extend({
256
+ options: {
257
+ className: 'umap-openstreetmap',
258
+ },
259
+
260
+ getName: function () {
261
+ const props = this.feature.properties
262
+ if (L.locale && props[`name:${L.locale}`]) return props[`name:${L.locale}`]
263
+ return props.name
264
+ },
265
+
266
+ renderBody: function () {
267
+ const props = this.feature.properties
268
+ const container = L.DomUtil.add('div')
269
+ const title = L.DomUtil.add('h3', 'popup-title', container)
270
+ const color = this.feature.getDynamicOption('color')
271
+ title.style.backgroundColor = color
272
+ const iconUrl = this.feature.getDynamicOption('iconUrl')
273
+ let icon = L.U.Icon.makeIconElement(iconUrl, title)
274
+ L.DomUtil.addClass(icon, 'icon')
275
+ L.U.Icon.setIconContrast(icon, title, iconUrl, color)
276
+ if (L.DomUtil.contrastedColor(title, color)) title.style.color = 'white'
277
+ L.DomUtil.add('span', '', title, this.getName())
278
+ const street = props['addr:street']
279
+ if (street) {
280
+ const row = L.DomUtil.add('address', 'address', container)
281
+ const number = props['addr:housenumber']
282
+ if (number) {
283
+ // Poor way to deal with international forms of writting addresses
284
+ L.DomUtil.add('span', '', row, `${L._('No.')}: ${number}`)
285
+ L.DomUtil.add('span', '', row, `${L._('Street')}: ${street}`)
286
+ } else {
287
+ L.DomUtil.add('span', '', row, street)
288
+ }
289
+ }
290
+ if (props.website) {
291
+ L.DomUtil.element(
292
+ 'a',
293
+ { href: props.website, textContent: props.website },
294
+ container
295
+ )
296
+ }
297
+ const phone = props.phone || props['contact:phone']
298
+ if (phone) {
299
+ L.DomUtil.add(
300
+ 'div',
301
+ '',
302
+ container,
303
+ L.DomUtil.element('a', { href: `tel:${phone}`, textContent: phone })
304
+ )
305
+ }
306
+ if (props.mobile) {
307
+ L.DomUtil.add(
308
+ 'div',
309
+ '',
310
+ container,
311
+ L.DomUtil.element('a', {
312
+ href: `tel:${props.mobile}`,
313
+ textContent: props.mobile,
314
+ })
315
+ )
316
+ }
317
+ const email = props.email || props['contact:email']
318
+ if (email) {
319
+ L.DomUtil.add(
320
+ 'div',
321
+ '',
322
+ container,
323
+ L.DomUtil.element('a', { href: `mailto:${email}`, textContent: email })
324
+ )
325
+ }
326
+ const id = props['@id']
327
+ if (id) {
328
+ L.DomUtil.add(
329
+ 'div',
330
+ 'osm-link',
331
+ container,
332
+ L.DomUtil.element('a', {
333
+ href: `https://www.openstreetmap.org/${id}`,
334
+ textContent: L._('See on OpenStreetMap'),
335
+ })
336
+ )
337
+ }
338
+ return container
339
+ },
340
+ })
@@ -0,0 +1,254 @@
1
+ L.U.Share = L.Class.extend({
2
+ EXPORT_TYPES: {
3
+ geojson: {
4
+ formatter: function (map) {
5
+ return JSON.stringify(map.toGeoJSON(), null, 2)
6
+ },
7
+ ext: '.geojson',
8
+ filetype: 'application/json',
9
+ },
10
+ gpx: {
11
+ formatter: function (map) {
12
+ return togpx(map.toGeoJSON())
13
+ },
14
+ ext: '.gpx',
15
+ filetype: 'application/gpx+xml',
16
+ },
17
+ kml: {
18
+ formatter: function (map) {
19
+ return tokml(map.toGeoJSON())
20
+ },
21
+ ext: '.kml',
22
+ filetype: 'application/vnd.google-earth.kml+xml',
23
+ },
24
+ csv: {
25
+ formatter: function (map) {
26
+ const table = []
27
+ map.eachFeature((feature) => {
28
+ const row = feature.toGeoJSON()['properties'],
29
+ center = feature.getCenter()
30
+ delete row['_umap_options']
31
+ row['Latitude'] = center.lat
32
+ row['Longitude'] = center.lng
33
+ table.push(row)
34
+ })
35
+ return csv2geojson.dsv.csvFormat(table)
36
+ },
37
+ ext: '.csv',
38
+ filetype: 'text/csv',
39
+ },
40
+ },
41
+
42
+ initialize: function (map) {
43
+ this.map = map
44
+ },
45
+
46
+ build: function () {
47
+ this.container = L.DomUtil.create('div', 'umap-share')
48
+ this.title = L.DomUtil.create('h3', '', this.container)
49
+ this.title.textContent = L._('Share and download')
50
+
51
+ L.DomUtil.createCopiableInput(
52
+ this.container,
53
+ L._('Link to view the map'),
54
+ window.location.protocol + L.Util.getBaseUrl()
55
+ )
56
+
57
+ if (this.map.options.shortUrl) {
58
+ L.DomUtil.createCopiableInput(
59
+ this.container,
60
+ L._('Short link'),
61
+ this.map.options.shortUrl
62
+ )
63
+ }
64
+
65
+ L.DomUtil.create('hr', '', this.container)
66
+
67
+ L.DomUtil.add('h4', '', this.container, L._('Download'))
68
+ L.DomUtil.add('small', 'label', this.container, L._("Only visible layers' data"))
69
+ for (const key in this.EXPORT_TYPES) {
70
+ if (this.EXPORT_TYPES.hasOwnProperty(key)) {
71
+ L.DomUtil.createButton(
72
+ 'download-file',
73
+ this.container,
74
+ this.EXPORT_TYPES[key].name || key,
75
+ () => this.download(key),
76
+ this
77
+ )
78
+ }
79
+ }
80
+ L.DomUtil.create('div', 'vspace', this.container)
81
+ L.DomUtil.add(
82
+ 'small',
83
+ 'label',
84
+ this.container,
85
+ L._('All data and settings of the map')
86
+ )
87
+ const downloadUrl = L.Util.template(this.map.options.urls.map_download, {
88
+ map_id: this.map.options.umap_id,
89
+ })
90
+ const link = L.DomUtil.createLink(
91
+ 'download-backup',
92
+ this.container,
93
+ L._('full backup'),
94
+ downloadUrl
95
+ )
96
+ let name = this.map.options.name || 'data'
97
+ name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
98
+ link.setAttribute('download', `${name}.umap`)
99
+ L.DomUtil.create('hr', '', this.container)
100
+
101
+ const embedTitle = L.DomUtil.add('h4', '', this.container, L._('Embed the map'))
102
+ const iframe = L.DomUtil.create('textarea', 'umap-share-iframe', this.container)
103
+ const urlTitle = L.DomUtil.add('h4', '', this.container, L._('Direct link'))
104
+ const exportUrl = L.DomUtil.createCopiableInput(
105
+ this.container,
106
+ L._('Share this link to open a customized map view'),
107
+ ''
108
+ )
109
+
110
+ exportUrl.type = 'text'
111
+ const UIFields = [
112
+ ['dimensions.width', { handler: 'Input', label: L._('width') }],
113
+ ['dimensions.height', { handler: 'Input', label: L._('height') }],
114
+ [
115
+ 'options.includeFullScreenLink',
116
+ { handler: 'Switch', label: L._('Include full screen link?') },
117
+ ],
118
+ [
119
+ 'options.currentView',
120
+ { handler: 'Switch', label: L._('Current view instead of default map view?') },
121
+ ],
122
+ [
123
+ 'options.keepCurrentDatalayers',
124
+ { handler: 'Switch', label: L._('Keep current visible layers') },
125
+ ],
126
+ [
127
+ 'options.viewCurrentFeature',
128
+ { handler: 'Switch', label: L._('Open current feature on load') },
129
+ ],
130
+ 'queryString.moreControl',
131
+ 'queryString.scrollWheelZoom',
132
+ 'queryString.miniMap',
133
+ 'queryString.scaleControl',
134
+ 'queryString.onLoadPanel',
135
+ 'queryString.captionBar',
136
+ 'queryString.captionMenus',
137
+ ]
138
+ for (let i = 0; i < this.map.HIDDABLE_CONTROLS.length; i++) {
139
+ UIFields.push(`queryString.${this.map.HIDDABLE_CONTROLS[i]}Control`)
140
+ }
141
+ const iframeExporter = new L.U.IframeExporter(this.map)
142
+ const buildIframeCode = () => {
143
+ iframe.innerHTML = iframeExporter.build()
144
+ exportUrl.value = window.location.protocol + iframeExporter.buildUrl()
145
+ }
146
+ buildIframeCode()
147
+ const builder = new L.U.FormBuilder(iframeExporter, UIFields, {
148
+ callback: buildIframeCode,
149
+ })
150
+ const iframeOptions = L.DomUtil.createFieldset(
151
+ this.container,
152
+ L._('Embed and link options')
153
+ )
154
+ iframeOptions.appendChild(builder.build())
155
+ },
156
+
157
+ open: function () {
158
+ if (!this.container) this.build()
159
+ this.map.ui.openPanel({ data: { html: this.container } })
160
+ },
161
+
162
+ format: function (mode) {
163
+ const type = this.EXPORT_TYPES[mode]
164
+ const content = type.formatter(this.map)
165
+ let name = this.map.options.name || 'data'
166
+ name = name.replace(/[^a-z0-9]/gi, '_').toLowerCase()
167
+ const filename = name + type.ext
168
+ return { content, filetype: type.filetype, filename }
169
+ },
170
+
171
+ download: function (mode) {
172
+ const { content, filetype, filename } = this.format(mode)
173
+ const blob = new Blob([content], { type: filetype })
174
+ window.URL = window.URL || window.webkitURL
175
+ const el = document.createElement('a')
176
+ el.download = filename
177
+ el.href = window.URL.createObjectURL(blob)
178
+ el.style.display = 'none'
179
+ document.body.appendChild(el)
180
+ el.click()
181
+ document.body.removeChild(el)
182
+ },
183
+ })
184
+
185
+ L.U.IframeExporter = L.Evented.extend({
186
+ options: {
187
+ includeFullScreenLink: true,
188
+ currentView: false,
189
+ keepCurrentDatalayers: false,
190
+ viewCurrentFeature: false,
191
+ },
192
+
193
+ queryString: {
194
+ scaleControl: false,
195
+ miniMap: false,
196
+ scrollWheelZoom: false,
197
+ zoomControl: true,
198
+ editMode: 'disabled',
199
+ moreControl: true,
200
+ searchControl: null,
201
+ tilelayersControl: null,
202
+ embedControl: null,
203
+ datalayersControl: true,
204
+ onLoadPanel: 'none',
205
+ captionBar: false,
206
+ captionMenus: true,
207
+ },
208
+
209
+ dimensions: {
210
+ width: '100%',
211
+ height: '300px',
212
+ },
213
+
214
+ initialize: function (map) {
215
+ this.map = map
216
+ this.baseUrl = L.Util.getBaseUrl()
217
+ // Use map default, not generic default
218
+ this.queryString.onLoadPanel = this.map.options.onLoadPanel
219
+ },
220
+
221
+ getMap: function () {
222
+ return this.map
223
+ },
224
+
225
+ buildUrl: function (options) {
226
+ const datalayers = []
227
+ if (this.options.viewCurrentFeature && this.map.currentFeature) {
228
+ this.queryString.feature = this.map.currentFeature.getSlug()
229
+ }
230
+ if (this.options.keepCurrentDatalayers) {
231
+ this.map.eachDataLayer((datalayer) => {
232
+ if (datalayer.isVisible() && datalayer.umap_id) {
233
+ datalayers.push(datalayer.umap_id)
234
+ }
235
+ })
236
+ this.queryString.datalayers = datalayers.join(',')
237
+ } else {
238
+ delete this.queryString.datalayers
239
+ }
240
+ const currentView = this.options.currentView ? window.location.hash : ''
241
+ const queryString = L.extend({}, this.queryString, options)
242
+ return `${this.baseUrl}?${L.Util.buildQueryString(queryString)}${currentView}`
243
+ },
244
+
245
+ build: function () {
246
+ const iframeUrl = this.buildUrl()
247
+ let code = `<iframe width="${this.dimensions.width}" height="${this.dimensions.height}" frameborder="0" allowfullscreen allow="geolocation" src="${iframeUrl}"></iframe>`
248
+ if (this.options.includeFullScreenLink) {
249
+ const fullUrl = this.buildUrl({ scrollWheelZoom: true })
250
+ code += `<p><a href="${fullUrl}">${L._('See full screen')}</a></p>`
251
+ }
252
+ return code
253
+ },
254
+ })
@@ -64,8 +64,10 @@ L.U.UI = L.Evented.extend({
64
64
  },
65
65
 
66
66
  closePanel: function () {
67
- L.DomUtil.removeClass(this.parent, 'umap-ui')
68
- this.fire('panel:closed')
67
+ if (L.DomUtil.hasClass(this.parent, 'umap-ui')) {
68
+ L.DomUtil.removeClass(this.parent, 'umap-ui')
69
+ this.fire('panel:closed')
70
+ }
69
71
  },
70
72
 
71
73
  alert: function (e) {
@@ -145,7 +145,6 @@ const locale = {
145
145
  "Display measure": "Display measure",
146
146
  "Display on load": "በመጫን ላይ እያለ አሳይ",
147
147
  "Download": "Download",
148
- "Download data": "መረጃውን አውርድ",
149
148
  "Drag to reorder": "Drag to reorder",
150
149
  "Draw a marker": "መለያ ሳል",
151
150
  "Draw a polygon": "ፖሊጎን ሳል",
@@ -210,8 +209,6 @@ const locale = {
210
209
  "Must be a valid CSS value (eg.: DarkBlue or #123456)": "Must be a valid CSS value (eg.: DarkBlue or #123456)",
211
210
  "No licence has been set": "ምንም ፈቃድ አልተሰጠም",
212
211
  "No results": "No results",
213
- "Only visible features will be downloaded.": "የሚታዩት ፊቸሮች ብቻ ይወርዳሉ",
214
- "Open download panel": "Open download panel",
215
212
  "Open link in…": "Open link in…",
216
213
  "Open this map extent in a map editor to provide more accurate data to OpenStreetMap": "ለOpernStreetMap ይበልጥ ትክክል ይሆነ መረጃ ለመስጠ የካርታውን ኤክስቴንት በካርታ ማረሚያ ክፈት",
217
214
  "Optional intensity property for heatmap": "ለሙቀት ካርታው ባህርይ አማራጭ ኢንቴንሲቲ",
@@ -243,7 +240,6 @@ const locale = {
243
240
  "See full screen": "ሙሉውን ስክሪን ተመልከት",
244
241
  "Set it to false to hide this layer from the slideshow, the data browser, the popup navigation…": "Set it to false to hide this layer from the slideshow, the data browser, the popup navigation…",
245
242
  "Shape properties": "Shape properties",
246
- "Short URL": "አጭር የድረ-ገፅ መገኛ",
247
243
  "Short credits": "አጭር ክሬዲት",
248
244
  "Show/hide layer": "ሌየሩን አሳይ/ደብቅ",
249
245
  "Simple link: [[http://example.com]]": "ቀላል መገኛ: [[http://example.com]]",
@@ -363,7 +359,6 @@ const locale = {
363
359
  "Star this map": "Star this map",
364
360
  "Symbol can be either a unicode character or an URL. You can use feature properties as variables: ex.: with \"http://myserver.org/images/{name}.png\", the {name} variable will be replaced by the \"name\" value of each marker.": "Symbol can be either a unicode character or an URL. You can use feature properties as variables: ex.: with \"http://myserver.org/images/{name}.png\", the {name} variable will be replaced by the \"name\" value of each marker.",
365
361
  "Direct link": "Direct link",
366
- "Export options": "Export options",
367
362
  "The zoom and center have been modified.": "The zoom and center have been modified.",
368
363
  "Congratulations, your map has been created!": "Congratulations, your map has been created!",
369
364
  "Copy link": "Copy link",
@@ -421,8 +416,6 @@ const locale = {
421
416
  "Update who can see and edit the map": "Update who can see and edit the map",
422
417
  "View": "View",
423
418
  "Add image URL": "Add image URL",
424
- "Backup data": "Backup data",
425
- "Download full data": "Download full data",
426
419
  "Emoji & Character": "Emoji & Character",
427
420
  "Generic": "Generic",
428
421
  "Symbol": "Symbol",
@@ -430,8 +423,25 @@ const locale = {
430
423
  "URL": "URL",
431
424
  "If false, the polygon or line will act as a part of the underlying map.": "If false, the polygon or line will act as a part of the underlying map.",
432
425
  "Save map": "Save map",
433
- "Share, download and embed this map": "Share, download and embed this map",
434
- "Toggle edit mode": "Toggle edit mode"
426
+ "Toggle edit mode": "Toggle edit mode",
427
+ "All data and settings of the map": "All data and settings of the map",
428
+ "Embed and link options": "Embed and link options",
429
+ "Go to \"{coords}\"": "Go to \"{coords}\"",
430
+ "Link to view the map": "Link to view the map",
431
+ "No.": "No.",
432
+ "Only visible layers' data": "Only visible layers' data",
433
+ "Open share & download panel": "Open share & download panel",
434
+ "OpenStreetMap": "OpenStreetMap",
435
+ "See on OpenStreetMap": "See on OpenStreetMap",
436
+ "Share and download": "Share and download",
437
+ "Share this link to open a customized map view": "Share this link to open a customized map view",
438
+ "Short link": "Short link",
439
+ "Street": "Street",
440
+ "Type a place name or coordinates": "Type a place name or coordinates",
441
+ "copy": "copy",
442
+ "full backup": "full backup",
443
+ "settings": "settings",
444
+ "{count} features in this layer": "{count} features in this layer"
435
445
  }
436
446
  L.registerLocale("am_ET", locale)
437
447
  L.setLocale("am_ET")