0001-dataviz-allow-disabling-filters-in-filters-cell-7165.patch
combo/apps/dataviz/forms.py | ||
---|---|---|
28 | 28 | |
29 | 29 |
from combo.utils import cache_during_request, requests, spooler |
30 | 30 | |
31 |
from .models import ChartCell, ChartNgCell |
|
31 |
from .models import ChartCell, ChartFiltersCell, ChartNgCell
|
|
32 | 32 | |
33 | 33 | |
34 | 34 |
class ChartForm(forms.ModelForm): |
... | ... | |
286 | 286 | |
287 | 287 |
def __init__(self, *args, **kwargs): |
288 | 288 |
page = kwargs.pop('page') |
289 |
filters_cell = kwargs.pop('filters_cell') |
|
289 | 290 |
filters_cell_id = kwargs.pop('filters_cell_id', None) |
290 | 291 |
super().__init__(*args, **kwargs) |
291 | 292 | |
... | ... | |
337 | 338 |
if 'time_range' in self.fields: |
338 | 339 |
self.update_time_range_choices(cell.statistic) |
339 | 340 | |
341 |
self.update_backoffice_filter_choices(filters_cell, dynamic_fields) |
|
342 |
dynamic_fields = { |
|
343 |
name: field for name, field in dynamic_fields.items() if filters_cell.filters[name]['enabled'] |
|
344 |
} |
|
340 | 345 |
self.fields.update(dynamic_fields) |
346 | ||
347 |
@staticmethod |
|
348 |
def update_backoffice_filter_choices(filters_cell, dynamic_fields): |
|
349 |
# remove absent filters from cell configuration, except if it was disabled |
|
350 |
filters_cell.filters = { |
|
351 |
k: v for k, v in filters_cell.filters.items() if k in dynamic_fields or not v['enabled'] |
|
352 |
} |
|
353 | ||
354 |
# add filters to cell configuration |
|
355 |
for field_name, field in dynamic_fields.items(): |
|
356 |
if not field_name in filters_cell.filters: |
|
357 |
filters_cell.filters[field_name] = {'label': str(field.label), 'enabled': True} |
|
358 |
continue |
|
359 | ||
360 |
filters_cell.save() |
|
361 | ||
362 | ||
363 |
class ChartFiltersConfigForm(forms.ModelForm): |
|
364 |
filters = forms.MultipleChoiceField( |
|
365 |
label=_('Filters'), widget=forms.CheckboxSelectMultiple, required=False |
|
366 |
) |
|
367 | ||
368 |
class Meta: |
|
369 |
model = ChartFiltersCell |
|
370 |
fields = [] |
|
371 | ||
372 |
def __init__(self, *args, **kwargs): |
|
373 |
super().__init__(*args, **kwargs) |
|
374 |
if not self.instance.filters: |
|
375 |
del self.fields['filters'] |
|
376 |
return |
|
377 | ||
378 |
self.initial['filters'] = [] |
|
379 |
self.fields['filters'].choices = [] |
|
380 |
for filter_id, config in self.instance.filters.items(): |
|
381 |
self.fields['filters'].choices.append((filter_id, config['label'])) |
|
382 | ||
383 |
if config['enabled']: |
|
384 |
self.initial['filters'].append(filter_id) |
|
385 | ||
386 |
def save(self, *args, **kwargs): |
|
387 |
for filter_id in self.instance.filters: |
|
388 |
self.instance.filters[filter_id]['enabled'] = bool(filter_id in self.cleaned_data['filters']) |
|
389 |
return super().save(*args, **kwargs) |
combo/apps/dataviz/migrations/0026_chartfilterscell_filters.py | ||
---|---|---|
1 |
# Generated by Django 2.2.26 on 2022-12-12 13:28 |
|
2 | ||
3 |
import django.contrib.postgres.fields.jsonb |
|
4 |
from django.db import migrations |
|
5 | ||
6 | ||
7 |
class Migration(migrations.Migration): |
|
8 | ||
9 |
dependencies = [ |
|
10 |
('dataviz', '0025_statistic_data_type'), |
|
11 |
] |
|
12 | ||
13 |
operations = [ |
|
14 |
migrations.AddField( |
|
15 |
model_name='chartfilterscell', |
|
16 |
name='filters', |
|
17 |
field=django.contrib.postgres.fields.jsonb.JSONField(default=dict, verbose_name='Filters'), |
|
18 |
), |
|
19 |
] |
combo/apps/dataviz/models.py | ||
---|---|---|
758 | 758 | |
759 | 759 |
@register_cell_class |
760 | 760 |
class ChartFiltersCell(CellBase): |
761 |
filters = JSONField(_('Filters'), default=dict) |
|
762 | ||
761 | 763 |
title = _('Filters') |
762 | 764 |
default_template_name = 'combo/chart-filters.html' |
765 |
manager_form_template = 'combo/chartfilterscell_form.html' |
|
763 | 766 |
max_one_by_page = True |
764 | 767 | |
765 | 768 |
class Meta: |
... | ... | |
777 | 780 |
ctx['form'] = ChartFiltersForm( |
778 | 781 |
data=context['request'].GET, |
779 | 782 |
page=self.page, |
783 |
filters_cell=self, |
|
780 | 784 |
filters_cell_id=context['request'].GET['filters_cell_id'], |
781 | 785 |
) |
782 | 786 |
else: |
783 |
ctx['form'] = ChartFiltersForm(page=self.page) |
|
787 |
ctx['form'] = ChartFiltersForm(page=self.page, filters_cell=self)
|
|
784 | 788 | |
785 | 789 |
return ctx |
790 | ||
791 |
def get_default_form_class(self): |
|
792 |
from .forms import ChartFiltersConfigForm |
|
793 | ||
794 |
return ChartFiltersConfigForm |
combo/apps/dataviz/templates/combo/chartfilterscell_form.html | ||
---|---|---|
1 |
{% load gadjo %} |
|
2 | ||
3 |
{% block cell-form %} |
|
4 |
{{form|with_template}} |
|
5 |
{% endblock %} |
|
6 |
tests/test_dataviz.py | ||
---|---|---|
2705 | 2705 |
assert 'filter-menu' in resp.form.fields |
2706 | 2706 | |
2707 | 2707 | |
2708 |
@with_httmock(new_api_mock) |
|
2709 |
def test_chart_filters_cell_select_filters(new_api_statistics, app, admin_user, nocache): |
|
2710 |
page = Page.objects.create(title='One', slug='index') |
|
2711 |
filters_cell = ChartFiltersCell.objects.create(page=page, order=1, placeholder='content') |
|
2712 |
app = login(app) |
|
2713 | ||
2714 |
# no chart cell, filters cell configuration is empty |
|
2715 |
resp = app.get('/manage/pages/%s/' % page.id) |
|
2716 |
field_prefix = 'cdataviz_chartfilterscell-%s-' % filters_cell.id |
|
2717 |
assert field_prefix + 'filters' not in resp.form.fields |
|
2718 | ||
2719 |
# add chart cell |
|
2720 |
cell = ChartNgCell.objects.create(page=page, order=2, placeholder='content') |
|
2721 |
cell.statistic = Statistic.objects.get(slug='one-serie') |
|
2722 |
cell.save() |
|
2723 | ||
2724 |
resp = app.get('/') |
|
2725 |
assert len(resp.form.fields) == 7 |
|
2726 |
assert 'filter-ou' in resp.form.fields |
|
2727 |
assert 'filter-service' in resp.form.fields |
|
2728 |
assert 'filter-time_range' in resp.form.fields |
|
2729 | ||
2730 |
# filters cell configuration shows filters |
|
2731 |
resp = app.get('/manage/pages/%s/' % page.id) |
|
2732 |
assert field_prefix + 'filters' in resp.forms[0].fields |
|
2733 | ||
2734 |
# all filters are active |
|
2735 |
assert all(resp.forms[0].get(field_prefix + 'filters', index=i).checked for i in range(3)) |
|
2736 |
assert [resp.forms[0].get(field_prefix + 'filters', index=i).value for i in range(3)] == [ |
|
2737 |
'ou', |
|
2738 |
'service', |
|
2739 |
'time_interval', |
|
2740 |
] |
|
2741 | ||
2742 |
# disable OU filter |
|
2743 |
resp.forms[0].get(field_prefix + 'filters', index=0).checked = False |
|
2744 |
manager_submit_cell(resp.forms[0]) |
|
2745 | ||
2746 |
resp = app.get('/') |
|
2747 |
assert len(resp.form.fields) == 6 |
|
2748 |
assert 'filter-ou' not in resp.form.fields |
|
2749 |
assert 'filter-service' in resp.form.fields |
|
2750 |
assert 'filter-time_range' in resp.form.fields |
|
2751 | ||
2752 |
# choose other statistic with different filters |
|
2753 |
cell.statistic = Statistic.objects.get(slug='filter-multiple') |
|
2754 |
cell.save() |
|
2755 | ||
2756 |
# OU filter has been kept as it is disabled, but other disappeared |
|
2757 |
resp = app.get('/manage/pages/%s/' % page.id) |
|
2758 |
assert [resp.forms[0].get(field_prefix + 'filters', index=i).value for i in range(2)] == [ |
|
2759 |
None, |
|
2760 |
'color', |
|
2761 |
] |
|
2762 |
resp.forms[0].get(field_prefix + 'filters', index=0).checked = True |
|
2763 |
assert resp.forms[0].get(field_prefix + 'filters', index=0).value == 'ou' |
|
2764 | ||
2765 | ||
2708 | 2766 |
@with_httmock(new_api_mock) |
2709 | 2767 |
@pytest.mark.freeze_time('2021-10-06') |
2710 | 2768 |
def test_chartng_cell_api_view_get_parameters(app, normal_user, new_api_statistics, nocache): |
2711 |
- |