umap-project 2.5.1__py3-none-any.whl → 2.6.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 (276) 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 +347 -235
  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 +9 -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 +8 -12
  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 +993 -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/importers/overpass.js +22 -8
  68. umap/static/umap/js/modules/permissions.js +280 -0
  69. umap/static/umap/js/{umap.icon.js → modules/rendering/icon.js} +77 -56
  70. umap/static/umap/js/modules/rendering/layers/base.js +105 -0
  71. umap/static/umap/js/modules/rendering/layers/classified.js +484 -0
  72. umap/static/umap/js/modules/rendering/layers/cluster.js +103 -0
  73. umap/static/umap/js/modules/rendering/layers/heat.js +182 -0
  74. umap/static/umap/js/modules/rendering/popup.js +99 -0
  75. umap/static/umap/js/modules/rendering/template.js +217 -0
  76. umap/static/umap/js/modules/rendering/ui.js +610 -0
  77. umap/static/umap/js/modules/rules.js +16 -3
  78. umap/static/umap/js/modules/schema.js +25 -1
  79. umap/static/umap/js/modules/share.js +66 -45
  80. umap/static/umap/js/modules/sync/updaters.js +9 -10
  81. umap/static/umap/js/modules/tableeditor.js +7 -7
  82. umap/static/umap/js/modules/ui/dialog.js +8 -4
  83. umap/static/umap/js/modules/utils.js +22 -13
  84. umap/static/umap/js/umap.controls.js +80 -146
  85. umap/static/umap/js/umap.core.js +9 -9
  86. umap/static/umap/js/umap.forms.js +41 -17
  87. umap/static/umap/js/umap.js +72 -65
  88. umap/static/umap/locale/am_ET.js +8 -2
  89. umap/static/umap/locale/am_ET.json +8 -2
  90. umap/static/umap/locale/ar.js +8 -2
  91. umap/static/umap/locale/ar.json +8 -2
  92. umap/static/umap/locale/ast.js +8 -2
  93. umap/static/umap/locale/ast.json +8 -2
  94. umap/static/umap/locale/bg.js +8 -2
  95. umap/static/umap/locale/bg.json +8 -2
  96. umap/static/umap/locale/br.js +42 -36
  97. umap/static/umap/locale/br.json +42 -36
  98. umap/static/umap/locale/ca.js +67 -61
  99. umap/static/umap/locale/ca.json +67 -61
  100. umap/static/umap/locale/cs_CZ.js +8 -2
  101. umap/static/umap/locale/cs_CZ.json +8 -2
  102. umap/static/umap/locale/da.js +8 -2
  103. umap/static/umap/locale/da.json +8 -2
  104. umap/static/umap/locale/de.js +143 -137
  105. umap/static/umap/locale/de.json +143 -137
  106. umap/static/umap/locale/el.js +54 -48
  107. umap/static/umap/locale/el.json +54 -48
  108. umap/static/umap/locale/en.js +10 -2
  109. umap/static/umap/locale/en.json +10 -2
  110. umap/static/umap/locale/en_US.json +8 -2
  111. umap/static/umap/locale/es.js +8 -2
  112. umap/static/umap/locale/es.json +8 -2
  113. umap/static/umap/locale/et.js +8 -2
  114. umap/static/umap/locale/et.json +8 -2
  115. umap/static/umap/locale/eu.js +346 -338
  116. umap/static/umap/locale/eu.json +346 -338
  117. umap/static/umap/locale/fa_IR.js +415 -407
  118. umap/static/umap/locale/fa_IR.json +415 -407
  119. umap/static/umap/locale/fi.js +8 -2
  120. umap/static/umap/locale/fi.json +8 -2
  121. umap/static/umap/locale/fr.js +11 -3
  122. umap/static/umap/locale/fr.json +11 -3
  123. umap/static/umap/locale/gl.js +8 -2
  124. umap/static/umap/locale/gl.json +8 -2
  125. umap/static/umap/locale/he.js +8 -2
  126. umap/static/umap/locale/he.json +8 -2
  127. umap/static/umap/locale/hr.js +8 -2
  128. umap/static/umap/locale/hr.json +8 -2
  129. umap/static/umap/locale/hu.js +31 -23
  130. umap/static/umap/locale/hu.json +31 -23
  131. umap/static/umap/locale/id.js +8 -2
  132. umap/static/umap/locale/id.json +8 -2
  133. umap/static/umap/locale/is.js +8 -2
  134. umap/static/umap/locale/is.json +8 -2
  135. umap/static/umap/locale/it.js +8 -2
  136. umap/static/umap/locale/it.json +8 -2
  137. umap/static/umap/locale/ja.js +8 -2
  138. umap/static/umap/locale/ja.json +8 -2
  139. umap/static/umap/locale/ko.js +8 -2
  140. umap/static/umap/locale/ko.json +8 -2
  141. umap/static/umap/locale/lt.js +8 -2
  142. umap/static/umap/locale/lt.json +8 -2
  143. umap/static/umap/locale/ms.js +8 -2
  144. umap/static/umap/locale/ms.json +8 -2
  145. umap/static/umap/locale/nl.js +8 -2
  146. umap/static/umap/locale/nl.json +8 -2
  147. umap/static/umap/locale/no.js +8 -2
  148. umap/static/umap/locale/no.json +8 -2
  149. umap/static/umap/locale/pl.js +54 -48
  150. umap/static/umap/locale/pl.json +54 -48
  151. umap/static/umap/locale/pl_PL.json +8 -2
  152. umap/static/umap/locale/pt.js +24 -18
  153. umap/static/umap/locale/pt.json +24 -18
  154. umap/static/umap/locale/pt_BR.js +8 -2
  155. umap/static/umap/locale/pt_BR.json +8 -2
  156. umap/static/umap/locale/pt_PT.js +214 -208
  157. umap/static/umap/locale/pt_PT.json +214 -208
  158. umap/static/umap/locale/ro.js +8 -2
  159. umap/static/umap/locale/ro.json +8 -2
  160. umap/static/umap/locale/ru.js +8 -2
  161. umap/static/umap/locale/ru.json +8 -2
  162. umap/static/umap/locale/sk_SK.js +8 -2
  163. umap/static/umap/locale/sk_SK.json +8 -2
  164. umap/static/umap/locale/sl.js +8 -2
  165. umap/static/umap/locale/sl.json +8 -2
  166. umap/static/umap/locale/sr.js +8 -2
  167. umap/static/umap/locale/sr.json +8 -2
  168. umap/static/umap/locale/sv.js +8 -2
  169. umap/static/umap/locale/sv.json +8 -2
  170. umap/static/umap/locale/th_TH.js +33 -27
  171. umap/static/umap/locale/th_TH.json +33 -27
  172. umap/static/umap/locale/tr.js +8 -2
  173. umap/static/umap/locale/tr.json +8 -2
  174. umap/static/umap/locale/uk_UA.js +8 -2
  175. umap/static/umap/locale/uk_UA.json +8 -2
  176. umap/static/umap/locale/vi.js +8 -2
  177. umap/static/umap/locale/vi.json +8 -2
  178. umap/static/umap/locale/vi_VN.json +8 -2
  179. umap/static/umap/locale/zh.js +8 -2
  180. umap/static/umap/locale/zh.json +8 -2
  181. umap/static/umap/locale/zh_CN.json +8 -2
  182. umap/static/umap/locale/zh_TW.Big5.json +8 -2
  183. umap/static/umap/locale/zh_TW.js +102 -96
  184. umap/static/umap/locale/zh_TW.json +102 -96
  185. umap/static/umap/map.css +111 -108
  186. umap/static/umap/nav.css +19 -10
  187. umap/static/umap/unittests/utils.js +230 -107
  188. umap/static/umap/vars.css +1 -0
  189. umap/static/umap/vendors/csv2geojson/csv2geojson.js +62 -40
  190. umap/static/umap/vendors/editable/Leaflet.Editable.js +2079 -1937
  191. umap/storage.py +1 -0
  192. umap/templates/404.html +5 -1
  193. umap/templates/500.html +3 -1
  194. umap/templates/auth/user_detail.html +8 -2
  195. umap/templates/auth/user_form.html +19 -10
  196. umap/templates/auth/user_stars.html +8 -2
  197. umap/templates/base.html +1 -0
  198. umap/templates/registration/login.html +18 -3
  199. umap/templates/umap/about.html +1 -0
  200. umap/templates/umap/about_summary.html +22 -7
  201. umap/templates/umap/components/alerts/alert.html +42 -21
  202. umap/templates/umap/content.html +2 -0
  203. umap/templates/umap/content_footer.html +7 -3
  204. umap/templates/umap/css.html +1 -0
  205. umap/templates/umap/dashboard_menu.html +15 -0
  206. umap/templates/umap/home.html +14 -4
  207. umap/templates/umap/js.html +4 -9
  208. umap/templates/umap/login_popup_end.html +10 -4
  209. umap/templates/umap/map_detail.html +8 -2
  210. umap/templates/umap/map_fragment.html +3 -1
  211. umap/templates/umap/map_init.html +2 -1
  212. umap/templates/umap/map_list.html +6 -3
  213. umap/templates/umap/map_table.html +36 -12
  214. umap/templates/umap/messages.html +0 -1
  215. umap/templates/umap/navigation.html +2 -1
  216. umap/templates/umap/password_change.html +5 -1
  217. umap/templates/umap/password_change_done.html +8 -2
  218. umap/templates/umap/search.html +8 -2
  219. umap/templates/umap/search_bar.html +1 -0
  220. umap/templates/umap/team_confirm_delete.html +19 -0
  221. umap/templates/umap/team_detail.html +27 -0
  222. umap/templates/umap/team_form.html +60 -0
  223. umap/templates/umap/user_dashboard.html +7 -9
  224. umap/templates/umap/user_teams.html +51 -0
  225. umap/tests/base.py +8 -1
  226. umap/tests/conftest.py +6 -0
  227. umap/tests/fixtures/test_circles_layer.geojson +219 -0
  228. umap/tests/fixtures/test_upload_georss.xml +20 -0
  229. umap/tests/integration/conftest.py +18 -4
  230. umap/tests/integration/helpers.py +12 -0
  231. umap/tests/integration/test_anonymous_owned_map.py +23 -0
  232. umap/tests/integration/test_basics.py +29 -0
  233. umap/tests/integration/test_browser.py +20 -0
  234. umap/tests/integration/test_caption.py +20 -0
  235. umap/tests/integration/test_circles_layer.py +69 -0
  236. umap/tests/integration/test_conditional_rules.py +102 -17
  237. umap/tests/integration/test_draw_polygon.py +138 -13
  238. umap/tests/integration/test_draw_polyline.py +8 -18
  239. umap/tests/integration/test_edit_datalayer.py +3 -3
  240. umap/tests/integration/test_import.py +124 -5
  241. umap/tests/integration/test_owned_map.py +21 -13
  242. umap/tests/integration/test_querystring.py +7 -0
  243. umap/tests/integration/test_team.py +47 -0
  244. umap/tests/integration/test_tilelayer.py +19 -2
  245. umap/tests/integration/test_view_marker.py +28 -1
  246. umap/tests/integration/test_websocket_sync.py +5 -5
  247. umap/tests/test_datalayer.py +32 -7
  248. umap/tests/test_datalayer_views.py +1 -1
  249. umap/tests/test_map.py +30 -4
  250. umap/tests/test_map_views.py +2 -2
  251. umap/tests/test_statics.py +40 -0
  252. umap/tests/test_team_views.py +131 -0
  253. umap/tests/test_views.py +15 -1
  254. umap/urls.py +23 -13
  255. umap/views.py +116 -10
  256. {umap_project-2.5.1.dist-info → umap_project-2.6.0.dist-info}/METADATA +14 -14
  257. {umap_project-2.5.1.dist-info → umap_project-2.6.0.dist-info}/RECORD +260 -253
  258. umap/static/umap/js/umap.datalayer.permissions.js +0 -70
  259. umap/static/umap/js/umap.features.js +0 -1290
  260. umap/static/umap/js/umap.layer.js +0 -1837
  261. umap/static/umap/js/umap.permissions.js +0 -208
  262. umap/static/umap/js/umap.popup.js +0 -341
  263. umap/static/umap/test/TableEditor.js +0 -104
  264. umap/static/umap/vendors/leaflet/leaflet-src.js +0 -14512
  265. umap/static/umap/vendors/leaflet/leaflet-src.js.map +0 -1
  266. umap/static/umap/vendors/leaflet/leaflet.js +0 -6
  267. umap/static/umap/vendors/leaflet/leaflet.js.map +0 -1
  268. umap/static/umap/vendors/markercluster/WhereAreTheJavascriptFiles.txt +0 -5
  269. umap/static/umap/vendors/markercluster/leaflet.markercluster-src.js +0 -2718
  270. umap/static/umap/vendors/markercluster/leaflet.markercluster-src.js.map +0 -1
  271. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.css +0 -117
  272. umap/static/umap/vendors/toolbar/leaflet.toolbar-src.js +0 -365
  273. umap/tests/integration/test_statics.py +0 -47
  274. {umap_project-2.5.1.dist-info → umap_project-2.6.0.dist-info}/WHEEL +0 -0
  275. {umap_project-2.5.1.dist-info → umap_project-2.6.0.dist-info}/entry_points.txt +0 -0
  276. {umap_project-2.5.1.dist-info → umap_project-2.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,94 @@
1
+ # Generated by Django 5.1 on 2024-08-15 11:33
2
+
3
+ import django.db.models.deletion
4
+ from django.conf import settings
5
+ from django.db import migrations, models
6
+
7
+ import umap.models
8
+
9
+
10
+ class Migration(migrations.Migration):
11
+ dependencies = [("umap", "0021_remove_map_description")]
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name="Team",
16
+ fields=[
17
+ (
18
+ "id",
19
+ models.AutoField(
20
+ auto_created=True,
21
+ primary_key=True,
22
+ serialize=False,
23
+ verbose_name="ID",
24
+ ),
25
+ ),
26
+ (
27
+ "name",
28
+ models.CharField(max_length=200, unique=True, verbose_name="name"),
29
+ ),
30
+ (
31
+ "description",
32
+ models.TextField(blank=True, null=True, verbose_name="description"),
33
+ ),
34
+ (
35
+ "users",
36
+ models.ManyToManyField(
37
+ related_name="teams", to=settings.AUTH_USER_MODEL
38
+ ),
39
+ ),
40
+ ],
41
+ ),
42
+ migrations.AddField(
43
+ model_name="map",
44
+ name="team",
45
+ field=models.ForeignKey(
46
+ blank=True,
47
+ null=True,
48
+ on_delete=django.db.models.deletion.SET_NULL,
49
+ to="umap.team",
50
+ verbose_name="team",
51
+ ),
52
+ ),
53
+ migrations.AlterField(
54
+ model_name="datalayer",
55
+ name="edit_status",
56
+ field=models.SmallIntegerField(
57
+ choices=[
58
+ (0, "Inherit"),
59
+ (1, "Everyone"),
60
+ (2, "Editors and team only"),
61
+ (3, "Owner only"),
62
+ ],
63
+ default=0,
64
+ verbose_name="edit status",
65
+ ),
66
+ ),
67
+ migrations.AlterField(
68
+ model_name="map",
69
+ name="edit_status",
70
+ field=models.SmallIntegerField(
71
+ choices=[
72
+ (1, "Everyone"),
73
+ (2, "Editors and team only"),
74
+ (3, "Owner only"),
75
+ ],
76
+ default=umap.models.get_default_edit_status,
77
+ verbose_name="edit status",
78
+ ),
79
+ ),
80
+ migrations.AlterField(
81
+ model_name="map",
82
+ name="share_status",
83
+ field=models.SmallIntegerField(
84
+ choices=[
85
+ (1, "Everyone (public)"),
86
+ (2, "Anyone with link"),
87
+ (3, "Editors and team only"),
88
+ (9, "Blocked"),
89
+ ],
90
+ default=umap.models.get_default_share_status,
91
+ verbose_name="share status",
92
+ ),
93
+ ),
94
+ ]
umap/models.py CHANGED
@@ -49,6 +49,26 @@ def get_default_edit_status():
49
49
  return settings.UMAP_DEFAULT_EDIT_STATUS or Map.OWNER
