backoffice: add options to item field for plotting choices on a map (#47066)
This commit is contained in:
parent
1daf66e50c
commit
0e9e91b2db
|
@ -1589,6 +1589,46 @@ def test_form_edit_item_field_data_source(pub):
|
|||
resp = app.get('/backoffice/forms/1/')
|
||||
|
||||
|
||||
def test_form_edit_item_field_geojson_data_source(pub, http_requests):
|
||||
NamedDataSource.wipe()
|
||||
create_superuser(pub)
|
||||
create_role()
|
||||
|
||||
NamedDataSource.wipe()
|
||||
data_source = NamedDataSource(name='foobar')
|
||||
data_source.data_source = {
|
||||
'type': 'geojson',
|
||||
'value': 'http://remote.example.net/geojson',
|
||||
}
|
||||
data_source.id_property = 'id'
|
||||
data_source.label_template_property = '{{ text }}'
|
||||
data_source.cache_duration = '5'
|
||||
data_source.store()
|
||||
|
||||
FormDef.wipe()
|
||||
formdef = FormDef()
|
||||
formdef.name = 'form title'
|
||||
formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')]
|
||||
formdef.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
|
||||
resp = app.get('/backoffice/forms/1/fields/1/')
|
||||
resp.form['display_mode'] = 'map'
|
||||
assert resp.pyquery('option[value=foobar][data-type=geojson]')
|
||||
resp.form['data_mode'] = 'data-source'
|
||||
resp.form['data_source$type'] = 'foobar'
|
||||
resp.form['min_zoom'] = 'Wide area'
|
||||
resp.form['max_zoom'] = 'Small road'
|
||||
resp = resp.form.submit('submit').follow()
|
||||
formdef = FormDef.get(formdef.id)
|
||||
assert formdef.fields[0].data_source == {'type': 'foobar'}
|
||||
assert formdef.fields[0].min_zoom == '9'
|
||||
|
||||
resp = app.get('/backoffice/forms/1/fields/1/')
|
||||
assert resp.form['min_zoom'].value == 'Wide area'
|
||||
|
||||
|
||||
def test_form_edit_items_field(pub):
|
||||
create_superuser(pub)
|
||||
create_role()
|
||||
|
|
|
@ -68,7 +68,7 @@ class DataSourceSelectionWidget(CompositeWidget):
|
|||
options.append(OptGroup(_('Cards')))
|
||||
options.extend(cards_options)
|
||||
|
||||
nds_options = [(x.slug, x.name, x.slug) for x in NamedDataSource.select()]
|
||||
nds_options = [(x.slug, x.name, x.slug, {'data-type': x.type}) for x in NamedDataSource.select()]
|
||||
nds_options.sort(key=lambda x: misc.simplify(x[1]))
|
||||
if nds_options:
|
||||
options.append(OptGroup(_('Manually Configured Data Sources')))
|
||||
|
|
|
@ -1434,7 +1434,44 @@ def item_items_stats(field, values):
|
|||
return r.getvalue()
|
||||
|
||||
|
||||
class ItemField(WidgetField):
|
||||
class MapOptionsMixin:
|
||||
initial_zoom = None
|
||||
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
|
||||
zoom_levels = [(None, '---'),
|
||||
('0', _('Whole world')),
|
||||
('6', _('Country')),
|
||||
('9', _('Wide area')),
|
||||
('11', _('Area')),
|
||||
('13', _('Town')),
|
||||
('16', _('Small road')),
|
||||
('18', _('Neighbourhood')),
|
||||
('19', _('Ant')),]
|
||||
form.add(SingleSelectWidget, 'initial_zoom', title=_('Initial zoom level'),
|
||||
value=self.initial_zoom or '13', options=zoom_levels, **kwargs)
|
||||
form.add(SingleSelectWidget, 'min_zoom', title=_('Minimal zoom level'),
|
||||
value=self.min_zoom, options=zoom_levels, required=False, **kwargs)
|
||||
form.add(SingleSelectWidget, 'max_zoom', title=_('Maximal zoom level'),
|
||||
value=self.max_zoom, options=zoom_levels, required=False, **kwargs)
|
||||
|
||||
def check_zoom_admin_form(self, form):
|
||||
initial_zoom = form.get_widget('initial_zoom').parse()
|
||||
min_zoom = form.get_widget('min_zoom').parse()
|
||||
max_zoom = form.get_widget('max_zoom').parse()
|
||||
if min_zoom and max_zoom:
|
||||
if int(min_zoom) > int(max_zoom):
|
||||
form.get_widget('min_zoom').set_error(
|
||||
_('Minimal zoom level cannot be greater than maximal zoom level.'))
|
||||
if (initial_zoom and min_zoom and int(initial_zoom) < int(min_zoom)) or (
|
||||
(initial_zoom and max_zoom and int(initial_zoom) > int(max_zoom))):
|
||||
form.get_widget('initial_zoom').set_error(
|
||||
_('Initial zoom level must be between minimal and maximal zoom levels.'))
|
||||
|
||||
|
||||
class ItemField(WidgetField, MapOptionsMixin):
|
||||
key = 'item'
|
||||
description = N_('List')
|
||||
|
||||
|
@ -1634,14 +1671,16 @@ class ItemField(WidgetField):
|
|||
WidgetField.fill_admin_form(self, form)
|
||||
form.add(CheckboxWidget, 'in_filters', title=_('Display in default filters'),
|
||||
value=self.in_filters, advanced=True)
|
||||
options = [('list', _('List')),
|
||||
('radio', _('Radio buttons')),
|
||||
('autocomplete', _('Autocomplete')),
|
||||
options = [('list', _('List'), 'list'),
|
||||
('radio', _('Radio buttons'), 'radio'),
|
||||
('autocomplete', _('Autocomplete'), 'autocomplete'),
|
||||
('map', _('Map (requires geographical data)'), 'map'),
|
||||
]
|
||||
form.add(RadiobuttonsWidget, 'display_mode',
|
||||
title=_('Display Mode'),
|
||||
options=options,
|
||||
value=self.display_mode)
|
||||
value=self.display_mode,
|
||||
attrs={'data-dynamic-display-parent': 'true'})
|
||||
real_data_source = data_sources.get_real(self.data_source)
|
||||
form.add(RadiobuttonsWidget, 'data_mode',
|
||||
title=_('Data'),
|
||||
|
@ -1669,11 +1708,14 @@ class ItemField(WidgetField):
|
|||
title=_('Display disabled items'),
|
||||
value=self.display_disabled_items,
|
||||
advanced=not(self.display_disabled_items))
|
||||
self.fill_zoom_admin_form(form,
|
||||
attrs={'data-dynamic-display-child-of': 'display_mode',
|
||||
'data-dynamic-display-value': 'map'})
|
||||
|
||||
def get_admin_attributes(self):
|
||||
return WidgetField.get_admin_attributes(self) + ['items',
|
||||
'display_mode', 'data_source', 'in_filters', 'anonymise',
|
||||
'display_disabled_items']
|
||||
'display_disabled_items', 'initial_zoom', 'min_zoom', 'max_zoom']
|
||||
|
||||
def check_admin_form(self, form):
|
||||
data_mode = form.get_widget('data_mode').parse()
|
||||
|
@ -1690,6 +1732,8 @@ class ItemField(WidgetField):
|
|||
data_source_type.set_value(None)
|
||||
data_source_type.transfer_form_value(get_request())
|
||||
|
||||
self.check_zoom_admin_form(form)
|
||||
|
||||
def stats(self, values):
|
||||
return item_items_stats(self, values)
|
||||
|
||||
|
@ -2420,13 +2464,10 @@ class TableRowsField(WidgetField):
|
|||
register_field_class(TableRowsField)
|
||||
|
||||
|
||||
class MapField(WidgetField):
|
||||
class MapField(WidgetField, MapOptionsMixin):
|
||||
key = 'map'
|
||||
description = N_('Map')
|
||||
|
||||
initial_zoom = None
|
||||
min_zoom = None
|
||||
max_zoom = None
|
||||
default_position = None
|
||||
init_with_geoloc = False
|
||||
|
||||
|
@ -2436,22 +2477,7 @@ class MapField(WidgetField):
|
|||
|
||||
def fill_admin_form(self, form):
|
||||
WidgetField.fill_admin_form(self, form)
|
||||
# 0: whole world, 9: wide area, 11: area, 13: town, 16: small road
|
||||
zoom_levels = [(None, '---'),
|
||||
('0', _('Whole world')),
|
||||
('6', _('Country')),
|
||||
('9', _('Wide area')),
|
||||
('11', _('Area')),
|
||||
('13', _('Town')),
|
||||
('16', _('Small road')),
|
||||
('18', _('Neighbourhood')),
|
||||
('19', _('Ant')),]
|
||||
form.add(SingleSelectWidget, 'initial_zoom', title=_('Initial zoom level'),
|
||||
value=self.initial_zoom or '13', options=zoom_levels)
|
||||
form.add(SingleSelectWidget, 'min_zoom', title=_('Minimal zoom level'),
|
||||
value=self.min_zoom, options=zoom_levels, required=False)
|
||||
form.add(SingleSelectWidget, 'max_zoom', title=_('Maximal zoom level'),
|
||||
value=self.max_zoom, options=zoom_levels, required=False)
|
||||
self.fill_zoom_admin_form(form)
|
||||
form.add(MapWidget, 'default_position', title=_('Initial Position'),
|
||||
value=self.default_position, default_zoom='9', required=False)
|
||||
form.add(CheckboxWidget, 'init_with_geoloc',
|
||||
|
@ -2459,17 +2485,7 @@ class MapField(WidgetField):
|
|||
value=self.init_with_geoloc, required=False)
|
||||
|
||||
def check_admin_form(self, form):
|
||||
initial_zoom = form.get_widget('initial_zoom').parse()
|
||||
min_zoom = form.get_widget('min_zoom').parse()
|
||||
max_zoom = form.get_widget('max_zoom').parse()
|
||||
if min_zoom and max_zoom:
|
||||
if int(min_zoom) > int(max_zoom):
|
||||
form.get_widget('min_zoom').set_error(
|
||||
_('Minimal zoom level cannot be greater than maximal zoom level.'))
|
||||
if (initial_zoom and min_zoom and int(initial_zoom) < int(min_zoom)) or (
|
||||
(initial_zoom and max_zoom and int(initial_zoom) > int(max_zoom))):
|
||||
form.get_widget('initial_zoom').set_error(
|
||||
_('Initial zoom level must be between minimal and maximal zoom levels.'))
|
||||
self.check_zoom_admin_form(form)
|
||||
|
||||
def get_admin_attributes(self):
|
||||
return WidgetField.get_admin_attributes(self) + ['initial_zoom',
|
||||
|
|
|
@ -254,4 +254,17 @@ $(function() {
|
|||
panned_svg.resize();
|
||||
});
|
||||
}
|
||||
|
||||
$('[type=radio][name=display_mode]').on('change', function() {
|
||||
if ($(this).val() == 'map') {
|
||||
$('input[name="data_mode"][value="data-source"]').click()
|
||||
$('select[name="data_source$type"] option:not([data-type="geojson"])').hide();
|
||||
if ($('select[name="data_source$type"] option:selected:visible').length == 0) {
|
||||
$('select[name="data_source$type"] option:visible').first().prop('selected', true);
|
||||
}
|
||||
} else {
|
||||
$('select[name="data_source$type"] option').show();
|
||||
}
|
||||
});
|
||||
$('[type=radio][name=display_mode]').trigger('change');
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue