Form UX: Use splitted date/time widgets

This commit is contained in:
Raphael Michel
2017-10-05 09:28:02 +02:00
parent a27f372785
commit 2f252f19c9
15 changed files with 223 additions and 85 deletions

View File

@@ -1,7 +1,9 @@
import os
from django import forms
from django.utils.formats import get_format
from django.utils.html import conditional_escape
from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _
from ...base.forms import I18nModelForm
@@ -98,3 +100,34 @@ class SlugWidget(forms.TextInput):
ctx = super().get_context(name, value, attrs)
ctx['pre'] = self.prefix
return ctx
class SplitDateTimePickerWidget(forms.SplitDateTimeWidget):
def __init__(self, attrs=None, date_format=None, time_format=None):
attrs = attrs or {}
if 'placeholder' in attrs:
del attrs['placeholder']
date_attrs = dict(attrs)
time_attrs = dict(attrs)
date_attrs.setdefault('class', 'form-control splitdatetimepart')
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
).strftime(df)
tf = time_format or get_format('TIME_INPUT_FORMATS')[0]
time_attrs['placeholder'] = now().replace(
year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0
).strftime(tf)
widgets = (
forms.DateInput(attrs=date_attrs, format=date_format),
forms.TimeInput(attrs=time_attrs, format=time_format),
)
# Skip one hierarchy level
forms.MultiWidget.__init__(self, widgets, attrs)

View File

@@ -12,7 +12,9 @@ from pretix.base.forms import I18nModelForm, PlaceholderValidator, SettingsForm
from pretix.base.models import Event, Organizer, TaxRule
from pretix.base.models.event import EventMetaValue
from pretix.base.reldate import RelativeDateField, RelativeDateTimeField
from pretix.control.forms import ExtFileField, SlugWidget
from pretix.control.forms import (
ExtFileField, SlugWidget, SplitDateTimePickerWidget,
)
from pretix.multidomain.urlreverse import build_absolute_uri
from pretix.presale.style import get_fonts
@@ -82,14 +84,18 @@ class EventWizardBasicsForm(I18nModelForm):
'presale_end',
'location',
]
field_classes = {
'date_from': forms.SplitDateTimeField,
'date_to': forms.SplitDateTimeField,
'presale_start': forms.SplitDateTimeField,
'presale_end': forms.SplitDateTimeField,
}
widgets = {
'date_from': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'date_to': forms.DateTimeInput(attrs={'class': 'datetimepicker',
'data-date-after': '#id_basics-date_from'}),
'presale_start': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'presale_end': forms.DateTimeInput(attrs={'class': 'datetimepicker',
'data-date-after': '#id_basics-presale_start'}),
'slug': SlugWidget
'date_from': SplitDateTimePickerWidget(),
'date_to': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_basics-date_from_0'}),
'presale_start': SplitDateTimePickerWidget(),
'presale_end': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_basics-presale_start_0'}),
'slug': SlugWidget,
}
def __init__(self, *args, **kwargs):
@@ -206,14 +212,19 @@ class EventUpdateForm(I18nModelForm):
'presale_end',
'location',
]
field_classes = {
'date_from': forms.SplitDateTimeField,
'date_to': forms.SplitDateTimeField,
'date_admission': forms.SplitDateTimeField,
'presale_start': forms.SplitDateTimeField,
'presale_end': forms.SplitDateTimeField,
}
widgets = {
'date_from': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'date_to': forms.DateTimeInput(attrs={'class': 'datetimepicker', 'data-date-after': '#id_date_from'}),
'date_admission': forms.DateTimeInput(attrs={'class': 'datetimepicker',
'data-date-default': '#id_date_from'}),
'presale_start': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'presale_end': forms.DateTimeInput(attrs={'class': 'datetimepicker',
'data-date-after': '#id_presale_start'}),
'date_from': SplitDateTimePickerWidget(),
'date_to': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_date_from_0'}),
'date_admission': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_date_from_0'}),
'presale_start': SplitDateTimePickerWidget(),
'presale_end': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_presale_start_0'}),
}

View File

@@ -12,6 +12,7 @@ from pretix.base.models import (
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
)
from pretix.base.models.items import ItemAddOn
from pretix.control.forms import SplitDateTimePickerWidget
class CategoryForm(I18nModelForm):
@@ -286,9 +287,13 @@ class ItemUpdateForm(I18nModelForm):
'min_per_order',
'checkin_attention'
]
field_classes = {
'available_from': forms.SplitDateTimeField,
'available_until': forms.SplitDateTimeField,
}
widgets = {
'available_from': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'available_until': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'available_from': SplitDateTimePickerWidget(),
'available_until': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_available_from_0'}),
}

