fields: add new option to align datetimes selection on a date (#50035)

This commit is contained in:
Frédéric Péters 2021-01-11 14:55:59 +01:00
parent 3cac5c56ff
commit b8f9e437a7
3 changed files with 128 additions and 2 deletions

View File

@ -9414,3 +9414,91 @@ def test_form_item_map_data_source(pub, http_requests):
data_id = formdef.data_class().select()[0].id
formdata = formdef.data_class().get(data_id)
assert formdata.data['1_structured']['geometry']['coordinates'] == [1, 2]
def test_form_item_timetable_data_source(pub, http_requests):
NamedDataSource.wipe()
data_source = NamedDataSource(name='foobar')
data_source.data_source = {
'type': 'json',
'value': 'http://remote.example.net/api/datetimes',
}
data_source.store()
formdef = create_formdef()
formdef.fields = [
fields.ItemField(id='1', label='datetime', display_mode='timetable', data_source={'type': 'foobar'}),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
data = {
"data": [
{"id": "1", "datetime": "2021-01-12 10:00:00", "text": "event 1"},
{"id": "2", "datetime": "2021-01-13 10:20:00", "text": "event 2"},
{"id": "3", "datetime": "2021-01-14 10:40:00", "text": "event 3"},
]
}
urlopen.side_effect = lambda *args: StringIO(json.dumps(data))
resp = app.get('/test/')
assert 'data-date="2021-01-12"' in resp and 'data-time="10:00"' in resp
assert 'data-date="2021-01-13"' in resp and 'data-time="10:20"' in resp
assert 'data-date="2021-01-14"' in resp and 'data-time="10:40"' in resp
resp.form['f1'] = '2' # would happen via javascript
resp = resp.form.submit('submit')
resp = resp.form.submit('submit')
assert formdef.data_class().count() == 1
data_id = formdef.data_class().select()[0].id
formdata = formdef.data_class().get(data_id)
assert formdata.data == {
'1': '2',
'1_display': 'event 2',
'1_structured': {'id': '2', 'datetime': '2021-01-13 10:20:00', 'text': 'event 2'},
}
def test_form_item_timetable_data_source_with_date_alignment(pub, http_requests):
NamedDataSource.wipe()
data_source = NamedDataSource(name='foobar')
data_source.data_source = {
'type': 'json',
'value': 'http://remote.example.net/api/datetimes',
}
data_source.store()
formdef = create_formdef()
formdef.fields = [
fields.PageField(id='1', label='page1', type='page'),
fields.DateField(id='2', label='date', type='date', varname='date'),
fields.PageField(id='3', label='page2', type='page'),
fields.ItemField(id='4', label='datetime', display_mode='timetable',
data_source={'type': 'foobar'},
initial_date_alignment='{{ form_var_date }}'),
]
formdef.store()
formdef.data_class().wipe()
app = get_app(pub)
with mock.patch('wcs.qommon.misc.urlopen') as urlopen:
data = {
"data": [
{"id": "1", "datetime": "2021-01-12 10:00:00", "text": "event 1"},
{"id": "2", "datetime": "2021-01-13 10:20:00", "text": "event 2"},
{"id": "3", "datetime": "2021-01-14 10:40:00", "text": "event 3"},
]
}
urlopen.side_effect = lambda *args: StringIO(json.dumps(data))
resp = app.get('/test/')
resp.form['f2'] = '2021-01-14'
resp = resp.form.submit('submit') # -> 2nd page
assert 'var ALIGN_DATE = "2021-01-14";' in resp
resp.form['f4'] = '2' # would happen via javascript
resp = resp.form.submit('submit')
resp = resp.form.submit('submit')
assert formdef.data_class().count() == 1

View File

@ -1488,6 +1488,7 @@ class ItemField(WidgetField, MapOptionsMixin):
in_filters = False
display_disabled_items = False
display_mode = 'list'
initial_date_alignment = None
def __init__(self, **kwargs):
self.items = []
@ -1731,6 +1732,12 @@ class ItemField(WidgetField, MapOptionsMixin):
title=_('Display disabled items'),
value=self.display_disabled_items,
advanced=not(self.display_disabled_items))
widget = form.add(StringWidget, 'initial_date_alignment',
title=_('Initial date alignment'),
value=self.initial_date_alignment,
validation_function=ComputedExpressionWidget.validate_template,
attrs={'data-dynamic-display-child-of': 'display_mode',
'data-dynamic-display-value': 'datetimes'})
self.fill_zoom_admin_form(form,
attrs={'data-dynamic-display-child-of': 'display_mode',
'data-dynamic-display-value': 'map'})
@ -1738,7 +1745,8 @@ class ItemField(WidgetField, MapOptionsMixin):
def get_admin_attributes(self):
return WidgetField.get_admin_attributes(self) + ['items',
'display_mode', 'data_source', 'in_filters', 'anonymise',
'display_disabled_items', 'initial_zoom', 'min_zoom', 'max_zoom']
'display_disabled_items', 'initial_zoom', 'min_zoom', 'max_zoom',
'initial_date_alignment']
def check_admin_form(self, form):
data_mode = form.get_widget('data_mode').parse()
@ -1760,6 +1768,20 @@ class ItemField(WidgetField, MapOptionsMixin):
def stats(self, values):
return item_items_stats(self, values)
def get_initial_date_alignment(self):
if not self.initial_date_alignment:
return
import wcs.workflows
try:
date = wcs.workflows.template_on_formdata(
None, self.initial_date_alignment, autoescape=False)
except TemplateError as e:
return
try:
return misc.get_as_datetime(date)
except ValueError:
return
def feed_session(self, value, display_value):
real_data_source = data_sources.get_real(self.data_source)
if real_data_source and real_data_source.get('type') == 'jsonp':

View File

@ -18,6 +18,10 @@
</div>
<script>
$(function() {
var ALIGN_DATE = null;
{% with widget.field.get_initial_date_alignment as alignment_date %}
{% if alignment_date %}var ALIGN_DATE = "{{ alignment_date|date:"Y-m-d" }}";{% endif %}
{% endwith %}
var WEEKDAYS = ["{% trans "Sunday" %}", "{% trans "Monday" %}",
"{% trans "Tuesday" %}", "{% trans "Wednesday" %}",
"{% trans "Thursday" %}", "{% trans "Friday" %}",
@ -50,7 +54,8 @@ $(function() {
var options = $select.find('option');
var current_date = null;
var current_day_div = null;
var current_offset = 0;
var current_offset = null;
var alignment_offset = null;
var nb_days = 0;
for (var i=0; i<options.length; i++) {
@ -80,6 +85,17 @@ $(function() {
current_offset = nb_days - 1;
$(option_span).addClass('on');
}
if (current_offset === null && ALIGN_DATE !== null && alignment_offset === null && option_date >= ALIGN_DATE) {
alignment_offset = nb_days - 1;
}
}
if (current_offset === null && ALIGN_DATE !== null && alignment_offset === null) {
alignment_offset = nb_days - 1;
}
if (current_offset === null && alignment_offset !== null) {
current_offset = Math.max(Math.min(alignment_offset, nb_days-column_count), 0);
} else if (current_offset === null) {
current_offset = 0;
}
var go_prev = $('<button class="prev"></button>');
var go_next = $('<button class="next"></button>');