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.
- umap/__init__.py +1 -1
- umap/locale/en/LC_MESSAGES/django.po +81 -31
- umap/locale/fr/LC_MESSAGES/django.mo +0 -0
- umap/locale/fr/LC_MESSAGES/django.po +117 -66
- umap/locale/pl/LC_MESSAGES/django.mo +0 -0
- umap/locale/pl/LC_MESSAGES/django.po +83 -78
- umap/locale/pt/LC_MESSAGES/django.mo +0 -0
- umap/locale/pt/LC_MESSAGES/django.po +129 -123
- umap/management/commands/run_websocket_server.py +23 -0
- umap/models.py +6 -1
- umap/settings/base.py +11 -3
- umap/static/umap/base.css +68 -186
- umap/static/umap/content.css +3 -2
- umap/static/umap/css/dialog.css +18 -0
- umap/static/umap/css/icon.css +8 -0
- umap/static/umap/css/importers.css +51 -0
- umap/static/umap/css/panel.css +18 -57
- umap/static/umap/css/tooltip.css +59 -0
- umap/static/umap/css/window.css +35 -0
- umap/static/umap/img/16-white.svg +1 -3
- umap/static/umap/img/alert-icon-error.svg +8 -0
- umap/static/umap/img/alert-icon-info.svg +4 -0
- umap/static/umap/img/alert-icon-success.svg +3 -0
- umap/static/umap/img/icon-external-link.svg +3 -0
- umap/static/umap/img/importers/communesfr.svg +5 -0
- umap/static/umap/img/importers/datasets.svg +13 -0
- umap/static/umap/img/importers/geodatamine.svg +10 -0
- umap/static/umap/img/importers/overpass.svg +7 -0
- umap/static/umap/img/importers/random.svg +18 -0
- umap/static/umap/img/importers/random1.svg +4 -0
- umap/static/umap/img/importers/random2.svg +4 -0
- umap/static/umap/img/source/16-white.svg +2 -4
- umap/static/umap/js/components/alerts/alert.css +160 -0
- umap/static/umap/js/components/alerts/alert.js +169 -0
- umap/static/umap/js/components/base.js +54 -0
- umap/static/umap/js/modules/autocomplete.js +347 -0
- umap/static/umap/js/modules/browser.js +14 -21
- umap/static/umap/js/modules/caption.js +119 -0
- umap/static/umap/js/modules/global.js +37 -11
- umap/static/umap/js/modules/help.js +255 -0
- umap/static/umap/js/modules/importer.js +308 -0
- umap/static/umap/js/modules/importers/communesfr.js +44 -0
- umap/static/umap/js/modules/importers/datasets.js +42 -0
- umap/static/umap/js/modules/importers/geodatamine.js +95 -0
- umap/static/umap/js/modules/importers/overpass.js +84 -0
- umap/static/umap/js/modules/request.js +12 -14
- umap/static/umap/js/modules/rules.js +241 -0
- umap/static/umap/js/modules/schema.js +63 -14
- umap/static/umap/js/modules/sync/engine.js +93 -0
- umap/static/umap/js/modules/sync/updaters.js +109 -0
- umap/static/umap/js/modules/sync/websocket.js +25 -0
- umap/static/umap/js/modules/ui/dialog.js +52 -0
- umap/static/umap/js/modules/{panel.js → ui/panel.js} +37 -20
- umap/static/umap/js/modules/ui/tooltip.js +116 -0
- umap/static/umap/js/modules/utils.js +25 -18
- umap/static/umap/js/umap.controls.js +37 -112
- umap/static/umap/js/umap.core.js +1 -327
- umap/static/umap/js/umap.features.js +77 -29
- umap/static/umap/js/umap.forms.js +17 -19
- umap/static/umap/js/umap.js +265 -228
- umap/static/umap/js/umap.layer.js +154 -76
- umap/static/umap/js/umap.permissions.js +5 -9
- umap/static/umap/js/umap.popup.js +2 -1
- umap/static/umap/js/umap.tableeditor.js +8 -8
- umap/static/umap/locale/am_ET.js +51 -16
- umap/static/umap/locale/am_ET.json +51 -16
- umap/static/umap/locale/ar.js +51 -16
- umap/static/umap/locale/ar.json +51 -16
- umap/static/umap/locale/ast.js +51 -16
- umap/static/umap/locale/ast.json +51 -16
- umap/static/umap/locale/bg.js +51 -16
- umap/static/umap/locale/bg.json +51 -16
- umap/static/umap/locale/br.js +55 -20
- umap/static/umap/locale/br.json +55 -20
- umap/static/umap/locale/ca.js +51 -16
- umap/static/umap/locale/ca.json +51 -16
- umap/static/umap/locale/cs_CZ.js +93 -58
- umap/static/umap/locale/cs_CZ.json +93 -58
- umap/static/umap/locale/da.js +51 -16
- umap/static/umap/locale/da.json +51 -16
- umap/static/umap/locale/de.js +56 -21
- umap/static/umap/locale/de.json +56 -21
- umap/static/umap/locale/el.js +51 -16
- umap/static/umap/locale/el.json +51 -16
- umap/static/umap/locale/en.js +52 -16
- umap/static/umap/locale/en.json +52 -16
- umap/static/umap/locale/en_US.json +51 -16
- umap/static/umap/locale/es.js +51 -16
- umap/static/umap/locale/es.json +51 -16
- umap/static/umap/locale/et.js +51 -16
- umap/static/umap/locale/et.json +51 -16
- umap/static/umap/locale/eu.js +51 -16
- umap/static/umap/locale/eu.json +51 -16
- umap/static/umap/locale/fa_IR.js +51 -16
- umap/static/umap/locale/fa_IR.json +51 -16
- umap/static/umap/locale/fi.js +51 -16
- umap/static/umap/locale/fi.json +51 -16
- umap/static/umap/locale/fr.js +61 -25
- umap/static/umap/locale/fr.json +61 -25
- umap/static/umap/locale/gl.js +51 -16
- umap/static/umap/locale/gl.json +51 -16
- umap/static/umap/locale/he.js +51 -16
- umap/static/umap/locale/he.json +51 -16
- umap/static/umap/locale/hr.js +51 -16
- umap/static/umap/locale/hr.json +51 -16
- umap/static/umap/locale/hu.js +51 -16
- umap/static/umap/locale/hu.json +51 -16
- umap/static/umap/locale/id.js +51 -16
- umap/static/umap/locale/id.json +51 -16
- umap/static/umap/locale/is.js +51 -16
- umap/static/umap/locale/is.json +51 -16
- umap/static/umap/locale/it.js +51 -16
- umap/static/umap/locale/it.json +51 -16
- umap/static/umap/locale/ja.js +51 -16
- umap/static/umap/locale/ja.json +51 -16
- umap/static/umap/locale/ko.js +51 -16
- umap/static/umap/locale/ko.json +51 -16
- umap/static/umap/locale/lt.js +51 -16
- umap/static/umap/locale/lt.json +51 -16
- umap/static/umap/locale/ms.js +51 -16
- umap/static/umap/locale/ms.json +51 -16
- umap/static/umap/locale/nl.js +51 -16
- umap/static/umap/locale/nl.json +51 -16
- umap/static/umap/locale/no.js +51 -16
- umap/static/umap/locale/no.json +51 -16
- umap/static/umap/locale/pl.js +93 -58
- umap/static/umap/locale/pl.json +93 -58
- umap/static/umap/locale/pl_PL.json +51 -16
- umap/static/umap/locale/pt.js +215 -180
- umap/static/umap/locale/pt.json +215 -180
- umap/static/umap/locale/pt_BR.js +51 -16
- umap/static/umap/locale/pt_BR.json +51 -16
- umap/static/umap/locale/pt_PT.js +51 -16
- umap/static/umap/locale/pt_PT.json +51 -16
- umap/static/umap/locale/ro.js +51 -16
- umap/static/umap/locale/ro.json +51 -16
- umap/static/umap/locale/ru.js +51 -16
- umap/static/umap/locale/ru.json +51 -16
- umap/static/umap/locale/si.js +51 -16
- umap/static/umap/locale/si.json +51 -16
- umap/static/umap/locale/sk_SK.js +51 -16
- umap/static/umap/locale/sk_SK.json +51 -16
- umap/static/umap/locale/sl.js +51 -16
- umap/static/umap/locale/sl.json +51 -16
- umap/static/umap/locale/sr.js +51 -16
- umap/static/umap/locale/sr.json +51 -16
- umap/static/umap/locale/sv.js +51 -16
- umap/static/umap/locale/sv.json +51 -16
- umap/static/umap/locale/th_TH.js +51 -16
- umap/static/umap/locale/th_TH.json +51 -16
- umap/static/umap/locale/tr.js +51 -16
- umap/static/umap/locale/tr.json +51 -16
- umap/static/umap/locale/uk_UA.js +51 -16
- umap/static/umap/locale/uk_UA.json +51 -16
- umap/static/umap/locale/vi.js +51 -16
- umap/static/umap/locale/vi.json +51 -16
- umap/static/umap/locale/vi_VN.json +51 -16
- umap/static/umap/locale/zh.js +51 -16
- umap/static/umap/locale/zh.json +51 -16
- umap/static/umap/locale/zh_CN.json +51 -16
- umap/static/umap/locale/zh_TW.Big5.json +51 -16
- umap/static/umap/locale/zh_TW.js +51 -16
- umap/static/umap/locale/zh_TW.json +51 -16
- umap/static/umap/map.css +40 -53
- umap/static/umap/unittests/sync.js +105 -0
- umap/static/umap/unittests/utils.js +78 -36
- umap/static/umap/vars.css +19 -1
- umap/static/umap/vendors/dompurify/purify.es.js +50 -15
- umap/static/umap/vendors/dompurify/purify.es.mjs.map +1 -1
- umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +2 -2
- umap/templates/umap/components/alerts/alert.html +89 -0
- umap/templates/umap/content.html +4 -3
- umap/templates/umap/css.html +4 -0
- umap/templates/umap/home.html +3 -0
- umap/templates/umap/js.html +0 -3
- umap/templates/umap/map_init.html +2 -8
- umap/templates/umap/messages.html +9 -11
- umap/templates/umap/search.html +3 -0
- umap/tests/base.py +3 -0
- umap/tests/integration/conftest.py +30 -0
- umap/tests/integration/test_anonymous_owned_map.py +8 -13
- umap/tests/integration/test_browser.py +81 -6
- umap/tests/integration/test_caption.py +27 -0
- umap/tests/integration/test_conditional_rules.py +201 -0
- umap/tests/integration/test_dashboard.py +1 -1
- umap/tests/integration/test_datalayer.py +2 -3
- umap/tests/integration/test_edit_datalayer.py +32 -3
- umap/tests/integration/test_edit_map.py +1 -1
- umap/tests/integration/test_facets_browser.py +7 -4
- umap/tests/integration/test_import.py +185 -49
- umap/tests/integration/test_map.py +31 -17
- umap/tests/integration/{test_collaborative_editing.py → test_optimistic_merge.py} +7 -7
- umap/tests/integration/test_owned_map.py +1 -1
- umap/tests/integration/test_picto.py +2 -2
- umap/tests/integration/test_statics.py +1 -1
- umap/tests/integration/test_view_marker.py +19 -2
- umap/tests/integration/test_websocket_sync.py +283 -0
- umap/tests/settings.py +5 -0
- umap/tests/test_datalayer_views.py +0 -1
- umap/tests/test_views.py +53 -0
- umap/urls.py +5 -0
- umap/views.py +40 -11
- umap/websocket_server.py +92 -0
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/METADATA +13 -11
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/RECORD +208 -172
- umap/static/umap/js/umap.autocomplete.js +0 -341
- umap/static/umap/js/umap.importer.js +0 -187
- umap/static/umap/js/umap.ui.js +0 -190
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/WHEEL +0 -0
- {umap_project-2.3.0.dist-info → umap_project-2.4.0.dist-info}/entry_points.txt +0 -0
- {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 (
|
|
65
|
-
value = value[
|
|
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>
|
umap/templates/umap/content.html
CHANGED
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
<header class="wrapper row">
|
|
13
13
|
{% include "umap/navigation.html" with title=SITE_NAME %}
|
|
14
14
|
</header>
|
|
15
|
-
{%
|
|
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
|
|
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)
|
umap/templates/umap/css.html
CHANGED
|
@@ -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' %}" />
|
umap/templates/umap/home.html
CHANGED
|
@@ -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" %}
|
umap/templates/umap/js.html
CHANGED
|
@@ -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
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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 %}
|
umap/templates/umap/search.html
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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": {
|
|
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": {
|
|
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
|
-
|
|
67
|
-
expect(
|
|
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("
|
|
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()
|