umap-project 2.4.0b2__py3-none-any.whl → 2.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.

Potentially problematic release.


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

Files changed (129) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/el/LC_MESSAGES/django.po +145 -90
  3. umap/locale/en/LC_MESSAGES/django.po +3 -3
  4. umap/locale/eu/LC_MESSAGES/django.po +145 -89
  5. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/pt/LC_MESSAGES/django.po +87 -37
  7. umap/static/umap/base.css +20 -6
  8. umap/static/umap/content.css +2 -2
  9. umap/static/umap/css/dialog.css +1 -1
  10. umap/static/umap/css/importers.css +2 -0
  11. umap/static/umap/css/panel.css +2 -2
  12. umap/static/umap/css/tooltip.css +1 -1
  13. umap/static/umap/img/16-white.svg +1 -3
  14. umap/static/umap/img/source/16-white.svg +2 -4
  15. umap/static/umap/js/components/alerts/alert.css +1 -1
  16. umap/static/umap/js/components/alerts/alert.js +1 -1
  17. umap/static/umap/js/modules/autocomplete.js +4 -4
  18. umap/static/umap/js/modules/browser.js +11 -11
  19. umap/static/umap/js/modules/caption.js +5 -5
  20. umap/static/umap/js/modules/dompurify.js +2 -3
  21. umap/static/umap/js/modules/facets.js +16 -10
  22. umap/static/umap/js/modules/global.js +16 -16
  23. umap/static/umap/js/modules/help.js +2 -2
  24. umap/static/umap/js/modules/importer.js +6 -6
  25. umap/static/umap/js/modules/importers/geodatamine.js +4 -4
  26. umap/static/umap/js/modules/importers/overpass.js +2 -2
  27. umap/static/umap/js/modules/orderable.js +2 -2
  28. umap/static/umap/js/modules/request.js +1 -1
  29. umap/static/umap/js/modules/rules.js +13 -10
  30. umap/static/umap/js/modules/sync/engine.js +3 -3
  31. umap/static/umap/js/modules/sync/updaters.js +10 -11
  32. umap/static/umap/js/modules/sync/websocket.js +1 -1
  33. umap/static/umap/js/modules/ui/dialog.js +1 -1
  34. umap/static/umap/js/modules/ui/panel.js +1 -1
  35. umap/static/umap/js/modules/ui/tooltip.js +6 -6
  36. umap/static/umap/js/modules/urls.js +1 -2
  37. umap/static/umap/js/modules/utils.js +19 -19
  38. umap/static/umap/js/umap.controls.js +26 -28
  39. umap/static/umap/js/umap.core.js +19 -15
  40. umap/static/umap/js/umap.datalayer.permissions.js +15 -18
  41. umap/static/umap/js/umap.features.js +102 -120
  42. umap/static/umap/js/umap.forms.js +46 -74
  43. umap/static/umap/js/umap.icon.js +17 -22
  44. umap/static/umap/js/umap.js +126 -131
  45. umap/static/umap/js/umap.layer.js +159 -167
  46. umap/static/umap/js/umap.permissions.js +6 -9
  47. umap/static/umap/js/umap.popup.js +20 -20
  48. umap/static/umap/js/umap.share.js +9 -15
  49. umap/static/umap/js/umap.slideshow.js +12 -14
  50. umap/static/umap/js/umap.tableeditor.js +5 -5
  51. umap/static/umap/locale/am_ET.json +5 -2
  52. umap/static/umap/locale/ar.json +5 -2
  53. umap/static/umap/locale/ast.json +5 -2
  54. umap/static/umap/locale/bg.json +5 -2
  55. umap/static/umap/locale/br.json +5 -2
  56. umap/static/umap/locale/ca.json +5 -2
  57. umap/static/umap/locale/cs_CZ.json +5 -2
  58. umap/static/umap/locale/da.json +5 -2
  59. umap/static/umap/locale/de.json +5 -2
  60. umap/static/umap/locale/el.json +10 -7
  61. umap/static/umap/locale/en.js +2 -1
  62. umap/static/umap/locale/en.json +5 -2
  63. umap/static/umap/locale/en_US.json +5 -2
  64. umap/static/umap/locale/es.js +9 -8
  65. umap/static/umap/locale/es.json +12 -9
  66. umap/static/umap/locale/et.json +5 -2
  67. umap/static/umap/locale/fa_IR.json +5 -2
  68. umap/static/umap/locale/fi.json +5 -2
  69. umap/static/umap/locale/fr.js +2 -1
  70. umap/static/umap/locale/fr.json +5 -2
  71. umap/static/umap/locale/gl.json +5 -2
  72. umap/static/umap/locale/he.json +5 -2
  73. umap/static/umap/locale/hr.json +5 -2
  74. umap/static/umap/locale/hu.json +5 -2
  75. umap/static/umap/locale/id.json +5 -2
  76. umap/static/umap/locale/is.json +5 -2
  77. umap/static/umap/locale/it.json +5 -2
  78. umap/static/umap/locale/ja.json +5 -2
  79. umap/static/umap/locale/ko.json +5 -2
  80. umap/static/umap/locale/lt.json +5 -2
  81. umap/static/umap/locale/ms.json +5 -2
  82. umap/static/umap/locale/nl.json +5 -2
  83. umap/static/umap/locale/no.json +5 -2
  84. umap/static/umap/locale/pl.json +5 -2
  85. umap/static/umap/locale/pl_PL.json +5 -2
  86. umap/static/umap/locale/pt.js +61 -60
  87. umap/static/umap/locale/pt.json +64 -61
  88. umap/static/umap/locale/pt_BR.json +5 -2
  89. umap/static/umap/locale/pt_PT.json +5 -2
  90. umap/static/umap/locale/ro.json +5 -2
  91. umap/static/umap/locale/ru.json +5 -2
  92. umap/static/umap/locale/sk_SK.json +5 -2
  93. umap/static/umap/locale/sl.json +5 -2
  94. umap/static/umap/locale/sr.json +5 -2
  95. umap/static/umap/locale/sv.json +5 -2
  96. umap/static/umap/locale/th_TH.json +5 -2
  97. umap/static/umap/locale/tr.json +5 -2
  98. umap/static/umap/locale/uk_UA.json +5 -2
  99. umap/static/umap/locale/vi.json +5 -2
  100. umap/static/umap/locale/vi_VN.json +5 -2
  101. umap/static/umap/locale/zh.json +5 -2
  102. umap/static/umap/locale/zh_CN.json +5 -2
  103. umap/static/umap/locale/zh_TW.Big5.json +5 -2
  104. umap/static/umap/locale/zh_TW.json +5 -2
  105. umap/static/umap/map.css +22 -22
  106. umap/static/umap/unittests/utils.js +5 -5
  107. umap/static/umap/vars.css +12 -1
  108. umap/storage.py +1 -1
  109. umap/tests/integration/test_browser.py +76 -3
  110. umap/tests/integration/test_edit_polygon.py +11 -0
  111. umap/tests/integration/test_map.py +29 -0
  112. umap/tests/integration/test_map_preview.py +36 -2
  113. umap/tests/integration/test_view_marker.py +2 -2
  114. umap/tests/test_views.py +2 -2
  115. umap/views.py +3 -2
  116. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/METADATA +3 -3
  117. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/RECORD +120 -129
  118. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/WHEEL +1 -1
  119. umap/.DS_Store +0 -0
  120. umap/static/.DS_Store +0 -0
  121. umap/static/umap/.DS_Store +0 -0
  122. umap/static/umap/favicons/.DS_Store +0 -0
  123. umap/static/umap/fonts/.DS_Store +0 -0
  124. umap/static/umap/img/.DS_Store +0 -0
  125. umap/static/umap/img/source/.DS_Store +0 -0
  126. umap/tests/.DS_Store +0 -0
  127. umap/tests/integration/.DS_Store +0 -0
  128. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/entry_points.txt +0 -0
  129. {umap_project-2.4.0b2.dist-info → umap_project-2.4.2.dist-info}/licenses/LICENSE +0 -0
