From 4c292ae402108a87df2f9c5041deeebb585d68af Mon Sep 17 00:00:00 2001 From: Daniel Grams Date: Wed, 28 Oct 2020 08:56:15 +0100 Subject: [PATCH] Event aus Vorschlag erzeugen --- forms/event_suggestion.py | 4 +- forms/widgets.py | 15 ++++++- migrations/versions/00daa8c472ba_.py | 42 +++++++++++++++++++ migrations/versions/50337ecd23db_.py | 42 +++++++++++++++++++ models.py | 7 ++++ templates/_macros.html | 4 +- templates/event_suggestion/review.html | 32 ++++++++------ templates/event_suggestion/review_status.html | 8 +++- views/event.py | 13 ++++++ views/event_suggestion.py | 4 +- 10 files changed, 148 insertions(+), 23 deletions(-) create mode 100644 migrations/versions/00daa8c472ba_.py create mode 100644 migrations/versions/50337ecd23db_.py diff --git a/forms/event_suggestion.py b/forms/event_suggestion.py index 6ad6228..6cd6170 100644 --- a/forms/event_suggestion.py +++ b/forms/event_suggestion.py @@ -33,10 +33,10 @@ class CreateEventSuggestionForm(FlaskForm): for name, field in self._fields.items(): if name == 'photo' and not obj.photo: obj.photo = Image() - if name == 'event_place_id' and isinstance(self.event_place_id.data, str): + if name == 'event_place_id' and self.event_place_id.is_free_text(): obj.event_place_text = self.event_place_id.data obj.event_place_id = None - elif name == 'organizer_id' and isinstance(self.organizer_id.data, str): + elif name == 'organizer_id' and self.organizer_id.is_free_text(): obj.organizer_text = self.organizer_id.data obj.organizer_id = None else: diff --git a/forms/widgets.py b/forms/widgets.py index e8e86ab..61f270b 100644 --- a/forms/widgets.py +++ b/forms/widgets.py @@ -1,8 +1,9 @@ from wtforms import DateTimeField, SelectMultipleField, SelectField from wtforms.widgets import html_params, HTMLString, ListWidget, CheckboxInput +from wtforms.validators import StopValidation import pytz from datetime import datetime -from flask_babelex import to_user_timezone +from flask_babelex import to_user_timezone, gettext from dateutils import berlin_tz class MultiCheckboxField(SelectMultipleField): @@ -91,5 +92,15 @@ def try_to_int(value): class TagSelectField(SelectField): - def __init__(self, label=None, validators=None, coerce=try_to_int, choices=None, validate_choice=False, **kwargs): + def __init__(self, label=None, validators=None, coerce=try_to_int, choices=None, validate_choice=True, **kwargs): super(TagSelectField, self).__init__(label, validators, coerce, choices, validate_choice, **kwargs) + + def pre_validate(self, form): + if self.is_free_text(): + if not self.data or not self.data.strip(): + raise StopValidation(gettext('This field is required')) + else: + super(TagSelectField, self).pre_validate(form) + + def is_free_text(self): + return isinstance(self.data, str) diff --git a/migrations/versions/00daa8c472ba_.py b/migrations/versions/00daa8c472ba_.py new file mode 100644 index 0000000..79f802e --- /dev/null +++ b/migrations/versions/00daa8c472ba_.py @@ -0,0 +1,42 @@ +"""empty message + +Revision ID: 00daa8c472ba +Revises: 50337ecd23db +Create Date: 2020-10-27 20:58:57.392619 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils +import db + + +# revision identifiers, used by Alembic. +revision = '00daa8c472ba' +down_revision = '50337ecd23db' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + #op.drop_table('spatial_ref_sys') + op.drop_constraint('eventsuggestion_event_id_fkey', 'eventsuggestion', type_='foreignkey') + op.create_foreign_key(None, 'eventsuggestion', 'event', ['event_id'], ['id'], ondelete='SET NULL') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'eventsuggestion', type_='foreignkey') + op.create_foreign_key('eventsuggestion_event_id_fkey', 'eventsuggestion', 'event', ['event_id'], ['id']) + op.create_table('spatial_ref_sys', + sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), + sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), + sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), + sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), + sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + ) + # ### end Alembic commands ### diff --git a/migrations/versions/50337ecd23db_.py b/migrations/versions/50337ecd23db_.py new file mode 100644 index 0000000..6e914f4 --- /dev/null +++ b/migrations/versions/50337ecd23db_.py @@ -0,0 +1,42 @@ +"""empty message + +Revision ID: 50337ecd23db +Revises: 6be822396123 +Create Date: 2020-10-27 20:31:42.566357 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils +import db + + +# revision identifiers, used by Alembic. +revision = '50337ecd23db' +down_revision = '6be822396123' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + #op.drop_table('spatial_ref_sys') + op.add_column('eventsuggestion', sa.Column('event_id', sa.Integer(), nullable=True)) + op.create_foreign_key(None, 'eventsuggestion', 'event', ['event_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'eventsuggestion', type_='foreignkey') + op.drop_column('eventsuggestion', 'event_id') + op.create_table('spatial_ref_sys', + sa.Column('srid', sa.INTEGER(), autoincrement=False, nullable=False), + sa.Column('auth_name', sa.VARCHAR(length=256), autoincrement=False, nullable=True), + sa.Column('auth_srid', sa.INTEGER(), autoincrement=False, nullable=True), + sa.Column('srtext', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), + sa.Column('proj4text', sa.VARCHAR(length=2048), autoincrement=False, nullable=True), + sa.CheckConstraint('(srid > 0) AND (srid <= 998999)', name='spatial_ref_sys_srid_check'), + sa.PrimaryKeyConstraint('srid', name='spatial_ref_sys_pkey') + ) + # ### end Alembic commands ### diff --git a/models.py b/models.py index c3cc107..b0bb6fe 100644 --- a/models.py +++ b/models.py @@ -295,6 +295,10 @@ class EventReferenceRequest(db.Model, TrackableMixin): class EventSuggestion(db.Model, TrackableMixin): __tablename__ = 'eventsuggestion' + __table_args__ = ( + CheckConstraint('NOT(event_place_id IS NULL AND event_place_text IS NULL)'), + CheckConstraint('NOT(organizer_id IS NULL AND organizer_text IS NULL)'), + ) id = Column(Integer(), primary_key=True) name = Column(Unicode(255), nullable=False) @@ -323,6 +327,9 @@ class EventSuggestion(db.Model, TrackableMixin): photo_id = db.Column(db.Integer, db.ForeignKey('image.id')) photo = db.relationship('Image', uselist=False) + event_id = db.Column(db.Integer, db.ForeignKey('event.id', ondelete='SET NULL'), nullable=True) + event = db.relationship('Event', uselist=False) + @hybrid_property def verified(self): return self.review_status == EventReviewStatus.verified diff --git a/templates/_macros.html b/templates/_macros.html index 3869819..df23b8a 100644 --- a/templates/_macros.html +++ b/templates/_macros.html @@ -236,8 +236,8 @@ {% endmacro %} {% macro render_event_review_status_pill(event) %} -{% if event.review_status and event.review_status != 2 %} - {{ event.review_status | loc_enum }} +{% if event.review_status %} + {{ event.review_status | loc_enum }} {% endif %} {% endmacro %} diff --git a/templates/event_suggestion/review.html b/templates/event_suggestion/review.html index e2d44a6..df4e967 100644 --- a/templates/event_suggestion/review.html +++ b/templates/event_suggestion/review.html @@ -40,20 +40,26 @@ -
- {{ _('Create event from suggestion') }} -
+{% if event_suggestion.verified and event_suggestion.event_id %} +
+ {{ _('View event') }} +
+{% else %} +
+ {{ _('Create event from suggestion') }} +
-
- oder -
+
+ oder +
-
-
- {{ form.hidden_tag() }} - {{ render_field_with_errors(form.rejection_resaon) }} -

