statistics: keep field items order in filter options (#80523) #703

Merged
vdeniaud merged 1 commits from wip/80523-stats-respecter-l-ordre-des-choi into main 2023-10-30 11:05:28 +01:00
4 changed files with 117 additions and 20 deletions

View File

@ -1,4 +1,5 @@
import datetime
import json
import os
import pytest
@ -77,23 +78,30 @@ def formdef(pub):
id='2',
varname='block-items',
label='Block items',
items=['foo', 'bar', 'baz'],
items=['Foo', 'Bar', 'Baz'],
anonymise='no',
display_locations=['statistics'],
),
]
block.store()
data_source = {
'type': 'jsonvalue',
'value': json.dumps(
[{'id': 'foo', 'text': 'Foo'}, {'id': 'bar', 'text': 'Bar'}, {'id': 'baz', 'text': 'Baz'}]
),
}
formdef = FormDef()
formdef.name = 'test'
formdef.workflow_id = workflow.id
item_field = fields.ItemField(id='2', varname='test-item', label='Test item', items=['foo', 'bar', 'baz'])
item_field = fields.ItemField(id='2', varname='test-item', label='Test item', data_source=data_source)
item_field.display_locations = ['statistics']
items_field = fields.ItemsField(
id='3',
varname='test-items',
label='Test items',
items=['foo', 'bar', 'baz'],
data_source=data_source,
anonymise='no',
)
items_field.display_locations = ['statistics']
@ -459,7 +467,11 @@ def test_statistics_forms_count_subfilters(pub, formdef):
assert resp.json['data']['subfilters'][4] == {
'id': 'filter-blockdata_block-items',
'label': 'Block items',
'options': [{'id': 'bar', 'label': 'Bar'}, {'id': 'foo', 'label': 'Foo'}],
'options': [
{'id': 'Foo', 'label': 'Foo'},
{'id': 'Bar', 'label': 'Bar'},
{'id': 'Baz', 'label': 'Baz'},
],
'required': False,
}
@ -513,12 +525,17 @@ def test_statistics_forms_count_subfilters(pub, formdef):
}
assert len(new_resp.json['data']['subfilters']) == len(resp.json['data']['subfilters']) + 1
# add item field with no formdata, it should not appear
# add item field with datasource and no formdata, it should not appear
item_field = fields.ItemField(
id='20',
varname='test-item-no-formdata',
label='Test item no formdata',
items=['foo', 'bar', 'baz'],
data_source={
'type': 'jsonvalue',
'value': json.dumps(
[{'id': 'foo', 'text': 'Foo'}, {'id': 'bar', 'text': 'Bar'}, {'id': 'baz', 'text': 'Baz'}]
),
},
display_locations=['statistics'],
)
formdef.fields.append(item_field)
@ -584,6 +601,31 @@ def test_statistics_forms_count_subfilters_empty_block_items_field(pub, formdef)
assert not any(x['id'] == 'filter-blockdata_block-items' for x in resp.json['data']['subfilters'])
def test_statistics_forms_count_subfilters_empty_item_field_no_datasource(pub, formdef):
formdef.workflow.backoffice_fields_formdef.fields.append(
fields.ItemField(
id='10',
varname='empty-item-field',
label='Empty item field',
anonymise='no',
display_locations=['statistics'],
),
)
formdef.workflow.store()
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.data['10'] = 'extra-option'
formdata.data['10_display'] = 'Extra option'
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.store()
resp = get_app(pub).get(sign_uri('/api/statistics/forms/count/?form=%s' % formdef.url_name))
filter_dict = [x for x in resp.json['data']['subfilters'] if x['id'] == 'filter-empty-item-field'][0]
assert filter_dict['options'] == [{'id': 'extra-option', 'label': 'Extra option'}]
def test_statistics_forms_count_subfilters_query(pub, formdef):
for i in range(20):
formdata = formdef.data_class()()
@ -785,8 +827,8 @@ def test_statistics_forms_count_group_by(pub, formdef, anonymise):
formdata.data['3_display'] = 'Bar, Baz'
formdata.data['4'] = {
'data': [
{'1': True, '2': ['baz'], '2_display': 'Baz'},
{'1': False, '2': ['foo'], '2_display': 'Foo'},
{'1': True, '2': ['Baz'], '2_display': 'Baz'},
{'1': False, '2': ['Foo'], '2_display': 'Foo'},
]
}
# "Web" channel has three equivalent values
@ -801,7 +843,7 @@ def test_statistics_forms_count_group_by(pub, formdef, anonymise):
formdata.data['1'] = False
formdata.data['2'] = 'baz'
formdata.data['3'] = ['baz']
formdata.data['4'] = {'data': [{'1': False, '2': ['foo', 'bar'], '2_display': 'Foo, Bar'}]}
formdata.data['4'] = {'data': [{'1': False, '2': ['Foo', 'Bar'], '2_display': 'Foo, Bar'}]}
if i == 3:
formdata.jump_status('3')
elif i == 9:
@ -889,9 +931,9 @@ def test_statistics_forms_count_group_by(pub, formdef, anonymise):
resp = get_app(pub).get(sign_uri(url + '&group-by=blockdata_block-items'))
assert resp.json['data']['x_labels'] == ['2021-01', '2021-02', '2021-03']
assert resp.json['data']['series'] == [
{'label': 'Foo', 'data': [16, None, None]},
{'label': 'Bar', 'data': [3, None, None]},
{'label': 'Baz', 'data': [13, None, None]},
{'label': 'Foo', 'data': [16, None, None]},
{'label': 'None', 'data': [None, None, 4]},
]