View File

@@ -5,6 +5,7 @@ from i18nfield.forms import I18nInlineFormSet
from pretix.base.forms import I18nModelForm
from pretix.base.models.event import SubEvent, SubEventMetaValue
from pretix.base.models.items import SubEventItem
from pretix.control.forms import SplitDateTimePickerWidget
class SubEventForm(I18nModelForm):
@@ -27,13 +28,19 @@ class SubEventForm(I18nModelForm):
'location',
'frontpage_text'
]
field_classes = {
'date_from': forms.SplitDateTimeField,
'date_to': forms.SplitDateTimeField,
'date_admission': forms.SplitDateTimeField,
'presale_start': forms.SplitDateTimeField,
'presale_end': forms.SplitDateTimeField,
}
widgets = {
'date_from': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'date_to': forms.DateTimeInput(attrs={'class': 'datetimepicker', 'data-date-after': '#id_date_from'}),
'date_admission': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'presale_start': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'presale_end': forms.DateTimeInput(attrs={'class': 'datetimepicker',
'data-date-after': '#id_presale_start'}),
'date_from': SplitDateTimePickerWidget(),
'date_to': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_date_from_0'}),
'date_admission': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_date_from_0'}),
'presale_start': SplitDateTimePickerWidget(),
'presale_end': SplitDateTimePickerWidget(attrs={'data-date-after': '#id_presale_start_0'}),
}

View File

@@ -8,6 +8,7 @@ from django.utils.translation import pgettext_lazy, ugettext_lazy as _
from pretix.base.forms import I18nModelForm
from pretix.base.models import Item, ItemVariation, Quota, Voucher
from pretix.control.forms import SplitDateTimePickerWidget
from pretix.control.signals import voucher_form_validation
@@ -27,8 +28,11 @@ class VoucherForm(I18nModelForm):
'code', 'valid_until', 'block_quota', 'allow_ignore_quota', 'value', 'tag',
'comment', 'max_usages', 'price_mode', 'subevent'
]
field_classes = {
'valid_until': forms.SplitDateTimeField,
}
widgets = {
'valid_until': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'valid_until': SplitDateTimePickerWidget(),
}
def __init__(self, *args, **kwargs):
@@ -218,8 +222,11 @@ class VoucherBulkForm(VoucherForm):
'valid_until', 'block_quota', 'allow_ignore_quota', 'value', 'tag', 'comment',
'max_usages', 'price_mode', 'subevent'
]
field_classes = {
'valid_until': forms.SplitDateTimeField,
}
widgets = {
'valid_until': forms.DateTimeInput(attrs={'class': 'datetimepicker'}),
'valid_until': SplitDateTimePickerWidget(),
}
labels = {
'max_usages': _('Maximum usages per voucher')

View File

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

View File

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

View File

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

View File

@@ -22,10 +22,10 @@
<legend>{% trans "General information" %}</legend>
{% bootstrap_field form.name layout="horizontal" %}
{% bootstrap_field form.active layout="horizontal" %}
{% bootstrap_field form.date_from layout="horizontal" %}
{% bootstrap_field form.date_to layout="horizontal" %}
{% bootstrap_field form.date_from layout="horizontal" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.date_to layout="horizontal" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.location layout="horizontal" %}
{% bootstrap_field form.date_admission layout="horizontal" %}
{% bootstrap_field form.date_admission layout="horizontal" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.frontpage_text layout="horizontal" %}
{% 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="horizontal" %}
{% bootstrap_field form.presale_end layout="horizontal" %}
{% bootstrap_field form.presale_start layout="horizontal" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.presale_end layout="horizontal" horizontal_field_class="col-md-9 splitdatetimerow" %}
</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="horizontal" %}
{% bootstrap_field form.valid_until layout="horizontal" horizontal_field_class="col-md-9 splitdatetimerow" %}
{% bootstrap_field form.block_quota layout="horizontal" %}
{% bootstrap_field form.allow_ignore_quota layout="horizontal" %}
<div class="form-group">

View File

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

View File

