diff --git a/forms/event.py b/forms/event.py index 581dae4..00d8bd6 100644 --- a/forms/event.py +++ b/forms/event.py @@ -1,10 +1,12 @@ from flask_babelex import lazy_gettext from flask_wtf import FlaskForm from flask_wtf.file import FileField, FileAllowed -from wtforms import StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField +from wtforms import DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField from wtforms.fields.html5 import DateTimeLocalField from wtforms.validators import DataRequired, Optional +from wtforms.widgets import html_params, HTMLString from models import EventTargetGroupOrigin, EventAttendanceMode, EventStatus +from .widgets import CustomDateTimeField class CreateEventForm(FlaskForm): submit = SubmitField(lazy_gettext("Create event")) @@ -12,9 +14,9 @@ class CreateEventForm(FlaskForm): external_link = StringField(lazy_gettext('Link URL'), validators=[Optional()]) ticket_link = StringField(lazy_gettext('Ticket Link URL'), validators=[Optional()]) description = TextAreaField(lazy_gettext('Description'), validators=[DataRequired()]) - start = DateTimeLocalField(lazy_gettext('Start'), format='%Y-%m-%dT%H:%M', validators=[DataRequired()]) - end = DateTimeLocalField(lazy_gettext('End'), format='%Y-%m-%dT%H:%M', validators=[Optional()]) - previous_start_date = DateTimeLocalField(lazy_gettext('Previous start date'), format='%Y-%m-%dT%H:%M', validators=[Optional()]) + start = CustomDateTimeField(lazy_gettext('Start'), validators=[DataRequired()]) + end = CustomDateTimeField(lazy_gettext('End'), validators=[Optional()]) + previous_start_date = CustomDateTimeField(lazy_gettext('Previous start date'), validators=[Optional()]) tags = StringField(lazy_gettext('Tags'), validators=[Optional()]) place_id = SelectField(lazy_gettext('Place'), validators=[DataRequired()], coerce=int) diff --git a/forms/event_suggestion.py b/forms/event_suggestion.py index 3cb9197..213afad 100644 --- a/forms/event_suggestion.py +++ b/forms/event_suggestion.py @@ -3,12 +3,13 @@ from flask_wtf import FlaskForm from wtforms import StringField, SubmitField, TextAreaField from wtforms.fields.html5 import DateTimeLocalField, EmailField from wtforms.validators import DataRequired, Optional +from .widgets import CustomDateTimeField class CreateEventSuggestionForm(FlaskForm): submit = SubmitField(lazy_gettext("Suggest event")) event_name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) description = TextAreaField(lazy_gettext('Description'), validators=[DataRequired()]) - start = DateTimeLocalField(lazy_gettext('Start'), format='%Y-%m-%dT%H:%M', validators=[DataRequired()]) + start = CustomDateTimeField(lazy_gettext('Start'), validators=[DataRequired()]) external_link = StringField(lazy_gettext('Link URL'), validators=[Optional()]) place_name = StringField(lazy_gettext('Event place'), validators=[DataRequired()]) diff --git a/forms/widgets.py b/forms/widgets.py new file mode 100644 index 0000000..4f52c17 --- /dev/null +++ b/forms/widgets.py @@ -0,0 +1,51 @@ +from wtforms import DateTimeField +from wtforms.widgets import html_params, HTMLString +import pytz +from datetime import datetime + +def create_option_string(count, value): + result = "" + for i in range(count): + selected = " selected" if i == value else "" + result = result + '' % (i, selected, i) + return result + +berlin_tz = pytz.timezone('Europe/Berlin') + +class CustomDateTimeWidget: + def __call__(self, field, **kwargs): + id = kwargs.pop('id', field.id) + date = '' + hour = minute = 0 + if field.data: + date = field.data.strftime("%Y-%m-%d") + hour = field.data.hour + minute = field.data.minute + + date_user_kwargs = dict(kwargs) + date_user_kwargs['class'] = kwargs['class'] + " datepicker" + date_user_kwargs['autocomplete'] = "off" + + date_hidden_params = html_params(name=field.name, id=id + '-date-hidden', value=date, **kwargs) + date_user_params = html_params(name="", id=id + '-date', value=date, **date_user_kwargs) + time_hour_params = html_params(name=field.name, id=id + '-hour', **kwargs) + time_minute_params = html_params(name=field.name, id=id + '-minute', **kwargs) + clear_button_id = id + '-clear-button' + return HTMLString('
:
'.format(date_hidden_params, date_user_params, clear_button_id, time_hour_params, create_option_string(24, hour), time_minute_params, create_option_string(60, minute))) + +class CustomDateTimeField(DateTimeField): + widget = CustomDateTimeWidget() + + def process_formdata(self, valuelist): + if valuelist: + try: + date_str, hour_str, minute_str = valuelist + if not date_str: + self.data = None + return + + date = datetime.strptime(date_str, "%Y-%m-%d") + date_time = datetime(date.year, date.month, date.day, int(hour_str), int(minute_str)) + self.data = berlin_tz.localize(date_time) + except: + raise ValueError('Not a valid datetime value. Looking for YYYY-MM-DD HH:mm.') diff --git a/static/site.css b/static/site.css index 6547c7c..5f9c0ad 100644 --- a/static/site.css +++ b/static/site.css @@ -73,7 +73,7 @@ tr.table-line-through td { width: 1%; } -.ui-autocomplete { +.ui-autocomplete, .ui-datepicker { z-index: 1025 !important; } diff --git a/templates/_macros.html b/templates/_macros.html index 2f01795..beb7e92 100644 --- a/templates/_macros.html +++ b/templates/_macros.html @@ -402,4 +402,25 @@ +{% endmacro %} + +{% macro render_datepicker_js(input_id) %} + { + var picker = $('#{{ input_id }}-date').datepicker({ + dateFormat: "D, dd.mm.yy", + altField: "#{{ input_id }}-date-hidden", + altFormat: "yy-mm-dd" + }); + + var hidden_value = $("#{{ input_id }}-date-hidden").val(); + if (hidden_value) { + picker.datepicker("setDate", moment(hidden_value).toDate()); + } + + $("#{{ input_id }}-clear-button").click(function() { + $('#{{ input_id }}-date').datepicker("setDate", null); + $("#{{ input_id }}-hour").val("00"); + $("#{{ input_id }}-minute").val("00"); + }); + } {% endmacro %} \ No newline at end of file diff --git a/templates/event/create.html b/templates/event/create.html index 4401796..88c60bc 100644 --- a/templates/event/create.html +++ b/templates/event/create.html @@ -1,6 +1,15 @@ {% extends "layout.html" %} -{% from "_macros.html" import render_field_with_errors, render_field %} +{% from "_macros.html" import render_datepicker_js, render_field_with_errors, render_field %} +{% block header %} + +{% endblock %} {% block content %}

{{ _('Create event') }}

diff --git a/templates/event/update.html b/templates/event/update.html index b5993c4..34703f3 100644 --- a/templates/event/update.html +++ b/templates/event/update.html @@ -1,6 +1,15 @@ {% extends "layout.html" %} -{% from "_macros.html" import render_field_with_errors, render_field %} +{% from "_macros.html" import render_datepicker_js, render_field_with_errors, render_field %} +{% block header %} + +{% endblock %} {% block content %}

{{ _('Update event') }}

diff --git a/templates/event_suggestion/create.html b/templates/event_suggestion/create.html index e36df47..8135b47 100644 --- a/templates/event_suggestion/create.html +++ b/templates/event_suggestion/create.html @@ -1,6 +1,13 @@ {% extends "layout.html" %} -{% from "_macros.html" import render_field_with_errors, render_field %} +{% from "_macros.html" import render_datepicker_js, render_field_with_errors, render_field %} +{% block header %} + +{% endblock %} {% block content %}

{{ _('Suggest event') }}

diff --git a/templates/layout.html b/templates/layout.html index b7b092c..ef09acc 100644 --- a/templates/layout.html +++ b/templates/layout.html @@ -33,6 +33,7 @@