From bc923ebde3ee2115e3ecca0b0501c80522b766d0 Mon Sep 17 00:00:00 2001 From: Daniel Grams Date: Mon, 25 Jan 2021 12:56:00 +0100 Subject: [PATCH] New flag AdminUnit.incoming_reference_requests_allowed #91 --- migrations/versions/b1a6e7630185_.py | 33 ++++++++++++++ project/access.py | 8 +++- project/forms/admin.py | 13 +++++- project/models.py | 1 + project/templates/admin/admin_units.html | 5 ++ .../templates/admin/update_admin_unit.html | 25 ++++++++++ .../translations/de/LC_MESSAGES/messages.mo | Bin 24138 -> 24490 bytes .../translations/de/LC_MESSAGES/messages.po | 43 ++++++++++++++---- project/views/admin.py | 34 +++++++++++++- tests/seeder.py | 1 + 10 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 migrations/versions/b1a6e7630185_.py create mode 100644 project/templates/admin/update_admin_unit.html diff --git a/migrations/versions/b1a6e7630185_.py b/migrations/versions/b1a6e7630185_.py new file mode 100644 index 0000000..2c136f8 --- /dev/null +++ b/migrations/versions/b1a6e7630185_.py @@ -0,0 +1,33 @@ +"""empty message + +Revision ID: b1a6e7630185 +Revises: 35a6577b6af8 +Create Date: 2021-01-25 11:38:36.483434 + +""" +from alembic import op +import sqlalchemy as sa +import sqlalchemy_utils +from project import dbtypes + + +# revision identifiers, used by Alembic. +revision = "b1a6e7630185" +down_revision = "35a6577b6af8" +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "adminunit", + sa.Column("incoming_reference_requests_allowed", sa.Boolean(), nullable=True), + ) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("adminunit", "incoming_reference_requests_allowed") + # ### end Alembic commands ### diff --git a/project/access.py b/project/access.py index 9baa8f1..6835864 100644 --- a/project/access.py +++ b/project/access.py @@ -4,6 +4,7 @@ from flask_security.utils import FsPermNeed from flask_principal import Permission from project.models import AdminUnitMember, AdminUnit from project.services.admin_unit import get_member_for_admin_unit_by_user_id +from sqlalchemy import and_ def has_current_user_permission(permission): @@ -101,7 +102,12 @@ def can_request_event_reference(event): def get_admin_units_for_event_reference_request(event): - return AdminUnit.query.filter(AdminUnit.id != event.admin_unit_id).all() + return AdminUnit.query.filter( + and_( + AdminUnit.id != event.admin_unit_id, + AdminUnit.incoming_reference_requests_allowed, + ) + ).all() def admin_units_the_current_user_is_member_of(): diff --git a/project/forms/admin.py b/project/forms/admin.py index 931ec2d..bef93ad 100644 --- a/project/forms/admin.py +++ b/project/forms/admin.py @@ -1,6 +1,6 @@ from flask_wtf import FlaskForm from flask_babelex import lazy_gettext -from wtforms import TextAreaField, SubmitField +from wtforms import TextAreaField, SubmitField, BooleanField from wtforms.validators import Optional from project.forms.widgets import MultiCheckboxField @@ -17,3 +17,14 @@ class AdminSettingsForm(FlaskForm): class UpdateUserForm(FlaskForm): roles = MultiCheckboxField(lazy_gettext("Roles")) submit = SubmitField(lazy_gettext("Update user")) + + +class UpdateAdminUnitForm(FlaskForm): + incoming_reference_requests_allowed = BooleanField( + lazy_gettext("Incoming reference requests allowed"), + description=lazy_gettext( + "If set, other admin units can ask this admin unit to reference their event." + ), + validators=[Optional()], + ) + submit = SubmitField(lazy_gettext("Update admin unit")) diff --git a/project/models.py b/project/models.py index 9a5660d..e6692f9 100644 --- a/project/models.py +++ b/project/models.py @@ -210,6 +210,7 @@ class AdminUnit(db.Model, TrackableMixin): widget_background_color = Column(ColorType) widget_primary_color = Column(ColorType) widget_link_color = Column(ColorType) + incoming_reference_requests_allowed = Column(Boolean()) @listens_for(AdminUnit, "before_insert") diff --git a/project/templates/admin/admin_units.html b/project/templates/admin/admin_units.html index 41436fe..04a7370 100644 --- a/project/templates/admin/admin_units.html +++ b/project/templates/admin/admin_units.html @@ -1,4 +1,5 @@ {% extends "layout.html" %} +{% from "_macros.html" import render_pagination %} {% block title %} {{ _('Admin Units') }} {% endblock %} @@ -16,16 +17,20 @@ {{ _('Name') }} + {% for admin_unit in admin_units %} {{ admin_unit.name }} + {{ _('Edit') }} {% endfor %} +
{{ render_pagination(pagination) }}
+ {% endblock %} \ No newline at end of file diff --git a/project/templates/admin/update_admin_unit.html b/project/templates/admin/update_admin_unit.html new file mode 100644 index 0000000..07b8730 --- /dev/null +++ b/project/templates/admin/update_admin_unit.html @@ -0,0 +1,25 @@ +{% extends "layout.html" %} +{% from "_macros.html" import render_field_with_errors, render_field %} +{% block title %} +{{ _('Update admin unit') }} +{% endblock %} +{% block content %} + +

