CustomDateTimeWidget

This commit is contained in:
Daniel Grams 2020-07-09 16:59:35 +02:00
parent 38ebac81fe
commit 77814390de
9 changed files with 110 additions and 9 deletions

View File

@ -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)

View File

@ -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()])

51
forms/widgets.py Normal file
View File

@ -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 + '<option value="%02d"%s>%02d</option>' % (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('<input type="hidden" {}/><div class="input-group-prepend mt-1"><input type="text" {}/><button class="btn btn-outline-secondary" type="button" id="{}"><i class="fa fa-times"></i></button></div><div class="mx-2"></div><div class="input-group-append mt-1"><select {}>{}</select><span class="input-group-text">:</span><select {}>{}</select></div>'.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.')

View File

@ -73,7 +73,7 @@ tr.table-line-through td {
width: 1%;
}
.ui-autocomplete {
.ui-autocomplete, .ui-datepicker {
z-index: 1025 !important;
}

View File

@ -402,4 +402,25 @@
<input id="location_search" type="text" class="form-control" placeholder="{{ _('Search location on Google') }}" autocomplete="on" runat="server" />
</div>
</div>
{% 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 %}

View File

@ -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 %}
<script>
$( function() {
{{ render_datepicker_js('start') }}
{{ render_datepicker_js('end') }}
{{ render_datepicker_js('previous_start_date') }}
});
</script>
{% endblock %}
{% block content %}
<h1>{{ _('Create event') }}</h1>

View File

@ -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 %}
<script>
$( function() {
{{ render_datepicker_js('start') }}
{{ render_datepicker_js('end') }}
{{ render_datepicker_js('previous_start_date') }}
});
</script>
{% endblock %}
{% block content %}
<h1>{{ _('Update event') }}</h1>

View File

@ -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 %}
<script>
$( function() {
{{ render_datepicker_js('start') }}
});
</script>
{% endblock %}
{% block content %}
<h1>{{ _('Suggest event') }}</h1>

View File

@ -33,6 +33,7 @@
<script>
moment.locale('de')
$.datepicker.setDefaults($.datepicker.regional["de"]);
$( function() {
$('[data-toggle="tooltip"]').tooltip();