@@ -102,7 +102,6 @@
102
102
  "Define link to open in a new window on polygon click.": "Define link to open in a new window on polygon click.",
103
103
  "define": "define",
104
104
  "Delay between two transitions when in play mode": "Delay between two transitions when in play mode",
105
- "Delete all layers": "Delete all layers",
106
105
  "Delete layer": "Delete layer",
107
106
  "Delete this feature": "Delete this feature",
108
107
  "Delete this property on all the features": "Delete this property on all the features",
@@ -481,5 +480,9 @@
481
480
  "Only geometry centers": "Only geometry centers",
482
481
  "Search area": "Search area",
483
482
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
484
- "Please define an expression for the query first": "Please define an expression for the query first"
483
+ "Please define an expression for the query first": "Please define an expression for the query first",
484
+ "Data successfully imported!": "Data successfully imported!",
485
+ "My Dashboard ({username})": "My Dashboard ({username})",
486
+ "Clear data": "Clear data",
487
+ "Remove layers": "Remove layers"
485
488
  }
@@ -102,7 +102,6 @@
102
102
  "Define link to open in a new window on polygon click.": "Define link to open in a new window on polygon click.",
103
103
  "define": "define",
104
104
  "Delay between two transitions when in play mode": "Delay between two transitions when in play mode",
