umap-project 2.5.1__py3-none-any.whl → 2.6.0b0__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 (193) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +6 -1
  3. umap/context_processors.py +2 -1
  4. umap/decorators.py +13 -2
  5. umap/forms.py +26 -2
  6. umap/locale/br/LC_MESSAGES/django.mo +0 -0
  7. umap/locale/br/LC_MESSAGES/django.po +252 -146
  8. umap/locale/ca/LC_MESSAGES/django.mo +0 -0
  9. umap/locale/ca/LC_MESSAGES/django.po +274 -162
  10. umap/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
  11. umap/locale/cs_CZ/LC_MESSAGES/django.po +261 -150
  12. umap/locale/de/LC_MESSAGES/django.mo +0 -0
  13. umap/locale/de/LC_MESSAGES/django.po +299 -187
  14. umap/locale/el/LC_MESSAGES/django.mo +0 -0
  15. umap/locale/el/LC_MESSAGES/django.po +215 -159
  16. umap/locale/en/LC_MESSAGES/django.po +211 -155
  17. umap/locale/es/LC_MESSAGES/django.mo +0 -0
  18. umap/locale/es/LC_MESSAGES/django.po +255 -144
  19. umap/locale/eu/LC_MESSAGES/django.mo +0 -0
  20. umap/locale/eu/LC_MESSAGES/django.po +254 -198
  21. umap/locale/fa_IR/LC_MESSAGES/django.mo +0 -0
  22. umap/locale/fa_IR/LC_MESSAGES/django.po +346 -234
  23. umap/locale/fr/LC_MESSAGES/django.mo +0 -0
  24. umap/locale/fr/LC_MESSAGES/django.po +216 -160
  25. umap/locale/hu/LC_MESSAGES/django.mo +0 -0
  26. umap/locale/hu/LC_MESSAGES/django.po +215 -159
  27. umap/locale/it/LC_MESSAGES/django.mo +0 -0
  28. umap/locale/it/LC_MESSAGES/django.po +252 -146
  29. umap/locale/ms/LC_MESSAGES/django.mo +0 -0
  30. umap/locale/ms/LC_MESSAGES/django.po +252 -146
  31. umap/locale/pl/LC_MESSAGES/django.mo +0 -0
  32. umap/locale/pl/LC_MESSAGES/django.po +254 -148
  33. umap/locale/pt/LC_MESSAGES/django.mo +0 -0
  34. umap/locale/pt/LC_MESSAGES/django.po +215 -159
  35. umap/locale/sv/LC_MESSAGES/django.mo +0 -0
  36. umap/locale/sv/LC_MESSAGES/django.po +254 -143
  37. umap/locale/th_TH/LC_MESSAGES/django.mo +0 -0
  38. umap/locale/th_TH/LC_MESSAGES/django.po +125 -70
  39. umap/locale/zh_TW/LC_MESSAGES/django.mo +0 -0
  40. umap/locale/zh_TW/LC_MESSAGES/django.po +256 -145
  41. umap/migrations/0022_add_team.py +94 -0
  42. umap/models.py +45 -10
  43. umap/settings/__init__.py +2 -0
  44. umap/settings/base.py +3 -2
  45. umap/static/umap/base.css +32 -41
  46. umap/static/umap/content.css +19 -25
  47. umap/static/umap/css/icon.css +63 -37
  48. umap/static/umap/css/importers.css +1 -1
  49. umap/static/umap/css/slideshow.css +7 -5
  50. umap/static/umap/css/tableeditor.css +4 -3
  51. umap/static/umap/img/16-white.svg +1 -4
  52. umap/static/umap/img/16.svg +2 -6
  53. umap/static/umap/img/24-white.svg +4 -4
  54. umap/static/umap/img/24.svg +6 -6
  55. umap/static/umap/img/source/16-white.svg +2 -5
  56. umap/static/umap/img/source/16.svg +3 -7
  57. umap/static/umap/img/source/24-white.svg +7 -14
  58. umap/static/umap/img/source/24.svg +10 -17
  59. umap/static/umap/js/components/alerts/alert.css +20 -8
  60. umap/static/umap/js/modules/autocomplete.js +3 -3
  61. umap/static/umap/js/modules/browser.js +4 -3
  62. umap/static/umap/js/modules/caption.js +9 -11
  63. umap/static/umap/js/modules/data/features.js +994 -0
  64. umap/static/umap/js/modules/data/layer.js +1210 -0
  65. umap/static/umap/js/modules/formatter.js +12 -3
  66. umap/static/umap/js/modules/global.js +21 -5
  67. umap/static/umap/js/modules/permissions.js +280 -0
  68. umap/static/umap/js/{umap.icon.js → modules/rendering/icon.js} +77 -56
  69. umap/static/umap/js/modules/rendering/layers/base.js +105 -0
  70. umap/static/umap/js/modules/rendering/layers/classified.js +484 -0
  71. umap/static/umap/js/modules/rendering/layers/cluster.js +103 -0
  72. umap/static/umap/js/modules/rendering/layers/heat.js +182 -0
  73. umap/static/umap/js/modules/rendering/popup.js +99 -0
  74. umap/static/umap/js/modules/rendering/template.js +217 -0
  75. umap/static/umap/js/modules/rendering/ui.js +573 -0
  76. umap/static/umap/js/modules/schema.js +24 -0
  77. umap/static/umap/js/modules/share.js +66 -45
  78. umap/static/umap/js/modules/sync/updaters.js +9 -10
  79. umap/static/umap/js/modules/tableeditor.js +7 -7
  80. umap/static/umap/js/modules/ui/dialog.js +8 -4
  81. umap/static/umap/js/modules/utils.js +22 -13
  82. umap/static/umap/js/umap.controls.js +79 -146
  83. umap/static/umap/js/umap.core.js +9 -9
  84. umap/static/umap/js/umap.forms.js +32 -12
  85. umap/static/umap/js/umap.js +65 -63
  86. umap/static/umap/locale/br.js +35 -35
  87. umap/static/umap/locale/br.json +35 -35
  88. umap/static/umap/locale/ca.js +50 -50
  89. umap/static/umap/locale/ca.json +50 -50
  90. umap/static/umap/locale/de.js +136 -136
  91. umap/static/umap/locale/de.json +136 -136
  92. umap/static/umap/locale/el.js +47 -47
  93. umap/static/umap/locale/el.json +47 -47
  94. umap/static/umap/locale/en.js +7 -1
  95. umap/static/umap/locale/en.json +7 -1
  96. umap/static/umap/locale/fa_IR.js +44 -44
  97. umap/static/umap/locale/fa_IR.json +44 -44
  98. umap/static/umap/locale/fr.js +8 -2
  99. umap/static/umap/locale/fr.json +8 -2
  100. umap/static/umap/locale/pt.js +17 -17
  101. umap/static/umap/locale/pt.json +17 -17
  102. umap/static/umap/locale/pt_PT.js +207 -207
  103. umap/static/umap/locale/pt_PT.json +207 -207
  104. umap/static/umap/locale/th_TH.js +25 -25
  105. umap/static/umap/locale/th_TH.json +25 -25
  106. umap/static/umap/map.css +107 -104
  107. umap/static/umap/nav.css +19 -10
  108. umap/static/umap/unittests/utils.js +230 -107
  109. umap/static/umap/vendors/csv2geojson/csv2geojson.js +62 -40
  110. umap/static/umap/vendors/markercluster/MarkerCluster.Default.css +1 -1
  111. umap/storage.py +1 -0
  112. umap/templates/404.html +5 -1
  113. umap/templates/500.html +3 -1
  114. umap/templates/auth/user_detail.html +8 -2
  115. umap/templates/auth/user_form.html +19 -10
  116. umap/templates/auth/user_stars.html +8 -2
  117. umap/templates/base.html +1 -0
  118. umap/templates/registration/login.html +18 -3
  119. umap/templates/umap/about.html +1 -0
  120. umap/templates/umap/about_summary.html +22 -7
  121. umap/templates/umap/components/alerts/alert.html +42 -21
  122. umap/templates/umap/content.html +2 -0
  123. umap/templates/umap/content_footer.html +6 -2
  124. umap/templates/umap/css.html +1 -0
  125. umap/templates/umap/dashboard_menu.html +15 -0
  126. umap/templates/umap/home.html +14 -4
  127. umap/templates/umap/js.html +4 -9
  128. umap/templates/umap/login_popup_end.html +10 -4
  129. umap/templates/umap/map_detail.html +8 -2
  130. umap/templates/umap/map_fragment.html +3 -1
  131. umap/templates/umap/map_init.html +2 -1
  132. umap/templates/umap/map_list.html +4 -3
  133. umap/templates/umap/map_table.html +36 -12
  134. umap/templates/umap/messages.html +0 -1
  135. umap/templates/umap/navigation.html +2 -1
  136. umap/templates/umap/password_change.html +5 -1
  137. umap/templates/umap/password_change_done.html +8 -2
  138. umap/templates/umap/search.html +8 -2
  139. umap/templates/umap/search_bar.html +1 -0
  140. umap/templates/umap/team_confirm_delete.html +19 -0
  141. umap/templates/umap/team_detail.html +27 -0
  142. umap/templates/umap/team_form.html +60 -0
  143. umap/templates/umap/user_dashboard.html +7 -9
  144. umap/templates/umap/user_teams.html +51 -0
  145. umap/tests/base.py +8 -1
  146. umap/tests/conftest.py +6 -0
  147. umap/tests/fixtures/test_circles_layer.geojson +219 -0
  148. umap/tests/fixtures/test_upload_georss.xml +20 -0
  149. umap/tests/integration/conftest.py +18 -4
  150. umap/tests/integration/helpers.py +12 -0
  151. umap/tests/integration/test_anonymous_owned_map.py +23 -0
  152. umap/tests/integration/test_basics.py +29 -0
  153. umap/tests/integration/test_caption.py +20 -0
  154. umap/tests/integration/test_circles_layer.py +69 -0
  155. umap/tests/integration/test_draw_polygon.py +110 -13
  156. umap/tests/integration/test_draw_polyline.py +8 -18
  157. umap/tests/integration/test_edit_datalayer.py +1 -1
  158. umap/tests/integration/test_import.py +64 -5
  159. umap/tests/integration/test_owned_map.py +21 -13
  160. umap/tests/integration/test_team.py +47 -0
  161. umap/tests/integration/test_tilelayer.py +19 -2
  162. umap/tests/integration/test_view_marker.py +28 -1
  163. umap/tests/integration/test_websocket_sync.py +5 -5
  164. umap/tests/test_datalayer.py +32 -7
  165. umap/tests/test_datalayer_views.py +1 -1
  166. umap/tests/test_map.py +30 -4
  167. umap/tests/test_map_views.py +2 -2
  168. umap/tests/test_statics.py +40 -0
  169. umap/tests/test_team_views.py +131 -0
  170. umap/tests/test_views.py +15 -1
  171. umap/urls.py +23 -13
  172. umap/views.py +116 -10
  173. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/METADATA +9 -9
  174. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/RECORD +177 -170
  175. umap/static/umap/js/umap.datalayer.permissions.js +0 -70
  176. umap/static/umap/js/umap.features.js +0 -1290
  177. umap/static/umap/js/umap.layer.js +0 -1837
  178. umap/static/umap/js/umap.permissions.js +0 -208
  179. umap/static/umap/js/umap.popup.js +0 -341
  180. umap/static/umap/test/TableEditor.js +0 -104
  181. umap/static/umap/vendors/leaflet/leaflet-src.js +0 -14512
  182. umap/static/umap/vendors/leaflet/leaflet-src.js.map +0 -1
  183. umap/static/umap/vendors/leaflet/leaflet.js +0 -6
  184. umap/static/umap/vendors/leaflet/leaflet.js.map +0 -1
  185. umap/static/umap/vendors/markercluster/WhereAreTheJavascriptFiles.txt +0 -5
  186. umap/static/umap/vendors/markercluster/leaflet.markercluster-src.js +0 -2718
  187. umap/static/umap/vendors/markercluster/leaflet.markercluster-src.js.map +0 -1
  188. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.css +0 -117
  189. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.js +0 -365
  190. umap/tests/integration/test_statics.py +0 -47
  191. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/WHEEL +0 -0
  192. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/entry_points.txt +0 -0
  193. {umap_project-2.5.1.dist-info → umap_project-2.6.0b0.dist-info}/licenses/LICENSE +0 -0
