Fix #732 -- Add date and time question types (#732)

* [WIP] add date/time question type

* Date/time questions python classes, types and form handling

* use own timepicker

* Fix argument naming

* Add css and js for datetimepickers

* remove not needed str call

* seperate splitdatetime widget template and fix date/time questions

* change date placeholder to dec 31

* do not show seconds in presale time pickers

* improve codestyle

* add new question types to api doc

* add test

* expand test to datetime question

* add new questiontypes to changelog

remove duplicate parens

* remove timezone from time only question answers

* improve codestyle

* Fix date and time formatting in control question overview
This commit is contained in:
Felix Rindt
2018-01-14 14:29:38 +01:00
committed by Raphael Michel
parent b8c041d0d6
commit 251d62f3c4
21 changed files with 304 additions and 25 deletions

View File

@@ -103,6 +103,7 @@ class SlugWidget(forms.TextInput):
class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
template_name = 'pretixbase/forms/widgets/splitdatetime.html'
def __init__(self, attrs=None, date_format=None, time_format=None):
attrs = attrs or {}
@@ -114,11 +115,10 @@ class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
time_attrs.setdefault('class', 'form-control splitdatetimepart')
date_attrs['class'] += ' datepickerfield'
time_attrs['class'] += ' timepickerfield'
time_attrs['class'] += ' timepickerfield'
df = date_format or get_format('DATE_INPUT_FORMATS')[0]
date_attrs['placeholder'] = now().replace(
year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0
).strftime(df)
tf = time_format or get_format('TIME_INPUT_FORMATS')[0]
time_attrs['placeholder'] = now().replace(
@@ -131,3 +131,39 @@ class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
)
# Skip one hierarchy level
forms.MultiWidget.__init__(self, widgets, attrs)
class DatePickerWidget(forms.DateInput):
def __init__(self, attrs=None, date_format=None):
attrs = attrs or {}
if 'placeholder' in attrs:
del attrs['placeholder']
date_attrs = dict(attrs)
date_attrs.setdefault('class', 'form-control')
date_attrs['class'] += ' datepickerfield'
df = date_format or get_format('DATE_INPUT_FORMATS')[0]
date_attrs['placeholder'] = now().replace(
year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0
).strftime(df)
forms.DateInput.__init__(self, date_attrs, date_format)
class TimePickerWidget(forms.TimeInput):
def __init__(self, attrs=None, time_format=None):
attrs = attrs or {}
if 'placeholder' in attrs:
del attrs['placeholder']
time_attrs = dict(attrs)
time_attrs.setdefault('class', 'form-control')
time_attrs['class'] += ' timepickerfield'
tf = time_format or get_format('TIME_INPUT_FORMATS')[0]
time_attrs['placeholder'] = now().replace(
year=2000, month=12, day=31, hour=18, minute=0, second=0, microsecond=0
).strftime(tf)
forms.TimeInput.__init__(self, time_attrs, time_format)

View File

@@ -9,10 +9,10 @@
<legend>{% trans "General information" %}</legend>
{% bootstrap_field form.name layout="control" %}
{% bootstrap_field form.slug layout="control" %}
{% bootstrap_field form.date_from layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_to layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_from layout="control" %}
{% bootstrap_field form.date_to layout="control" %}
{% bootstrap_field form.location layout="control" %}
{% bootstrap_field form.date_admission layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_admission layout="control" %}
{% bootstrap_field form.currency layout="control" %}
{% bootstrap_field form.is_public layout="control" %}
@@ -51,9 +51,9 @@
</fieldset>
<fieldset>
<legend>{% trans "Timeline" %}</legend>
{% bootstrap_field form.presale_start layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_start layout="control" %}
{% bootstrap_field sform.presale_start_show_date layout="control" %}
{% bootstrap_field form.presale_end layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_end layout="control" %}
{% bootstrap_field sform.show_items_outside_presale_period layout="control" %}
{% bootstrap_field sform.last_order_modification_date layout="control" %}
</fieldset>

View File