105
- "Delete all layers": "Delete all layers",
106
105
  "Delete layer": "Delete layer",
107
106
  "Delete this feature": "删除对象",
108
107
  "Delete this property on all the features": "删除全部要素的该属性",
@@ -481,5 +480,9 @@
481
480
  "Only geometry centers": "Only geometry centers",
482
481
  "Search area": "Search area",
483
482
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
484
- "Please define an expression for the query first": "Please define an expression for the query first"
483
+ "Please define an expression for the query first": "Please define an expression for the query first",
484
+ "Data successfully imported!": "Data successfully imported!",
485
+ "My Dashboard ({username})": "My Dashboard ({username})",
486
+ "Clear data": "Clear data",
487
+ "Remove layers": "Remove layers"
485
488
  }
@@ -102,7 +102,6 @@
102
102
  "Define link to open in a new window on polygon click.": "Define link to open in a new window on polygon click.",
103
103
  "define": "define",
104
104
  "Delay between two transitions when in play mode": "Delay between two transitions when in play mode",
105
- "Delete all layers": "Delete all layers",
106
105
  "Delete layer": "Delete layer",
107
106
  "Delete this feature": "Delete this feature",
108
107
  "Delete this property on all the features": "Delete this property on all the features",
@@ -481,5 +480,9 @@
481
480
  "Only geometry centers": "Only geometry centers",
482
481
  "Search area": "Search area",
483
482
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
484
- "Please define an expression for the query first": "Please define an expression for the query first"
483
+ "Please define an expression for the query first": "Please define an expression for the query first",
484
+ "Data successfully imported!": "Data successfully imported!",
485
+ "My Dashboard ({username})": "My Dashboard ({username})",
486
+ "Clear data": "Clear data",
487
+ "Remove layers": "Remove layers"
485
488
  }
@@ -102,7 +102,6 @@
102
102
  "Define link to open in a new window on polygon click.": "Define link to open in a new window on polygon click.",
103
103
  "define": "define",
104
104
  "Delay between two transitions when in play mode": "Delay between two transitions when in play mode",
105
- "Delete all layers": "Delete all layers",
106
105
  "Delete layer": "Delete layer",
107
106
  "Delete this feature": "Delete this feature",
108
107
  "Delete this property on all the features": "Delete this property on all the features",
@@ -481,5 +480,9 @@
481
480
  "Only geometry centers": "Only geometry centers",
482
481
  "Search area": "Search area",
483
482
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
484
- "Please define an expression for the query first": "Please define an expression for the query first"
483
+ "Please define an expression for the query first": "Please define an expression for the query first",
484
+ "Data successfully imported!": "Data successfully imported!",
485
+ "My Dashboard ({username})": "My Dashboard ({username})",
486
+ "Clear data": "Clear data",
487
+ "Remove layers": "Remove layers"
485
488
  }
@@ -102,7 +102,6 @@
102
102
  "Define link to open in a new window on polygon click.": "指定點多邊形連結時開新視窗。",
103
103
  "define": "定義",
104
104
  "Delay between two transitions when in play mode": "播放模式下兩個轉換間會延遲",
105
- "Delete all layers": "刪除所有圖層",
106
105
  "Delete layer": "刪除圖層",
107
106
  "Delete this feature": "刪除此圖徵",
108
107
  "Delete this property on all the features": "從所有圖徵中刪除此屬性",
@@ -481,5 +480,9 @@
481
480
  "Only geometry centers": "Only geometry centers",
482
481
  "Search area": "Search area",
483
482
  "Type area name, or let empty to load data in current map view": "Type area name, or let empty to load data in current map view",
484
- "Please define an expression for the query first": "Please define an expression for the query first"
483
+ "Please define an expression for the query first": "Please define an expression for the query first",
484
+ "Data successfully imported!": "Data successfully imported!",
485
+ "My Dashboard ({username})": "My Dashboard ({username})",
486
+ "Clear data": "Clear data",
487
+ "Remove layers": "Remove layers"
485
488
  }
umap/static/umap/map.css CHANGED
@@ -228,7 +228,7 @@
228
228
  ul.photon-autocomplete {
229
229
  position: absolute;
230
230
  background-color: white;
231
- z-index: 1000;
231
+ z-index: var(--zindex-autocomplete);
232
232
  display: none;
233
233
  }
