umap-project 2.1.1__py3-none-any.whl → 2.1.3__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.

Potentially problematic release.


This version of umap-project might be problematic. Click here for more details.

Files changed (44) hide show
  1. umap/__init__.py +1 -1
  2. umap/models.py +20 -11
  3. umap/static/umap/js/modules/request.js +1 -1
  4. umap/static/umap/js/umap.controls.js +29 -0
  5. umap/static/umap/js/umap.features.js +3 -1
  6. umap/static/umap/js/umap.importer.js +4 -5
  7. umap/static/umap/js/umap.js +27 -36
  8. umap/static/umap/js/umap.layer.js +7 -6
  9. umap/static/umap/test/Map.js +0 -304
  10. umap/static/umap/test/Polygon.js +0 -256
  11. umap/static/umap/test/Polyline.js +0 -116
  12. umap/static/umap/test/index.html +1 -4
  13. umap/tests/conftest.py +9 -0
  14. umap/tests/fixtures/test_upload_data.csv +2 -1
  15. umap/tests/fixtures/test_upload_data.umap +171 -0
  16. umap/tests/fixtures/test_upload_data_osm.json +33 -0
  17. umap/tests/integration/conftest.py +5 -0
  18. umap/tests/integration/test_anonymous_owned_map.py +3 -0
  19. umap/tests/integration/test_browser.py +4 -11
  20. umap/tests/integration/test_choropleth.py +89 -0
  21. umap/tests/integration/test_collaborative_editing.py +30 -1
  22. umap/tests/integration/test_datalayer.py +130 -0
  23. umap/tests/integration/test_edit_datalayer.py +134 -0
  24. umap/tests/integration/test_edit_map.py +15 -0
  25. umap/tests/integration/test_facets_browser.py +31 -0
  26. umap/tests/integration/test_import.py +347 -2
  27. umap/tests/integration/test_map.py +17 -37
  28. umap/tests/integration/test_owned_map.py +18 -0
  29. umap/tests/integration/test_picto.py +20 -33
  30. umap/tests/integration/test_polygon.py +363 -0
  31. umap/tests/integration/test_polyline.py +325 -0
  32. umap/tests/integration/test_tableeditor.py +27 -0
  33. umap/tests/test_datalayer.py +31 -17
  34. umap/views.py +2 -1
  35. {umap_project-2.1.1.dist-info → umap_project-2.1.3.dist-info}/METADATA +4 -4
  36. {umap_project-2.1.1.dist-info → umap_project-2.1.3.dist-info}/RECORD +39 -36
  37. umap/static/umap/test/Choropleth.js +0 -245
  38. umap/static/umap/test/DataLayer.js +0 -463
  39. umap/static/umap/test/Permissions.js +0 -74
  40. umap/static/umap/test/TableEditor.js +0 -104
  41. umap/tests/integration/test_drawing.py +0 -243
  42. {umap_project-2.1.1.dist-info → umap_project-2.1.3.dist-info}/WHEEL +0 -0
  43. {umap_project-2.1.1.dist-info → umap_project-2.1.3.dist-info}/entry_points.txt +0 -0
  44. {umap_project-2.1.1.dist-info → umap_project-2.1.3.dist-info}/licenses/LICENSE +0 -0
umap/__init__.py CHANGED
@@ -1 +1 @@
1
- VERSION = "2.1.1"
1
+ VERSION = "2.1.3"
umap/models.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import json
2
+ import operator
2
3
  import os
3
4
  import time
4
5
  import uuid
@@ -442,6 +443,8 @@ class DataLayer(NamedModel):
442
443
  "name": self.name,
443
444
  "displayOnLoad": self.display_on_load,
444
445
  }
446
+ if self.old_id:
447
+ obj["old_id"] = self.old_id
445
448
  obj["id"] = self.pk
446
449
  obj["permissions"] = {"edit_status": self.edit_status}
447
450
  obj["editMode"] = "advanced" if self.can_edit(user, request) else "disabled"
@@ -471,17 +474,14 @@ class DataLayer(NamedModel):
471
474
  "size": self.geojson.storage.size(self.get_version_path(name)),
472
475
  }
473
476
 
474
- def get_versions(self):
477
+ @property
478
+ def versions(self):
475
479
  root = self.storage_root()
476
480
  names = self.geojson.storage.listdir(root)[1]
477
481
  names = [name for name in names if self.is_valid_version(name)]
478
- names.sort(reverse=True) # Recent first.
479
- return names
480
-
481
- @property
482
- def versions(self):
483
- names = self.get_versions()
484
- return [self.version_metadata(name) for name in names]
482
+ versions = [self.version_metadata(name) for name in names]
483
+ versions.sort(reverse=True, key=operator.itemgetter("at"))
484
+ return versions
485
485
 
