umap-project 1.11.0__py3-none-any.whl → 1.11.1__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 (55) hide show
  1. umap/__init__.py +1 -1
  2. umap/admin.py +7 -3
  3. umap/autocomplete.py +3 -5
  4. umap/bin/__init__.py +2 -5
  5. umap/decorators.py +4 -5
  6. umap/forms.py +5 -5
  7. umap/locale/en/LC_MESSAGES/django.po +14 -14
  8. umap/management/commands/generate_js_locale.py +9 -11
  9. umap/management/commands/import_pictograms.py +1 -1
  10. umap/managers.py +5 -3
  11. umap/middleware.py +2 -3
  12. umap/migrations/0001_initial.py +204 -56
  13. umap/migrations/0002_tilelayer_tms.py +3 -4
  14. umap/migrations/0003_add_tilelayer.py +13 -9
  15. umap/migrations/0004_add_licence.py +3 -6
  16. umap/migrations/0005_remove_map_tilelayer.py +3 -4
  17. umap/migrations/0006_auto_20190407_0719.py +6 -5
  18. umap/migrations/0007_auto_20190416_1757.py +13 -5
  19. umap/migrations/0008_alter_map_settings.py +0 -1
  20. umap/migrations/0009_star.py +27 -8
  21. umap/migrations/0010_alter_map_edit_status_alter_map_share_status.py +20 -8
  22. umap/migrations/0011_alter_map_edit_status_alter_map_share_status.py +21 -8
  23. umap/migrations/0014_map_created_at.py +1 -1
  24. umap/models.py +6 -6
  25. umap/settings/base.py +1 -4
  26. umap/static/umap/base.css +2 -0
  27. umap/static/umap/js/umap.core.js +2 -0
  28. umap/static/umap/js/umap.features.js +2 -2
  29. umap/static/umap/js/umap.js +9 -5
  30. umap/static/umap/js/umap.layer.js +3 -2
  31. umap/static/umap/map.css +21 -12
  32. umap/static/umap/vendors/formbuilder/Leaflet.FormBuilder.js +13 -1
  33. umap/templates/auth/user_form.html +2 -2
  34. umap/templates/base.html +9 -3
  35. umap/templates/umap/map_table.html +3 -3
  36. umap/templatetags/umap_tags.py +32 -34
  37. umap/tests/base.py +2 -1
  38. umap/tests/conftest.py +0 -1
  39. umap/tests/integration/test_picto.py +1 -1
  40. umap/tests/integration/test_slideshow.py +70 -0
  41. umap/tests/settings.py +7 -5
  42. umap/tests/test_datalayer.py +7 -6
  43. umap/tests/test_map.py +6 -5
  44. umap/tests/test_map_views.py +4 -10
  45. umap/tests/test_tilelayer.py +17 -11
  46. umap/tests/test_views.py +7 -6
  47. umap/urls.py +3 -3
  48. umap/utils.py +1 -2
  49. umap/views.py +11 -23
  50. umap/wsgi.py +2 -2
  51. {umap_project-1.11.0.dist-info → umap_project-1.11.1.dist-info}/METADATA +11 -9
  52. {umap_project-1.11.0.dist-info → umap_project-1.11.1.dist-info}/RECORD +55 -54
  53. {umap_project-1.11.0.dist-info → umap_project-1.11.1.dist-info}/WHEEL +0 -0
  54. {umap_project-1.11.0.dist-info → umap_project-1.11.1.dist-info}/entry_points.txt +0 -0
  55. {umap_project-1.11.0.dist-info → umap_project-1.11.1.dist-info}/licenses/LICENSE +0 -0
@@ -5,18 +5,15 @@ from django.db import migrations
5
5
 
6
6
 
7
7
  def add_licence(apps, *args):
8
- Licence = apps.get_model('umap', 'Licence')
8
+ Licence = apps.get_model("umap", "Licence")
9
9
  if Licence.objects.count():
10
10
  return
11
- Licence(
12
- name='ODbL',
13
- details='http://opendatacommons.org/licenses/odbl/').save()
11
+ Licence(name="ODbL", details="http://opendatacommons.org/licenses/odbl/").save()
14
12
 
15
13
 
16
14
  class Migration(migrations.Migration):
17
-
18
15
  dependencies = [
19
- ('umap', '0003_add_tilelayer'),
16
+ ("umap", "0003_add_tilelayer"),
20
17
  ]
21
18
 