{{ form.submit(class="btn btn-danger")|safe }}

-
-
+
+
+ {{ form.hidden_tag() }} + {{ render_field_with_errors(form.rejection_resaon) }} +

{{ form.submit(class="btn btn-danger")|safe }}

+
+
+{% endif %} {% endblock %} \ No newline at end of file diff --git a/templates/event_suggestion/review_status.html b/templates/event_suggestion/review_status.html index 4d3e8ad..70f34ac 100644 --- a/templates/event_suggestion/review_status.html +++ b/templates/event_suggestion/review_status.html @@ -7,9 +7,11 @@

{{ event_suggestion.name }}

+ {% if not event_suggestion.verified or not event_suggestion.event_id %} + {% endif %}
@@ -17,8 +19,10 @@
{{ render_event_review_status(event_suggestion) }} - {% if event_suggestion.verified %} - {{ _('View') }} + {% if event_suggestion.verified and event_suggestion.event_id %} + {% endif %}
diff --git a/views/event.py b/views/event.py index 827bd90..cdbe3ec 100644 --- a/views/event.py +++ b/views/event.py @@ -13,6 +13,7 @@ from services.event import upsert_event_category, update_event_dates_with_recurr from services.place import get_event_places from sqlalchemy.sql import asc, func from sqlalchemy.exc import SQLAlchemyError +from .event_suggestion import send_event_suggestion_review_status_mail @app.route('/event/') def event(event_id): @@ -39,6 +40,10 @@ def event_create_for_admin_unit_id(id): if event_suggestion_id > 0: event_suggestion = EventSuggestion.query.get_or_404(event_suggestion_id) access_or_401(event_suggestion.admin_unit, 'event:verify') + + if event_suggestion.verified and event_suggestion.event_id: + return redirect(url_for('event_suggestion_review_status', event_suggestion_id=event_suggestion.id)) + prepare_event_form_for_suggestion(form, event_suggestion) if form.is_submitted(): form.process(request.form) @@ -55,9 +60,17 @@ def event_create_for_admin_unit_id(id): event.organizer.admin_unit_id = event.admin_unit_id try: + if event_suggestion: + event_suggestion.event = event + event_suggestion.review_status = EventReviewStatus.verified + event_suggestion.rejection_resaon = None + db.session.add(event) db.session.commit() + if event_suggestion: + send_event_suggestion_review_status_mail(event_suggestion) + flash_message(gettext('Event successfully created'), url_for('event', event_id=event.id)) return redirect(url_for('manage_admin_unit_events', id=event.admin_unit_id)) except SQLAlchemyError as e: diff --git a/views/event_suggestion.py b/views/event_suggestion.py index 1bf0974..559cf7a 100644 --- a/views/event_suggestion.py +++ b/views/event_suggestion.py @@ -24,8 +24,8 @@ def event_suggestion_create_for_admin_unit(au_short_name): places = get_event_places(admin_unit.id) form.event_place_id.choices = [(p.id, p.name) for p in places] - form.organizer_id.choices.insert(0, (0, '')) - form.event_place_id.choices.insert(0, (0, '')) + form.organizer_id.choices.insert(0, ('', '')) + form.event_place_id.choices.insert(0, ('', '')) if form.validate_on_submit(): event_suggestion = EventSuggestion()