@@ -179,11 +179,22 @@ $(function () {
today: 'fa fa-screenshot',
clear: 'fa fa-trash',
close: 'fa fa-remove'
}
},
};
if ($(this).is('[data-is-payment-date]'))
opts["daysOfWeekDisabled"] = JSON.parse($("body").attr("data-payment-weekdays-disabled"));
$(this).datetimepicker(opts);
if ($(this).parent().is('.splitdatetimerow')) {
$(this).on("dp.change", function (ev) {
var $timepicker = $(this).closest(".splitdatetimerow").find(".timepickerfield");
var date = $(this).data('DateTimePicker').date();
if (date === null) {
return;
}
date.set({'hour': 0, 'minute': 0, 'second': 0});
$timepicker.data('DateTimePicker').date(date);
});
}
});
$(".timepickerfield").each(function() {

View File

@@ -190,3 +190,26 @@ pre.mail-preview {
margin-right: 10px;
}
}
.splitdatetimerow {
display: flex;
flex-direction: row;
flex-wrap: wrap;
.help-block {
width: 100%;
}
}
.splitdatetimepart {
width: 50%;
display: inline-block;
&.datepickerfield {
border-bottom-right-radius: 0;
border-top-right-radius: 0;
}
&.timepickerfield {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
border-left: 0;
}
}

View File

@@ -50,18 +50,21 @@ class EventsTest(SoupTest):
def test_settings(self):
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
doc.select("[name=date_to]")[0]['value'] = "2013-12-30 17:00:00"
doc.select("[name=date_to_0]")[0]['value'] = "2013-12-30"
doc.select("[name=date_to_1]")[0]['value'] = "17:00:00"
doc.select("[name=settings-max_items_per_order]")[0]['value'] = "12"
doc = self.post_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug),
extract_form_fields(doc.select('.container-fluid form')[0]))
assert len(doc.select(".alert-success")) > 0
assert doc.select("[name=date_to]")[0]['value'] == "2013-12-30 17:00:00"
assert doc.select("[name=date_to_0]")[0]['value'] == "2013-12-30"
assert doc.select("[name=date_to_1]")[0]['value'] == "17:00:00"
assert doc.select("[name=settings-max_items_per_order]")[0]['value'] == "12"
def test_settings_timezone(self):
doc = self.get_doc('/control/event/%s/%s/settings/' % (self.orga1.slug, self.event1.slug))
doc.select("[name=date_to]")[0]['value'] = "2013-12-30 17:00:00"
doc.select("[name=date_to_0]")[0]['value'] = "2013-12-30"
doc.select("[name=date_to_1]")[0]['value'] = "17:00:00"
doc.select("[name=settings-max_items_per_order]")[0]['value'] = "12"
doc.select("[name=settings-timezone]")[0]['value'] = "Asia/Tokyo"
doc.find('option', {"value": "Asia/Tokyo"})['selected'] = 'selected'
@@ -71,7 +74,8 @@ class EventsTest(SoupTest):
extract_form_fields(doc.select('.container-fluid form')[0]))
assert len(doc.select(".alert-success")) > 0
# date_to should not be changed even though the timezone is changed
assert doc.select("[name=date_to]")[0]['value'] == "2013-12-30 17:00:00"
assert doc.select("[name=date_to_0]")[0]['value'] == "2013-12-30"
assert doc.select("[name=date_to_1]")[0]['value'] == "17:00:00"
assert 'selected' in doc.find('option', {"value": "Asia/Tokyo"}).attrs
assert doc.select("[name=settings-max_items_per_order]")[0]['value'] == "12"
@@ -293,16 +297,20 @@ class EventsTest(SoupTest):
'basics-name_0': '33C3',
'basics-name_1': '33C3',
'basics-slug': '31c3',
'basics-date_from': '2016-12-27 10:00:00',
'basics-date_to': '2016-12-30 19:00:00',
'basics-date_from_0': '2016-12-27',
'basics-date_from_1': '10:00:00',
'basics-date_to_0': '2016-12-30',
'basics-date_to_1': '19:00:00',
'basics-location_0': 'Hamburg',
'basics-location_1': 'Hamburg',
'basics-currency': 'EUR',
'basics-tax_rate': '',
'basics-locale': 'en',
'basics-timezone': 'Europe/Berlin',
'basics-presale_start': '2016-11-01 10:00:00',
'basics-presale_end': '2016-11-30 18:00:00',
'basics-presale_start_0': '2016-11-01',
'basics-presale_start_1': '10:00:00',
'basics-presale_end_0': '2016-11-30',
'basics-presale_end_1': '18:00:00',
})
assert doc.select(".alert-danger")
@@ -325,16 +333,20 @@ class EventsTest(SoupTest):
'basics-name_0': '33C3',
'basics-name_1': '33C3',
'basics-slug': '33c3',
'basics-date_from': '2016-12-27 10:00:00',
'basics-date_to': '2016-12-30 19:00:00',
'basics-date_from_0': '2016-12-27',
'basics-date_from_1': '10:00:00',
'basics-date_to_0': '2016-12-30',
'basics-date_to_1': '19:00:00',
'basics-location_0': 'Hamburg',
'basics-location_1': 'Hamburg',
'basics-currency': 'EUR',
'basics-tax_rate': '19.00',
'basics-locale': 'en',
'basics-timezone': 'Europe/Berlin',
'basics-presale_start': '2016-11-01 10:00:00',
'basics-presale_end': '2016-11-30 18:00:00',
'basics-presale_start_0': '2016-11-01',
'basics-presale_start_1': '10:00:00',
'basics-presale_end_0': '2016-11-30',
'basics-presale_end_1': '18:00:00',
})
assert doc.select("#id_copy-copy_from_event_1")
@@ -379,16 +391,20 @@ class EventsTest(SoupTest):
'basics-name_0': '33C3',
'basics-name_1': '33C3',
'basics-slug': '33c3',
'basics-date_from': '2016-12-27 10:00:00',
'basics-date_to': '2016-12-30 19:00:00',
'basics-date_from_0': '2016-12-27',
'basics-date_from_1': '10:00:00',
'basics-date_to_0': '2016-12-30',
'basics-date_to_1': '19:00:00',
'basics-location_0': 'Hamburg',
'basics-location_1': 'Hamburg',
'basics-currency': 'EUR',
'basics-tax_rate': '',
'basics-locale': 'en',
'basics-timezone': 'Europe/Berlin',
'basics-presale_start': '2016-11-01 10:00:00',
'basics-presale_end': '2016-11-30 18:00:00',
'basics-presale_start_0': '2016-11-01',
'basics-presale_start_1': '10:00:00',
'basics-presale_end_0': '2016-11-30',
'basics-presale_end_1': '18:00:00',
})
self.post_doc('/control/events/add', {
'event_wizard-current_step': 'copy',
@@ -409,15 +425,19 @@ class EventsTest(SoupTest):
'event_wizard-current_step': 'basics',
'basics-name_0': '33C3',
'basics-slug': '33c3',
'basics-date_from': '2016-12-27 10:00:00',
'basics-date_to': '',
'basics-date_from_0': '2016-12-27',
'basics-date_from_1': '10:00:00',
'basics-date_to_0': '',
'basics-date_to_1': '',
'basics-location_0': 'Hamburg',
'basics-currency': 'EUR',
'basics-tax_rate': '',
'basics-locale': 'en',
'basics-timezone': 'UTC',
'basics-presale_start': '',
'basics-presale_end': '',
'basics-presale_start_0': '',
'basics-presale_start_1': '',
'basics-presale_end_0': '',
'basics-presale_end_1': '',
})
self.post_doc('/control/events/add', {
'event_wizard-current_step': 'copy',
@@ -449,15 +469,19 @@ class EventsTest(SoupTest):
'event_wizard-current_step': 'basics',
'basics-name_0': '33C3',
'basics-slug': '33c3',
'basics-date_from': '',
'basics-date_to': '2016-12-30 19:00:00',
'basics-date_from_0': '',
'basics-date_from_1': '',
'basics-date_to_0': '2016-12-30',
'basics-date_to_1': '19:00:00',
'basics-location_0': 'Hamburg',
'basics-currency': 'EUR',
'basics-tax_rate': '',
'basics-locale': 'en',
'basics-timezone': 'Europe/Berlin',
'basics-presale_start': '2016-11-20 11:00:00',
'basics-presale_end': '2016-11-24 18:00:00',
'basics-presale_start_0': '2016-11-01',
'basics-presale_start_1': '10:00:00',
'basics-presale_end_0': '2016-11-30',
'basics-presale_end_1': '18:00:00',
})
assert doc.select(".alert-danger")
@@ -472,15 +496,19 @@ class EventsTest(SoupTest):
'event_wizard-current_step': 'basics',
'basics-name_0': '33C3',
'basics-slug': '31c4',
'basics-date_from': '2016-12-27 10:00:00',
'basics-date_to': '2016-12-30 19:00:00',
'basics-date_from_0': '2016-12-27',
'basics-date_from_1': '10:00:00',
'basics-date_to_0': '2016-12-30',
'basics-date_to_1': '19:00:00',
'basics-location_0': 'Hamburg',
'basics-currency': '$',
'basics-tax_rate': '',
'basics-locale': 'en',
'basics-timezone': 'Europe/Berlin',
'basics-presale_start': '2016-11-01 10:00:00',
'basics-presale_end': '2016-11-30 18:00:00',
'basics-presale_start_0': '2016-11-01',
'basics-presale_start_1': '10:00:00',
'basics-presale_end_0': '2016-11-30',
'basics-presale_end_1': '18:00:00',
})
assert doc.select(".alert-danger")
@@ -495,15 +523,19 @@ class EventsTest(SoupTest):
'event_wizard-current_step': 'basics',
'basics-name_0': '33C3',
'basics-slug': '31c5',
'basics-date_from': '2016-12-27 10:00:00',
'basics-date_to': '2016-12-30 19:00:00',
'basics-date_from_0': '2016-12-27',
'basics-date_from_1': '10:00:00',
'basics-date_to_0': '2016-12-30',
'basics-date_to_1': '19:00:00',
'basics-location_0': 'Hamburg',
'basics-currency': 'ASD',
'basics-tax_rate': '',
'basics-locale': 'en',
'basics-timezone': 'Europe/Berlin',
'basics-presale_start': '2016-11-01 10:00:00',
'basics-presale_end': '2016-11-30 18:00:00',
'basics-presale_start_0': '2016-11-01',
'basics-presale_start_1': '10:00:00',
'basics-presale_end_0': '2016-11-30',
'basics-presale_end_1': '18:00:00',
})
assert doc.select(".alert-danger")
@@ -543,10 +575,13 @@ class SubEventsTest(SoupTest):
doc = self.post_doc('/control/event/ccc/30c3/subevents/add', {
'name_0': 'SE2',
'active': 'on',
'date_from': '2017-07-01 10:00:00',
'date_to': '2017-07-01 12:00:00',
'date_from_0': '2017-07-01',
'date_from_1': '10:00:00',
'date_to_0': '2017-07-01',
'date_to_1': '12:00:00',
'location_0': 'Hamburg',
'presale_start': '2017-06-20 10:00:00',
'presale_start_0': '2017-06-20',
'presale_start_1': '10:00:00',
'quotas-TOTAL_FORMS': '1',
'quotas-INITIAL_FORMS': '0',
'quotas-MIN_NUM_FORMS': '0',
@@ -579,10 +614,13 @@ class SubEventsTest(SoupTest):
doc = self.post_doc('/control/event/ccc/30c3/subevents/%d/' % self.subevent1.pk, {
'name_0': 'SE2',
'active': 'on',
'date_from': '2017-07-01 10:00:00',
'date_to': '2017-07-01 12:00:00',
'date_from_0': '2017-07-01',
'date_from_1': '10:00:00',
'date_to_0': '2017-07-01',
'date_to_1': '12:00:00',
'location_0': 'Hamburg',
'presale_start': '2017-06-20 10:00:00',
'presale_start_0': '2017-06-20',
'presale_start_1': '10:00:00',
'quotas-TOTAL_FORMS': '1',
'quotas-INITIAL_FORMS': '0',
'quotas-MIN_NUM_FORMS': '0',

View File

@@ -194,7 +194,8 @@ class VoucherFormTest(SoupTest):
self._create_voucher({
'itemvar': '%d-%d' % (self.shirt.pk, self.shirt_red.pk),
'block_quota': 'on',
'valid_until': (now() - datetime.timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')
'valid_until_0': (now() - datetime.timedelta(days=3)).strftime('%Y-%m-%d'),
'valid_until_1': (now() - datetime.timedelta(days=3)).strftime('%H:%M:%S')
})
def test_create_blocking_variation_voucher_quota_free(self):
@@ -276,7 +277,8 @@ class VoucherFormTest(SoupTest):
v = self.event.vouchers.create(item=self.ticket, valid_until=now() - datetime.timedelta(days=3),
block_quota=True)
self._change_voucher(v, {
'valid_until': (now() + datetime.timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')
'valid_until_0': (now() + datetime.timedelta(days=3)).strftime('%Y-%m-%d'),
'valid_until_1': (now() + datetime.timedelta(days=3)).strftime('%H:%M:%S')
}, expected_failure=True)
v.refresh_from_db()
assert v.valid_until < now()
@@ -285,7 +287,8 @@ class VoucherFormTest(SoupTest):
v = self.event.vouchers.create(item=self.ticket, valid_until=now() - datetime.timedelta(days=3),
block_quota=True)
self._change_voucher(v, {
'valid_until': (now() + datetime.timedelta(days=3)).strftime('%Y-%m-%d %H:%M:%S')
'valid_until_0': (now() + datetime.timedelta(days=3)).strftime('%Y-%m-%d'),
'valid_until_1': (now() + datetime.timedelta(days=3)).strftime('%H:%M:%S')
})
v.refresh_from_db()
assert v.valid_until > now()