umap-project 2.3.0__py3-none-any.whl → 2.4.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.

Potentially problematic release.


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

Files changed (211) hide show
  1. umap/__init__.py +1 -1
  2. umap/locale/en/LC_MESSAGES/django.po +81 -31
  3. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  4. umap/locale/fr/LC_MESSAGES/django.po +117 -66
  5. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  6. umap/locale/pl/LC_MESSAGES/django.po +83 -78
  7. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  8. umap/locale/pt/LC_MESSAGES/django.po +129 -123
  9. umap/management/commands/run_websocket_server.py +23 -0
  10. umap/models.py +6 -1
  11. umap/settings/base.py +11 -3
  12. umap/static/umap/base.css +68 -186
  13. umap/static/umap/content.css +3 -2
  14. umap/static/umap/css/dialog.css +18 -0
  15. umap/static/umap/css/icon.css +8 -0
  16. umap/static/umap/css/importers.css +51 -0
  17. umap/static/umap/css/panel.css +18 -57
  18. umap/static/umap/css/tooltip.css +59 -0
  19. umap/static/umap/css/window.css +35 -0
  20. umap/static/umap/img/16-white.svg +1 -3
  21. umap/static/umap/img/alert-icon-error.svg +8 -0
  22. umap/static/umap/img/alert-icon-info.svg +4 -0
  23. umap/static/umap/img/alert-icon-success.svg +3 -0
  24. umap/static/umap/img/icon-external-link.svg +3 -0
  25. umap/static/umap/img/importers/communesfr.svg +5 -0
  26. umap/static/umap/img/importers/datasets.svg +13 -0
  27. umap/static/umap/img/importers/geodatamine.svg +10 -0
  28. umap/static/umap/img/importers/overpass.svg +7 -0
  29. umap/static/umap/img/importers/random.svg +18 -0
  30. umap/static/umap/img/importers/random1.svg +4 -0
  31. umap/static/umap/img/importers/random2.svg +4 -0
  32. umap/static/umap/img/source/16-white.svg +2 -4
  33. umap/static/umap/js/components/alerts/alert.css +160 -0
  34. umap/static/umap/js/components/alerts/alert.js +169 -0
  35. umap/static/umap/js/components/base.js +54 -0
  36. umap/static/umap/js/modules/autocomplete.js +347 -0
  37. umap/static/umap/js/modules/browser.js +14 -21
  38. umap/static/umap/js/modules/caption.js +119 -0
  39. umap/static/umap/js/modules/global.js +37 -11
  40. umap/static/umap/js/modules/help.js +255 -0
  41. umap/static/umap/js/modules/importer.js +308 -0
  42. umap/static/umap/js/modules/importers/communesfr.js +44 -0
  43. umap/static/umap/js/modules/importers/datasets.js +42 -0
  44. umap/static/umap/js/modules/importers/geodatamine.js +95 -0
  45. umap/static/umap/js/modules/importers/overpass.js +84 -0
  46. umap/static/umap/js/modules/request.js +12 -14
  47. umap/static/umap/js/modules/rules.js +241 -0
  48. umap/static/umap/js/modules/schema.js +63 -14
  49. umap/static/umap/js/modules/sync/engine.js +93 -0
  50. umap/static/umap/js/modules/sync/updaters.js +109 -0
  51. umap/static/umap/js/modules/sync/websocket.js +25 -0
  52. umap/static/umap/js/modules/ui/dialog.js +52 -0
  53. umap/static/umap/js/modules/{panel.js → ui/panel.js} +37 -20
  54. umap/static/umap/js/modules/ui/tooltip.js +116 -0
  55. umap/static/umap/js/modules/utils.js +25 -18
  56. umap/static/umap/js/umap.controls.js +37 -112
  57. umap/static/umap/js/umap.core.js +1 -327
  58. umap/static/umap/js/umap.features.js +77 -29
  59. umap/static/umap/js/umap.forms.js +17 -19
  60. umap/static/umap/js/umap.js +265 -228
  61. umap/static/umap/js/umap.layer.js +154 -76
  62. umap/static/umap/js/umap.permissions.js +5 -9
  63. umap/static/umap/js/umap.popup.js +2 -1
  64. umap/static/umap/js/umap.tableeditor.js +8 -8
  65. umap/static/umap/locale/am_ET.js +51 -16
  66. umap/static/umap/locale/am_ET.json +51 -16
  67. umap/static/umap/locale/ar.js +51 -16
  68. umap/static/umap/locale/ar.json +51 -16
  69. umap/static/umap/locale/ast.js +51 -16
  70. umap/static/umap/locale/ast.json +51 -16
  71. umap/static/umap/locale/bg.js +51 -16
  72. umap/static/umap/locale/bg.json +51 -16
  73. umap/static/umap/locale/br.js +55 -20
  74. umap/static/umap/locale/br.json +55 -20
  75. umap/static/umap/locale/ca.js +51 -16
  76. umap/static/umap/locale/ca.json +51 -16
  77. umap/static/umap/locale/cs_CZ.js +93 -58
  78. umap/static/umap/locale/cs_CZ.json +93 -58
  79. umap/static/umap/locale/da.js +51 -16
  80. umap/static/umap/locale/da.json +51 -16
  81. umap/static/umap/locale/de.js +56 -21
  82. umap/static/umap/locale/de.json +56 -21
  83. umap/static/umap/locale/el.js +51 -16
  84. umap/static/umap/locale/el.json +51 -16
  85. umap/static/umap/locale/en.js +52 -16
  86. umap/static/umap/locale/en.json +52 -16
  87. umap/static/umap/locale/en_US.json +51 -16
  88. umap/static/umap/locale/es.js +51 -16
  89. umap/static/umap/locale/es.json +51 -16
  90. umap/static/umap/locale/et.js +51 -16
  91. umap/static/umap/locale/et.json +51 -16
  92. umap/static/umap/locale/eu.js +51 -16
  93. umap/static/umap/locale/eu.json +51 -16
  94. umap/static/umap/locale/fa_IR.js +51 -16
  95. umap/static/umap/locale/fa_IR.json +51 -16
  96. umap/static/umap/locale/fi.js +51 -16
  97. umap/static/umap/locale/fi.json +51 -16
  98. umap/static/umap/locale/fr.js +61 -25
  99. umap/static/umap/locale/fr.json +61 -25
  100. umap/static/umap/locale/gl.js +51 -16
  101. umap/static/umap/locale/gl.json +51 -16
  102. umap/static/umap/locale/he.js +51 -16
  103. umap/static/umap/locale/he.json +51 -16
  104. umap/static/umap/locale/hr.js +51 -16
  105. umap/static/umap/locale/hr.json +51 -16
  106. umap/static/umap/locale/hu.js +51 -16
  107. umap/static/umap/locale/hu.json +51 -16
  108. umap/static/umap/locale/id.js +51 -16
  109. umap/static/umap/locale/id.json +51 -16
  110. umap/static/umap/locale/is.js +51 -16
  111. umap/static/umap/locale/is.json +51 -16
  112. umap/static/umap/locale/it.js +51 -16
  113. umap/static/umap/locale/it.json +51 -16
  114. umap/static/umap/locale/ja.js +51 -16
  115. umap/static/umap/locale/ja.json +51 -16
  116. umap/static/umap/locale/ko.js +51 -16
  117. umap/static/umap/locale/ko.json +51 -16
  118. umap/static/umap/locale/lt.js +51 -16
  119. umap/static/umap/locale/lt.json +51 -16
  120. umap/static/umap/locale/ms.js +51 -16
  121. umap/static/umap/locale/ms.json +51 -16
  122. umap/static/umap/locale/nl.js +51 -16
  123. umap/static/umap/locale/nl.json +51 -16
  124. umap/static/umap/locale/no.js +51 -16
  125. umap/static/umap/locale/no.json +51 -16
  126. umap/static/umap/locale/pl.js +93 -58
  127. umap/static/umap/locale/pl.json +93 -58
  128. umap/static/umap/locale/pl_PL.json +51 -16
  129. umap/static/umap/locale/pt.js +215 -180
  130. umap/static/umap/locale/pt.json +215 -180
  131. umap/static/umap/locale/pt_BR.js +51 -16
  132. umap/static/umap/locale/pt_BR.json +51 -16
  133. umap/static/umap/locale/pt_PT.js +51 -16
  134. umap/static/umap/locale/pt_PT.json +51 -16
  135. umap/static/umap/locale/ro.js +51 -16
  136. umap/static/umap/locale/ro.json +51 -16
  137. umap/static/umap/locale/ru.js +51 -16
  138. umap/static/umap/locale/ru.json +51 -16
  139. umap/static/umap/locale/si.js +51 -16
  140. umap/static/umap/locale/si.json +51 -16
  141. umap/static/umap/locale/sk_SK.js +51 -16
  142. umap/static/umap/locale/sk_SK.json +51 -16
  143. umap/static/umap/locale/sl.js +51 -16
  144. umap/static/umap/locale/sl.json +51 -16
  145. umap/static/umap/locale/sr.js +51 -16
  146. umap/static/umap/locale/sr.json +51 -16
  147. umap/static/umap/locale/sv.js +51 -16
  148. umap/static/umap/locale/sv.json +51 -16
  149. umap/static/umap/locale/th_TH.js +51 -16
  150. umap/static/umap/locale/th_TH.json +51 -16
  151. umap/static/umap/locale/tr.js +51 -16
  152. umap/static/umap/locale/tr.json +51 -16
  153. umap/static/umap/locale/uk_UA.js +51 -16
  154. umap/static/umap/locale/uk_UA.json +51 -16
  155. umap/static/umap/locale/vi.js +51 -16
  156. umap/static/umap/locale/vi.json +51 -16
  157. umap/static/umap/locale/vi_VN.json +51 -16
  158. umap/static/umap/locale/zh.js +51 -16
  159. umap/static/umap/locale/zh.json +51 -16
  160. umap/static/umap/locale/zh_CN.json +51 -16
  161. umap/static/umap/locale/zh_TW.Big5.json +51 -16
  162. umap/static/umap/locale/zh_TW.js +51 -16
  163. umap/static/umap/locale/zh_TW.json +51 -16
  164. umap/static/umap/map.css +40 -53
  165. umap/static/umap/unittests/sync.js +105 -0
  166. umap/static/umap/unittests/utils.js +78 -36
  167. umap/static/umap/vars.css +19 -1
  168. umap/static/umap/vendors/dompurify/purify.es.js +50 -15
  169. umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
  170. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +2 -2
  171. umap/templates/umap/components/alerts/alert.html +89 -0
  172. umap/templates/umap/content.html +4 -3
  173. umap/templates/umap/css.html +4 -0
  174. umap/templates/umap/home.html +3 -0
  175. umap/templates/umap/js.html +0 -3
  176. umap/templates/umap/map_init.html +2 -8
  177. umap/templates/umap/messages.html +9 -11
  178. umap/templates/umap/search.html +3 -0
  179. umap/tests/base.py +3 -0
  180. umap/tests/integration/conftest.py +30 -0
  181. umap/tests/integration/test_anonymous_owned_map.py +8 -13
  182. umap/tests/integration/test_browser.py +81 -6
  183. umap/tests/integration/test_caption.py +27 -0
  184. umap/tests/integration/test_conditional_rules.py +201 -0
  185. umap/tests/integration/test_dashboard.py +1 -1
  186. umap/tests/integration/test_datalayer.py +2 -3
  187. umap/tests/integration/test_edit_datalayer.py +32 -3
  188. umap/tests/integration/test_edit_map.py +1 -1
  189. umap/tests/integration/test_facets_browser.py +7 -4
  190. umap/tests/integration/test_import.py +185 -49
  191. umap/tests/integration/test_map.py +31 -17
  192. umap/tests/integration/{test_collaborative_editing.py → test_optimistic_merge.py} +7 -7
  193. umap/tests/integration/test_owned_map.py +1 -1
  194. umap/tests/integration/test_picto.py +2 -2
  195. umap/tests/integration/test_statics.py +1 -1
  196. umap/tests/integration/test_view_marker.py +19 -2
  197. umap/tests/integration/test_websocket_sync.py +283 -0
  198. umap/tests/settings.py +5 -0
  199. umap/tests/test_datalayer_views.py +0 -1
  200. umap/tests/test_views.py +53 -0
  201. umap/urls.py +5 -0
  202. umap/views.py +40 -11
  203. umap/websocket_server.py +92 -0
  204. {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/METADATA +13 -11
  205. {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/RECORD +208 -172
  206. umap/static/umap/js/umap.autocomplete.js +0 -341
  207. umap/static/umap/js/umap.importer.js +0 -187
  208. umap/static/umap/js/umap.ui.js +0 -190
  209. {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/WHEEL +0 -0
  210. {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/entry_points.txt +0 -0
  211. {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -61,8 +61,8 @@ L.FormBuilder = L.Evented.extend({
61
61
  getter: function (field) {
62
62
  var path = field.split('.'),
63
63
  value = this.obj;
64
- for (var i = 0, l = path.length; i < l; i++) {
65
- value = value[path[i]];
64
+ for (const prop of path) {
65
+ value = value[prop];
66
66
  }
67
67
  return value;
68
68
  },
@@ -0,0 +1,89 @@
1
+ {% load i18n static %}
2
+
3
+ <style type="text/css">
4
+ @import "{% static 'umap/js/components/alerts/alert.css' %}";
5
+ </style>
6
+
7
+ <template id="umap-alert-template">
8
+ <div role="dialog" class="dark window">
9
+ <div>
10
+ <p role="alert"></p>
11
+ </div>
12
+ <ul class="buttons">
13
+ <li>
14
+ <button class="icon icon-16 icon-close" aria-label="{% translate "Close" %}" data-close></button>
15
+ </li>
16
+ </ul>
17
+ </div>
18
+ </template>
19
+
20
+ <umap-alert></umap-alert>
21
+
22
+ <template id="umap-alert-creation-template">
23
+ <div role="dialog" class="dark window">
24
+ <div>
25
+ <h3 role="alert"></h3>
26
+ {% url "login" as login_url %}
27
+ <p><em>{% blocktranslate %}Pro-tip: to easily find back your maps, <a href="{{ login_url }}" target="_blank">create an account</a> or <a href="{{ login_url }}" target="_blank">log in</a>.{% endblocktranslate %}</em></p>
28
+ <div id="link-wrapper">
29
+ <form>
30
+ <label for="url">{% translate "Here is your secret link to edit the map, please keep it safe:" %}</label>
31
+ <fieldset role="group">
32
+ <input type="url" name="url" id="url">
33
+ <input type="button" value="{% translate "Copy link" %}">
34
+ </fieldset>
35
+ </form>
36
+ </div>
37
+ <div id="form-wrapper" hidden>
38
+ <form>
39
+ <label for="email">{% translate "Enter your email address to receive the secret link:" %}</label>
40
+ <fieldset role="group">
41
+ <input type="email" name="email" id="email" placeholder="{% translate "Email" %}" required>
42
+ <input type="submit" value="{% translate "Send me the link" %}" class="umap-action">
43
+ </fieldset>
44
+ </form>
45
+ </div>
46
+ </div>
47
+ <ul class="buttons">
48
+ <li>
49
+ <button class="icon icon-16 icon-close" aria-label="{% translate "Close" %}" data-close></button>
50
+ </li>
51
+ </ul>
52
+ </div>
53
+ </template>
54
+
55
+ <umap-alert-creation></umap-alert-creation>
56
+
57
+ <template id="umap-alert-conflict-template">
58
+ <div role="dialog" class="dark window">
59
+ <div>
60
+ <p role="alert"></p>
61
+ <div id="conflict-wrapper">
62
+ <form>
63
+ <a href="#" onclick="document.url" target="_blank">{% translate "See their edits in another tab" %}</a>
64
+ <input id="your-changes" type="submit" value="{% translate "Keep your changes and loose theirs" %}">
65
+ <input id="their-changes" type="submit" value="{% translate "Keep their changes and loose yours" %}">
66
+ </form>
67
+ </div>
68
+ </div>
69
+ <ul class="buttons">
70
+ <li>
71
+ <button class="icon icon-16 icon-close" aria-label="{% translate "Close" %}" data-close></button>
72
+ </li>
73
+ </ul>
74
+ </div>
75
+ </template>
76
+
77
+ <umap-alert-conflict></umap-alert-conflict>
78
+
79
+ <script type="module">
80
+ import { register } from '{% static 'umap/js/components/base.js' %}'
81
+ import {
82
+ uMapAlert,
83
+ uMapAlertCreation,
84
+ uMapAlertConflict
85
+ } from '{% static 'umap/js/components/alerts/alert.js' %}'
86
+ register(uMapAlert, 'umap-alert')
87
+ register(uMapAlertCreation, 'umap-alert-creation')
88
+ register(uMapAlertConflict, 'umap-alert-conflict')
89
+ </script>
@@ -12,7 +12,9 @@
12
12
  <header class="wrapper row">
13
13
  {% include "umap/navigation.html" with title=SITE_NAME %}
14
14
  </header>
15
- {% include "umap/messages.html" with title=SITE_NAME %}
15
+ {% block messages %}
16
+ {% include "umap/messages.html" with title=SITE_NAME %}
17
+ {% endblock messages %}
16
18
  {% endblock header %}
17
19
  {% block content %}
18
20
  {% if UMAP_READONLY %}
@@ -38,8 +40,7 @@
38
40
  {{ block.super }}
39
41
  <script type="text/javascript">
40
42
  window.addEventListener('DOMContentLoaded', event => {
41
- const ui = new U.UI(document.querySelector('header'))
42
- const server = new U.ServerRequest(ui)
43
+ const server = new U.ServerRequest()
43
44
  const getMore = async function (e) {
44
45
  L.DomEvent.stop(e)
45
46
  const [{html}, response, error] = await server.get(this.href)
@@ -29,4 +29,8 @@
29
29
  <link rel="stylesheet" href="{% static 'umap/nav.css' %}" />
30
30
  <link rel="stylesheet" href="{% static 'umap/map.css' %}" />
31
31
  <link rel="stylesheet" href="{% static 'umap/css/panel.css' %}" />
32
+ <link rel="stylesheet" href="{% static 'umap/css/window.css' %}" />
33
+ <link rel="stylesheet" href="{% static 'umap/css/tooltip.css' %}" />
34
+ <link rel="stylesheet" href="{% static 'umap/css/dialog.css' %}" />
35
+ <link rel="stylesheet" href="{% static 'umap/css/importers.css' %}" />
32
36
  <link rel="stylesheet" href="{% static 'umap/theme.css' %}" />
@@ -1,5 +1,8 @@
1
1
  {% extends "umap/content.html" %}
2
2
  {% load umap_tags i18n %}
3
+ {% block messages %}
4
+ {# We don't want maps in the list to display errors. #}
5
+ {% endblock messages %}
3
6
  {% block maincontent %}
4
7
  {% include "umap/search_bar.html" %}
5
8
  {% include "umap/about_summary.html" %}
@@ -46,7 +46,6 @@
46
46
  <script src="{% static 'umap/vendors/simple-statistics/simple-statistics.min.js' %}"
47
47
  defer></script>
48
48
  <script src="{% static 'umap/js/umap.core.js' %}" defer></script>
49
- <script src="{% static 'umap/js/umap.autocomplete.js' %}" defer></script>
50
49
  <script src="{% static 'umap/js/umap.popup.js' %}" defer></script>
51
50
  <script src="{% static 'umap/js/umap.forms.js' %}" defer></script>
52
51
  <script src="{% static 'umap/js/umap.icon.js' %}" defer></script>
@@ -57,8 +56,6 @@
57
56
  <script src="{% static 'umap/js/umap.controls.js' %}" defer></script>
58
57
  <script src="{% static 'umap/js/umap.slideshow.js' %}" defer></script>
59
58
  <script src="{% static 'umap/js/umap.tableeditor.js' %}" defer></script>
60
- <script src="{% static 'umap/js/umap.importer.js' %}" defer></script>
61
59
  <script src="{% static 'umap/js/umap.share.js' %}" defer></script>
62
60
  <script src="{% static 'umap/js/umap.js' %}" defer></script>
63
- <script src="{% static 'umap/js/umap.ui.js' %}" defer></script>
64
61
  <script src="{% static 'umap/js/components/fragment.js' %}" defer></script>
@@ -1,17 +1,11 @@
1
1
  {% load umap_tags %}
2
+
3
+ {% include "umap/messages.html" %}
2
4
  <div id="map"></div>
3
5
  <!-- djlint:off -->
4
6
  <script defer type="text/javascript">
5
7
  window.addEventListener('DOMContentLoaded', (event) => {
6
8
  U.MAP = new U.Map("map", {{ map_settings|notag|safe }})
7
- {% for m in messages %}
8
- {# We have just one, but we need to loop, as for messages API #}
9
- U.MAP.ui.alert({
10
- content: "{{ m }}",
11
- level: "{{ m.tags }}",
12
- duration: 100000
13
- })
14
- {% endfor %}
15
9
  })
16
10
  </script>
17
11
  <!-- djlint:on -->
@@ -1,11 +1,9 @@
1
- <div class="wrapper">
2
- <div class="row">
3
- {% if messages %}
4
- <ul class="messages">
5
- {% for message in messages %}
6
- <li {% if message.tags %}class="{{ message.tags }}"{% endif %}>{{ message }}</li>
7
- {% endfor %}
8
- </ul>
9
- {% endif %}
10
- </div>
11
- </div>
1
+ {% load i18n %}
2
+
3
+ {% include "umap/components/alerts/alert.html" %}
4
+
5
+ {% for message in messages %}
6
+ <script type="module" defer>
7
+ U.Alert.success("{{ message }}")
8
+ </script>
9
+ {% endfor %}
@@ -1,5 +1,8 @@
1
1
  {% extends "umap/content.html" %}
2
2
  {% load i18n %}
3
+ {% block messages %}
4
+ {# We don't want maps from the results list to display errors in the main page. #}
5
+ {% endblock messages %}
3
6
  {% block maincontent %}
4
7
  {% include "umap/search_bar.html" %}
5
8
  <div class="wrapper">
umap/tests/base.py CHANGED
@@ -125,7 +125,10 @@ class DataLayerFactory(factory.django.DjangoModelFactory):
125
125
  **kwargs["settings"],
126
126
  }
127
127
  data.setdefault("_umap_options", {})
128
+ kwargs["settings"]["name"] = kwargs["name"]
128
129
  data["_umap_options"]["name"] = kwargs["name"]
130
+ data.setdefault("type", "FeatureCollection")
131
+ data.setdefault("features", [])
129
132
  kwargs["geojson"] = ContentFile(json.dumps(data), "foo.json")
130
133
  return kwargs
131
134
 
@@ -1,9 +1,17 @@
1
1
  import os
2
+ import subprocess
3
+ import time
4
+ from pathlib import Path
2
5
 
3
6
  import pytest
4
7
  from playwright.sync_api import expect
5
8
 
6
9
 
10
+ @pytest.fixture(scope="session")
11
+ def browser_context_args(browser_context_args):
12
+ return {**browser_context_args, "locale": "en-GB", "timezone_id": "Europe/Paris"}
13
+
14
+
7
15
  @pytest.fixture(autouse=True)
8
16
  def set_timeout(context):
9
17
  timeout = int(os.environ.get("PLAYWRIGHT_TIMEOUT", 7500))
@@ -33,3 +41,25 @@ def login(context, settings, live_server):
33
41
  return page
34
42
 
35
43
  return do_login
44
+
45
+
46
+ @pytest.fixture
47
+ def websocket_server():
48
+ # Find the test-settings, and put them in the current environment
49
+ settings_path = (Path(__file__).parent.parent / "settings.py").absolute().as_posix()
50
+ os.environ["UMAP_SETTINGS"] = settings_path
51
+
52
+ ds_proc = subprocess.Popen(
53
+ [
54
+ "umap",
55
+ "run_websocket_server",
56
+ ],
57
+ stdout=subprocess.PIPE,
58
+ stderr=subprocess.STDOUT,
59
+ )
60
+ time.sleep(2)
61
+ # Ensure it started properly before yielding
62
+ assert not ds_proc.poll(), ds_proc.stdout.read().decode("utf-8")
63
+ yield ds_proc
64
+ # Shut it down at the end of the pytest session
65
+ ds_proc.terminate()
@@ -164,17 +164,14 @@ def test_alert_message_after_create(
164
164
  page.goto(f"{live_server.url}/en/map/new")
165
165
  save = page.get_by_role("button", name="Save")
166
166
  expect(save).to_be_visible()
167
- alert = page.locator(".umap-alert")
167
+ alert = page.locator('umap-alert-creation div[role="dialog"]')
168
168
  expect(alert).to_be_hidden()
169
169
  with page.expect_response(re.compile(r".*/map/create/")):
170
170
  save.click()
171
171
  new_map = Map.objects.last()
172
172
  expect(alert).to_be_visible()
173
173
  expect(
174
- alert.get_by_text(
175
- "Your map has been created! As you are not logged in, here is your secret "
176
- "link to edit the map, please keep it safe:"
177
- )
174
+ alert.get_by_text("Your map has been created with an anonymous account!")
178
175
  ).to_be_visible()
179
176
  expect(alert.get_by_role("button", name="Copy")).to_be_visible()
180
177
  expect(alert.get_by_role("button", name="Send me the link")).to_be_visible()
@@ -194,14 +191,15 @@ def test_alert_message_after_create(
194
191
 
195
192
  def test_email_sending_error_are_catched(tilelayer, page, live_server):
196
193
  page.goto(f"{live_server.url}/en/map/new")
197
- alert = page.locator(".umap-alert")
194
+ alert_creation = page.locator('umap-alert-creation div[role="dialog"]')
198
195
  with page.expect_response(re.compile(r".*/map/create/")):
199
196
  page.get_by_role("button", name="Save").click()
200
- alert.get_by_placeholder("Email").fill("foo@bar.com")
197
+ alert_creation.get_by_placeholder("Email").fill("foo@bar.com")
201
198
  with patch("umap.views.send_mail", side_effect=SMTPException) as patched:
202
199
  with page.expect_response(re.compile("/en/map/.*/send-edit-link/")):
203
- alert.get_by_role("button", name="Send me the link").click()
200
+ alert_creation.get_by_role("button", name="Send me the link").click()
204
201
  assert patched.called
202
+ alert = page.locator('umap-alert div[role="dialog"]')
205
203
  expect(alert.get_by_text("Can't send email to foo@bar.com")).to_be_visible()
206
204
 
207
205
 
@@ -214,13 +212,10 @@ def test_alert_message_after_create_show_link_even_without_mail(
214
212
  page.goto(f"{live_server.url}/en/map/new")
215
213
  with page.expect_response(re.compile(r".*/map/create/")):
216
214
  page.get_by_role("button", name="Save").click()
217
- alert = page.locator(".umap-alert")
215
+ alert = page.locator('umap-alert-creation div[role="dialog"]')
218
216
  expect(alert).to_be_visible()
219
217
  expect(
220
- alert.get_by_text(
221
- "Your map has been created! As you are not logged in, here is your secret "
222
- "link to edit the map, please keep it safe:"
223
- )
218
+ alert.get_by_text("Your map has been created with an anonymous account!")
224
219
  ).to_be_visible()
225
220
  expect(alert.get_by_role("button", name="Copy")).to_be_visible()
226
221
  expect(alert.get_by_role("button", name="Send me the link")).to_be_hidden()
@@ -1,3 +1,4 @@
1
+ import re
1
2
  from copy import deepcopy
2
3
  from time import sleep
3
4
 
@@ -14,12 +15,16 @@ DATALAYER_DATA = {
14
15
  "features": [
15
16
  {
16
17
  "type": "Feature",
17
- "properties": {"name": "one point in france", "foo": "point"},
18
+ "properties": {"name": "one point in france", "foo": "point", "bar": "one"},
18
19
  "geometry": {"type": "Point", "coordinates": [3.339844, 46.920255]},
19
20
  },
20
21
  {
21
22
  "type": "Feature",
22
- "properties": {"name": "one polygon in greenland", "foo": "polygon"},
23
+ "properties": {
24
+ "name": "one polygon in greenland",
25
+ "foo": "polygon",
26
+ "bar": "two",
27
+ },
23
28
  "geometry": {
24
29
  "type": "Polygon",
25
30
  "coordinates": [
@@ -35,7 +40,11 @@ DATALAYER_DATA = {
35
40
  },
36
41
  {
37
42
  "type": "Feature",
38
- "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
+ },
39
48
  "geometry": {
40
49
  "type": "LineString",
41
50
  "coordinates": [
@@ -63,8 +72,9 @@ def bootstrap(map, live_server):
63
72
 
64
73
  def test_data_browser_should_be_open(live_server, page, bootstrap, map):
65
74
  page.goto(f"{live_server.url}{map.get_absolute_url()}")
66
- el = page.locator(".umap-browser")
67
- expect(el).to_be_visible()
75
+ panel = page.locator(".panel.left.on")
76
+ expect(panel).to_have_class(re.compile(".*expanded.*"))
77
+ expect(panel.locator(".umap-browser")).to_be_visible()
68
78
  expect(page.get_by_text("one point in france")).to_be_visible()
69
79
  expect(page.get_by_text("one line in new zeland")).to_be_visible()
70
80
  expect(page.get_by_text("one polygon in greenland")).to_be_visible()
@@ -101,6 +111,71 @@ def test_data_browser_should_be_filterable(live_server, page, bootstrap, map):
101
111
  expect(paths).to_have_count(0)
102
112
 
103
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
+
104
179
  def test_data_browser_can_show_only_visible_features(live_server, page, bootstrap, map):
105
180
  # Zoom on France
106
181
  page.goto(f"{live_server.url}{map.get_absolute_url()}#6/51.000/2.000")
@@ -176,7 +251,7 @@ def test_data_browser_bbox_filter_should_be_persistent(
176
251
  expect(browser.get_by_text("one point in france")).to_be_hidden()
177
252
  expect(browser.get_by_text("one line in new zeland")).to_be_hidden()
178
253
  expect(browser.get_by_text("one polygon in greenland")).to_be_hidden()
179
- page.get_by_title("See layers").click()
254
+ page.get_by_title("Open browser").click()
180
255
  expect(browser.get_by_text("one point in france")).to_be_visible()
181
256
  expect(browser.get_by_text("one line in new zeland")).to_be_hidden()
182
257
  expect(browser.get_by_text("one polygon in greenland")).to_be_hidden()
@@ -0,0 +1,27 @@
1
+ import re
2
+
3
+ import pytest
4
+ from playwright.sync_api import expect
5
+
6
+ from ..base import DataLayerFactory
7
+
8
+ pytestmark = pytest.mark.django_db
9
+
10
+
11
+ def test_caption(live_server, page, map):
12
+ map.settings["properties"]["onLoadPanel"] = "caption"
13
+ map.save()
14
+ basic = DataLayerFactory(map=map, name="Basic layer")
15
+ non_loaded = DataLayerFactory(
16
+ map=map, name="Non loaded", settings={"displayOnLoad": False}
17
+ )
18
+ hidden = DataLayerFactory(map=map, name="Hidden", settings={"inCaption": False})
19
+ page.goto(f"{live_server.url}{map.get_absolute_url()}")
20
+ panel = page.locator(".panel.left.on")
21
+ expect(panel).to_have_class(re.compile(".*condensed.*"))
22
+ expect(panel.locator(".umap-caption")).to_be_visible()
23
+ expect(panel.locator(".datalayer-legend").get_by_text(basic.name)).to_be_visible()
24
+ expect(
25
+ panel.locator(".datalayer-legend .off").get_by_text(non_loaded.name)
26
+ ).to_be_visible()
27
+ expect(panel.locator(".datalayer-legend").get_by_text(hidden.name)).to_be_hidden()