22
19
  operations = [
@@ -4,14 +4,13 @@ from django.db import migrations
4
4
 
5
5
 
6
6
  class Migration(migrations.Migration):
7
-
8
7
  dependencies = [
9
- ('umap', '0004_add_licence'),
8
+ ("umap", "0004_add_licence"),
10
9
  ]
11
10
 
12
11
  operations = [
13
12
  migrations.RemoveField(
14
- model_name='map',
15
- name='tilelayer',
13
+ model_name="map",
14
+ name="tilelayer",
16
15
  ),
17
16
  ]
@@ -5,15 +5,16 @@ from django.db import migrations
5
5
 
6
6
 
7
7
  class Migration(migrations.Migration):
8
-
9
8
  dependencies = [
10
- ('umap', '0005_remove_map_tilelayer'),
9
+ ("umap", "0005_remove_map_tilelayer"),
11
10
  ]
12
11
 
13
12
  operations = [
14
13
  migrations.AlterField(
15
- model_name='map',
16
- name='settings',
17
- field=django.contrib.postgres.fields.jsonb.JSONField(blank=True, default=dict, null=True, verbose_name='settings'),
14
+ model_name="map",
15
+ name="settings",
16
+ field=django.contrib.postgres.fields.jsonb.JSONField(
17
+ blank=True, default=dict, null=True, verbose_name="settings"
18
+ ),
18
19
  ),
19
20
  ]
@@ -4,15 +4,23 @@ from django.db import migrations, models
4
4
 
5
5
 
6
6
  class Migration(migrations.Migration):
7
-
8
7
  dependencies = [
9
- ('umap', '0006_auto_20190407_0719'),
8
+ ("umap", "0006_auto_20190407_0719"),
10
9
  ]
11
10
 
12
11
  operations = [
13
12
  migrations.AlterField(
14
- model_name='map',
15
- name='share_status',
16
- field=models.SmallIntegerField(choices=[(1, 'everyone (public)'), (2, 'anyone with link'), (3, 'editors only'), (9, 'blocked')], default=1, verbose_name='share status'),
13
+ model_name="map",
14
+ name="share_status",
15
+ field=models.SmallIntegerField(
16
+ choices=[
17
+ (1, "everyone (public)"),
18
+ (2, "anyone with link"),
19
+ (3, "editors only"),
20
+ (9, "blocked"),
21
+ ],
22
+ default=1,
23
+ verbose_name="share status",
24
+ ),
17
25
  ),
18
26
  ]
@@ -4,7 +4,6 @@ from django.db import migrations, models
4
4
 
5
5
 
6
6
  class Migration(migrations.Migration):
7
-
8
7
  dependencies = [
9
8
  ("umap", "0007_auto_20190416_1757"),
10
9
  ]
@@ -1,25 +1,44 @@
1
1
  # Generated by Django 4.1.7 on 2023-05-05 18:02
2
2
 
3
+ import django.db.models.deletion
3
4
  from django.conf import settings
4
5
  from django.db import migrations, models
5
- import django.db.models.deletion
6
6
 
7
7
 
8
8
  class Migration(migrations.Migration):
9
-
10
9
  dependencies = [
11
10
  migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
- ('umap', '0008_alter_map_settings'),
11
+ ("umap", "0008_alter_map_settings"),
13
12
  ]
14
13
 
15
14
  operations = [
16
15
  migrations.CreateModel(
17
- name='Star',
16
+ name="Star",
18
17
  fields=[
19
- ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
- ('at', models.DateTimeField(auto_now=True)),
21
- ('by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='stars', to=settings.AUTH_USER_MODEL)),
22
- ('map', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='umap.map')),
18
+ (
19
+ "id",
20
+ models.AutoField(
21
+ auto_created=True,
22
+ primary_key=True,
23
+ serialize=False,
24
+ verbose_name="ID",
25
+ ),
26
+ ),
27
+ ("at", models.DateTimeField(auto_now=True)),
28
+ (
29
+ "by",
30
+ models.ForeignKey(
31
+ on_delete=django.db.models.deletion.CASCADE,
32
+ related_name="stars",
33
+ to=settings.AUTH_USER_MODEL,
34
+ ),
35
+ ),
36
+ (
37
+ "map",
38
+ models.ForeignKey(
39
+ on_delete=django.db.models.deletion.CASCADE, to="umap.map"
40
+ ),
41
+ ),
23
42
  ],
24
43
  ),
25
44
  ]
@@ -4,20 +4,32 @@ from django.db import migrations, models
4
4
 
5
5
 
6
6
  class Migration(migrations.Migration):
7
-
8
7
  dependencies = [
9
- ('umap', '0009_star'),
8
+ ("umap", "0009_star"),
10
9
  ]
11
10
 
12
11
  operations = [
13
12
  migrations.AlterField(
14
- model_name='map',
15
- name='edit_status',
16
- field=models.SmallIntegerField(choices=[(1, 'Everyone'), (2, 'Editors only'), (3, 'Owner only')], default=3, verbose_name='edit status'),
13
+ model_name="map",
14
+ name="edit_status",
15
+ field=models.SmallIntegerField(
16
+ choices=[(1, "Everyone"), (2, "Editors only"), (3, "Owner only")],
17
+ default=3,
18
+ verbose_name="edit status",
19
+ ),
17
20
  ),
18
21
  migrations.AlterField(
19
- model_name='map',
20
- name='share_status',
21
- field=models.SmallIntegerField(choices=[(1, 'Everyone (public)'), (2, 'Anyone with link'), (3, 'Editors only'), (9, 'Blocked')], default=1, verbose_name='share status'),
22
+ model_name="map",
23
+ name="share_status",
24
+ field=models.SmallIntegerField(
25
+ choices=[
26
+ (1, "Everyone (public)"),
27
+ (2, "Anyone with link"),
28
+ (3, "Editors only"),
29
+ (9, "Blocked"),
30
+ ],
31
+ default=1,
32
+ verbose_name="share status",
33
+ ),
22
34
  ),
23
35
  ]
@@ -1,24 +1,37 @@
1
1
  # Generated by Django 4.2.2 on 2023-08-07 06:07
2
2
 
3
3
  from django.db import migrations, models
4
+
4
5
  import umap.models
5
6
 
6
7
 
7
8
  class Migration(migrations.Migration):
8
-
9
9
  dependencies = [
10
- ('umap', '0010_alter_map_edit_status_alter_map_share_status'),
10
+ ("umap", "0010_alter_map_edit_status_alter_map_share_status"),
11
11
  ]
12
12
 
13
13
  operations = [
14
14
  migrations.AlterField(
15
- model_name='map',
16
- name='edit_status',
17
- field=models.SmallIntegerField(choices=[(1, 'Everyone'), (2, 'Editors only'), (3, 'Owner only')], default=umap.models.get_default_edit_status, verbose_name='edit status'),
15
+ model_name="map",
16
+ name="edit_status",
17
+ field=models.SmallIntegerField(
18
+ choices=[(1, "Everyone"), (2, "Editors only"), (3, "Owner only")],
19
+ default=umap.models.get_default_edit_status,
20
+ verbose_name="edit status",
21
+ ),
18
22
  ),
19
23
  migrations.AlterField(
20
- model_name='map',
21
- name='share_status',
22
- field=models.SmallIntegerField(choices=[(1, 'Everyone (public)'), (2, 'Anyone with link'), (3, 'Editors only'), (9, 'Blocked')], default=umap.models.get_default_share_status, verbose_name='share status'),
24
+ model_name="map",
25
+ name="share_status",
26
+ field=models.SmallIntegerField(
27
+ choices=[
28
+ (1, "Everyone (public)"),
29
+ (2, "Anyone with link"),
30
+ (3, "Editors only"),
31
+ (9, "Blocked"),
32
+ ],
33
+ default=umap.models.get_default_share_status,
34
+ verbose_name="share status",
35
+ ),
23
36
  ),
24
37
  ]
@@ -1,7 +1,7 @@
1
1
  # Generated by Django 4.2.2 on 2023-09-27 08:50
2
2
 
3
- from django.db import migrations, models
4
3
  import django.utils.timezone
4
+ from django.db import migrations, models
5
5
 
6
6
 
7
7
  class Migration(migrations.Migration):
umap/models.py CHANGED
@@ -1,14 +1,14 @@
1
1
  import os
2
2
  import time
3
3
 
4
+ from django.conf import settings
4
5
  from django.contrib.auth.models import User
5
6
  from django.contrib.gis.db import models
6
- from django.conf import settings
7
- from django.urls import reverse
8
- from django.utils.translation import gettext_lazy as _
7
+ from django.core.files.base import File
9
8
  from django.core.signing import Signer
10
9
  from django.template.defaultfilters import slugify
11
- from django.core.files.base import File
10
+ from django.urls import reverse
11
+ from django.utils.translation import gettext_lazy as _
12
12
 
13
13
  from .managers import PublicManager
14
14
 
@@ -380,7 +380,7 @@ class DataLayer(NamedModel):
380
380
  }