{{ _('Update admin unit') }}

+ +
+ {{ form.hidden_tag() }} + +
+
+ {{ admin_unit.name }} +
+
+ {{ render_field_with_errors(form.incoming_reference_requests_allowed, style="width: fit-content; flex: initial;") }} +
+
+ + {{ render_field(form.submit) }} +
+ +{% endblock %} diff --git a/project/translations/de/LC_MESSAGES/messages.mo b/project/translations/de/LC_MESSAGES/messages.mo index 77be93a54dcd7f1a7c16529159df187bd1bdf160..ee999972d4b45044f67fdbceaa5702826caf60aa 100644 GIT binary patch delta 5926 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 Y%MWFCsaECZ>y*_SU#C21eE;D81K|X^v;Y7A delta 5644 zcmYM%33QKF8prV~dmKJOdeI#lb}fm*(= zq5?`Ce@51Ft`S}fQ}35QJ7b;WuPfsRL);OJ#-kX4Ut%CuV-Vi9{kme+P!+7pSAW zj_kqtHS{)=fV!WC8lQze#<(do6xs8rg_fd@n-x3^#ns*Vk;2j)+4>1o%G$H?*xRFZH#1q&8zr)tpm`YN=4=Pi$PyxM&+Tm(c zMmC@}@D?g#dr%7=Mv~yppyuB;LleCtPWI8zjT}@;$D$VeEm9V)6!m~zsBy=!Eq;yK zc`Sv~4s$RAXQPU88)^e5%^#3Gx#rEh+Q>ovI^TGHsz?^27I@v;)^R1{1{SB3&eaMD=?w>T2$_sX*%DjuJfuB(+4o~(b zCZNWrnjKN8&bIzQ>yJjwe+sqWLez7Xp#m$#V7>nvXejcn=#L*^09K$DI%$4s*RNv% z*KeX8l$qjuUs z{{d>@5MB{2TnBYO9*NB*nSJc~EY$e&{xXJ}|=S5P~xMitj>)R}&d z5%?2^V{JZnN?||$| zU2!iefO}XMe=tLMRdiJGsMMyT0?#({P)F0x9Ab_{J#PYPBU3P%_1$b5kywHR>DD4& zS@$t=I_{=fpAS4umy5k{9_HeHla}%*XN)XScf{QH&93QE-F)}P~*;ZBL7Os zk6cjdYj6sNQjvOZXQ3iqfC_Xm>NQ=Cs+n!5e|nW6n|IfcGI8~}sD3``tQTMou17z- zgfG`}uCfdH*N$gqdH=fgVHEvEs0_S{ig*hufH$qb8oxSI+$bTi`U@h(j=>ySKn-)N3~d zTi{CMEA94}m8if&dpruj=i1TGS$0JgO%7`3Lof~}B5Sz$sA}GWd}G{6Y=93i9%Hk; z`E60D?|}_*Ch7>6qf)-gT!(Rb|2NanneRo_!g172FQZa^5A_zfo|bCV^%PVJGf*4o zj!JbNDzL$*`%j?)oQK-rD%A5gVW5x39vWKUeN-`hij(jhk}a3TIppCyq;TB<+=cg0 zJKREPYXgUHGM>R}z2Bdsc61Guk#A7dUxPY= zK%&vk8e=1DiOnz%o8wgTB~%UUM$Nl`I=VZkfE(wNe=XEL-&-IHbw=5!RQ5sD!V{?P z!6ekeGp#=#HEuC#-b(AQwfkF814M zrfM1K+n;&fDi#ddw6^%r3P*H@s%t;S${4HdvfpIz9FigXuh!hY0*L*`M`0>@Dk z&zoP_{eNRH*KeVU>|4~hz&>8_MW8?ZR8-(;sJF|PK|?8g92GzzPQnSO2Y!T_cmfsJ zX;k%}$Jg*Gsz?_+?)`H5J7&_qfqZ*hQeUsw#$Xfr8&S3J52T2F?mUebxUjUJw?Jrt zx6=qr50`&#kih92fqQ+fBO}v6+(^X?Sb{^#Qi%@~>LS^6pYWz{u_vIu;VihVA z_XpYg|BwqxVenvY$I+;X38)k|L)}kD?H~)a(?O^&=NwdxEWndumkFM>LSR%G<+8m@Cqt`2dMcCpYTjW?X(-} zDDzPp>yO%4p^rukjqz9y=VBC=pi;ITo8vC*hi6d>HZAl5>WUNT&%mj83X?H&nD-$Y zgDT?bs3Um=bMbZS`zmRu=&CUSgNA!G5NozYMcx~=lL6KriQ35obE@4hHlIcnWeG;( z8`uU9U@N?do%R05jNre)T*IEe!9%FC zKZjcIKI#a5wtllQ-gDD%3D7hBqyr;KYasg QmDevwi7X#JW~l%F0pv$&cK`qY diff --git a/project/translations/de/LC_MESSAGES/messages.po b/project/translations/de/LC_MESSAGES/messages.po index 298f193..dfe7864 100644 --- a/project/translations/de/LC_MESSAGES/messages.po +++ b/project/translations/de/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2021-01-25 10:17+0100\n" +"POT-Creation-Date: 2021-01-25 11:56+0100\n" "PO-Revision-Date: 2020-06-07 18:51+0200\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -158,6 +158,21 @@ msgstr "Rollen" msgid "Update user" msgstr "Nutzer aktualisieren" +#: project/forms/admin.py:24 +msgid "Incoming reference requests allowed" +msgstr "Eingehende Empfehlungsanfragen erlauben" + +#: project/forms/admin.py:25 +msgid "" +"If set, other admin units can ask this admin unit to reference their " +"event." +msgstr "Wenn gesetzt, können andere Organisationen diese Organisation bitten, deren Veranstaltungen zu empfehlen." + +#: project/forms/admin.py:30 project/templates/admin/update_admin_unit.html:4 +#: project/templates/admin/update_admin_unit.html:8 +msgid "Update admin unit" +msgstr "Organisation aktualisieren" + #: project/forms/admin_unit.py:17 project/forms/event.py:32 #: project/forms/event_place.py:17 project/forms/organizer.py:16 msgid "Street" @@ -194,7 +209,7 @@ msgstr "Längengrad" #: project/forms/event_suggestion.py:25 project/forms/organizer.py:29 #: project/forms/organizer.py:56 project/forms/reference.py:39 #: project/forms/reference_request.py:21 project/templates/_macros.html:115 -#: project/templates/admin/admin_units.html:18 +#: project/templates/admin/admin_units.html:19 #: project/templates/event_place/list.html:19 project/templates/profile.html:19 #: project/templates/profile.html:39 msgid "Name" @@ -1099,7 +1114,7 @@ msgid "Profile" msgstr "Profil" #: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9 -#: project/templates/admin/admin_units.html:9 +#: project/templates/admin/admin_units.html:10 #: project/templates/admin/users.html:10 project/templates/layout.html:130 msgid "Admin" msgstr "Administration" @@ -1182,8 +1197,8 @@ msgid "Invitations" msgstr "Einladungen" #: project/templates/admin/admin.html:19 -#: project/templates/admin/admin_units.html:3 -#: project/templates/admin/admin_units.html:10 +#: project/templates/admin/admin_units.html:4 +#: project/templates/admin/admin_units.html:11 #: project/templates/manage/admin_units.html:3 #: project/templates/manage/admin_units.html:16 #: project/templates/profile.html:34 @@ -1195,6 +1210,7 @@ msgstr "Organisationen" msgid "Users" msgstr "Benutzer" +#: project/templates/admin/admin_units.html:27 #: project/templates/admin/users.html:27 #: project/templates/manage/events.html:27 #: project/templates/manage/members.html:35 @@ -1485,11 +1501,16 @@ msgstr "Optionale Details" msgid "Preview" msgstr "Vorschau" -#: project/views/admin.py:41 project/views/manage.py:247 +#: project/views/admin.py:45 +#, fuzzy +msgid "Admin unit successfully updated" +msgstr "Organisation erfolgreich aktualisiert" + +#: project/views/admin.py:68 project/views/manage.py:247 msgid "Settings successfully updated" msgstr "Einstellungen erfolgreich aktualisiert" -#: project/views/admin.py:76 +#: project/views/admin.py:103 msgid "User successfully updated" msgstr "Nutzer erfolgreich aktualisiert" @@ -1638,14 +1659,16 @@ msgstr "Empfehlungsanfrage erfolgreich aktualisiert" msgid "" "An entry with the entered values ​​already exists. Duplicate entries are " "not allowed." -msgstr "Ein Eintrag mit den eingegebenen Werten existiert bereits. Doppelte Einträge sind nicht erlaubt." +msgstr "" +"Ein Eintrag mit den eingegebenen Werten existiert bereits. Doppelte " +"Einträge sind nicht erlaubt." -#: project/views/utils.py:61 +#: project/views/utils.py:63 #, python-format msgid "Error in the %s field - %s" msgstr "Fehler im Feld %s: %s" -#: project/views/utils.py:69 +#: project/views/utils.py:71 msgid "Show" msgstr "Anzeigen" diff --git a/project/views/admin.py b/project/views/admin.py index ff787b0..76f2ed3 100644 --- a/project/views/admin.py +++ b/project/views/admin.py @@ -3,7 +3,7 @@ from project.models import AdminUnit, User, Role from flask import render_template, flash, url_for, redirect from flask_babelex import gettext from flask_security import roles_required -from project.forms.admin import AdminSettingsForm, UpdateUserForm +from project.forms.admin import AdminSettingsForm, UpdateUserForm, UpdateAdminUnitForm from project.services.admin import upsert_settings from project.services.user import set_roles_for_user from project.views.utils import ( @@ -24,7 +24,37 @@ def admin(): @app.route("/admin/admin_units") @roles_required("admin") def admin_admin_units(): - return render_template("admin/admin_units.html", admin_units=AdminUnit.query.all()) + admin_units = AdminUnit.query.order_by(func.lower(AdminUnit.name)).paginate() + return render_template( + "admin/admin_units.html", + admin_units=admin_units.items, + pagination=get_pagination_urls(admin_units), + ) + + +@app.route("/admin/admin_unit//update", methods=("GET", "POST")) +@roles_required("admin") +def admin_admin_unit_update(id): + admin_unit = AdminUnit.query.get_or_404(id) + + form = UpdateAdminUnitForm(obj=admin_unit) + + if form.validate_on_submit(): + form.populate_obj(admin_unit) + + try: + db.session.commit() + flash(gettext("Admin unit successfully updated"), "success") + return redirect(url_for("admin_admin_units")) + except SQLAlchemyError as e: + db.session.rollback() + flash(handleSqlError(e), "danger") + else: + flash_errors(form) + + return render_template( + "admin/update_admin_unit.html", admin_unit=admin_unit, form=form + ) @app.route("/admin/settings", methods=("GET", "POST")) diff --git a/tests/seeder.py b/tests/seeder.py index 1702bc9..080b73b 100644 --- a/tests/seeder.py +++ b/tests/seeder.py @@ -50,6 +50,7 @@ class Seeder(object): admin_unit = AdminUnit() admin_unit.name = name admin_unit.short_name = name.lower().replace(" ", "") + admin_unit.incoming_reference_requests_allowed = True insert_admin_unit_for_user(admin_unit, user) self._db.session.commit() admin_unit_id = admin_unit.id