@@ -29,8 +29,8 @@
</div>
</div>
</div>
{% bootstrap_field form.date_from layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_to layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_from layout="control" %}
{% bootstrap_field form.date_to layout="control" %}
{% bootstrap_field form.location layout="control" %}
{% bootstrap_field form.currency layout="control" %}
{% bootstrap_field form.tax_rate addon_after="%" layout="control" %}
@@ -43,8 +43,8 @@
{% if form.presale_start %}
<fieldset>
<legend>{% trans "Timeline" %}</legend>
{% bootstrap_field form.presale_start layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_end layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_start layout="control" %}
{% bootstrap_field form.presale_end layout="control" %}
</fieldset>
{% endif %}
{% endblock %}

View File

@@ -23,8 +23,8 @@
</fieldset>
<fieldset>
<legend>{% trans "Availability" %}</legend>
{% bootstrap_field form.available_from layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.available_until layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.available_from layout="control" %}
{% bootstrap_field form.available_until layout="control" %}
{% bootstrap_field form.max_per_order layout="control" %}
{% bootstrap_field form.min_per_order layout="control" %}
{% bootstrap_field form.require_voucher layout="control" %}

View File

@@ -22,10 +22,10 @@
<legend>{% trans "General information" %}</legend>
{% bootstrap_field form.name layout="control" %}
{% bootstrap_field form.active layout="control" %}
{% bootstrap_field form.date_from layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_to layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_from layout="control" %}
{% bootstrap_field form.date_to layout="control" %}
{% bootstrap_field form.location layout="control" %}
{% bootstrap_field form.date_admission layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_admission layout="control" %}
{% bootstrap_field form.frontpage_text layout="control" %}
{% if meta_forms %}
<div class="form-group metadata-group">
@@ -49,8 +49,8 @@
</fieldset>
<fieldset>
<legend>{% trans "Timeline" %}</legend>
{% bootstrap_field form.presale_start layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_end layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_start layout="control" %}
{% bootstrap_field form.presale_end layout="control" %}
</fieldset>
<fieldset>
<legend>{% trans "Quotas" %}</legend>

View File

@@ -38,7 +38,7 @@
</fieldset>
<fieldset>
<legend>{% trans "Voucher details" %}</legend>
{% bootstrap_field form.valid_until layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.valid_until layout="control" %}
{% bootstrap_field form.block_quota layout="control" %}
{% bootstrap_field form.allow_ignore_quota layout="control" %}
<div class="form-group">

View File

@@ -26,7 +26,7 @@
<legend>{% trans "Voucher details" %}</legend>
{% bootstrap_field form.code layout="control" %}
{% bootstrap_field form.max_usages layout="control" %}
{% bootstrap_field form.valid_until layout="control" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.valid_until layout="control" %}
{% bootstrap_field form.block_quota layout="control" %}
{% bootstrap_field form.allow_ignore_quota layout="control" %}
<div class="form-group">

View File

@@ -55,6 +55,20 @@ def get_javascript_format(format_name):
)
def get_format_without_seconds(format_name):
formats = get_format(format_name)
formats_no_seconds = [f for f in formats if '%S' not in f]
return formats_no_seconds[0] if formats_no_seconds else formats[0]
def get_javascript_format_without_seconds(format_name):
f = get_format_without_seconds(format_name)
return toJavascript_re.sub(
lambda x: date_conversion_to_moment[x.group()],
f
)
def get_moment_locale(locale=None):
cur_lang = locale or translation.get_language()
if cur_lang in moment_locales:

View File

@@ -430,6 +430,12 @@ class QuestionView(EventPermissionRequiredMixin, QuestionMixin, ChartContainingV
for a in qs:
a['answer'] = str(a['options__answer'])
del a['options__answer']
elif self.object.type in (Question.TYPE_TIME, Question.TYPE_DATE, Question.TYPE_DATETIME):
qs = qs.order_by('answer')
qs_model = qs
qs = qs.values('answer').annotate(count=Count('id')).order_by('-count')
for a, a_model in zip(qs, qs_model):
a['answer'] = str(a_model)
else:
qs = qs.order_by('answer').values('answer').annotate(count=Count('id')).order_by('-count')