@@ -1,11 +1,17 @@
1
1
  {% load i18n %}
2
- <h3>{% trans "You are logged in. Continuing..." %}</h3>
2
+
3
+ <h3>
4
+ {% trans "You are logged in. Continuing..." %}
5
+ </h3>
3
6
  <script type="text/javascript">
4
7
  function proceed() {
5
- if (window.opener && window.opener.umap_proceed) {
6
- window.opener.umap_proceed()
8
+ if (window.opener?.onLogin) {
9
+ // We are in the normal process login
10
+ window.opener.onLogin()
11
+ window.close()
7
12
  } else {
8
- // Trade off as Twitter does not allow us to access window.opener
13
+ // we may be in login process that includes a magic link, so user
14
+ // has opened a new window from this link, and we cannot close it then.
9
15
  window.location.href = '{% url "user_dashboard" %}'
10
16
  }
11
17
  }
@@ -1,5 +1,7 @@
1
1
  {% extends "base.html" %}
2
+
2
3
  {% load umap_tags i18n %}
4
+
3
5
  {% block head_title %}
4
6
  {{ map.name }} - {{ SITE_NAME }}
5
7
  {% endblock head_title %}
@@ -8,12 +10,16 @@
8
10
  {% endblock body_class %}
9
11
  {% block extra_head %}
10
12
  {% if preconnect_domains %}
11
- {% for domain in preconnect_domains %}<link rel="preconnect" href="{{ domain }}" />{% endfor %}
13
+ {% for domain in preconnect_domains %}
14
+ <link rel="preconnect" href="{{ domain }}" />
15
+ {% endfor %}
12
16
  {% endif %}
13
17
  {% umap_css %}
14
18
  {{ block.super }}
15
19
  {% umap_js locale=locale %}
16
- {% if object.share_status != object.PUBLIC %}<meta name="robots" content="noindex">{% endif %}
20
+ {% if object.share_status != object.PUBLIC %}
21
+ <meta name="robots" content="noindex">
22
+ {% endif %}
17
23
  <link rel="alternate"
18
24
  type="application/json+oembed"
19
25
  href="{{ oembed_absolute_uri }}?url={{ quoted_absolute_uri }}&format=json"
@@ -1,4 +1,6 @@
1
1
  {% load umap_tags %}
2
+
2
3
  <umap-fragment data-settings='{{ map_settings|escape }}'>
3
- <div id="{{ unique_id }}" class="map_fragment"></div>
4
+ <div id="{{ unique_id }}" class="map_fragment">
5
+ </div>
4
6
  </umap-fragment>
@@ -1,7 +1,8 @@
1
1
  {% load umap_tags %}
2
2
 
3
3
  {% include "umap/messages.html" %}
4
- <div id="map"></div>
4
+ <div id="map">
5
+ </div>
5
6
  <!-- djlint:off -->
6
7
  <script defer type="text/javascript">
7
8
  window.addEventListener('DOMContentLoaded', (event) => {
@@ -1,13 +1,14 @@
1
1
  {% load umap_tags i18n %}
2
+
2
3
  {% for map_inst in maps %}
3
4
  <hr />
4
5
  <div class="col wide">
5
6
  {% map_fragment map_inst prefix=prefix page=request.GET.p %}
6
7
  <div class="legend">
7
8
  <a href="{{ map_inst.get_absolute_url }}">{{ map_inst.name }}</a>
8
- {% if map_inst.owner %}
9
- <em>{% trans "by" %} <a href="{{ map_inst.owner.get_url }}">{{ map_inst.owner }}</a></em>
10
- {% endif %}
9
+ {% with author=map_inst.get_author %}
10
+ <em>{% trans "by" %} <a href="{{ author.get_url }}">{{ author }}</a></em>
11
+ {% endwith %}
11
12
  </div>
12
13
  </div>
13
14
  {% endfor %}
@@ -1,15 +1,30 @@
1
1
  {% load umap_tags i18n %}
2
+
2
3
  <div class="table-wrapper">
3
4
  <table>
4
5
  <thead>
5
6
  <tr>
6
- <th>{% blocktrans %}Name{% endblocktrans %}</th>
7
- <th>{% blocktrans %}Preview{% endblocktrans %}</th>
8
- <th>{% blocktrans %}Who can see{% endblocktrans %}</th>
9
- <th>{% blocktrans %}Who can edit{% endblocktrans %}</th>
10
- <th>{% blocktrans %}Last save{% endblocktrans %}</th>
11
- <th>{% blocktrans %}Owner{% endblocktrans %}</th>
12
- <th>{% blocktrans %}Actions{% endblocktrans %}</th>
7
+ <th>
8
+ {% blocktrans %}Name{% endblocktrans %}
9
+ </th>
10
+ <th>
11
+ {% blocktrans %}Preview{% endblocktrans %}
12
+ </th>
13
+ <th>
14
+ {% blocktrans %}Who can see{% endblocktrans %}
15
+ </th>
16
+ <th>
17
+ {% blocktrans %}Who can edit{% endblocktrans %}
18
+ </th>
19
+ <th>
20
+ {% blocktrans %}Last save{% endblocktrans %}
21
+ </th>
22
+ <th>
23
+ {% blocktrans %}Owner{% endblocktrans %}
24
+ </th>
25
+ <th>
26
+ {% blocktrans %}Actions{% endblocktrans %}
27
+ </th>
13
28
  </tr>
14
29
  </thead>
15
30
  <tbody>
@@ -29,16 +44,25 @@
29
44
  </button>
30
45
  <dialog>
31
46
  <form method="dialog">
32
- <div id="{{ unique_id }}_target" class="map_fragment"></div>
47
+ <div id="{{ unique_id }}_target" class="map_fragment">
48
+ </div>
33
49
  <p class="close-dialog">
34
- <button class="button" type="submit">Close</button>
50
+ <button class="button" type="submit">
51
+ Close
52
+ </button>
35
53
  </p>
36
54
  </form>
37
55
  </dialog>
38
56
  </td>
39
- <td>{{ map_inst.get_share_status_display }}</td>
40
- <td>{{ map_inst.get_edit_status_display }}</td>
41
- <td>{{ map_inst.modified_at }}</td>
57
+ <td>
58
+ {{ map_inst.get_share_status_display }}
59
+ </td>
60
+ <td>
61
+ {{ map_inst.get_edit_status_display }}
62
+ </td>
63
+ <td>
64
+ {{ map_inst.modified_at }}
65
+ </td>
42
66
  <td>
43
67
  <a href="{{ map_inst.owner.get_url }}">{{ map_inst.owner }}</a>
44
68
  </td>
@@ -1,7 +1,6 @@
1
1
  {% load i18n %}
2
2
 
3
3
  {% include "umap/components/alerts/alert.html" %}
4
-
5
4
  {% for message in messages %}
6
5
  <script type="module" defer>
7
6
  U.Alert.success("{{ message }}")
@@ -1,4 +1,5 @@
1
1
  {% load i18n %}
2
+
2
3
  <nav class="umap-nav">
3
4
  <section>
4
5
  {% include "umap/branding.html" %}
@@ -21,7 +22,7 @@
21
22
  <a href="{% url "about" %}">{% trans "About" %}</a>
22
23
  </li>
23
24
  <li>
24
- <a href="{{ UMAP_FEEDBACK_LINK }}">{% trans "Help" %}</a>
25
+ <a href="{{ UMAP_HELP_URL }}">{% trans "Help" %}</a>
25
26
  </li>
26
27
  {% if user.is_authenticated %}
27
28
  {% if user.has_usable_password %}
@@ -1,7 +1,11 @@
1
1
  {% extends "umap/content.html" %}
2
+
2
3
  {% load i18n %}
4
+
3
5
  {% block content %}
4
- <h2 class="section">{% trans "Password change" %}</h2>
6
+ <h2 class="section">
7
+ {% trans "Password change" %}
8
+ </h2>
5
9
  <p>
6
10
  {% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}
7
11
  </p>
@@ -1,8 +1,14 @@
1
1
  {% extends "umap/content.html" %}
2
+
2
3
  {% load i18n %}
4
+
3
5
  {% block content %}
4
- <h2 class="section">{% trans "Password change successful" %}</h2>
5
- <p>{% trans "Your password was changed." %}</p>
6
+ <h2 class="section">
7
+ {% trans "Password change successful" %}
8
+ </h2>
9
+ <p>
10
+ {% trans "Your password was changed." %}
11
+ </p>
6
12
  <p>
7
13
  <a href="{% url 'home' %}">Home</a>
8
14
  </p>
@@ -1,5 +1,7 @@
1
1
  {% extends "umap/content.html" %}
2
+
2
3
  {% load i18n %}
4
+
3
5
  {% block messages %}
4
6
  {# We don't want maps from the results list to display errors in the main page. #}
5
7
  {% endblock messages %}
@@ -18,10 +20,14 @@
18
20
  </h2>
19
21
  {% include "umap/map_list.html" with prefix="search_map" %}
20
22
  {% else %}
21
- <h2>{% trans "No map found." %}</h2>
23
+ <h2>
24
+ {% trans "No map found." %}
25
+ </h2>
22
26
  {% endif %}
23
27
  {% else %}
24
- <h2>{% trans "Latest created maps" %}</h2>
28
+ <h2>
29
+ {% trans "Latest created maps" %}
30
+ </h2>
25
31
  {% include "umap/map_list.html" with prefix="search_map" %}
26
32
  {% endif %}
27
33
  </div>
@@ -1,4 +1,5 @@
1
1
  {% load i18n %}
2
+
2
3
  {% url "search" as search_url %}
3
4
  {% trans "Search maps" as default_placeholder %}
4
5
  <div class="wrapper search_wrapper">
@@ -0,0 +1,19 @@
1
+ {% extends "umap/content.html" %}
2
+
3
+ {% load i18n %}
4
+
5
+ {% block maincontent %}
6
+ {% include "umap/dashboard_menu.html" with selected="teams" %}
7
+ <div class="wrapper">
8
+ <div class="row">
9
+ <form method="post">
10
+ {% csrf_token %}
11
+ <p>
12
+ Are you sure you want to delete "{{ object }}"?
13
+ </p>
14
+ {{ form }}
15
+ <input type="submit" value="Confirm">
16
+ </form>
17
+ </div>
18
+ </div>
19
+ {% endblock maincontent %}
@@ -0,0 +1,27 @@
1
+ {% extends "umap/content.html" %}
2
+
3
+ {% load i18n %}
4
+
5
+ {% block maincontent %}
6
+ <div class="wrapper">
7
+ <div class="row">
8
+ <div class="col wide">
9
+ <h2 class="section">
10
+ {% blocktrans %}Browse {{ current_team }}'s maps{% endblocktrans %}
11
+ </h2>
12
+ {% if current_team.description %}
13
+ <p>{{ current_team.description }}</p>
14
+ {% endif %}
15
+ </div>
16
+ </div>
17
+ <div class="map_list row">
18
+ {% if maps %}
19
+ {% include "umap/map_list.html" %}
20
+ {% else %}
21
+ <div>
22
+ {% blocktrans %}{{ current_team }} has no public maps.{% endblocktrans %}
23
+ </div>
24
+ {% endif %}
25
+ </div>
26
+ </div>
27
+ {% endblock maincontent %}
@@ -0,0 +1,60 @@
1
+ {% extends "umap/content.html" %}
2
+
3
+ {% load i18n %}
4
+
5
+ {% block maincontent %}
6
+ {% include "umap/dashboard_menu.html" with selected="teams" %}
7
+ <div class="wrapper">
8
+ <div class="row">
9
+ {% if form.non_field_errors %}
10
+ <ul class="form-errors">
11
+ {% for error in form.non_field_errors %}
12
+ <li>
13
+ {{ error }}
14
+ </li>
15
+ {% endfor %}
16
+ </ul>
17
+ {% endif %}
18
+ <form id="team_form" method="post">
19
+ {% csrf_token %}
20
+ {{ form }}
21
+ <input type="submit" value="{% trans "Save" %}" />
22
+ </form>
23
+ {% if team.users.count == 1 %}
24
+ <a href="{% url 'team_delete' team.pk %}">{% trans "Delete this team" %}</a>
25
+ {% endif %}
26
+ </div>
27
+ </div>
28
+ <script type="module" defer>
29
+ const form = document.querySelector("#team_form")
30
+ const select = form.querySelector('#id_members')
31
+ if (select) {
32
+ function onSelect({item: {value, label}}) {
33
+ const option = document.createElement('option')
34
+ option.value = value
35
+ option.textContent = label
36
+ option.selected = "selected"
37
+ select.appendChild(option)
38
+ }
39
+ function onUnselect({item: {value, label}}) {
40
+ const option = select.querySelector(`[value="${value}"]`)
41
+ select.removeChild(option)
42
+ }
43
+ const options = {
44
+ className: 'edit-team-members',
45
+ on_select: onSelect,
46
+ on_unselect: onUnselect,
47
+ placeholder: "{% trans "Add user" %}"
48
+ }
49
+ const autocomplete = new U.AjaxAutocompleteMultiple(form, options)
50
+ for (const option of select.options) {
51
+ autocomplete.displaySelected({
52
+ item: { value: option.value, label: option.textContent },
53
+ })
54
+ }
55
+ const submit = form.querySelector('input[type="submit"]')
56
+ // Move it after the autocomplete widget.
57
+ form.appendChild(submit)
58
+ }
59
+ </script>
60
+ {% endblock maincontent %}
@@ -1,23 +1,21 @@
1
1
  {% extends "umap/content.html" %}
2
+
2
3
  {% load i18n %}
4
+
3
5
  {% block head_title %}
4
6
  {{ SITE_NAME }} - {% trans "My Dashboard" %}
5
7
  {% endblock head_title %}
6
8
  {% block maincontent %}
7
9
  {% trans "Search my maps" as placeholder %}
8
- <div class="row">
9
- <h2 class="section tabs">
10
- <a class="selected" href="{% url 'user_dashboard' %}">{% blocktranslate with count=maps.paginator.count %}My Maps ({{ count }}){% endblocktranslate %}
11
- </a>
12
- <a href="{% url 'user_profile' %}">{% trans "My profile" %}</a>
13
- </h2>
14
- </div>
10
+ {% include "umap/dashboard_menu.html" with selected="maps" %}
15
11
  <div class="wrapper">
16
12
  <div class="row">
17
13
  <div class="table-header">
18
14
  <form action="{{ request.get_full_path }}" method="get">
19
15
  <span>
20
- <label class="sr-only" for="q">{% translate "Map’s title" %}</label>
16
+ <label class="sr-only" for="q">
17
+ {% translate "Map’s title" %}
18
+ </label>
21
19
  <input id="q"
22
20
  name="q"
23
21
  type="search"
@@ -55,7 +53,7 @@
55
53
  const button = event.target.closest('button')
56
54
  button.nextElementSibling.showModal()
57
55
  const mapId = button.dataset.mapId
58
- if (!document.querySelector(`#${mapId}_target`).hasChildNodes()) {
56
+ if (!document.querySelector(`#${mapId}_target`).children.length) {
59
57
  const previewSettings = JSON.parse(document.getElementById(mapId).textContent)
60
58
  const map = new U.Map(`${mapId}_target`, previewSettings)
61
59
  CACHE[mapId] = map
@@ -0,0 +1,51 @@
1
+ {% extends "umap/content.html" %}
2
+
3
+ {% load i18n %}
4
+
5
+ {% block maincontent %}
6
+ {% include "umap/dashboard_menu.html" with selected="teams" %}
7
+ <div class="wrapper">
8
+ <div class="row">
9
+ <div class="table-wrapper">
10
+ <table>
11
+ <thead>
12
+ <tr>
13
+ <th>
14
+ {% blocktrans %}Name{% endblocktrans %}
15
+ </th>
16
+ <th>
17
+ {% blocktrans %}Users{% endblocktrans %}
18
+ </th>
19
+ <th>
20
+ {% blocktrans %}Actions{% endblocktrans %}
21
+ </th>
22
+ </tr>
23
+ </thead>
24
+ <tbody>
25
+ {% for team in teams %}
26
+ <tr>
27
+ <th scope="row">
28
+ <a href="{% url 'team_maps' team.pk %}">{{ team }}</a>
29
+ </th>
30
+ <td>
31
+ {% for user in team.users.all %}
32
+ {{ user }}{% if not forloop.last %}, {% endif %}
33
+ {% endfor %}
34
+ </td>
35
+ <td>
36
+ <a href="{% url 'team_update' team.pk %}"
37
+ class="icon-link"
38
+ title="{% translate "Edit" %}">
39
+ <span class="icon-dashboard icon-edit"></span>
40
+ <span class="sr-only">{% translate "Edit" %}</span>
41
+ </a>
42
+ </td>
43
+ </tr>
44
+ {% endfor %}
45
+ </tbody>
46
+ </table>
47
+ </div>
48
+ <a class="button" href="{% url 'team_new' %}">{% trans "New team" %}</a>
49
+ </div>
50
+ </div>
51
+ {% endblock maincontent %}
umap/tests/base.py CHANGED
@@ -7,7 +7,7 @@ from django.core.files.base import ContentFile
7
7
  from django.urls import reverse
8
8
 
9
9
  from umap.forms import DEFAULT_CENTER
10
- from umap.models import DataLayer, Licence, Map, TileLayer
10
+ from umap.models import DataLayer, Licence, Map, Team, TileLayer
11
11
 
12
12
  User = get_user_model()
13
13
 
@@ -58,6 +58,13 @@ class UserFactory(factory.django.DjangoModelFactory):
58
58
  model = User
59
59
 
60
60
 
61
+ class TeamFactory(factory.django.DjangoModelFactory):
62
+ name = "Awesome Team"
63
+
64
+ class Meta:
65
+ model = Team
66
+
67
+
61
68
  class MapFactory(factory.django.DjangoModelFactory):
62
69
  name = "test map"
63
70
  slug = "test-map"
umap/tests/conftest.py CHANGED
@@ -11,6 +11,7 @@ from .base import (
11
11
  DataLayerFactory,
12
12
  LicenceFactory,
13
13
  MapFactory,
14
+ TeamFactory,
14
15
  TileLayerFactory,
15
16
  UserFactory,
16
17
  )
@@ -29,6 +30,11 @@ def pytest_runtest_teardown():
29
30
  cache.clear()
30
31
 
31
32
 
33
+ @pytest.fixture
34
+ def team():
35
+ return TeamFactory()
36
+
37
+
32
38
  @pytest.fixture
33
39
  def user():
34
40
  return UserFactory(password="123123")