View File

@ -1,3 +1,4 @@
import json
import os
import random
import re
@ -1435,6 +1436,15 @@ def test_item_options_in_custom_view(pub):
carddata.store()
subcards.append(carddata)
data_source_16 = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in list('azertyuiopqsdfghjklmwxcvbn')[:16]]),
}
data_source_15 = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in list('azertyuiopqsdfghjklmwxcvbn')[:15]]),
}
carddef = CardDef()
carddef.name = 'card-title'
carddef.digest_templates = {'default': '{{ form_var_foo }}'}
@ -1448,7 +1458,7 @@ def test_item_options_in_custom_view(pub):
id='2',
label='2nd field',
type='item',
items=list('azertyuiopqsdfghjklmwxcvbn')[:16],
data_source=data_source_16,
display_locations=['validation', 'summary', 'listings'],
display_mode='list',
),
@ -1456,7 +1466,7 @@ def test_item_options_in_custom_view(pub):
id='3',
label='3rd field',
type='item',
items=list('azertyuiopqsdfghjklmwxcvbn')[:15],
data_source=data_source_15,
display_locations=['validation', 'summary', 'listings'],
display_mode='list',
),
@ -1464,7 +1474,7 @@ def test_item_options_in_custom_view(pub):
id='4',
label='4th field',
type='item',
items=list('azertyuiopqsdfghjklmwxcvbn')[:16],
data_source=data_source_16,
display_locations=['validation', 'summary', 'listings'],
display_mode='autocomplete',
),
@ -1472,7 +1482,7 @@ def test_item_options_in_custom_view(pub):
id='5',
label='5th field',
type='item',
items=list('azertyuiopqsdfghjklmwxcvbn')[:15],
data_source=data_source_15,
display_locations=['validation', 'summary', 'listings'],
display_mode='autocomplete',
),
@ -1484,6 +1494,14 @@ def test_item_options_in_custom_view(pub):
display_locations=['validation', 'summary', 'listings'],
display_mode='list',
),
fields.ItemField(
id='7',
label='7th field',
type='item',
items=list('azertyuiopqsdfghjklmwxcvbn')[:16],
display_locations=['validation', 'summary', 'listings'],
display_mode='list',
),
]
carddef.workflow_roles = {'_editor': role.id}
carddef.store()
@ -1538,6 +1556,7 @@ def test_item_options_in_custom_view(pub):
resp.forms['listing-settings']['filter-4'].checked = True
resp.forms['listing-settings']['filter-5'].checked = True
resp.forms['listing-settings']['filter-6'].checked = True
resp.forms['listing-settings']['filter-7'].checked = True
resp = resp.forms['listing-settings'].submit()
# field 2: select - all used options are listed
@ -1576,6 +1595,11 @@ def test_item_options_in_custom_view(pub):
resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=6&_search=')
assert len([x['id'] for x in resp2.json['data']]) == len(used_subcards)
# field 7: select - no datasource - all items are listed
assert [x[0] for x in resp.forms['listing-settings']['filter-7-value'].options] == [''] + list(
'azertyuiopqsdfghjklmwxcvbn'
)[:16]
resp = app.get('/backoffice/data/card-title/custom-test-view-for-datasource/')
# enable filters
resp.forms['listing-settings']['filter-1'].checked = True
@ -1584,6 +1608,7 @@ def test_item_options_in_custom_view(pub):
resp.forms['listing-settings']['filter-4'].checked = True
resp.forms['listing-settings']['filter-5'].checked = True
resp.forms['listing-settings']['filter-6'].checked = True
resp.forms['listing-settings']['filter-7'].checked = True
resp = resp.forms['listing-settings'].submit()
# field 2: select2 - all items are listed
@ -1611,6 +1636,11 @@ def test_item_options_in_custom_view(pub):
resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=6&_search=')
assert len([x['id'] for x in resp2.json['data']]) == 16
# field 7: select2 - all items are listed
assert [x[0] for x in resp.forms['listing-settings']['filter-7-value'].options] == ['', '{}']
resp2 = app.get(resp.request.path + 'filter-options?filter_field_id=7&_search=')
assert [x['id'] for x in resp2.json['data']] == list('azertyuiopqsdfghjklmwxcvbn')[:15] + ['{}']
datasource_custom_view.filters = {
'filter-5': 'on',
'filter-5-value': '{{ form_var_foo }}',

View File

@ -1,4 +1,5 @@
import datetime
import json
import os
import time
import uuid
@ -279,6 +280,11 @@ def test_backoffice_item_filter(pub):
role = pub.role_class(name='test')
role.store()
data_source = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in ['â', 'b', 'c', 'd']]),
}
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form-title'
@ -286,7 +292,7 @@ def test_backoffice_item_filter(pub):
fields.ItemField(
id='4',
label='4th field',
items=['â', 'b', 'c', 'd'],
data_source=data_source,
display_locations=['validation', 'summary', 'listings'],
)
]
@ -429,6 +435,15 @@ def test_backoffice_item_double_filter(pub):
role = pub.role_class(name='test')
role.store()
data_source = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in ['â', 'b', 'c', 'd']]),
}
data_source2 = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in ['E', 'F', 'G', 'H']]),
}
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form-title'
@ -436,13 +451,13 @@ def test_backoffice_item_double_filter(pub):
fields.ItemField(
id='4',
label='4th field',
items=['â', 'b', 'c', 'd'],
data_source=data_source,
display_locations=['validation', 'summary', 'listings'],
),
fields.ItemField(
id='5',
label='5th field',
items=['E', 'F', 'G', 'H'],
data_source=data_source2,
display_locations=['validation', 'summary', 'listings'],
),
]
@ -518,6 +533,11 @@ def test_backoffice_bofield_item_filter(pub):
role = pub.role_class(name='test')
role.store()
data_source = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in ['â', 'b', 'c', 'd']]),
}
workflow = Workflow.get_default_workflow()
workflow.id = '2'
workflow.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(workflow)
@ -525,7 +545,7 @@ def test_backoffice_bofield_item_filter(pub):
fields.ItemField(
id='bo0-1',
label='4th field',
items=['â', 'b', 'c', 'd'],
data_source=data_source,
display_locations=['validation', 'summary', 'listings'],
)
]
@ -632,6 +652,11 @@ def test_backoffice_items_filter(pub):
role = pub.role_class(name='test')
role.store()
data_source = {
'type': 'jsonvalue',
'value': json.dumps([{'id': x, 'text': x} for x in ['â', 'b', 'c', 'd']]),
}
FormDef.wipe()
formdef = FormDef()
formdef.name = 'form-title'
@ -639,7 +664,7 @@ def test_backoffice_items_filter(pub):
fields.ItemsField(
id='4',
label='4th field',
items=['â', 'b', 'c', 'd'],
data_source=data_source,
display_locations=['validation', 'summary', 'listings'],
)
]

View File

@ -997,7 +997,7 @@ class FormPage(Directory, TempfileDirectoryMixin):
criterias=None,
anonymised=False,
):
if self.view and self.view.visibility == 'datasource':
if (self.view and self.view.visibility == 'datasource') or filter_field.items:
return filter_field.get_options()
# remove potential filter on self
filter_field_id = get_field_id(filter_field)