486
486
  def get_version(self, name):
487
487
  path = self.get_version_path(name)
@@ -493,8 +493,13 @@ class DataLayer(NamedModel):
493
493
 
494
494
  def purge_old_versions(self):
495
495
  root = self.storage_root()
496
- names = self.get_versions()[settings.UMAP_KEEP_VERSIONS :]
497
- for name in names:
496
+ versions = self.versions[settings.UMAP_KEEP_VERSIONS :]
497
+ for version in versions:
498
+ name = version["name"]
499
+ # Should not be in the list, but ensure to not delete the file
500
+ # currently used in database
501
+ if self.geojson.name.endswith(name):
502
+ continue
498
503
  try:
499
504
  self.geojson.storage.delete(os.path.join(root, name))
500
505
  except FileNotFoundError:
@@ -503,8 +508,12 @@ class DataLayer(NamedModel):
503
508
  def purge_gzip(self):
504
509
  root = self.storage_root()
505
510
  names = self.geojson.storage.listdir(root)[1]
511
+ prefixes = [f"{self.pk}_"]
512
+ if self.old_id:
513
+ prefixes.append(f"{self.old_id}_")
514
+ prefixes = tuple(prefixes)
506
515
  for name in names:
507
- if name.startswith(f"{self.pk}_") and name.endswith(".gz"):
516
+ if name.startswith(prefixes) and name.endswith(".gz"):
508
517
  self.geojson.storage.delete(os.path.join(root, name))
509
518
 
510
519
  def can_edit(self, user=None, request=None):