381
381
  obj["id"] = self.pk
382
382
  obj["permissions"] = {"edit_status": self.edit_status}
383
- obj["editMode"] = "advanced" if self.can_edit(user, request) else 'disabled'
383
+ obj["editMode"] = "advanced" if self.can_edit(user, request) else "disabled"
384
384
  return obj
385
385
 
386
386
  def clone(self, map_inst=None):
@@ -436,7 +436,7 @@ class DataLayer(NamedModel):
436
436
  root = self.storage_root()
437
437
  names = self.geojson.storage.listdir(root)[1]
438
438
  for name in names:
439
- if name.startswith(f'{self.pk}_') and name.endswith(".gz"):
439
+ if name.startswith(f"{self.pk}_") and name.endswith(".gz"):
440
440
  self.geojson.storage.delete(os.path.join(root, name))
441
441
 
442
442
  def can_edit(self, user=None, request=None):
umap/settings/base.py CHANGED
@@ -4,7 +4,6 @@ from email.utils import parseaddr
4
4
 
5
5
  import environ
6
6
  from django.conf.locale import LANG_INFO
7
- from django.template.defaultfilters import slugify
8
7
 
9
8
  env = environ.Env()
10
9
 
@@ -244,9 +243,7 @@ UMAP_MAPS_PER_PAGE = 5
244
243
  UMAP_MAPS_PER_SEARCH = 25
