From 3291431518dc96c2203c1163620a95bfc8b51fe7 Mon Sep 17 00:00:00 2001 From: Daniel Grams Date: Wed, 30 Sep 2020 20:31:08 +0200 Subject: [PATCH] Update reference --- app.py | 79 +++--------------------- forms/common.py | 15 +++++ forms/event.py | 51 +--------------- forms/reference.py | 18 ++++++ rights.py | 0 templates/manage/references.html | 1 + templates/reference/update.html | 20 ++++++ user.py | 0 views/__init__.py | 0 views/reference.py | 102 +++++++++++++++++++++++++++++++ 10 files changed, 166 insertions(+), 120 deletions(-) create mode 100644 forms/common.py create mode 100644 forms/reference.py create mode 100644 rights.py create mode 100644 templates/reference/update.html create mode 100644 user.py create mode 100644 views/__init__.py create mode 100644 views/reference.py diff --git a/app.py b/app.py index f33f7c5..f5b3a28 100644 --- a/app.py +++ b/app.py @@ -69,7 +69,7 @@ app.json_encoder = DateTimeEncoder # Setup Flask-Security # Define models -from models import AdminUnitMemberInvitation, Analytics, EventRejectionReason, EventReviewStatus, EventPlace, EventOrganizer, EventCategory, Image, OrgOrAdminUnit, Actor, Place, Location, User, Role, AdminUnit, AdminUnitMember, AdminUnitMemberRole, OrgMember, OrgMemberRole, Organization, AdminUnitOrg, AdminUnitOrgRole, Event, EventDate, EventReference, EventReferenceRequestRejectionReason, EventReferenceRequestReviewStatus +from models import AdminUnitMemberInvitation, Analytics, EventRejectionReason, EventReviewStatus, EventPlace, EventOrganizer, EventCategory, Image, OrgOrAdminUnit, Actor, Place, Location, User, Role, AdminUnit, AdminUnitMember, AdminUnitMemberRole, OrgMember, OrgMemberRole, Organization, AdminUnitOrg, AdminUnitOrgRole, Event, EventDate, EventReference user_datastore = SQLAlchemySessionUserDatastore(db.session, User, Role) security = Security(app, user_datastore) from oauth import blueprint @@ -734,6 +734,9 @@ def can_delete_event(event): def can_reference_event(event): return len(get_admin_units_for_event_reference(event)) > 0 +def can_update_reference(reference): + return has_current_user_permission_for_admin_unit(reference.admin_unit, 'reference:update') + def can_delete_reference(reference): return has_current_user_permission_for_admin_unit(reference.admin_unit, 'reference:delete') @@ -809,6 +812,7 @@ def create_initial_data(): "event:delete", "event:reference", "event_suggestion:read", + "reference:update", "reference:delete"] upsert_admin_unit_member_role('admin', 'Administrator', admin_permissions) @@ -1248,76 +1252,7 @@ def event_review(event_id): dates=dates, event=event) -@app.route('/event//reference', methods=('GET', 'POST')) -def event_reference(event_id): - event = Event.query.get_or_404(event_id) - user_can_reference_event = can_reference_event(event) - - if not user_can_reference_event: - abort(401) - - form = ReferenceEventForm() - form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in get_admin_units_for_event_reference(event)], key=lambda admin_unit: admin_unit[1]) - - if form.validate_on_submit(): - reference = EventReference() - form.populate_obj(reference) - reference.event = event - reference.review_status = EventReferenceRequestReviewStatus.verified - - try: - db.session.add(reference) - db.session.commit() - flash(gettext('Event successfully referenced'), 'success') - return redirect(url_for('event', event_id=event.id)) - except SQLAlchemyError as e: - db.session.rollback() - flash(handleSqlError(e), 'danger') - else: - flash_errors(form) - - return render_template('event/reference.html', - form=form, - event=event) - -@app.route('/manage/admin_unit//references') -@auth_required() -def manage_admin_unit_references(id): - admin_unit = get_admin_unit_for_manage_or_404(id) - references = EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id).order_by(EventReference.created_at).paginate() - - return render_template('manage/references.html', - admin_unit=admin_unit, - references=references.items, - pagination=get_pagination_urls(references, id=id)) - -@app.route('/reference//delete', methods=('GET', 'POST')) -def reference_delete(id): - reference = EventReference.query.get_or_404(id) - - if not can_delete_reference(reference): - abort(401) - - form = DeleteReferenceForm() - - if form.validate_on_submit(): - if form.name.data != reference.event.name: - flash(gettext('Entered name does not match event name'), 'danger') - else: - try: - db.session.delete(reference) - db.session.commit() - flash(gettext('Reference successfully deleted'), 'success') - return redirect(url_for('manage_admin_unit_references', id=reference.admin_unit_id)) - except SQLAlchemyError as e: - db.session.rollback() - flash(handleSqlError(e), 'danger') - else: - flash_errors(form) - - return render_template('reference/delete.html', - form=form, - reference=reference) +from views import reference @app.route("/eventdates") def event_dates(): @@ -1416,7 +1351,7 @@ def api_event_places(id): return jsonify(result) -from forms.event import CreateEventForm, UpdateEventForm, DeleteEventForm, DeleteReferenceForm, EventContactForm, ReviewEventForm, ReferenceEventForm +from forms.event import CreateEventForm, UpdateEventForm, DeleteEventForm, EventContactForm, ReviewEventForm from forms.place import CreatePlaceForm, UpdatePlaceForm from forms.organization import CreateOrganizationForm, UpdateOrganizationForm from forms.organizer import CreateOrganizerForm, UpdateOrganizerForm, DeleteOrganizerForm diff --git a/forms/common.py b/forms/common.py new file mode 100644 index 0000000..f975696 --- /dev/null +++ b/forms/common.py @@ -0,0 +1,15 @@ +from flask_babelex import lazy_gettext + +event_rating_choices = [ + (0,lazy_gettext('0 (Little relevant)')), + (10,'1'), + (20,'2'), + (30,'3'), + (40,'4'), + (50,'5'), + (60,'6'), + (70,'7'), + (80,'8'), + (90,'9'), + (100,lazy_gettext('10 (Highlight)')) + ] diff --git a/forms/event.py b/forms/event.py index de46d24..7ebaa7e 100644 --- a/forms/event.py +++ b/forms/event.py @@ -6,6 +6,7 @@ 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, Place, EventOrganizer, EventRejectionReason, EventReviewStatus +from .common import event_rating_choices from .widgets import CustomDateTimeField class EventPlaceLocationForm(FlaskForm): @@ -67,19 +68,7 @@ class BaseEventForm(FlaskForm): (int(EventAttendanceMode.mixed), lazy_gettext('EventAttendanceMode.mixed'))]) photo_file = FileField(lazy_gettext('Photo'), validators=[FileAllowed(['jpg', 'jpeg', 'png'], lazy_gettext('Images only!'))]) - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=[ - (0,lazy_gettext('0 (Little relevant)')), - (10,'1'), - (20,'2'), - (30,'3'), - (40,'4'), - (50,'5'), - (60,'6'), - (70,'7'), - (80,'8'), - (90,'9'), - (100,lazy_gettext('10 (Highlight)')) - ]) + rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) class CreateEventForm(BaseEventForm): event_place_choice = RadioField(lazy_gettext('Place'), choices=[(1,lazy_gettext('Select existing place')), (2,lazy_gettext('Enter new place'))], default=1, coerce=int) @@ -141,44 +130,10 @@ class ReviewEventForm(FlaskForm): (int(EventRejectionReason.untrustworthy), lazy_gettext('EventRejectionReason.untrustworthy')), (int(EventRejectionReason.illegal), lazy_gettext('EventRejectionReason.illegal'))]) - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=[ - (0,lazy_gettext('0 (Little relevant)')), - (10,'1'), - (20,'2'), - (30,'3'), - (40,'4'), - (50,'5'), - (60,'6'), - (70,'7'), - (80,'8'), - (90,'9'), - (100,lazy_gettext('10 (Highlight)')) - ]) + rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) submit = SubmitField(lazy_gettext("Save review")) -class ReferenceEventForm(FlaskForm): - admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int) - rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=[ - (0,lazy_gettext('0 (Little relevant)')), - (10,'1'), - (20,'2'), - (30,'3'), - (40,'4'), - (50,'5'), - (60,'6'), - (70,'7'), - (80,'8'), - (90,'9'), - (100,lazy_gettext('10 (Highlight)')) - ]) - - submit = SubmitField(lazy_gettext("Save reference")) - -class DeleteReferenceForm(FlaskForm): - submit = SubmitField(lazy_gettext("Delete reference")) - name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) - class FindEventForm(FlaskForm): class Meta: csrf = False diff --git a/forms/reference.py b/forms/reference.py new file mode 100644 index 0000000..89271e3 --- /dev/null +++ b/forms/reference.py @@ -0,0 +1,18 @@ +from flask_babelex import lazy_gettext, gettext +from flask_wtf import FlaskForm +from wtforms import SelectField, StringField, SubmitField +from wtforms.validators import DataRequired +from .common import event_rating_choices + +class CreateEventReferenceForm(FlaskForm): + admin_unit_id = SelectField(lazy_gettext('Admin unit'), validators=[DataRequired()], coerce=int) + rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) + submit = SubmitField(lazy_gettext("Save reference")) + +class UpdateEventReferenceForm(FlaskForm): + rating = SelectField(lazy_gettext('Rating'), default=50, coerce=int, choices=event_rating_choices) + submit = SubmitField(lazy_gettext("Update reference")) + +class DeleteReferenceForm(FlaskForm): + submit = SubmitField(lazy_gettext("Delete reference")) + name = StringField(lazy_gettext('Name'), validators=[DataRequired()]) \ No newline at end of file diff --git a/rights.py b/rights.py new file mode 100644 index 0000000..e69de29 diff --git a/templates/manage/references.html b/templates/manage/references.html index 9c81400..04291b2 100644 --- a/templates/manage/references.html +++ b/templates/manage/references.html @@ -17,6 +17,7 @@ diff --git a/templates/reference/update.html b/templates/reference/update.html new file mode 100644 index 0000000..2ef9d07 --- /dev/null +++ b/templates/reference/update.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} +{% from "_macros.html" import render_field_with_errors, render_field %} +{% block title %} +{{ _('Update reference to event "%(name)s"', name=reference.event.name) }} +{% endblock %} +{% block content %} + +

