diff --git a/forms/event_date.py b/forms/event_date.py new file mode 100644 index 0000000..766dccb --- /dev/null +++ b/forms/event_date.py @@ -0,0 +1,22 @@ +from flask_babelex import lazy_gettext, gettext +from flask_wtf import FlaskForm +from flask_wtf.file import FileField, FileAllowed +from wtforms import SelectMultipleField, FieldList, RadioField, DateTimeField, StringField, SubmitField, TextAreaField, SelectField, BooleanField, IntegerField, FormField +from wtforms.fields.html5 import DateTimeLocalField, EmailField +from wtforms.validators import DataRequired, Optional +from wtforms.widgets import html_params, HTMLString +from models import EventContact, EventPlace, EventTargetGroupOrigin, EventAttendanceMode, EventStatus, Location, EventOrganizer, EventRejectionReason, EventReviewStatus +from .common import event_rating_choices +from .widgets import CustomDateField + +class FindEventDateForm(FlaskForm): + class Meta: + csrf = False + + date_from = CustomDateField(lazy_gettext('From'), validators=[Optional()]) + date_to = CustomDateField(lazy_gettext('to'), validators=[Optional()]) + keyword = StringField(lazy_gettext('Keyword'), validators=[Optional()]) + + category_id = SelectField(lazy_gettext('Category'), validators=[Optional()], coerce=int) + + submit = SubmitField(lazy_gettext("Find")) \ No newline at end of file diff --git a/forms/widgets.py b/forms/widgets.py index 027d349..9a652e5 100644 --- a/forms/widgets.py +++ b/forms/widgets.py @@ -3,6 +3,7 @@ from wtforms.widgets import html_params, HTMLString, ListWidget, CheckboxInput import pytz from datetime import datetime from flask_babelex import to_user_timezone +from dateutils import berlin_tz class MultiCheckboxField(SelectMultipleField): widget = ListWidget(prefix_label=False) @@ -15,8 +16,6 @@ def create_option_string(count, value): 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) @@ -50,3 +49,30 @@ class CustomDateTimeField(DateTimeField): self.data = berlin_tz.localize(date_time) except: raise ValueError('Not a valid datetime value. Looking for YYYY-MM-DD HH:mm.') + +class CustomDateWidget: + def __call__(self, field, **kwargs): + id = kwargs.pop('id', field.id) + date = '' + if field.data: + date_value = to_user_timezone(field.data) + date = date_value.strftime("%Y-%m-%d") + + date_params = html_params(name=field.name, id=id, value=date, **kwargs) + return HTMLString(''.format(date_params)) + +class CustomDateField(DateTimeField): + widget = CustomDateWidget() + + def process_formdata(self, valuelist): + if valuelist: + try: + date_str = valuelist[0] + if not date_str: + self.data = None + return + + date = datetime.strptime(date_str, "%Y-%m-%d") + self.data = berlin_tz.localize(date) + except: + raise ValueError('Not a valid date value. Looking for YYYY-MM-DD.') diff --git a/services/event.py b/services/event.py index 2cee52c..b5459c5 100644 --- a/services/event.py +++ b/services/event.py @@ -27,6 +27,13 @@ def get_event_dates_query(params): like_keyword = '%' + params.keyword + '%' event_filter = and_(event_filter, or_(Event.name.ilike(like_keyword), Event.description.ilike(like_keyword), Event.tags.ilike(like_keyword))) + if params.category_id: + if type(params.category_id) is list: + category_ids = params.category_id + else: + category_ids = [params.category_id] + event_filter = and_(event_filter, Event.category_id.in_(category_ids)) + if params.latitude and params.longitude and params.distance: point = 'POINT({} {})'.format(params.longitude, params.latitude) event_filter = and_(event_filter, func.ST_DistanceSphere(Location.coordinate, point) <= params.distance) diff --git a/services/event_search.py b/services/event_search.py index 45bf8dd..ececf8e 100644 --- a/services/event_search.py +++ b/services/event_search.py @@ -14,6 +14,7 @@ class EventSearchParams(object): self.latitude = None self.longitude = None self.distance = None + self.category_id = None @property def date_from(self): @@ -72,3 +73,6 @@ class EventSearchParams(object): if "distance" in request.args: self.distance = request.args['distance'] + + if "category_id" in request.args: + self.category_id = request.args.getlist('category_id') diff --git a/templates/_macros.html b/templates/_macros.html index b5cb447..ab7ca16 100644 --- a/templates/_macros.html +++ b/templates/_macros.html @@ -573,4 +573,38 @@ $( function() { {{ subfield.label(class="form-check-label") }} {% endfor %} +{% endmacro %} + +{% macro render_event_dates_filter_form(form) %} +
+
+
+ {{ form.date_from.label() }} +
+ {{ form.date_from(class="form-control datepicker")|safe }} +
+ +
+
+ {{ form.date_to.label() }} +
+ {{ form.date_to(class="form-control datepicker")|safe }} +
+ +
+
+ {{ form.category_id.label() }} +
+ {{ form.category_id(class="form-control")|safe }} +
+ +
+
+ {{ form.keyword.label() }} +
+ {{ form.keyword(class="form-control")|safe }} +
+ + +
{% endmacro %} \ No newline at end of file diff --git a/templates/event_date/list.html b/templates/event_date/list.html index 4bc2149..b9249e8 100644 --- a/templates/event_date/list.html +++ b/templates/event_date/list.html @@ -1,5 +1,5 @@ {% extends "layout.html" %} -{% from "_macros.html" import render_pagination, render_event_status_pill, render_place, render_events_sub_menu %} +{% from "_macros.html" import render_event_dates_filter_form, render_pagination, render_event_status_pill, render_place, render_events_sub_menu %} {% block title %} {{ _('Event Dates') }} {% endblock %} @@ -7,31 +7,7 @@

{{ _('Event Dates') }}

-
- -
-
- {{ _('From') }} -
- -
- -
-
- {{ _('to') }} -
- -
- -
-
- {{ _('Keyword') }} -
- -
- - -
+ {{ render_event_dates_filter_form(form) }} {% for date in dates %}
diff --git a/templates/widget/event_date/list.html b/templates/widget/event_date/list.html index bdb29b3..ba401d7 100644 --- a/templates/widget/event_date/list.html +++ b/templates/widget/event_date/list.html @@ -1,5 +1,5 @@ {% extends "layout.html" %} -{% from "_macros.html" import render_pagination, render_event_status_pill, render_event_status_pill, render_place, render_events_sub_menu %} +{% from "_macros.html" import render_event_dates_filter_form, render_pagination, render_event_status_pill, render_event_status_pill, render_place, render_events_sub_menu %} {% block title %} {{ _('Widget') }} {% endblock %} @@ -10,31 +10,7 @@ {% endblock %} {% block content %} -
- -
-
- {{ _('From') }} -
- -
- -
-
- {{ _('to') }} -
- -
- -
-
- {{ _('Keyword') }} -
- -
- - -
+ {{ render_event_dates_filter_form(form) }} {% for date in dates %} diff --git a/views/event.py b/views/event.py index a1c92bd..74ec54c 100644 --- a/views/event.py +++ b/views/event.py @@ -158,9 +158,12 @@ def event_create_base(admin_unit, organizer_id=0): flash_errors(form) return render_template('event/create.html', form=form) +def get_event_category_choices(): + return sorted([(c.id, get_event_category_name(c)) for c in EventCategory.query.all()], key=lambda category: category[1]) + def prepare_event_form(form, admin_unit): form.organizer_id.choices = [(o.id, o.name) for o in EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name))] - form.category_id.choices = sorted([(c.id, get_event_category_name(c)) for c in EventCategory.query.all()], key=lambda category: category[1]) + form.category_id.choices = get_event_category_choices() if form.organizer_id.data: places = get_event_places(form.organizer_id.data) diff --git a/views/event_date.py b/views/event_date.py index 8be157f..e49f0b6 100644 --- a/views/event_date.py +++ b/views/event_date.py @@ -10,16 +10,28 @@ import json from jsonld import get_sd_for_event_date, DateTimeEncoder from services.event_search import EventSearchParams from services.event import get_event_dates_query +from forms.event_date import FindEventDateForm +from .event import get_event_category_choices + +def prepare_event_date_form(form): + form.category_id.choices = get_event_category_choices() + form.category_id.choices.insert(0, (0, '')) @app.route("/eventdates") def event_dates(): params = EventSearchParams() params.set_default_date_range() - params.load_from_request() + + form = FindEventDateForm(formdata=request.args, obj=params) + prepare_event_date_form(form) + + if form.validate(): + form.populate_obj(params) dates = get_event_dates_query(params).paginate() return render_template('event_date/list.html', + form=form, params=params, dates=dates.items, pagination=get_pagination_urls(dates)) diff --git a/views/widget.py b/views/widget.py index dd03694..e58812e 100644 --- a/views/widget.py +++ b/views/widget.py @@ -9,6 +9,8 @@ from services.event_search import EventSearchParams from .utils import get_pagination_urls import json from jsonld import DateTimeEncoder, get_sd_for_event_date +from forms.event_date import FindEventDateForm +from .event_date import prepare_event_date_form @app.route("//widget/eventdates") def widget_event_dates(au_short_name): @@ -16,12 +18,18 @@ def widget_event_dates(au_short_name): params = EventSearchParams() params.set_default_date_range() - params.load_from_request() - params.admin_unit_id = admin_unit.id + form = FindEventDateForm(formdata=request.args, obj=params) + prepare_event_date_form(form) + + if form.validate(): + form.populate_obj(params) + + params.admin_unit_id = admin_unit.id dates = get_event_dates_query(params).paginate() return render_template('widget/event_date/list.html', + form=form, params=params, dates=dates.items, pagination=get_pagination_urls(dates, au_short_name=au_short_name))