50
50
 
51
51
 
52
+ class Team(models.Model):
53
+ name = models.CharField(
54
+ max_length=200, verbose_name=_("name"), unique=True, blank=False, null=False
55
+ )
56
+ description = models.TextField(blank=True, null=True, verbose_name=_("description"))
57
+ users = models.ManyToManyField(User, related_name="teams")
58
+
59
+ def __unicode__(self):
60
+ return self.name
61
+
62
+ def __str__(self):
63
+ return self.name
64
+
65
+ def get_url(self):
66
+ return reverse("team_maps", kwargs={"pk": self.pk})
67
+
68
+ def get_metadata(self):
69
+ return {"id": self.pk, "name": self.name, "url": self.get_url()}
70
+
71
+
52
72
  class NamedModel(models.Model):
53
73
  name = models.CharField(max_length=200, verbose_name=_("name"))
54
74
 
@@ -137,7 +157,7 @@ class Map(NamedModel):
137
157
  """
138
158
 
139
159
  ANONYMOUS = 1
140
- EDITORS = 2
160
+ COLLABORATORS = 2
141
161
  OWNER = 3
142
162
  PUBLIC = 1
143
163
  OPEN = 2
@@ -145,13 +165,13 @@ class Map(NamedModel):
145
165
  BLOCKED = 9
146
166
  EDIT_STATUS = (
147
167
  (ANONYMOUS, _("Everyone")),
148
- (EDITORS, _("Editors only")),
168
+ (COLLABORATORS, _("Editors and team only")),
149
169
  (OWNER, _("Owner only")),
150
170
  )
151
171
  SHARE_STATUS = (
152
172
  (PUBLIC, _("Everyone (public)")),
153
173
  (OPEN, _("Anyone with link")),
154
- (PRIVATE, _("Editors only")),
174
+ (PRIVATE, _("Editors and team only")),
155
175
  (BLOCKED, _("Blocked")),
156
176
  )
157
177
  slug = models.SlugField(db_index=True)
@@ -180,6 +200,13 @@ class Map(NamedModel):
180
200
  editors = models.ManyToManyField(
181
201
  settings.AUTH_USER_MODEL, blank=True, verbose_name=_("editors")
182
202
  )
203
+ team = models.ForeignKey(
204
+ Team,
205
+ blank=True,
206
+ null=True,
207
+ verbose_name=_("team"),
208
+ on_delete=models.SET_NULL,
209
+ )
183
210
  edit_status = models.SmallIntegerField(
184
211
  choices=EDIT_STATUS,
185
212
  default=get_default_edit_status,
@@ -251,6 +278,9 @@ class Map(NamedModel):
251
278
  path = reverse("map_anonymous_edit_url", kwargs={"signature": signature})
252
279
  return settings.SITE_URL + path
253
280
 
281
+ def get_author(self):
282
+ return self.team or self.owner
283
+
254
284
  def is_owner(self, user=None, request=None):
255
285
  if user and self.owner == user:
256
286
  return True
@@ -281,7 +311,7 @@ class Map(NamedModel):
281
311
 
282
312
  In owner mode:
283
313
  - only owner by default (OWNER)
284
- - any editor if mode is EDITORS
314
+ - any editor or team member if mode is COLLABORATORS
285
315
  - anyone otherwise (ANONYMOUS)
286
316
  In anonymous owner mode:
287
317
  - only owner (has ownership cookie) by default (OWNER)
@@ -297,8 +327,9 @@ class Map(NamedModel):
297
327
  can = False
298
328
  elif user == self.owner:
299
329
  can = True
300
- elif self.edit_status == self.EDITORS and user in self.editors.all():
301
- can = True
330
+ elif self.edit_status == self.COLLABORATORS:
331
+ if user in self.editors.all() or self.team in user.teams.all():
332
+ can = True
302
333
  return can
303
334
 
304
335
  def can_view(self, request):
@@ -308,12 +339,15 @@ class Map(NamedModel):
308
339
  can = True
309
340
  elif self.share_status in [self.PUBLIC, self.OPEN]:
310
341
  can = True
342
+ elif not request.user.is_authenticated:
343
+ can = False
311
344
  elif request.user == self.owner:
312
345
  can = True
313
346
  else:
314
347
  can = not (
315
348
  self.share_status == self.PRIVATE
316
349
  and request.user not in self.editors.all()
350
+ and self.team not in request.user.teams.all()
317
351
  )
318
352
  return can
319
353
 
@@ -383,12 +417,12 @@ class DataLayer(NamedModel):
383
417
 
384
418
  INHERIT = 0
385
419
  ANONYMOUS = 1
386
- EDITORS = 2
420
+ COLLABORATORS = 2
387
421
  OWNER = 3
388
422
  EDIT_STATUS = (
389
423
  (INHERIT, _("Inherit")),
390
424
  (ANONYMOUS, _("Everyone")),
391
- (EDITORS, _("Editors only")),
425
+ (COLLABORATORS, _("Editors and team only")),
392
426
  (OWNER, _("Owner only")),
393
427
  )
394
428
  uuid = models.UUIDField(
@@ -538,8 +572,9 @@ class DataLayer(NamedModel):
538
572
  can = True
539
573
  elif user is not None and user == self.map.owner:
540
574
  can = True
541
- elif self.edit_status == self.EDITORS and user in self.map.editors.all():
542
- can = True
575
+ elif user is not None and self.edit_status == self.COLLABORATORS:
576
+ if user in self.map.editors.all() or self.map.team in user.teams.all():
577
+ can = True
543
578
  return can
544
579
 
545
580
 
umap/settings/__init__.py CHANGED
@@ -41,5 +41,7 @@ if path:
41
41
  globals()["TEMPLATES"][0]["DIRS"] = [value]
42
42
  elif key == "UMAP_CUSTOM_STATICS":
43
43
  globals()["STATICFILES_DIRS"].insert(0, value)
44
+ elif key == "UMAP_FEEDBACK_LINK":
45
+ globals()["UMAP_HELP_URL"] = value
44
46
  else:
45
47
  globals()[key] = value
umap/settings/base.py CHANGED
@@ -51,6 +51,12 @@ LANG_INFO.update(
51
51
  "name": "Malay",
52
52
  "name_local": "Bahasa Melayu",
53
53
  },
54
+ "fa-ir": {
55
+ "bidi": True,
56
+ "code": "fa-ir",
57
+ "name": "Persian (Iran)",
58
+ "name_local": "فارسی",
59
+ },
54
60
  }
55
61
  )
56
62
  # Local time zone for this installation. Choices can be found here:
@@ -152,7 +158,7 @@ WSGI_APPLICATION = "umap.wsgi.application"
152
158
 
153
159
  LOGIN_URL = "/login/"
154
160
  LOGOUT_URL = "/logout/"
155
- LOGIN_REDIRECT_URL = "/"
161
+ LOGIN_REDIRECT_URL = "login_popup_end"
156
162
 
157
163
  STATIC_URL = "/static/"
158
164
  MEDIA_URL = "/uploads/"
@@ -251,7 +257,7 @@ UMAP_MAPS_PER_PAGE = 5
251
257
  UMAP_MAPS_PER_SEARCH = 25
252
258
  UMAP_MAPS_PER_PAGE_OWNER = 10
253
259
  UMAP_SEARCH_CONFIGURATION = "simple"
254
- UMAP_FEEDBACK_LINK = "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help"
260
+ UMAP_HELP_URL = "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help"
255
261
  USER_MAPS_URL = "user_maps"
256
262
  DATABASES = {"default": env.db(default="postgis://localhost:5432/umap")}
257
263
  UMAP_DEFAULT_SHARE_STATUS = None
@@ -259,6 +265,7 @@ UMAP_DEFAULT_EDIT_STATUS = None
259
265
  UMAP_DEFAULT_FEATURES_HAVE_OWNERS = False
260
266
  UMAP_HOME_FEED = "latest"
261
267
  UMAP_IMPORTERS = {}
268
+ UMAP_HOST_INFOS = {}
262
269
 
263
270
  UMAP_READONLY = env("UMAP_READONLY", default=False)
264
271
  UMAP_GZIP = True
umap/static/umap/base.css CHANGED
@@ -119,13 +119,13 @@ dt {
119
119
  margin-bottom: 2rem;
120
120
  }
121
121
  .col {
122
- float: left;
122
+ float: inline-start;
123
123
  }
124
124
  .right {
125
125
  float: right;
126
126
  }
127
127
  .col + .col {
128
- padding-left: 20px;
128
+ padding-inline-start: 20px;
129
129
  }
130
130
  .half {
131
131
  width: 50%;
@@ -143,7 +143,7 @@ dt {
143
143
  width: 100%;
144
144
  }
145
145
  .col + .wide {
146
- padding-left: inherit;
146
+ padding-inline-start: inherit;
147
147
  }
148
148
  .mshow, .tshow {
149
149
  display: none;
@@ -186,7 +186,7 @@ input[type="range"] {
186
186
  width: 100%;
187
187
  }
188
188
  input[type="radio"] {
189
- margin-right: var(--text-margin);
189
+ margin-inline-end: var(--text-margin);
190
190
  }
191
191
  input[type="checkbox"] {
192
192
  margin: 0 var(--text-margin);
@@ -272,7 +272,7 @@ button.flat,
272
272
  border: none;
273
273
  background-color: inherit;
274
274
  padding: 0;
275
- text-align: left;
275
+ text-align: start;
276
276
  min-height: inherit;
277
277
  width: initial;
278
278
  display: initial;
@@ -345,7 +345,7 @@ input + .error {
345
345
  input[type="file"] + .error {
346
346
  margin-top: 0;
347
347
  }
348
- input:invalid {
348
+ input[value]:invalid {
349
349
  border-color: red;
350
350
  background-color: darkred;
351
351
  }
@@ -356,8 +356,8 @@ input:invalid {
356
356
  }
357
357
  details {
358
358
  margin-bottom: 5px;
359
- border-top-left-radius: 4px;
360
- border-top-right-radius: 4px;
359
+ border-start-start-radius: 4px;
360
+ border-start-end-radius: 4px;
361
361
  }
362
362
  .dark details {
363
363
  border: 1px solid #222;
@@ -392,7 +392,7 @@ fieldset legend {
392
392
  }
393
393
  [data-badge]:after {
394
394
  position: absolute;
395
- right: -6px;
395
+ inset-inline-end: -6px;
396
396
  top: -6px;
397
397
  min-width: 8px;
398
398
  min-height: 8px;
@@ -417,7 +417,7 @@ input.switch:empty {
417
417
  input.switch:empty ~ label {
418
418
  white-space: nowrap;
419
419
  position: relative;
420
- float: left;
420
+ float: inline-start;
421
421
  line-height: 2em;
422
422
  height: 2em;
423
423
  text-indent: 6em;
@@ -436,7 +436,7 @@ input.switch:empty ~ label:after {
436
436
  display: block;
437
437
  top: 0;
438
438
  bottom: 0;
439
- left: 0;
439
+ inset-inline-start: 0;
440
440
  content: ' ';
441
441
  width: 6em;
442
442
  -webkit-transition: all 100ms ease-in;
@@ -451,7 +451,7 @@ input.switch:empty ~ label:after {
451
451
  }
452
452
  input.switch:empty ~ label:after {
453
453
  width: 3em;
454
- margin-left: 0.1em;
454
+ margin-inline-start: 0.1em;
455
455
  background-color: #ededed;
456
456
  content: "OFF";
457
457
  text-indent: 3.5em;
@@ -472,7 +472,7 @@ input.switch:checked ~ label:before {
472
472
  color: var(--color-darkGray);
473
473
  content: "ON";
474
474
  text-indent: 0.7em;
475
- text-align: left;
475
+ text-align: start;
476
476
  font-weight: bold;
477
477
  }
478
478
  .dark input.switch:checked ~ label:before {
@@ -480,7 +480,7 @@ input.switch:checked ~ label:before {
480
480
  background-color: var(--color-accent);
481
481
  }
482
482
  input.switch:checked ~ label:after {
483
- margin-left: 3em;
483
+ margin-inline-start: 3em;
484
484
  }
485
485
  .button-bar, .umap-multiplechoice {
486
486
  margin-top: 5px;
@@ -552,21 +552,21 @@ input.switch:checked ~ label:after {
552
552
  .umap-field-iconUrl .action-button,
553
553
  .inheritable .define,
554
554
  .inheritable .undefine {
555
- float: right;
555
+ float: inline-end;
556
556
  width: initial;
557
557
  min-height: 18px;
558
558
  line-height: 18px;
559
559
  margin-bottom: 0;
560
560
  }
561
561
  .inheritable .quick-actions {
562
- float: right;
562
+ float: inline-end;
563
563
  }
564
564
  .inheritable .quick-actions .formbox {
565
565
  margin-bottom: 0;
566
566
  }
567
567
  .inheritable .quick-actions input {
568
568
  width: 100px;
569
- margin-right: 5px;
569
+ margin-inline-end: 5px;
570
570
  }
571
571
  .inheritable .define,
572
572
  .inheritable.undefined .undefine,
@@ -581,7 +581,7 @@ i.info {
581
581
  background-image: url('./img/16.svg');
582
582
  background-position: -170px -50px;
583
583
  display: inline-block;
584
- margin-left: 5px;
584
+ margin-inline-start: 5px;
585
585
  vertical-align: middle;
586
586
  width: 16px;
587
587
  height: 18px;
@@ -592,8 +592,7 @@ i.info {
592
592
  .with-transition {
593
593
  transition: all .7s;
594
594
  }
595
-
596
- .umap-delete:before, .umap-empty:before, .umap-to-polygon:before,
595
+ .umap-empty:before, .umap-to-polygon:before,
597
596
  .umap-clone:before, .umap-edit:before, .umap-download:before,
598
597
  .umap-to-polyline:before {
599
598
  background-repeat: no-repeat;
@@ -605,7 +604,7 @@ i.info {
605
604
  vertical-align: bottom;
606
605
  content: " ";
607
606
  }
608
- .dark .umap-delete:before, .dark .umap-empty:before,
607
+ .dark .umap-empty:before,
609
608
  .dark .umap-to-polygon:before,
610
609
  .dark .umap-clone:before,
611
610
  .dark .umap-edit:before, .dark .umap-download:before,
@@ -614,25 +613,19 @@ i.info {
614
613
  vertical-align: middle;
615
614
  }
616
615
  .umap-to-polygon:before {
617
- background-position: -80px -48px;
616
+ background-position: -72px -42px;
618
617
  }
619
618
  .umap-to-polyline:before {
620
- background-position: -120px -48px;
619
+ background-position: -106px -42px;
621
620
  }
622
621
  .umap-clone:before {
623
- background-position: -150px -78px;
624
- }
625
- .umap-delete:before {
626
- background-position: -32px -8px;
627
- }
628
- .umap-edit:before {
629
- background-position: -6px -6px;
622
+ background-position: -144px -78px;
630
623
  }
631
624
  .umap-empty:before {
632
- background-position: -110px -78px;
625
+ background-position: -108px -78px;
633
626
  }
634
627
  .umap-download:before {
635
- background-position: -77px -78px;
628
+ background-position: -72px -78px;
636
629
  }
637
630
  .permissions-panel,
638
631
  .umap-upload,
@@ -711,7 +704,7 @@ i.info {
711
704
 
712
705
  .umap-pictogram-choice .leaflet-marker-icon {
713
706
  bottom: 0;
714
- left: 30px;
707
+ inset-inline-start: 30px;
715
708
  position: absolute;
716
709
  }
717
710
  .umap-color-picker {
@@ -727,14 +720,14 @@ i.info {
727
720
  padding: 0;
728
721
  margin: 0;
729
722
  cursor: pointer;
730
- float: left;
723
+ float: inline-start;
731
724
  }
732
725
  input.blur {
733
726
  width: calc(100% - 40px);
734
727
  display: inline-block;
735
728
  vertical-align: middle;
736
- border-top-right-radius: 0;
737
- border-bottom-right-radius: 0;
729
+ border-start-end-radius: 0;
730
+ border-end-end-radius: 0;
738
731
  }
739
732
  .blur + .button:before,
740
733
  .blur + [type="button"]:before {
@@ -747,8 +740,8 @@ input.blur {
747
740
  display: inline-block;
748
741
  vertical-align: middle;
749
742
  line-height: 18px;
750
- border-top-left-radius: 0;
751
- border-bottom-left-radius: 0;
743
+ border-start-start-radius: 0;
744
+ border-end-start-radius: 0;
752
745
  box-sizing: border-box;
753
746
  }
754
747
  input[type=hidden].blur + .button,
@@ -763,9 +756,7 @@ input[type=hidden].blur + [type="button"] {
763
756
  border-radius: initial;
764
757
  }
765
758
  .copiable-input button {
766
- background-repeat: no-repeat;
767
- background-image: url('./img/16.svg');
768
- background-position: -141px -140px;
759
+ background-position: -46px -92px;
769
760
  display: inline;
770
761
  padding: 0 10px;
771
762
  height: 32px;
@@ -50,7 +50,7 @@ body.login header {
50
50
  background-size: 92px 92px;
51
51
  height: 92px;
52
52
  width: 92px;
53
- margin-right: 10px;
53
+ margin-inline-end: 10px;
54
54
  }
55
55
  .login-grid .login-github {
56
56
  background-image: url("./github.png");
@@ -107,7 +107,7 @@ body.login header {
107
107
  .umap-features-list li:before {
108
108
  content: "✔";
109
109
  color: #323E56;
110
- padding-right: 5px;
110
+ padding-inline-end: 5px;
111
111
  }
112
112
  .summary {
113
113
  background-color: #eee;
@@ -133,9 +133,11 @@ h2.section {
133
133
  text-align: center;
134
134
  }
135
135
  h2.tabs {
136
+ display: flex;
137
+ justify-content: space-around;
136
138
  text-transform: uppercase;
137
139
  color: var(--color-darkBlue);
138
- text-align: left;
140
+ text-align: start;
139
141
  padding-top: 28px;
140
142
  }
141
143
  h2.tabs a {
@@ -144,13 +146,13 @@ h2.tabs a {
144
146
  text-decoration-thickness: 3px;
145
147
  text-decoration-skip-ink: none;
146
148
  text-underline-offset: 7px;
147
- margin-right: 2rem;
149
+ display: inline-block;
148
150
  }
149
151
  h2.tabs a:not(.selected) {
150
152
  font-weight: normal;
151
153
  color: var(--color-darkBlue);
152
154
  text-decoration: none;
153
- margin-right: 0;
155
+ margin-inline-end: 0;
154
156
  }
155
157
  h2.tabs a:hover {
156
158
  text-decoration: underline;
@@ -192,26 +194,15 @@ input[type="submit"],
192
194
  .button-primary {
193
195
  font-weight: bold;
194
196
  }
195
- .wrapper input[type="submit"]:hover {
196
- background-color: #35537c;
197
- }
198
197
  .wrapper .neutral, .wrapper input[type="submit"].neutral {
199
198
  background-color: var(--button-neutral-background);
200
199
  color: var(--button-neutral-color);
201
200
  }
202
- .wrapper.somber {
203
- background-color: #2E3641;
204
- color: #efefef;
205
- padding-top: 20px;
206
- margin-top: 20px;
207
- }
208
- .wrapper.somber .row {
209
- margin-top: 0;
210
- }
211
201
  .wrapper .button,
212
202
  .wrapper input {
213
203
  height: 56px;
214
204
  line-height: 43px;
205
+ font-weight: bold;
215
206
  }
216
207
 
217
208
  /* **************************** */
@@ -272,13 +263,11 @@ ul.umap-autocomplete {
272
263
  border: 1px solid #202425;
273
264
  padding: 7px;
274
265
  color: #eeeeec;
275
- }
276
- .umap-multiresult li + li {
277
- margin-top: 7px;
266
+ margin-bottom: 7px;
278
267
  }
279
268
  .umap-singleresult div .close,
280
269
  .umap-multiresult li .close {
281
- float: right;
270
+ float: inline-end;
282
271
  cursor: pointer;
283
272
  }
284
273
 
@@ -358,6 +347,11 @@ ul.umap-autocomplete {
358
347
  .content .icon-delete {
359
348
  background-image: url('./img/icon-delete.svg');
360
349
  }
350
+ html[dir="rtl"] .content .icon-edit,
351
+ html[dir="rtl"] .content .icon-share,
352
+ html[dir="rtl"] .content .icon-delete {
353
+ background-position: initial; /* this takes precedence over similar selector in icon.css and fixes position */
354
+ }
361
355
  .table-header {
362
356
  display: flex;
363
357
  justify-content: space-between;
@@ -427,8 +421,8 @@ ul.umap-autocomplete {
427
421
  .table-wrapper table thead tr th,
428
422
  .table-wrapper table th[scope="row"] {
429
423
  color: var(--color-darkBlue);
430
- text-align: left;
431
- padding-left: 2px;
424
+ text-align: start;
425
+ padding-inline-start: 2px;
432
426
  }
433
427
  .table-wrapper table thead tr th {
434
428
  line-height: 1.2;
@@ -525,7 +519,7 @@ dialog::backdrop {
525
519
  }
526
520
  .twide {
527
521
  width: 100%;
528
- padding-left: 0!important;
522
+ padding-inline-start: 0!important;
529
523
  }
530
524
  .tthird {
531
525
  width: 33.3333%;
@@ -542,7 +536,7 @@ dialog::backdrop {
542
536
  }
543
537
  @media only screen and (max-width: 639px) {
544
538
  .mwide {
545
- padding-left: 0!important;
539
+ padding-inline-start: 0!important;
546
540
  width: 100%;
547
541
  }
548
542
  .mwide + .mwide {