234
234
  .photon-autocomplete li {
@@ -579,7 +579,7 @@ ul.photon-autocomplete {
579
579
  line-height: var(--control-size);
580
580
  cursor: auto;
581
581
  border-bottom: 1px solid #222;
582
- z-index: 1000;
582
+ z-index: var(--zindex-panels);
583
583
  opacity: 0.98;
584
584
  color: #fff;
585
585
  display: flex;
@@ -672,13 +672,15 @@ ul.photon-autocomplete {
672
672
  cursor: auto;
673
673
  border-top: 1px solid var(--color-lightGray);
674
674
  opacity: 0.93;
675
- z-index: 1000;
675
+ z-index: var(--zindex-panels);
676
676
  }
677
677
  .umap-help {
678
678
  font-style: italic;
679
679
  }
680
680
  .umap-slideshow-toolbox {
681
- float: right;
681
+ position: absolute;
682
+ right: 0;
683
+ top: 0;
682
684
  display: none;
683
685
  }
684
686
  .umap-slideshow-enabled .umap-slideshow-toolbox {
@@ -690,9 +692,9 @@ ul.photon-autocomplete {
690
692
  font-size: 1.5em;
691
693
  background-color: #464646;
692
694
  color: #fff;
693
- height: 46px;
694
- width: 70px;
695
- line-height: 46px;
695
+ width: calc(var(--footer-height) * 2);
696
+ height: var(--footer-height);
697
+ line-height: var(--footer-height);
696
698
  vertical-align: middle;
697
699
  text-align: center;
698
700
  }
@@ -704,24 +706,24 @@ ul.photon-autocomplete {
704
706
  }
705
707
  .umap-slideshow-active .umap-slideshow-toolbox .play,
706
708
  .umap-slideshow-toolbox .play {
707
- width: 100px;
709
+ width: calc(var(--footer-height) * 3);
708
710
  text-align: left;
709
711
  padding-left: 20px;
710
712
  }
711
713
  .umap-slideshow-toolbox .play:after {
712
- content: '';
714
+ content: '⏯︎';
713
715
  }
714
716
  .umap-slideshow-active .umap-slideshow-toolbox .play:after {
715
- content: ' ❚❚';
717
+ content: '⏸︎';
716
718
  }
717
719
  .umap-slideshow-toolbox .stop:before {
718
- content: '';
720
+ content: '';
719
721
  }
720
722
  .umap-slideshow-toolbox .next:before {
721
- content: '';
723
+ content: '⏵︎';
722
724
  }
723
725
  .umap-slideshow-toolbox .prev:before {
724
- content: '';
726
+ content: '⏴︎';
725
727
  }
726
728
  .umap-slideshow-toolbox .play div {
727
729
  height: 20px;
@@ -1127,6 +1129,7 @@ a.umap-control-caption,
1127
1129
  }
1128
1130
 
1129
1131
  .umap-popup-footer {
1132
+ position: relative;
1130
1133
  background-color: rgb(68, 68, 68);
1131
1134
  color: white;
1132
1135
  display: table;
@@ -1325,7 +1328,7 @@ span.popup-icon {
1325
1328
  width: 2px;
1326
1329
  }
1327
1330
  .umap-icon-active {
1328
- z-index: 9500!important;
1331
+ z-index: var(--zindex-icon-active)!important;
1329
1332
  opacity: 1.0!important;
1330
1333
  }
1331
1334
  .umap-edit-enabled .readonly {
@@ -1349,15 +1352,14 @@ span.popup-icon {
1349
1352
  -o-animation-delay: .2s;
1350
1353
  animation-delay: .2s;
1351
1354
  }
1352
- .umap-loader
1353
- {
1355
+ .umap-loader {
1354
1356
  position: absolute;
1355
1357
  display: none;
1356
1358
  top: 0;
1357
1359
  left: 0;
1358
1360
  right: 0;
1359
1361
  height: 4px;
1360
- z-index: 10100;
1362
+ z-index: var(--zindex-loader);
1361
1363
  background-color: #79c1c0 !important;
1362
1364
  -webkit-transform: translateX(100%);
1363
1365
  -moz-transform: translateX(100%);
@@ -1519,10 +1521,10 @@ span.popup-icon {
1519
1521
  margin-left: 10px;
1520
1522
  }
1521
1523
  .leaflet-top {
1522
- z-index: 1001;
1524
+ z-index: calc(var(--zindex-panels) + 1);
1523
1525
  }
1524
1526
  .leaflet-popup-content {
1525
- min-width: 100px;
1527
+ min-width: 200px;
1526
1528
  line-height: inherit;
1527
1529
  }
1528
1530
  .leaflet-popup-content-wrapper, .leaflet-popup-tip {
@@ -1559,8 +1561,6 @@ span.popup-icon {
1559
1561
  }
1560
1562
  .umap-popup-container {
1561
1563
  flex-grow: 1;
1562
- word-break: break-word;
1563
- white-space: pre-line;
1564
1564
  margin-bottom: 10px;
1565
1565
  }
1566
1566
  .umap-popup-container ul {
@@ -1593,7 +1593,7 @@ span.popup-icon {
1593
1593
  text-align: center;
1594
1594
  }
1595
1595
  .leaflet-inplace-toolbar {
1596
- z-index: 10000!important;
1596
+ z-index: var(--zindex-toolbar)!important;
1597
1597
  }
1598
1598
  .leaflet-inplace-toolbar a {
1599
1599
  background-image: url('./img/16-white.svg');
@@ -11,14 +11,14 @@ global.JSDOM = JSDOM
11
11
  describe('Utils', function () {
12
12
  describe('#toHTML()', function () {
13
13
  it('should handle title', function () {
14
- assert.equal(Utils.toHTML('# A title'), '<h3>A title</h3>')
14
+ assert.equal(Utils.toHTML('# A title'), '<h4>A title</h4>')
15
15
  })
16
16
  it('should handle title followed by text', function () {
17
- assert.equal(Utils.toHTML('# A title\nSome text.'), '<h3>A title</h3>Some text.')
17
+ assert.equal(Utils.toHTML('# A title\nSome text.'), '<h4>A title</h4>Some text.')
18
18
  })
19
19
 
20
20
  it('should handle title in the middle of the content', function () {
21
- assert.equal(Utils.toHTML('A phrase\n## A title'), 'A phrase\n<h4>A title</h4>')
21
+ assert.equal(Utils.toHTML('A phrase\n## A title'), 'A phrase\n<h5>A title</h5>')
22
22
  })
23
23
 
24
24
  it('should handle hr', function () {
@@ -43,7 +43,7 @@ describe('Utils', function () {
43
43
  it('should handle simple link in title', function () {
44
44
  assert.equal(
45
45
  Utils.toHTML('# http://osm.org'),
46
- '<h3><a href="http://osm.org" target="_blank">http://osm.org</a></h3>'
46
+ '<h4><a href="http://osm.org" target="_blank">http://osm.org</a></h4>'
47
47
  )
48
48
  })
49
49
 
@@ -180,7 +180,7 @@ describe('Utils', function () {
180
180
  it('title followed by bullet points', function () {
181
181
  assert.equal(
182
182
  Utils.toHTML('## Some title\n* First *point*\n* Second **point**\n* Last [[https://here.org|point]]'),
183
- '<h4>Some title</h4><ul><li>First <em>point</em></li><li>Second <strong>point</strong></li><li>Last <a href="https://here.org" target="_blank">point</a></li></ul>'
183
+ '<h5>Some title</h5><ul><li>First <em>point</em></li><li>Second <strong>point</strong></li><li>Last <a href="https://here.org" target="_blank">point</a></li></ul>'
184
184
  )
185
185
  })
186
186
  })
umap/static/umap/vars.css CHANGED
@@ -29,12 +29,23 @@
29
29
  --panel-width: 400px;
30
30
  --header-height: 46px;
31
31
  --current-header-height: 0px;
32
- --footer-height: 28px;
32
+ --footer-height: 32px;
33
33
  --current-footer-height: 0px;
34
34
  --control-size: 36px;
35
35
  --border-radius: 4px;
36
36
  --box-padding: 20px;
37
37
  --box-margin: 14px;
38
+ --text-margin: 7px;
39
+
40
+ /* z-indexes (leaflet CSS sets the map at 400 by default) */
41
+ --zindex-alert: 500;
42
+ --zindex-loader: 490;
43
+ --zindex-toolbar: 480;
44
+ --zindex-autocomplete: 470;
45
+ --zindex-dialog: 460;
46
+ --zindex-icon-active: 450;
47
+ --zindex-panels: 440;
48
+ --zindex-dragover: 410;
38
49
  }
39
50
  .dark {
40
51
  --background-color: var(--color-darkGray);
umap/storage.py CHANGED
@@ -9,7 +9,7 @@ from rjsmin import jsmin
9
9
  class UmapManifestStaticFilesStorage(ManifestStaticFilesStorage):
10
10
  support_js_module_import_aggregation = True
11
11
 
12
- # We remove `;` at the end of all regexps to match our prettier config.
12
+ # We remove `;` at the end of all regexps to match our biome config.
13
13
  _js_module_import_aggregation_patterns = (
14
14
  "*.js",
15
15
  (
@@ -15,12 +15,16 @@ DATALAYER_DATA = {
15
15
  "features": [
16
16
  {
17
17
  "type": "Feature",
18
- "properties": {"name": "one point in france", "foo": "point"},
18
+ "properties": {"name": "one point in france", "foo": "point", "bar": "one"},
19
19
  "geometry": {"type": "Point", "coordinates": [3.339844, 46.920255]},
20
20
  },
21
21
  {
22
22
  "type": "Feature",
23
- "properties": {"name": "one polygon in greenland", "foo": "polygon"},
23
+ "properties": {
24
+ "name": "one polygon in greenland",
25
+ "foo": "polygon",
26
+ "bar": "two",
27
+ },
24
28
  "geometry": {
25
29
  "type": "Polygon",
26
30
  "coordinates": [
@@ -36,7 +40,11 @@ DATALAYER_DATA = {
36
40
  },
37
41
  {
38
42
  "type": "Feature",
39
- "properties": {"name": "one line in new zeland", "foo": "line"},
43
+ "properties": {
44
+ "name": "one line in new zeland",
45
+ "foo": "line",
46
+ "bar": "three",
47
+ },
40
48
  "geometry": {
41
49
  "type": "LineString",
42
50
  "coordinates": [
@@ -103,6 +111,71 @@ def test_data_browser_should_be_filterable(live_server, page, bootstrap, map):
103
111
  expect(paths).to_have_count(0)
104
112
 
105
113
 
114
+ def test_filter_uses_layer_setting_if_any(live_server, page, bootstrap, map):
115
+ datalayer = map.datalayer_set.first()
116
+ datalayer.settings["labelKey"] = "foo"
117
+ datalayer.save()
118
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
119
+ expect(page.get_by_title("Features in this layer: 3")).to_be_visible()
120
+ markers = page.locator(".leaflet-marker-icon")
121
+ paths = page.locator(".leaflet-overlay-pane path")
122
+ expect(markers).to_have_count(1)
123
+ expect(paths).to_have_count(2)
124
+ expect(page.get_by_text("point")).to_be_visible()
125
+ expect(page.get_by_text("polygon")).to_be_visible()
126
+ expect(page.get_by_text("line")).to_be_visible()
127
+ page.locator(".filters summary").click()
128
+ filter_ = page.locator("input[name='filter']")
129
+ expect(filter_).to_be_visible()
130
+ filter_.type("po")
131
+ expect(page.get_by_title("Features in this layer: 2/3")).to_be_visible()
132
+ expect(page.get_by_title("Features in this layer: 2/3")).to_have_text("(2/3)")
133
+ expect(page.get_by_text("line")).to_be_hidden()
134
+ expect(page.get_by_text("point")).to_be_visible()
135
+ expect(page.get_by_text("polygon")).to_be_visible()
136
+ expect(markers).to_have_count(1)
137
+ expect(paths).to_have_count(1) # Only polygon
138
+ # Empty the filter
139
+ filter_.fill("")
140
+ filter_.blur()
141
+ expect(markers).to_have_count(1)
142
+ expect(paths).to_have_count(2)
143
+ filter_.type("point")
144
+ expect(page.get_by_text("point")).to_be_visible()
145
+ expect(page.get_by_text("line")).to_be_hidden()
146
+ expect(page.get_by_text("polygon")).to_be_hidden()
147
+ expect(markers).to_have_count(1)
148
+ expect(paths).to_have_count(0)
149
+
150
+
151
+ def test_filter_works_with_variable_in_labelKey(live_server, page, map):
152
+ map.settings["properties"]["onLoadPanel"] = "databrowser"
153
+ map.save()
154
+ data = deepcopy(DATALAYER_DATA)
155
+ data["_umap_options"]["labelKey"] = "{name} ({bar})"
156
+ DataLayerFactory(map=map, data=data)
157
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
158
+ expect(page.get_by_title("Features in this layer: 3")).to_be_visible()
159
+ markers = page.locator(".leaflet-marker-icon")
160
+ paths = page.locator(".leaflet-overlay-pane path")
161
+ expect(markers).to_have_count(1)
162
+ expect(paths).to_have_count(2)
163
+ expect(page.get_by_text("one point in france (one)")).to_be_visible()
164
+ expect(page.get_by_text("one line in new zeland (three)")).to_be_visible()
165
+ expect(page.get_by_text("one polygon in greenland (two)")).to_be_visible()
166
+ page.locator(".filters summary").click()
167
+ filter_ = page.locator("input[name='filter']")
168
+ expect(filter_).to_be_visible()
169
+ filter_.type("two")
170
+ expect(page.get_by_title("Features in this layer: 1/3")).to_be_visible()
171
+ expect(page.get_by_title("Features in this layer: 1/3")).to_have_text("(1/3)")
172
+ expect(page.get_by_text("one polygon in greenland (two)")).to_be_visible()
173
+ expect(page.get_by_text("one line in new zeland (three)")).to_be_hidden()
174
+ expect(page.get_by_text("one point in france (one)")).to_be_hidden()
175
+ expect(markers).to_have_count(0)
176
+ expect(paths).to_have_count(1) # Only polygon
177
+
178
+
106
179
  def test_data_browser_can_show_only_visible_features(live_server, page, bootstrap, map):
107
180
  # Zoom on France
108
181
  page.goto(f"{live_server.url}{map.get_absolute_url()}#6/51.000/2.000")
@@ -120,3 +120,14 @@ def test_should_reset_style_on_cancel(live_server, openmap, page, bootstrap):
120
120
  page.once("dialog", lambda dialog: dialog.accept())
121
121
  page.get_by_role("button", name="Cancel edits").click()
122
122
  expect(page.locator(".leaflet-overlay-pane path[fill='DarkBlue']")).to_have_count(1)
123
+
124
+
125
+ def test_can_change_datalayer(live_server, openmap, page, bootstrap):
126
+ other = DataLayerFactory(
127
+ name="Layer 2", map=openmap, settings={"color": "GoldenRod"}
128
+ )
129
+ page.goto(f"{live_server.url}{openmap.get_absolute_url()}?edit")
130
+ expect(page.locator("path[fill='DarkBlue']")).to_have_count(1)
131
+ page.locator("path").click(modifiers=["Shift"])
132
+ page.get_by_role("combobox").select_option(other.name)
133
+ expect(page.locator("path[fill='GoldenRod']")).to_have_count(1)
@@ -204,3 +204,32 @@ def test_zoom_control_on_load(map, live_server, page):
204
204
  map.save()
205
205
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
206
206
  expect(page.locator(".leaflet-control-zoom")).to_be_hidden()
207
+
208
+
209
+ def test_feature_in_query_string_has_precedence_over_onloadpanel(
210
+ map, live_server, page
211
+ ):
212
+ map.settings["properties"]["onLoadPanel"] = "caption"
213
+ map.name = "This is my map"
214
+ map.save()
215
+ data = {
216
+ "type": "FeatureCollection",
217
+ "features": [
218
+ {
219
+ "type": "Feature",
220
+ "properties": {"name": "FooBar"},
221
+ "geometry": {
222
+ "type": "Point",
223
+ "coordinates": [2.12, 49.57],
224
+ },
225
+ }
226
+ ],
227
+ "_umap_options": {"popupShape": "Panel"},
228
+ }
229
+ DataLayerFactory(map=map, data=data)
230
+ page.goto(f"{live_server.url}{map.get_absolute_url()}?feature=FooBar")
231
+ expect(page.get_by_role("heading", name="FooBar")).to_be_visible()
232
+ expect(page.get_by_role("heading", name="This is my map")).to_be_hidden()
233
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
234
+ expect(page.get_by_role("heading", name="FooBar")).to_be_hidden()
235
+ expect(page.get_by_role("heading", name="This is my map")).to_be_visible()
@@ -21,6 +21,21 @@ GEOJSON = {
21
21
  }
22
22
  ],
23
23
  }
24
+ GEOJSON2 = {
25
+ "type": "FeatureCollection",
26
+ "features": [
27
+ {
28
+ "type": "Feature",
29
+ "properties": {
30
+ "name": "Montmorency Falls",
31
+ },
32
+ "geometry": {
33
+ "type": "Point",
34
+ "coordinates": [-71.14, 46.89],
35
+ },
36
+ }
37
+ ],
38
+ }
24
39
  CSV = "name,latitude,longitude\nNiagara Falls,43.08,-79.04"
25
40
 
26
41
 
@@ -43,10 +58,29 @@ def test_map_preview_can_load_remote_geojson(page, live_server, tilelayer):
43
58
  expect(markers).to_have_count(1)
44
59
 
45
60
 
61
+ def test_map_preview_can_load_mutiple_remote_geojson(page, live_server, tilelayer):
62
+ def handle(route):
63
+ if "2" in route.request.url:
64
+ route.fulfill(json=GEOJSON2)
65
+ else:
66
+ route.fulfill(json=GEOJSON)
67
+
68
+ # Intercept the route to the proxy
69
+ page.route("*/**/ajax-proxy/**", handle)
70
+
71
+ page.goto(
72
+ (
73
+ f"{live_server.url}/map/?"
74
+ "dataUrl=http://some.org/geo.json&dataUrl=http://some.org/geo2.json"
75
+ )
76
+ )
77
+ markers = page.locator(".leaflet-marker-icon")
78
+ expect(markers).to_have_count(2)
79
+
80
+
46
81
  def test_map_preview_can_load_remote_csv(page, live_server, tilelayer):
47
82
  def handle(route):
48
- csv = """name,latitude,longitude\nNiagara Falls,43.08,-79.04"""
49
- route.fulfill(body=csv)
83
+ route.fulfill(body=CSV)
50
84
 
51
85
  # Intercept the route to the proxy
52
86
  page.route("*/**/ajax-proxy/**", handle)
@@ -39,8 +39,8 @@ def test_should_open_popup_on_click(live_server, map, page, bootstrap):
39
39
  expect(page.locator(".leaflet-popup-content-wrapper")).to_be_visible()
40
40
  expect(page.get_by_role("heading", name="test marker")).to_be_visible()
41
41
  expect(page.get_by_text("Some description")).to_be_visible()
42
- # Close popup
43
- page.locator("#map").click()
42
+ # Close popup, clicking on the map, but outside of the popup.
43
+ page.locator("#map").click(position={"x": 50, "y": 50})
44
44
  expect(page.locator(".umap-icon-active")).to_be_hidden()
45
45
 
46
46
 
umap/tests/test_views.py CHANGED
@@ -122,7 +122,7 @@ def test_valid_proxy_request_with_invalid_ttl(client):
122
122
 
123
123
  def test_invalid_proxy_url_should_return_400(client):
124
124
  url = reverse("ajax-proxy")
125
- params = {"url": "http://example.org/a space is invalid"}
125
+ params = {"url": "http://example.org/a\ncarriage\r\nreturn is invalid"}
126
126
  headers = {
127
127
  "HTTP_X_REQUESTED_WITH": "XMLHttpRequest",
128
128
  "HTTP_REFERER": settings.SITE_URL,
@@ -144,7 +144,7 @@ def test_valid_proxy_request_with_x_accel_redirect(client, settings):
144
144
  assert "X-Accel-Redirect" in response.headers
145
145
  assert (
146
146
  response["X-Accel-Redirect"]
147
- == "/proxy/http%3A//example.org%3Ffoo%3Dbar%26bar%3Dfoo"
147
+ == "/proxy/http%3A%2F%2Fexample.org%3Ffoo%3Dbar%26bar%3Dfoo"
148
148
  )
149
149
  assert "X-Accel-Expires" in response.headers
150
150
  assert response["X-Accel-Expires"] == "300"
umap/views.py CHANGED
@@ -11,7 +11,7 @@ from io import BytesIO
11
11
  from pathlib import Path
12
12
  from smtplib import SMTPException
13
13
  from urllib.error import HTTPError, URLError
14
- from urllib.parse import quote, quote_plus, urlparse
14
+ from urllib.parse import quote_plus, urlparse
15
15
  from urllib.request import Request, build_opener
16
16
 
17
17
  from django.conf import settings
@@ -403,13 +403,14 @@ class AjaxProxy(View):
403
403
  ttl = None
404
404
  if getattr(settings, "UMAP_XSENDFILE_HEADER", None):
405
405
  response = HttpResponse()
406
- response[settings.UMAP_XSENDFILE_HEADER] = f"/proxy/{quote(url)}"
406
+ response[settings.UMAP_XSENDFILE_HEADER] = f"/proxy/{quote_plus(url)}"
407
407
  if ttl:
408
408
  response["X-Accel-Expires"] = ttl
409
409
  return response
410
410
 
411
411
  # You should not use this in production (use Nginx or so)
412
412
  headers = {"User-Agent": "uMapProxy +http://wiki.openstreetmap.org/wiki/UMap"}
413
+ url = url.replace(" ", "+")
413
414
  request = Request(url, headers=headers)
414
415
  opener = build_opener()
415
416
  try:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: umap-project
3
- Version: 2.4.0b2
3
+ Version: 2.4.2
4
4
  Summary: Create maps with OpenStreetMap layers in a minute and embed them in your site.
5
5
  Author-email: Yohan Boniface <yb@enix.org>
6
6
  Maintainer-email: David Larlet <david@larlet.fr>
@@ -37,7 +37,7 @@ Requires-Dist: mkdocs-material==9.5.27; extra == 'dev'
37
37
  Requires-Dist: mkdocs-static-i18n==1.2.3; extra == 'dev'
38
38
  Requires-Dist: mkdocs==1.6.0; extra == 'dev'
39
39
  Requires-Dist: pymdown-extensions==10.8.1; extra == 'dev'
40
- Requires-Dist: ruff==0.4.9; extra == 'dev'
40
+ Requires-Dist: ruff==0.4.10; extra == 'dev'
41
41
  Requires-Dist: vermin==1.6.0; extra == 'dev'
42
42
  Provides-Extra: docker
43
43
  Requires-Dist: uwsgi==2.0.26; extra == 'docker'