245
244
  UMAP_MAPS_PER_PAGE_OWNER = 10
246
245
  UMAP_SEARCH_CONFIGURATION = "simple"
247
- UMAP_FEEDBACK_LINK = (
248
- "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help" # noqa
249
- )
246
+ UMAP_FEEDBACK_LINK = "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help"
250
247
  USER_MAPS_URL = "user_maps"
251
248
  DATABASES = {"default": env.db(default="postgis://localhost:5432/umap")}
252
249
  UMAP_DEFAULT_SHARE_STATUS = None
umap/static/umap/base.css CHANGED
@@ -202,6 +202,8 @@ button.flat,
202
202
  padding: 0;
203
203
  text-align: left;
204
204
  min-height: inherit;
205
+ width: initial;
206
+ display: initial;
205
207
  text-decoration: underline;
206
208
  }
207
209
  .help-text, .helptext {
@@ -698,12 +698,14 @@ L.U.Orderable = L.Evented.extend({
698
698
  },
699
699
 
700
700
  onDragOver: function (e) {
701
+ L.DomEvent.stop(e)
701
702
  if (e.preventDefault) e.preventDefault() // Necessary. Allows us to drop.
702
703
  e.dataTransfer.dropEffect = 'move'
703
704
  return false
704
705
  },
705
706
 
706
707
  onDragEnter: function (e) {
708
+ L.DomEvent.stop(e)
707
709
  // e.target is the current hover target.
708
710
  const dst = this.findTarget(e.target)
709
711
  if (!dst || dst === this.src) return
@@ -680,8 +680,8 @@ L.U.Marker = L.Marker.extend({
680
680
  appendEditFieldsets: function (container) {
681
681
  L.U.FeatureMixin.appendEditFieldsets.call(this, container)
682
682
  const coordinatesOptions = [
683
- ['_latlng.lat', { handler: 'FloatInput', label: L._('Latitude'), step: 'any' }],
684
- ['_latlng.lng', { handler: 'FloatInput', label: L._('Longitude'), step: 'any' }],
683
+ ['_latlng.lat', { handler: 'FloatInput', label: L._('Latitude') }],
684
+ ['_latlng.lng', { handler: 'FloatInput', label: L._('Longitude') }],
685
685
  ]
686
686
  const builder = new L.U.FormBuilder(this, coordinatesOptions, {
687
687
  callback: function () {
@@ -688,7 +688,11 @@ L.U.Map.include({
688
688
  // FIXME An invalid hash will cause the load to fail
689
689
  this._hash.update()
690
690
  } else if (this.options.defaultView === 'locate' && !this.options.noControl) {
691
- this.once('locationerror', this._setDefaultCenter)
691
+ // When using locate as default map view AND activating easing
692
+ // Leaflet.locate will ask the map view to compute transition to user
693
+ // position, so in this case we do need a default center, so let's
694
+ // set it anyway
695
+ this._setDefaultCenter()
692
696
  this._controls.locate.start()
693
697
  } else if (this.options.defaultView === 'data') {
694
698
  this.onceDataLoaded(() => {
@@ -1744,16 +1748,16 @@ L.U.Map.include({
1744
1748
  this.permissions.addOwnerLink('span', container)
1745
1749
  if (this.options.captionMenus) {
1746
1750
  L.DomUtil.createButton(
1747
- 'umap-about-link',
1751
+ 'umap-about-link flat',
1748
1752
  container,
1749
- ` — ${L._('About')}`,
1753
+ L._('About'),
1750
1754
  this.displayCaption,
1751
1755
  this
1752
1756
  )
1753
1757
  L.DomUtil.createButton(
1754
- 'umap-open-browser-link',
1758
+ 'umap-open-browser-link flat',
1755
1759
  container,
1756
- ` | ${L._('Browse data')}`,
1760
+ L._('Browse data'),
1757
1761
  this.openBrowser,
1758
1762
  this
1759
1763
  )
@@ -1347,13 +1347,14 @@ L.U.DataLayer = L.Evented.extend({
1347
1347
  const date = new Date(parseInt(data.at, 10))
1348
1348
  const content = `${date.toLocaleString(L.lang)} (${parseInt(data.size) / 1000}Kb)`
1349
1349
  const el = L.DomUtil.create('div', 'umap-datalayer-version', versionsContainer)
1350
- const a = L.DomUtil.createButton(
1350
+ const button = L.DomUtil.createButton(
1351
1351
  '',
1352
1352
  el,
1353
- L._('Restore this version'),
1353
+ '',
1354
1354
  () => this.restore(data.name),
1355
1355
  this
1356
1356
  )
1357
+ button.title = L._('Restore this version')
1357
1358
  L.DomUtil.add('span', '', el, content)
1358
1359
  }
1359
1360
 
umap/static/umap/map.css CHANGED
@@ -600,6 +600,13 @@ ul.photon-autocomplete {
600
600
  .umap-main-edit-toolbox h3 {
601
601
  display: inline;
602
602
  }
603
+ .umap-caption-bar button {
604
+ margin-left: 10px;
605
+ }
606
+ .umap-caption-bar button + button:before {
607
+ content: '|';
608
+ padding-right: 10px;
609
+ }
603
610
  .umap-main-edit-toolbox .umap-user {
604
611
  color: #fff;
605
612
  }
@@ -724,18 +731,14 @@ ul.photon-autocomplete {
724
731
  padding: 5px 0;
725
732
  border-bottom: 1px solid #202425;
726
733
  }
727
- .umap-datalayer-version a {
734
+ .umap-datalayer-version button {
728
735
  display: inline-block;
729
- width: 20px;
730
- height: 20px;
731
- margin-left: 5px;
732
- background-position: -123px -75px;
736
+ width: 24px;
737
+ min-height: 24px;
738
+ background-position: -122px -73px;
733
739
  background-repeat: no-repeat;
734
740
  background-image: url('./img/16-white.svg');
735
- vertical-align: middle;
736
- margin-right: 5px;
737
- border: 1px solid #202425;
738
- background-color: #2c3233;
741
+ margin-right: 10px;
739
742
  }
740
743
 
741
744
 
@@ -1207,7 +1210,9 @@ a.add-datalayer:hover,
1207
1210
  .umap-popup-footer li.next:before {
1208
1211
  background-position: -5px -77px;
1209
1212
  }
1210
-
1213
+ .umap-popup a:hover {
1214
+ text-decoration: underline;
1215
+ }
1211
1216
 
1212
1217
  /* ************* */
1213
1218
  /* Marker's Icon */
@@ -1298,7 +1303,6 @@ a.add-datalayer:hover,
1298
1303
  vertical-align: middle;
1299
1304
  color: white;
1300
1305
  font-weight: bold;
1301
- font-size: 1.2rem;
1302
1306
  }
1303
1307
  .umap-circle-icon {
1304
1308
  border: 1px solid white;
@@ -1620,8 +1624,13 @@ a.add-datalayer:hover,
1620
1624
  height: 36px;
1621
1625
  line-height: 34px;
1622
1626
  }
1627
+ /* Links are blue by default */
1623
1628
  .leaflet-container a {
1624
- color: #323737;
1629
+ color: #0078a8;
1630
+ }
1631
+ /* But not in controls */
1632
+ .leaflet-bar a {
1633
+ color: black;
1625
1634
  }
1626
1635
 
1627
1636
  /* ****** */
@@ -124,12 +124,14 @@ L.FormBuilder = L.Evented.extend({
124
124
 
125
125
  L.FormBuilder.Element = L.Evented.extend({
126
126
 
127
+ options: {},
128
+
127
129
  initialize: function (builder, field, options) {
128
130
  this.builder = builder;
129
131
  this.obj = this.builder.obj;
130
132
  this.form = this.builder.form;
131
133
  this.field = field;
132
- this.options = options;
134
+ L.setOptions(this, options);
133
135
  this.fieldEls = this.field.split('.');
134
136
  this.name = this.builder.getName(field);
135
137
  this.parentNode = this.getParentNode();
@@ -340,10 +342,20 @@ L.FormBuilder.FloatMixin = {
340
342
  };
341
343
 
342
344
  L.FormBuilder.FloatInput = L.FormBuilder.Input.extend({
345
+
346
+ options: {
347
+ step: 'any'
348
+ },
349
+
343
350
  includes: [L.FormBuilder.FloatMixin]
344
351
  });
345
352
 
346
353
  L.FormBuilder.BlurFloatInput = L.FormBuilder.BlurInput.extend({
354
+
355
+ options: {
356
+ step: 'any'
357
+ },
358
+
347
359
  includes: [L.FormBuilder.FloatMixin]
348
360
  });
349
361
 
@@ -3,7 +3,7 @@
3
3
  {% block maincontent %}
4
4
  <div class="col wide">
5
5
  <h2 class="section tabs">
6
- <a href="{% url 'user_dashboard' %}">{% trans "My Dashboard" %}</a> | {% trans "My Profile" %}
6
+ <a href="{% url "user_dashboard" %}">{% trans "My Dashboard" %}</a> | {% trans "My Profile" %}
7
7
  </h2>
8
8
  </div>
9
9
  <div class="wrapper">
@@ -16,7 +16,7 @@
16
16
  <form id="user_form" method="post">
17
17
  {% csrf_token %}
18
18
  {{ form }}
19
- <input type="submit" value="{% trans 'Save' %}" />
19
+ <input type="submit" value="{% trans "Save" %}" />
20
20
  </form>
21
21
  </div>
22
22
  {% if backends.backends|length %}
umap/templates/base.html CHANGED
@@ -16,9 +16,15 @@
16
16
  <meta name="viewport"
17
17
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
18
18
  {# See https://evilmartians.com/chronicles/how-to-favicon-in-2021-six-files-that-fit-most-needs #}
19
- <link rel="icon" href="{{ STATIC_URL }}umap/favicons/favicon.ico" sizes="32x32">
20
- <link rel="icon" href="{{ STATIC_URL }}umap/favicons/icon.svg" type="image/svg+xml">
21
- <link rel="apple-touch-icon" href="{{ STATIC_URL }}umap/favicons/apple-touch-icon.png"><!-- 180×180 -->
19
+ <link rel="icon"
20
+ href="{{ STATIC_URL }}umap/favicons/favicon.ico"
21
+ sizes="32x32">
22
+ <link rel="icon"
23
+ href="{{ STATIC_URL }}umap/favicons/icon.svg"
24
+ type="image/svg+xml">
25
+ <link rel="apple-touch-icon"
26
+ href="{{ STATIC_URL }}umap/favicons/apple-touch-icon.png">
27
+ <!-- 180×180 -->
22
28
  <link rel="manifest" href="/manifest.webmanifest">
23
29
  </head>
24
30
  <body class="{% block body_class %}{% endblock body_class %}">
@@ -25,9 +25,9 @@
25
25
  <a href="{{ map_inst.owner.get_url }}">{{ map_inst.owner }}</a>
26
26
  </td>
27
27
  <td>
28
- <a href="{{ map_inst.get_absolute_url }}?share">{% translate "Share" %}</a>
29
- <a href="{{ map_inst.get_absolute_url }}?edit">{% translate "Edit" %}</a>
30
- <a href="{{ map_inst.get_absolute_url }}?download">{% translate "Download" %}</a>
28
+ <a href="{{ map_inst.get_absolute_url }}?share">{% translate "Share" %}</a> |
29
+ <a href="{{ map_inst.get_absolute_url }}?edit">{% translate "Edit" %}</a> |
30
+ <a href="{% url 'map_download' map_inst.pk %}">{% translate "Download" %}</a>
31
31
  </td>
32
32
  </tr>
33
33
  {% endfor %}