wip/72896-dataviz-afficher-les-filtres-boo #52
|
@ -75,57 +75,15 @@ class ChartFiltersMixin:
|
||||||
):
|
):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
has_option_groups = isinstance(filter_['options'][0], list)
|
|
||||||
if filter_['options'] and has_option_groups:
|
|
||||||
choices = {
|
|
||||||
group: [(opt['id'], opt['label']) for opt in options]
|
|
||||||
for group, options in filter_['options']
|
|
||||||
}
|
|
||||||
choices_to_complete = choices[None] = choices.get(None, [])
|
|
||||||
choices = list(choices.items())
|
|
||||||
else:
|
|
||||||
choices = [(option['id'], option['label']) for option in filter_['options']]
|
|
||||||
choices_to_complete = choices
|
|
||||||
|
|
||||||
initial = cell.filter_params.get(filter_id, filter_.get('default'))
|
initial = cell.filter_params.get(filter_id, filter_.get('default'))
|
||||||
|
|
||||||
if filter_id == 'time_interval':
|
|
||||||
self.extend_time_interval_choices(choices)
|
|
||||||
|
|
||||||
required = filter_.get('required', False)
|
required = filter_.get('required', False)
|
||||||
multiple = filter_.get('multiple')
|
|
||||||
if not required:
|
|
||||||
choices_to_complete.insert(0, BLANK_CHOICE_DASH[0])
|
|
||||||
|
|
||||||
extra_variables = cell.page.get_extra_variables_keys()
|
if required and {x['id'] for x in filter_['options'] if isinstance(x, dict)} == {'true', 'false'}:
|
||||||
variable_choices = [('variable:' + key, key) for key in extra_variables]
|
field = self.build_boolean_field(cell, filter_, initial)
|
||||||
|
|
||||||
if has_option_groups:
|
|
||||||
possible_choices = {choice[0] for _, group_choices in choices for choice in group_choices}
|
|
||||||
else:
|
else:
|
||||||
possible_choices = {choice[0] for choice in choices}
|
field = self.build_choice_field(cell, filter_, initial)
|
||||||
for choice in initial if isinstance(initial, list) else [initial]:
|
|
||||||
if not choice:
|
|
||||||
continue
|
|
||||||
if choice.startswith('variable:'):
|
|
||||||
variable = choice.replace('variable:', '')
|
|
||||||
if not variable in extra_variables:
|
|
||||||
variable_choices.append((choice, _('%s (unavailable)') % variable))
|
|
||||||
elif choice not in possible_choices:
|
|
||||||
choices_to_complete.append((choice, _('%s (unavailable)') % choice))
|
|
||||||
|
|
||||||
if variable_choices and not multiple and filter_id != 'time_interval':
|
fields[filter_id] = field
|
||||||
choices.append((_('Page variables'), variable_choices))
|
|
||||||
|
|
||||||
field_class = forms.MultipleChoiceField if multiple else forms.ChoiceField
|
|
||||||
widget_class = MultiSelectWidget if multiple else forms.Select
|
|
||||||
fields[filter_id] = field_class(
|
|
||||||
label=filter_['label'],
|
|
||||||
choices=choices,
|
|
||||||
required=required,
|
|
||||||
initial=initial,
|
|
||||||
widget=widget_class,
|
|
||||||
)
|
|
||||||
if filter_.get('deprecated'):
|
if filter_.get('deprecated'):
|
||||||
fields[filter_id].label += ' (%s)' % _('deprecated')
|
fields[filter_id].label += ' (%s)' % _('deprecated')
|
||||||
fields[filter_id].help_text = filter_.get('deprecation_hint')
|
fields[filter_id].help_text = filter_.get('deprecation_hint')
|
||||||
|
@ -133,6 +91,65 @@ class ChartFiltersMixin:
|
||||||
|
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
|
def build_choice_field(self, cell, filter_, initial):
|
||||||
|
filter_id = filter_['id']
|
||||||
|
|
||||||
|
has_option_groups = isinstance(filter_['options'][0], list)
|
||||||
|
if filter_['options'] and has_option_groups:
|
||||||
|
choices = {
|
||||||
|
group: [(opt['id'], opt['label']) for opt in options] for group, options in filter_['options']
|
||||||
|
}
|
||||||
|
choices_to_complete = choices[None] = choices.get(None, [])
|
||||||
|
choices = list(choices.items())
|
||||||
|
else:
|
||||||
|
choices = [(option['id'], option['label']) for option in filter_['options']]
|
||||||
|
choices_to_complete = choices
|
||||||
|
|
||||||
|
if filter_id == 'time_interval':
|
||||||
|
self.extend_time_interval_choices(choices)
|
||||||
|
|
||||||
|
required = filter_.get('required', False)
|
||||||
|
multiple = filter_.get('multiple')
|
||||||
|
if not required:
|
||||||
|
choices_to_complete.insert(0, BLANK_CHOICE_DASH[0])
|
||||||
|
|
||||||
|
extra_variables = cell.page.get_extra_variables_keys()
|
||||||
|
variable_choices = [('variable:' + key, key) for key in extra_variables]
|
||||||
|
|
||||||
|
if has_option_groups:
|
||||||
|
possible_choices = {choice[0] for _, group_choices in choices for choice in group_choices}
|
||||||
|
else:
|
||||||
|
possible_choices = {choice[0] for choice in choices}
|
||||||
|
for choice in initial if isinstance(initial, list) else [initial]:
|
||||||
|
if not choice:
|
||||||
|
continue
|
||||||
|
if choice.startswith('variable:'):
|
||||||
|
variable = choice.replace('variable:', '')
|
||||||
|
if not variable in extra_variables:
|
||||||
|
variable_choices.append((choice, _('%s (unavailable)') % variable))
|
||||||
|
elif choice not in possible_choices:
|
||||||
|
choices_to_complete.append((choice, _('%s (unavailable)') % choice))
|
||||||
|
|
||||||
|
if variable_choices and not multiple and filter_id != 'time_interval':
|
||||||
|
choices.append((_('Page variables'), variable_choices))
|
||||||
|
|
||||||
|
field_class = forms.MultipleChoiceField if multiple else forms.ChoiceField
|
||||||
|
widget_class = MultiSelectWidget if multiple else forms.Select
|
||||||
|
return field_class(
|
||||||
|
label=filter_['label'],
|
||||||
|
choices=choices,
|
||||||
|
required=required,
|
||||||
|
initial=initial,
|
||||||
|
widget=widget_class,
|
||||||
|
)
|
||||||
|
|
||||||
|
def build_boolean_field(self, cell, filter_, initial):
|
||||||
|
return forms.BooleanField(
|
||||||
|
label=filter_['label'],
|
||||||
|
required=False,
|
||||||
|
initial=bool(initial == 'true'),
|
||||||
|
)
|
||||||
|
|
||||||
def extend_time_interval_choices(self, choices):
|
def extend_time_interval_choices(self, choices):
|
||||||
choice_ids = {choice_id for choice_id, _ in choices}
|
choice_ids = {choice_id for choice_id, _ in choices}
|
||||||
if 'day' in choice_ids:
|
if 'day' in choice_ids:
|
||||||
|
@ -224,7 +241,11 @@ class ChartNgForm(ChartFiltersMixin, forms.ModelForm):
|
||||||
else:
|
else:
|
||||||
for filter_ in self.instance.available_filters:
|
for filter_ in self.instance.available_filters:
|
||||||
if filter_['id'] in self.cleaned_data:
|
if filter_['id'] in self.cleaned_data:
|
||||||
self.instance.filter_params[filter_['id']] = self.cleaned_data[filter_['id']]
|
value = self.cleaned_data[filter_['id']]
|
||||||
|
if isinstance(value, bool):
|
||||||
|
value = 'true' if value is True else 'false'
|
||||||
|
|
||||||
|
self.instance.filter_params[filter_['id']] = value
|
||||||
|
|
||||||
cell = super().save(*args, **kwargs)
|
cell = super().save(*args, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -564,6 +564,23 @@ STATISTICS_LIST = {
|
||||||
'id': 'deprecated',
|
'id': 'deprecated',
|
||||||
'deprecated': True,
|
'deprecated': True,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'url': 'https://authentic.example.com/api/statistics/required-boolean/',
|
||||||
|
'name': 'Required boolean choices',
|
||||||
|
'id': 'required-boolean',
|
||||||
|
"filters": [
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
"label": "Test",
|
||||||
|
"options": [
|
||||||
|
{"id": "true", "label": "True"},
|
||||||
|
{"id": "false", "label": "False"},
|
||||||
|
],
|
||||||
|
"default": "true",
|
||||||
|
"required": True,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1656,6 +1673,19 @@ def test_chartng_cell_manager_new_api(app, admin_user, new_api_statistics):
|
||||||
cell.refresh_from_db()
|
cell.refresh_from_db()
|
||||||
assert cell.filter_params == {'test': 'b'}
|
assert cell.filter_params == {'test': 'b'}
|
||||||
|
|
||||||
|
required_boolean_stat = Statistic.objects.get(slug='required-boolean')
|
||||||
|
resp.form[field_prefix + 'statistic'] = required_boolean_stat.pk
|
||||||
|
manager_submit_cell(resp.form)
|
||||||
|
assert resp.form[field_prefix + 'test'].checked is True
|
||||||
|
cell.refresh_from_db()
|
||||||
|
assert cell.filter_params == {'test': 'true'}
|
||||||
|
|
||||||
|
manager_submit_cell(resp.form)
|
||||||
|
resp.form[field_prefix + 'test'] = False
|
||||||
|
manager_submit_cell(resp.form)
|
||||||
|
cell.refresh_from_db()
|
||||||
|
assert cell.filter_params == {'test': 'false'}
|
||||||
|
|
||||||
deprecated_stat = Statistic.objects.get(slug='deprecated-filter')
|
deprecated_stat = Statistic.objects.get(slug='deprecated-filter')
|
||||||
resp.form[field_prefix + 'statistic'] = deprecated_stat.pk
|
resp.form[field_prefix + 'statistic'] = deprecated_stat.pk
|
||||||
manager_submit_cell(resp.form)
|
manager_submit_cell(resp.form)
|
||||||
|
|
Loading…
Reference in New Issue