@@ -146,7 +146,7 @@ export class ServerRequest extends Request {
146
146
  _onNOK(error) {
147
147
  if (error.status === 403) {
148
148
  this.ui.alert({
149
- content: message || L._('Action not allowed :('),
149
+ content: error.message || L._('Action not allowed :('),
150
150
  level: 'error',
151
151
  })
152
152
  }
@@ -1234,6 +1234,35 @@ U.StarControl = L.Control.extend({
1234
1234
  },
1235
1235
  })
1236
1236
 
1237
+ /*
1238
+ * Take control over L.Control.Locate to be able to
1239
+ * call start() before adding the control (and thus the button) to the map.
1240
+ */
1241
+ U.Locate = L.Control.Locate.extend({
1242
+ initialize: function (map, options) {
1243
+ // When calling start(), it will try to add a location marker
1244
+ // on the layer, which is normally added in the addTo/onAdd method
1245
+ this._layer = this.options.layer = new L.LayerGroup()
1246
+ // When calling start(), it will call _activate(), which then adds
1247
+ // location related event listeners on the map
1248
+ this.map = map
1249
+ L.Control.Locate.prototype.initialize.call(this, options)
1250
+ },
1251
+
1252
+ onAdd: function (map) {
1253
+ const active = this._active
1254
+ const container = L.Control.Locate.prototype.onAdd.call(this, map)
1255
+ this._active = active
1256
+ return container
1257
+ },
1258
+
1259
+ _activate: function () {
1260
+ this._map = this.map
1261
+ L.Control.Locate.prototype._activate.call(this)
1262
+ this._map = null
1263
+ }
1264
+ })
1265
+
1237
1266
  U.Search = L.PhotonSearch.extend({
1238
1267
  initialize: function (map, input, options) {
1239
1268
  this.options.placeholder = L._('Type a place name or coordinates')
@@ -888,7 +888,9 @@ U.PathMixin = {
888
888
  const other = new (this instanceof U.Polyline ? U.Polyline : U.Polygon)(
889
889
  this.map,
890
890
  shape,
891
- { geojson: { properties: properties } }
891
+ {
892
+ geojson: { properties },
893
+ }
892
894
  )
893
895
  this.datalayer.addLayer(other)
894
896
  other.edit()
@@ -39,11 +39,10 @@ U.Importer = L.Class.extend({
39
39
  this.container,
40
40
  L._('Choose the layer to import in')
41
41
  )
42
- this.clearLabel = L.DomUtil.add(
42
+ this.clearLabel = L.DomUtil.element(
43
43
  'label',
44
- '',
45
- this.container,
46
- L._('Replace layer content')
44
+ { textContent: L._('Replace layer content'), for: 'datalayer-clear-check' },
45
+ this.container
47
46
  )
48
47
  this.submitInput = L.DomUtil.element(
49
48
  'input',
@@ -59,7 +58,7 @@ U.Importer = L.Class.extend({
59
58
  )
60
59
  this.clearFlag = L.DomUtil.element(
61
60
  'input',
62
- { type: 'checkbox', name: 'clear' },
61
+ { type: 'checkbox', name: 'clear', id: 'datalayer-clear-check' },
63
62
  this.clearLabel
64
63
  )
65
64
  let option
@@ -67,14 +67,15 @@ U.Map = L.Map.extend({
67
67
  this.description = this.options.description
68
68
  this.demoTileInfos = this.options.demoTileInfos
69
69
  this.options.zoomControl = zoomControl !== undefined ? zoomControl : true
70
- this.options.fullscreenControl = fullscreenControl !== undefined ? fullscreenControl : true
71
- this.datalayersOnLoad = L.Util.queryString('datalayers')
72
- if (this.datalayersOnLoad) {
73
- this.datalayersOnLoad = this.datalayersOnLoad.toString().split(',')
70
+ this.options.fullscreenControl =
71
+ fullscreenControl !== undefined ? fullscreenControl : true
72
+ this.datalayersFromQueryString = L.Util.queryString('datalayers')
73
+ if (this.datalayersFromQueryString) {
74
+ this.datalayersFromQueryString = this.datalayersFromQueryString
75
+ .toString()
76
+ .split(',')
74
77
  }
75
78
 
76
- if (L.Browser.ielt9) this.options.editMode = 'disabled' // TODO include ie9
77
-
78
79
  let editedFeature = null
79
80
  const self = this
80
81
  try {
@@ -114,12 +115,12 @@ U.Map = L.Map.extend({
114
115
  // Needed for actions labels
115
116
  this.help = new U.Help(this)
116
117
 
117
- if (this.options.hash) this.addHash()
118
- this.initTileLayers()
119
- // Needs tilelayer to exist for minimap
120
118
  this.initControls()
121
119
  // Needs locate control and hash to exist
122
120
  this.initCenter()
121
+ this.initTileLayers()
122
+ // Needs tilelayer to exist for minimap
123
+ this.renderControls()
123
124
  this.handleLimitBounds()
124
125
  this.initDataLayers()
125
126
 
@@ -268,9 +269,9 @@ U.Map = L.Map.extend({
268
269
  },
269
270
 
270
271
  overrideSchema: function (schema) {
271
- for (const [key, extra] of Object.entries(schema)) {
272
- U.SCHEMA[key] = L.extend({}, U.SCHEMA[key], extra)
273
- }
272
+ for (const [key, extra] of Object.entries(schema)) {
273
+ U.SCHEMA[key] = L.extend({}, U.SCHEMA[key], extra)
274
+ }
274
275
  },
275
276
 
276
277
  initControls: function () {
@@ -297,7 +298,7 @@ U.Map = L.Map.extend({
297
298
  zoomOutTitle: L._('Zoom out'),
298
299
  })
299
300
  this._controls.datalayers = new U.DataLayersControl(this)
300
- this._controls.locate = L.control.locate({
301
+ this._controls.locate = new U.Locate(this, {
301
302
  strings: {
302
303
  title: L._('Center map on your location'),
303
304
  },
@@ -336,9 +337,6 @@ U.Map = L.Map.extend({
336
337
  this.drop = new U.DropControl(this)
337
338
  this.share = new U.Share(this)
338
339
  this._controls.tilelayers = new U.TileLayerControl(this)
339
- this._controls.tilelayers.setLayers()
340
-
341
- this.renderControls()
342
340
  },
343
341
 
344
342
  renderControls: function () {
@@ -353,13 +351,13 @@ U.Map = L.Map.extend({
353
351
  'umap-slideshow-enabled',
354
352
  this.options.slideshow && this.options.slideshow.active
355
353
  )
356
- for (const i in this._controls) {
357
- this.removeControl(this._controls[i])
354
+ for (const control of Object.values(this._controls)) {
355
+ this.removeControl(control)
358
356
  }
359
357
  if (this.options.noControl) return
360
358
 
361
359
  this._controls.attribution = new U.AttributionControl().addTo(this)
362
- if (this.options.miniMap && !this.options.noControl) {
360
+ if (this.options.miniMap) {
363
361
  this.whenReady(function () {
364
362
  if (this.selected_tilelayer) {
365
363
  this._controls.miniMap = new L.Control.MiniMap(this.selected_tilelayer, {
@@ -392,6 +390,7 @@ U.Map = L.Map.extend({
392
390
  if (this.getOption('permanentCredit')) this._controls.permanentCredit.addTo(this)
393
391
  if (this.getOption('moreControl')) this._controls.more.addTo(this)
394
392
  if (this.getOption('scaleControl')) this._controls.scale.addTo(this)
393
+ this._controls.tilelayers.setLayers()
395
394
  },
396
395
 
397
396
  initDataLayers: async function (datalayers) {
@@ -652,26 +651,18 @@ U.Map = L.Map.extend({
652
651
  },
653
652
 
654
653
  initCenter: function () {
654
+ this._setDefaultCenter()
655
+ if (this.options.hash) this.addHash()
655
656
  if (this.options.hash && this._hash.parseHash(location.hash)) {
656
657
  // FIXME An invalid hash will cause the load to fail
657
658
  this._hash.update()
658
659
  } else if (this.options.defaultView === 'locate' && !this.options.noControl) {
659
- // When using locate as default map view AND activating easing
660
- // Leaflet.locate will ask the map view to compute transition to user
661
- // position, so in this case we do need a default center, so let's
662
- // set it anyway
663
- this._setDefaultCenter()
664
660
  this._controls.locate.start()
665
661
  } else if (this.options.defaultView === 'data') {
666
- this.onceDataLoaded(() => {
667
- if (!this.fitDataBounds()) return this._setDefaultCenter()
668
- })
662
+ this.onceDataLoaded(this.fitDataBounds)
669
663
  } else if (this.options.defaultView === 'latest') {
670
664
  this.onceDataLoaded(() => {
671
- if (!this.hasData()) {
672
- this._setDefaultCenter()
673
- return
674
- }
665
+ if (!this.hasData()) return
675
666
  const datalayer = this.firstVisibleDatalayer()
676
667
  let feature
677
668
  if (datalayer) {
@@ -681,11 +672,7 @@ U.Map = L.Map.extend({
681
672
  return
682
673
  }
683
674
  }
684
- // Fallback, no datalayer or no feature found
685
- this._setDefaultCenter()
686
675
  })
687
- } else {
688
- this._setDefaultCenter()
689
676
  }
690
677
  },
691
678
 
@@ -974,6 +961,8 @@ U.Map = L.Map.extend({
974
961
  formData.append('settings', JSON.stringify(geojson))
975
962
  const uri = this.urls.get('map_save', { map_id: this.options.umap_id })
976
963
  const [data, response, error] = await this.server.post(uri, {}, formData)
964
+ // FIXME: login_required response will not be an error, so it will not
965
+ // stop code while it should
977
966
  if (!error) {
978
967
  let duration = 3000,
979
968
  alert = { content: L._('Map has been saved!'), level: 'info' }
@@ -1538,7 +1527,9 @@ U.Map = L.Map.extend({
1538
1527
  metadataFields = ['options.name', 'options.description'],
1539
1528
  title = L.DomUtil.create('h3', '', container)
1540
1529
  title.textContent = L._('Edit map properties')
1541
- const builder = new U.FormBuilder(this, metadataFields)
1530
+ const builder = new U.FormBuilder(this, metadataFields, {
1531
+ className: 'map-metadata',
1532
+ })
1542
1533
  const form = builder.build()
1543
1534
  container.appendChild(form)
1544
1535
  this._editControls(container)
@@ -609,12 +609,13 @@ U.DataLayer = L.Evented.extend({
609
609
  },
610
610
 
611
611
  autoLoaded: function () {
612
- return (
613
- (this.map.datalayersOnLoad &&
614
- this.umap_id &&
615
- this.map.datalayersOnLoad.indexOf(this.umap_id.toString()) !== -1) ||
616
- (!this.map.datalayersOnLoad && this.options.displayOnLoad)
617
- )
612
+ if (!this.map.datalayersFromQueryString) return this.options.displayOnLoad
613
+ const datalayerIds = this.map.datalayersFromQueryString
614
+ let loadMe = datalayerIds.includes(this.umap_id.toString())
615
+ if (this.options.old_id) {
616
+ loadMe = loadMe || datalayerIds.includes(this.options.old_id.toString())
617
+ }
618
+ return loadMe
618
619
  },
619
620
 
620
621
  insertBefore: function (other) {
@@ -19,310 +19,6 @@ describe('U.Map', () => {
19
19
  resetMap()
20
20
  })
21
21
 
22
- describe('#init()', () => {
23
- it('should be initialized', function () {
24
- assert.equal(map.options.umap_id, 99)
25
- })
26
-
27
- it('should have created the edit button', function () {
28
- assert.ok(qs('div.leaflet-control-edit-enable'))
29
- })
30
-
31
- it('should have datalayer control div', function () {
32
- assert.ok(qs('div.leaflet-control-browse'))
33
- })
34
-
35
- it('should have datalayer actions div', function () {
36
- assert.ok(qs('div.umap-browse-actions'))
37
- })
38
-
39
- it('should have icon container div', function () {
40
- assert.ok(qs('div.icon_container'))
41
- })
42
-
43
- it('should hide icon container div when hiding datalayer', function () {
44
- var el = qs(
45
- '.leaflet-control-browse #browse_data_toggle_' +
46
- L.stamp(datalayer) +
47
- ' .layer-toggle'
48
- )
49
- happen.click(el)
50
- assert.notOk(qs('div.icon_container'))
51
- })
52
-
53
- it('enable edit on click on toggle button', function () {
54
- var el = qs('div.leaflet-control-edit-enable button')
55
- happen.click(el)
56
- assert.isTrue(L.DomUtil.hasClass(document.body, 'umap-edit-enabled'))
57
- })
58
-
59
- it('should have only one datalayer in its index', function () {
60
- assert.equal(map.datalayers_index.length, 1)
61
- })
62
- })
63
-
64
- describe('#editMetadata()', function () {
65
- var form, input
66
-
67
- it('should build a form on editMetadata control click', function (done) {
68
- var button = qs('a.update-map-settings')
69
- assert.ok(button)
70
- happen.click(button)
71
- form = qs('form.umap-form')
72
- input = qs('form[class="umap-form"] input[name="name"]')
73
- assert.ok(form)
74
- assert.ok(input)
75
- done()
76
- })
77
-
78
- it('should update map name on input change', function () {
79
- var new_name = 'This is a new name'
80
- input.value = new_name
81
- happen.once(input, { type: 'input' })
82
- assert.equal(map.options.name, new_name)
83
- })
84
-
85
- it('should have made Map dirty', function () {
86
- assert.ok(map.isDirty)
87
- })
88
-
89
- it('should have added dirty class on map container', function () {
90
- assert.ok(L.DomUtil.hasClass(map._container, 'umap-is-dirty'))
91
- })
92
- })
93
-
94
- describe('#delete()', function () {
95
- let path = '/map/99/update/delete/',
96
- oldConfirm,
97
- newConfirm = function () {
98
- return true
99
- }
100
-
101
- before(function () {
102
- oldConfirm = window.confirm
103
- window.confirm = newConfirm
104
- })
105
- after(function () {
106
- window.confirm = oldConfirm
107
- })
108
-
109
- it('should ask for confirmation on delete link click', async function () {
110
- let button = qs('a.update-map-settings')
111
- assert.ok(button, 'update map info button exists')
112
- happen.click(button)
113
- let deleteLink = qs('button.umap-delete')
114
- assert.ok(deleteLink, 'delete map button exists')
115
- sinon.spy(window, 'confirm')
116
- await fetchMock.post(path, { redirect: '#' })
117
- happen.click(deleteLink)
118
- assert(window.confirm.calledOnce)
119
- window.confirm.restore()
120
- })
121
- })
122
-
123
- describe('#importData()', function () {
124
- let fileInput, textarea, submit, formatSelect, layerSelect, clearFlag
125
-
126
- it('should build a form on click', function () {
127
- happen.click(qs('a.upload-data'))
128
- fileInput = qs('.umap-upload input[type="file"]')
129
- textarea = qs('.umap-upload textarea')
130
- submit = qs('.umap-upload input[type="button"]')
131
- formatSelect = qs('.umap-upload select[name="format"]')
132
- layerSelect = qs('.umap-upload select[name="datalayer"]')
133
- assert.ok(fileInput)
134
- assert.ok(submit)
135
- assert.ok(textarea)
136
- assert.ok(formatSelect)
137
- assert.ok(layerSelect)
138
- })
139
-
140
- it('should import geojson from textarea', function () {
141
- datalayer.empty()
142
- assert.equal(datalayer._index.length, 0)
143
- textarea.value =
144
- '{"type": "FeatureCollection", "features": [{"geometry": {"type": "Point", "coordinates": [6.922931671142578, 47.481161607175736]}, "type": "Feature", "properties": {"color": "", "name": "Chez R\u00e9my", "description": ""}}, {"geometry": {"type": "LineString", "coordinates": [[2.4609375, 48.88639177703194], [2.48291015625, 48.76343113791796], [2.164306640625, 48.719961222646276]]}, "type": "Feature", "properties": {"color": "", "name": "P\u00e9rif", "description": ""}}]}'
145
- changeSelectValue(formatSelect, 'geojson')
146
- happen.click(submit)
147
- assert.equal(datalayer._index.length, 2)
148
- })
149
-
150
- it('should remove dot in property name', function () {
151
- datalayer.empty()
152
- assert.equal(datalayer._index.length, 0)
153
- textarea.value =
154
- '{"type": "FeatureCollection", "features": [{"geometry": {"type": "Point", "coordinates": [6.922931671142578, 47.481161607175736]}, "type": "Feature", "properties": {"color": "", "name": "Chez R\u00e9my", "A . in the name": ""}}, {"geometry": {"type": "LineString", "coordinates": [[2.4609375, 48.88639177703194], [2.48291015625, 48.76343113791796], [2.164306640625, 48.719961222646276]]}, "type": "Feature", "properties": {"color": "", "name": "P\u00e9rif", "with a dot.": ""}}]}'
155
- changeSelectValue(formatSelect, 'geojson')
156
- happen.click(submit)
157
- assert.equal(datalayer._index.length, 2)
158
- assert.ok(datalayer._propertiesIndex.includes('A _ in the name'))
159
- assert.ok(datalayer._propertiesIndex.includes('with a dot_'))
160
- })
161
-
162
- it('should import osm from textarea', function () {
163
- datalayer.empty()
164
- happen.click(qs('a.upload-data'))
165
- textarea = qs('.umap-upload textarea')
166
- submit = qs('.umap-upload input[type="button"]')
167
- formatSelect = qs('.umap-upload select[name="format"]')
168
- assert.equal(datalayer._index.length, 0)
169
- textarea.value =
170
- '{"version": 0.6,"generator": "Overpass API 0.7.55.4 3079d8ea","osm3s": {"timestamp_osm_base": "2018-09-22T05:26:02Z","copyright": "The data included in this document is from www.openstreetmap.org. The data is made available under ODbL."},"elements": [{"type": "node","id": 3619112991,"lat": 48.9352995,"lon": 2.3570684,"tags": {"information": "map","map_size": "city","map_type": "scheme","tourism": "information"}},{"type": "node","id": 3682500756,"lat": 48.9804426,"lon": 2.2719725,"tags": {"information": "map","level": "0","tourism": "information"}}]}'
171
- changeSelectValue(formatSelect, 'osm')
172
- happen.click(submit)
173
- assert.equal(datalayer._index.length, 2)
174
- assert.equal(
175
- datalayer._layers[datalayer._index[0]].properties.tourism,
176
- 'information'
177
- )
178
- })
179
-
180
- it('should import kml from textarea', function () {
181
- datalayer.empty()
182
- happen.click(qs('a.upload-data'))
183
- textarea = qs('.umap-upload textarea')
184
- submit = qs('.umap-upload input[type="button"]')
185
- formatSelect = qs('.umap-upload select[name="format"]')
186
- assert.equal(datalayer._index.length, 0)
187
- textarea.value = kml_example
188
- changeSelectValue(formatSelect, 'kml')
189
- happen.click(submit)
190
- assert.equal(datalayer._index.length, 3)
191
- })
192
-
193
- it('should import gpx from textarea', function () {
194
- datalayer.empty()
195
- happen.click(qs('a.upload-data'))
196
- textarea = qs('.umap-upload textarea')
197
- submit = qs('.umap-upload input[type="button"]')
198
- formatSelect = qs('.umap-upload select[name="format"]')
199
- assert.equal(datalayer._index.length, 0)
200
- textarea.value = gpx_example
201
- changeSelectValue(formatSelect, 'gpx')
202
- happen.click(submit)
203
- assert.equal(datalayer._index.length, 2)
204
- })
205
-
206
- it('should import csv from textarea', function () {
207
- datalayer.empty()
208
- happen.click(qs('a.upload-data'))
209
- textarea = qs('.umap-upload textarea')
210
- submit = qs('.umap-upload input[type="button"]')
211
- formatSelect = qs('.umap-upload select[name="format"]')
212
- assert.equal(datalayer._index.length, 0)
213
- textarea.value = csv_example
214
- changeSelectValue(formatSelect, 'csv')
215
- happen.click(submit)
216
- assert.equal(datalayer._index.length, 1)
217
- })
218
-
219
- it('should replace content if asked so', function () {
220
- happen.click(qs('a.upload-data'))
221
- textarea = qs('.umap-upload textarea')
222
- submit = qs('.umap-upload input[type="button"]')
223
- formatSelect = qs('.umap-upload select[name="format"]')
224
- clearFlag = qs('.umap-upload input[name="clear"]')
225
- clearFlag.checked = true
226
- assert.equal(datalayer._index.length, 1)
227
- textarea.value = csv_example
228
- changeSelectValue(formatSelect, 'csv')
229
- happen.click(submit)
230
- assert.equal(datalayer._index.length, 1)
231
- })
232
-
233
- it('should import GeometryCollection from textarea', function () {
234
- datalayer.empty()
235
- textarea.value =
236
- '{"type": "GeometryCollection","geometries": [{"type": "Point","coordinates": [-80.66080570220947,35.04939206472683]},{"type": "Polygon","coordinates": [[[-80.66458225250244,35.04496519190309],[-80.66344499588013,35.04603679820616],[-80.66258668899536,35.045580049697556],[-80.66387414932251,35.044280059194946],[-80.66458225250244,35.04496519190309]]]},{"type": "LineString","coordinates": [[-80.66237211227417,35.05950973022538],[-80.66269397735596,35.0592638296087],[-80.66284418106079,35.05893010615862],[-80.66308021545409,35.05833291342246],[-80.66359519958496,35.057753281001425],[-80.66387414932251,35.05740198662245],[-80.66441059112549,35.05703312589789],[-80.66486120223999,35.056787217822475],[-80.66541910171509,35.05650617911516],[-80.66563367843628,35.05631296444281],[-80.66601991653441,35.055891403570705],[-80.66619157791138,35.05545227534804],[-80.66619157791138,35.05517123204622],[-80.66625595092773,35.05489018777713],[-80.6662130355835,35.054222703761525],[-80.6662130355835,35.05392409072499],[-80.66595554351807,35.05290528508858],[-80.66569805145262,35.052044560077285],[-80.66550493240356,35.0514824490509],[-80.665762424469,35.05048117920187],[-80.66617012023926,35.04972582715769],[-80.66651344299316,35.049286665781096],[-80.66692113876343,35.0485313026898],[-80.66700696945189,35.048215102112344],[-80.66707134246826,35.04777593261294],[-80.66704988479614,35.04738946150025],[-80.66696405410767,35.04698542156371],[-80.66681385040283,35.046353007216055],[-80.66659927368164,35.04596652937105],[-80.66640615463257,35.04561518428889],[-80.6659984588623,35.045193568195565],[-80.66552639007568,35.044877354697526],[-80.6649899482727,35.04454357245502],[-80.66449642181396,35.04417465365292],[-80.66385269165039,35.04387600387859],[-80.66303730010986,35.043717894732545]]}]}'
237
- formatSelect = qs('.umap-upload select[name="format"]')
238
- changeSelectValue(formatSelect, 'geojson')
239
- happen.click(submit)
240
- assert.equal(datalayer._index.length, 3)
241
- })
242
-
243
- it('should import multipolygon', function () {
244
- datalayer.empty()
245
- textarea.value =
246
- '{"type": "Feature", "properties": { "name": "Some states" }, "geometry": { "type": "MultiPolygon", "coordinates": [[[[-109, 36], [-109, 40], [-102, 37], [-109, 36]], [[-108, 39], [-107, 37], [-104, 37], [-108, 39]]], [[[-119, 42], [-120, 39], [-114, 41], [-119, 42]]]] }}'
247
- changeSelectValue(formatSelect, 'geojson')
248
- happen.click(submit)
249
- assert.equal(datalayer._index.length, 1)
250
- var layer = datalayer.getFeatureByIndex(0)
251
- assert.equal(layer._latlngs.length, 2) // Two shapes.
252
- assert.equal(layer._latlngs[0].length, 2) // Hole.
253
- })
254
-
255
- it('should import multipolyline', function () {
256
- datalayer.empty()
257
- textarea.value =
258
- '{"type": "FeatureCollection", "features": [{ "type": "Feature", "properties": {}, "geometry": { "type": "MultiLineString", "coordinates": [[[-108, 46], [-113, 43]], [[-112, 45], [-115, 44]]] } }]}'
259
- changeSelectValue(formatSelect, 'geojson')
260
- happen.click(submit)
261
- assert.equal(datalayer._index.length, 1)
262
- var layer = datalayer.getFeatureByIndex(0)
263
- assert.equal(layer._latlngs.length, 2) // Two shapes.
264
- })
265
-
266
- it('should import raw umap data from textarea', function () {
267
- //Right now, the import function will try to save and reload. Stop this from happening.
268
- var disabledSaveFunction = map.save
269
- map.save = function () {}
270
- happen.click(qs('a.upload-data'))
271
- var initialLayerCount = Object.keys(map.datalayers).length
272
- formatSelect = qs('.umap-upload select[name="format"]')
273
- textarea = qs('.umap-upload textarea')
274
- textarea.value =
275
- '{ "type": "umap", "geometry": { "type": "Point", "coordinates": [3.0528, 50.6269] }, "properties": { "umap_id": 666, "longCredit": "the illustrious mapmaker", "shortCredit": "the mapmaker", "slideshow": {}, "captionBar": true, "dashArray": "5,5", "fillOpacity": "0.5", "fillColor": "Crimson", "fill": true, "weight": "2", "opacity": "0.9", "smoothFactor": "1", "iconClass": "Drop", "color": "Red", "limitBounds": {}, "tilelayer": { "maxZoom": 18, "url_template": "http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg", "minZoom": 0, "attribution": "Map tiles by [[http://stamen.com|Stamen Design]], under [[http://creativecommons.org/licenses/by/3.0|CC BY 3.0]]. Data by [[http://openstreetmap.org|OpenStreetMap]], under [[http://creativecommons.org/licenses/by-sa/3.0|CC BY SA]].", "name": "Watercolor" }, "licence": { "url": "", "name": "No licence set" }, "description": "Map description", "name": "Imported map", "tilelayersControl": true, "onLoadPanel": "caption", "displayPopupFooter": true, "miniMap": true, "moreControl": true, "scaleControl": true, "zoomControl": true, "scrollWheelZoom": true, "datalayersControl": true, "zoom": 6 }, "layers": [{ "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "Polygon", "coordinates": [ [ [4.2939, 50.8893], [4.2441, 50.8196], [4.3869, 50.7642], [4.4813, 50.7929], [4.413, 50.9119], [4.2939, 50.8893] ] ] }, "properties": { "name": "Bruxelles", "description": "polygon" } }, { "type": "Feature", "geometry": { "type": "Point", "coordinates": [3.0528, 50.6269] }, "properties": { "_umap_options": { "color": "Orange" }, "name": "Lille", "description": "une ville" } }], "_umap_options": { "displayOnLoad": true, "name": "Cities", "id": 108, "remoteData": {}, "description": "A layer with some cities", "color": "Navy", "iconClass": "Drop", "smoothFactor": "1", "dashArray": "5,1", "fillOpacity": "0.5", "fillColor": "Blue", "fill": true } }, { "type": "FeatureCollection", "features": [{ "type": "Feature", "geometry": { "type": "LineString", "coordinates": [ [1.7715, 50.9255], [1.6589, 50.9696], [1.4941, 51.0128], [1.4199, 51.0638], [1.2881, 51.1104] ] }, "properties": { "_umap_options": { "weight": "4" }, "name": "tunnel sous la Manche" } }], "_umap_options": { "displayOnLoad": true, "name": "Tunnels", "id": 109, "remoteData": {} } }]}'
276
- formatSelect.value = 'umap'
277
- submit = qs('.umap-upload input[type="button"]')
278
- happen.click(submit)
279
- assert.equal(Object.keys(map.datalayers).length, initialLayerCount + 2)
280
- assert.equal(map.options.name, 'Imported map')
281
- var foundFirstLayer = false
282
- var foundSecondLayer = false
283
- for (var idx in map.datalayers) {
284
- var datalayer = map.datalayers[idx]
285
- if (datalayer.options.name === 'Cities') {
286
- foundFirstLayer = true
287
- assert.equal(datalayer._index.length, 2)
288
- }
289
- if (datalayer.options.name === 'Tunnels') {
290
- foundSecondLayer = true
291
- assert.equal(datalayer._index.length, 1)
292
- }
293
- }
294
- assert.equal(foundFirstLayer, true)
295
- assert.equal(foundSecondLayer, true)
296
- })
297
-
298
- it('should only import options on the whitelist (umap format import)', function () {
299
- assert.equal(map.options.umap_id, 99)
300
- })
301
-
302
- it('should update title bar (umap format import)', function () {
303
- var title = qs('#map div.umap-main-edit-toolbox button.map-name')
304
- assert.equal(title.innerHTML, 'Imported map')
305
- })
306
-
307
- it('should reinitialize controls (umap format import)', function () {
308
- var minimap = qs('#map div.leaflet-control-container div.leaflet-control-minimap')
309
- assert.ok(minimap)
310
- })
311
-
312
- it('should update the tilelayer switcher control (umap format import)', function () {
313
- //The tilelayer in the imported data isn't in the tilelayer list (set in _pre.js), there should be no selection on the tilelayer switcher
314
- var selectedLayer = qs('.umap-tilelayer-switcher-container li.selected')
315
- assert.equal(selectedLayer, null)
316
- })
317
-
318
- it('should set the tilelayer (umap format import)', function () {
319
- assert.equal(
320
- map.selected_tilelayer._url,
321
- 'http://{s}.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg'
322
- )
323
- })
324
- })
325
-
326
22
  describe('#localizeUrl()', function () {
327
23
  it('should replace known variables', function () {
328
24
  assert.equal(