From 61cdf80cff8e669089c4ebd4cd92aef049ee0a2e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Thu, 21 Oct 2021 09:11:56 +0200
Subject: [PATCH] misc: add settings for default map zoom level (#27154)

---
 tests/admin_pages/test_settings.py |  9 +++++++++
 tests/form_pages/test_all.py       | 19 +++++++++++++++++++
 wcs/admin/settings.py              | 24 +++++++++++++++++++++++-
 wcs/fields.py                      | 16 ++++++++++++----
 wcs/qommon/form.py                 |  2 ++
 wcs/qommon/publisher.py            |  3 +++
 6 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/tests/admin_pages/test_settings.py b/tests/admin_pages/test_settings.py
index 9453f5f04..06f798b6e 100644
--- a/tests/admin_pages/test_settings.py
+++ b/tests/admin_pages/test_settings.py
@@ -752,6 +752,9 @@ def test_settings_logs(pub):
 def test_settings_geolocation(pub):
     create_superuser(pub)
     app = login(get_app(pub))
+
+    assert pub.get_default_zoom_level() == '13'
+
     resp = app.get('/backoffice/settings/')
     resp = resp.click('Geolocation')
     resp.form['default-position$latlng'].value = '1.234;-1.234'
@@ -765,6 +768,12 @@ def test_settings_geolocation(pub):
     pub.reload_cfg()
     assert pub.cfg['misc']['default-position'] == '1.234;-1.234'
 
+    assert pub.cfg['misc']['default-zoom-level'] == '13'
+    resp = resp.click('Geolocation')
+    resp.form['default-zoom-level'] = '16'
+    resp = resp.form.submit().follow()
+    assert pub.cfg['misc']['default-zoom-level'] == '16'
+
 
 def test_settings_permissions(pub):
     create_superuser(pub)
diff --git a/tests/form_pages/test_all.py b/tests/form_pages/test_all.py
index 2941ccc9c..66ed6482c 100644
--- a/tests/form_pages/test_all.py
+++ b/tests/form_pages/test_all.py
@@ -3589,6 +3589,25 @@ def test_form_map_field_back_and_submit(pub):
     assert data.data == {'1': 'bla', '0': '1.234;-1.234'}
 
 
+def test_form_map_initial_zoom_level(pub):
+    formdef = create_formdef()
+    formdef.fields = [
+        fields.MapField(id='0', label='map'),
+    ]
+    formdef.store()
+    resp = get_app(pub).get('/test/')
+    assert 'data-initial_zoom="13"' in resp.text
+    pub.cfg['misc']['default-zoom-level'] = '16'
+    pub.write_cfg()
+    resp = get_app(pub).get('/test/')
+    assert 'data-initial_zoom="16"' in resp.text
+
+    formdef.fields[0].initial_zoom = '11'
+    formdef.store()
+    resp = get_app(pub).get('/test/')
+    assert 'data-initial_zoom="11"' in resp.text
+
+
 def test_form_map_geolocation_text_field(pub):
     formdef = create_formdef()
     formdef.fields = [
diff --git a/wcs/admin/settings.py b/wcs/admin/settings.py
index 92317796e..b0d82a87b 100644
--- a/wcs/admin/settings.py
+++ b/wcs/admin/settings.py
@@ -36,6 +36,7 @@ from quixote.html import TemplateIO, htmltext
 from wcs.blocks import BlockDef
 from wcs.carddef import CardDef
 from wcs.data_sources import NamedDataSource
+from wcs.fields import MapOptionsMixin
 from wcs.formdef import FormDef
 from wcs.qommon import _, errors, get_cfg, ident, misc, template
 from wcs.qommon.admin.cfg import cfg_submit
@@ -1332,6 +1333,16 @@ class SettingsDirectory(QommonSettingsDirectory):
             default_zoom='9',
             required=False,
         )
+        zoom_levels = [(x[0], x[1], x[0]) for x in MapOptionsMixin.get_zoom_levels()]
+        form.add(
+            SingleSelectWidget,
+            'default-zoom-level',
+            title=_('Default zoom level'),
+            value=get_publisher().get_default_zoom_level(),
+            options=zoom_levels,
+            required=False,
+        )
+
         form.add_submit('submit', _('Submit'))
         form.add_submit('cancel', _('Cancel'))
 
@@ -1339,7 +1350,7 @@ class SettingsDirectory(QommonSettingsDirectory):
             return redirect('.')
 
         if form.is_submitted() and not form.has_errors():
-            cfg_submit(form, 'misc', ['default-position'])
+            cfg_submit(form, 'misc', ['default-position', 'default-zoom-level'])
             return redirect('.')
 
         get_response().breadcrumb.append(('geolocation', _('Geolocation Settings')))
@@ -1347,6 +1358,17 @@ class SettingsDirectory(QommonSettingsDirectory):
         r = TemplateIO(html=True)
         r += htmltext('<h2>%s</h2>') % _('Geolocation Settings')
         r += form.render()
+        r += htmltext(
+            '''<script>
+$('#form_default-zoom-level').on('change', function() {
+  var map = $('.qommon-map')[0].leaflet_map;
+  var new_zoom = parseInt($(this).val());
+  if (! isNaN(new_zoom)) {
+    map.setZoom(parseInt($(this).val()));
+  }
+});
+</script>'''
+        )
         return r.getvalue()
 
     def user_templates(self):
diff --git a/wcs/fields.py b/wcs/fields.py
index d48907a4c..028776f86 100644
--- a/wcs/fields.py
+++ b/wcs/fields.py
@@ -1708,8 +1708,8 @@ class MapOptionsMixin:
     min_zoom = None
     max_zoom = None
 
-    def fill_zoom_admin_form(self, form, **kwargs):
-        # 0: whole world, 9: wide area, 11: area, 13: town, 16: small road
+    @classmethod
+    def get_zoom_levels(cls):
         zoom_levels = [
             (None, '---'),
             ('0', _('Whole world')),
@@ -1721,12 +1721,20 @@ class MapOptionsMixin:
             ('18', _('Neighbourhood')),
             ('19', _('Ant')),
         ]
+        return zoom_levels
+
+    def fill_zoom_admin_form(self, form, **kwargs):
+        zoom_levels = self.get_zoom_levels()
+        zoom_levels_dict = dict(zoom_levels)
+        default_zoom_level = get_publisher().get_default_zoom_level()
+        initial_zoom_levels = zoom_levels[:]
+        initial_zoom_levels[0] = (None, _('Default (%s)') % zoom_levels_dict[default_zoom_level])
         form.add(
             SingleSelectWidget,
             'initial_zoom',
             title=_('Initial zoom level'),
-            value=self.initial_zoom or '13',
-            options=zoom_levels,
+            value=self.initial_zoom,
+            options=initial_zoom_levels,
             **kwargs,
         )
         form.add(
diff --git a/wcs/qommon/form.py b/wcs/qommon/form.py
index 210b46154..d5127e217 100644
--- a/wcs/qommon/form.py
+++ b/wcs/qommon/form.py
@@ -2676,6 +2676,8 @@ class MapWidget(CompositeWidget):
         self.map_attributes = {}
         self.map_attributes.update(get_publisher().get_map_attributes())
         self.sync_map_and_address_fields = get_publisher().has_site_option('sync-map-and-address-fields')
+        if kwargs.get('initial_zoom') is None:
+            kwargs['initial_zoom'] = get_publisher().get_default_zoom_level()
         for attribute in ('initial_zoom', 'min_zoom', 'max_zoom', 'init_with_geoloc'):
             if attribute in kwargs:
                 self.map_attributes['data-' + attribute] = kwargs.pop(attribute)
diff --git a/wcs/qommon/publisher.py b/wcs/qommon/publisher.py
index 28d7d3941..61e3b35d1 100644
--- a/wcs/qommon/publisher.py
+++ b/wcs/qommon/publisher.py
@@ -803,6 +803,9 @@ class QommonPublisher(Publisher):
             default_position = '50.84;4.36'
         return default_position
 
+    def get_default_zoom_level(self):
+        return self.cfg.get('misc', {}).get('default-zoom-level', '13')
+
     def get_map_attributes(self):
         attrs = {}
         attrs['data-def-lat'], attrs['data-def-lng'] = self.get_default_position().split(';')
-- 
2.33.0