{{ _('Update reference to event "%(name)s"', name=reference.event.name) }}

+ +
+ {{ form.hidden_tag() }} + + {% if form.rating.choices|length > 1 %} + {{ render_field_with_errors(form.rating) }} + {% endif %} + + {{ render_field(form.submit) }} +
+ +{% endblock %} \ No newline at end of file diff --git a/user.py b/user.py new file mode 100644 index 0000000..e69de29 diff --git a/views/__init__.py b/views/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/views/reference.py b/views/reference.py new file mode 100644 index 0000000..4ce92ac --- /dev/null +++ b/views/reference.py @@ -0,0 +1,102 @@ +from app import app, db, can_update_reference, get_admin_unit_for_manage_or_404, get_pagination_urls, can_reference_event, get_admin_units_for_event_reference, flash_errors, handleSqlError, can_delete_reference +from forms.reference import CreateEventReferenceForm, UpdateEventReferenceForm, DeleteReferenceForm +from flask import render_template, flash, redirect, url_for +from flask_babelex import gettext +from flask_security import auth_required +from models import EventReference, Event + +@app.route('/event//reference', methods=('GET', 'POST')) +def event_reference(event_id): + event = Event.query.get_or_404(event_id) + user_can_reference_event = can_reference_event(event) + + if not user_can_reference_event: + abort(401) + + form = CreateEventReferenceForm() + form.admin_unit_id.choices = sorted([(admin_unit.id, admin_unit.name) for admin_unit in get_admin_units_for_event_reference(event)], key=lambda admin_unit: admin_unit[1]) + + if form.validate_on_submit(): + reference = EventReference() + form.populate_obj(reference) + reference.event = event + + try: + db.session.add(reference) + db.session.commit() + flash(gettext('Event successfully referenced'), 'success') + return redirect(url_for('event', event_id=event.id)) + except SQLAlchemyError as e: + db.session.rollback() + flash(handleSqlError(e), 'danger') + else: + flash_errors(form) + + return render_template('event/reference.html', + form=form, + event=event) + +@app.route('/reference//update', methods=('GET', 'POST')) +def event_reference_update(id): + reference = EventReference.query.get_or_404(id) + + if not can_update_reference(reference): + abort(401) + + form = UpdateEventReferenceForm(obj=reference) + + if form.validate_on_submit(): + form.populate_obj(reference) + + try: + db.session.commit() + flash(gettext('Reference successfully updated'), 'success') + return redirect(url_for('manage_admin_unit_references', id=reference.admin_unit_id)) + except SQLAlchemyError as e: + db.session.rollback() + flash(handleSqlError(e), 'danger') + else: + flash_errors(form) + + return render_template('reference/update.html', + form=form, + reference=reference) + +@app.route('/manage/admin_unit//references') +@auth_required() +def manage_admin_unit_references(id): + admin_unit = get_admin_unit_for_manage_or_404(id) + references = EventReference.query.filter(EventReference.admin_unit_id == admin_unit.id).order_by(EventReference.created_at).paginate() + + return render_template('manage/references.html', + admin_unit=admin_unit, + references=references.items, + pagination=get_pagination_urls(references, id=id)) + +@app.route('/reference//delete', methods=('GET', 'POST')) +def reference_delete(id): + reference = EventReference.query.get_or_404(id) + + if not can_delete_reference(reference): + abort(401) + + form = DeleteReferenceForm() + + if form.validate_on_submit(): + if form.name.data != reference.event.name: + flash(gettext('Entered name does not match event name'), 'danger') + else: + try: + db.session.delete(reference) + db.session.commit() + flash(gettext('Reference successfully deleted'), 'success') + return redirect(url_for('manage_admin_unit_references', id=reference.admin_unit_id)) + except SQLAlchemyError as e: + db.session.rollback() + flash(handleSqlError(e), 'danger') + else: + flash_errors(form) + + return render_template('reference/delete.html', + form=form, + reference=reference) \ No newline at end of file