diff --git a/.flake8 b/.flake8 index 7663589..e44c8df 100644 --- a/.flake8 +++ b/.flake8 @@ -1,5 +1,5 @@ [flake8] -extend-ignore = E501, E203 +extend-ignore = E501, E203, E711 exclude = .git, .github, diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1db9fdf..e8f251d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -35,6 +35,19 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 + redis: + # Docker Hub image + image: redis + # Set health checks to wait until redis has started + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + ports: + # Maps port 6379 on service container to the host + - 6379:6379 + steps: - name: Check out repository code uses: actions/checkout@v2 @@ -53,6 +66,7 @@ jobs: run: pytest --cov=project --splits 4 --group ${{ matrix.group }} env: TEST_DATABASE_URL: postgresql://postgres:postgres@localhost/eventcally_tests + TEST_REDIS_URL: redis://redis:6379 - name: Upload coverage uses: actions/upload-artifact@v2 diff --git a/messages.pot b/messages.pot index 3306229..0240f75 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2023-03-24 21:24+0100\n" +"POT-Creation-Date: 2023-03-28 17:04+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -208,7 +208,7 @@ msgstr "" msgid "Legal notice" msgstr "" -#: project/forms/admin.py:13 project/templates/_macros.html:1395 +#: project/forms/admin.py:13 project/templates/_macros.html:1397 #: project/templates/layout.html:302 #: project/templates/widget/event_suggestion/create.html:204 #: project/views/admin_unit.py:73 project/views/root.py:69 @@ -225,6 +225,7 @@ msgid "Start page" msgstr "" #: project/forms/admin.py:17 project/forms/oauth2_client.py:24 +#: project/forms/user.py:13 msgid "Save" msgstr "" @@ -285,7 +286,7 @@ msgstr "" msgid "Update organization" msgstr "" -#: project/forms/admin.py:63 +#: project/forms/admin.py:63 project/forms/admin.py:70 msgid "Recipient" msgstr "" @@ -293,6 +294,22 @@ msgstr "" msgid "Send test mail synchronously" msgstr "" +#: project/forms/admin.py:72 project/forms/admin.py:78 +msgid "Test recipient" +msgstr "" + +#: project/forms/admin.py:73 +msgid "All users with enabled newsletter setting" +msgstr "" + +#: project/forms/admin.py:79 +msgid "Message" +msgstr "" + +#: project/forms/admin.py:80 +msgid "Send newsletter" +msgstr "" + #: project/forms/admin_unit.py:15 project/forms/event_place.py:12 #: project/forms/organizer.py:12 msgid "Street" @@ -342,7 +359,7 @@ msgstr "" msgid "The short name is used to create a unique identifier for your events" msgstr "" -#: project/forms/admin_unit.py:41 project/templates/_macros.html:1531 +#: project/forms/admin_unit.py:41 project/templates/_macros.html:1533 msgid "Short name must contain only letters numbers or underscore" msgstr "" @@ -355,20 +372,21 @@ msgstr "" #: project/forms/admin_unit.py:48 project/forms/admin_unit_member.py:11 #: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28 #: project/forms/event.py:107 project/forms/event_suggestion.py:38 -#: project/forms/organizer.py:27 project/templates/_macros.html:235 -#: project/templates/_macros.html:1491 project/templates/admin/admin.html:27 +#: project/forms/organizer.py:27 project/templates/_macros.html:237 +#: project/templates/_macros.html:1493 project/templates/admin/admin.html:27 +#: project/templates/admin/email.html:4 project/templates/admin/email.html:66 #: project/templates/admin/users.html:19 msgid "Email" msgstr "" #: project/forms/admin_unit.py:49 project/forms/event.py:108 #: project/forms/event_suggestion.py:31 project/forms/organizer.py:28 -#: project/templates/_macros.html:288 +#: project/templates/_macros.html:290 msgid "Phone" msgstr "" #: project/forms/admin_unit.py:50 project/forms/event.py:109 -#: project/forms/organizer.py:29 project/templates/_macros.html:296 +#: project/forms/organizer.py:29 project/templates/_macros.html:298 msgid "Fax" msgstr "" @@ -566,16 +584,16 @@ msgstr "" msgid "All-day" msgstr "" -#: project/forms/event.py:54 project/templates/_macros.html:1711 +#: project/forms/event.py:54 project/templates/_macros.html:1713 #: project/templates/widget/event_suggestion/create.html:240 msgid "Recurring event" msgstr "" -#: project/forms/event.py:61 project/templates/_macros.html:1252 +#: project/forms/event.py:61 project/templates/_macros.html:1254 msgid "The start must be before the end." msgstr "" -#: project/forms/event.py:67 project/templates/_macros.html:1269 +#: project/forms/event.py:67 project/templates/_macros.html:1271 msgid "An event can last a maximum of 14 days." msgstr "" @@ -609,7 +627,7 @@ msgstr "" msgid "Enter a link where tickets can be purchased." msgstr "" -#: project/forms/event.py:136 project/templates/_macros.html:217 +#: project/forms/event.py:136 project/templates/_macros.html:219 msgid "Tags" msgstr "" @@ -659,7 +677,7 @@ msgstr "" msgid "If the participants needs to register for the event." msgstr "" -#: project/forms/event.py:170 project/templates/_macros.html:249 +#: project/forms/event.py:170 project/templates/_macros.html:251 #: project/templates/layout.html:110 msgid "Booked up" msgstr "" @@ -739,8 +757,8 @@ msgid "" " course it works without it." msgstr "" -#: project/forms/event.py:242 project/templates/_macros.html:396 -#: project/templates/_macros.html:559 +#: project/forms/event.py:242 project/templates/_macros.html:398 +#: project/templates/_macros.html:561 msgid "Previous start date" msgstr "" @@ -786,7 +804,7 @@ msgstr "" #: project/forms/event.py:286 project/forms/event.py:295 #: project/forms/event.py:368 project/forms/event_suggestion.py:50 -#: project/templates/_macros.html:436 project/templates/_macros.html:599 +#: project/templates/_macros.html:438 project/templates/_macros.html:601 #: project/templates/event/create.html:284 #: project/templates/event/update.html:166 #: project/templates/event_place/create.html:31 @@ -805,8 +823,8 @@ msgstr "" #: project/forms/event.py:302 project/forms/event.py:311 #: project/forms/event.py:376 project/forms/event.py:439 -#: project/forms/event_suggestion.py:60 project/templates/_macros.html:473 -#: project/templates/_macros.html:636 project/templates/event/create.html:253 +#: project/forms/event_suggestion.py:60 project/templates/_macros.html:475 +#: project/templates/_macros.html:638 project/templates/event/create.html:253 #: project/templates/event/update.html:156 #: project/templates/organizer/create.html:27 #: project/templates/organizer/delete.html:13 @@ -891,7 +909,7 @@ msgstr "" msgid "PublicStatus.published" msgstr "" -#: project/forms/event.py:402 project/templates/_macros.html:255 +#: project/forms/event.py:402 project/templates/_macros.html:257 msgid "PublicStatus.draft" msgstr "" @@ -904,7 +922,7 @@ msgstr "" msgid "Update event" msgstr "" -#: project/forms/event.py:423 project/templates/_macros.html:1224 +#: project/forms/event.py:423 project/templates/_macros.html:1226 #: project/templates/event/actions.html:66 #: project/templates/event/delete.html:6 msgid "Delete event" @@ -925,7 +943,7 @@ msgid "Keyword" msgstr "" #: project/forms/event.py:436 project/forms/event_date.py:21 -#: project/forms/planing.py:19 project/templates/_macros.html:369 +#: project/forms/planing.py:19 project/templates/_macros.html:371 msgid "Category" msgstr "" @@ -934,7 +952,7 @@ msgid "Find events" msgstr "" #: project/forms/event_date.py:24 project/forms/planing.py:22 -#: project/templates/_macros.html:303 +#: project/templates/_macros.html:305 #: project/templates/admin_unit/create.html:38 #: project/templates/admin_unit/update.html:39 #: project/templates/event_place/create.html:40 @@ -1077,7 +1095,7 @@ msgid "Weekdays" msgstr "" #: project/forms/reference.py:11 project/forms/reference_request.py:16 -#: project/templates/_macros.html:489 project/templates/_macros.html:652 +#: project/templates/_macros.html:491 project/templates/_macros.html:654 #: project/templates/admin_unit/create.html:28 #: project/templates/admin_unit/update.html:29 #: project/templates/layout.html:242 @@ -1105,7 +1123,7 @@ msgstr "" msgid "Delete request" msgstr "" -#: project/forms/reference_request.py:28 project/templates/_macros.html:1407 +#: project/forms/reference_request.py:28 project/templates/_macros.html:1409 #: project/templates/event_suggestion/review_status.html:18 #: project/templates/reference_request/review_status.html:12 msgid "Review status" @@ -1163,43 +1181,53 @@ msgstr "" msgid "Deny" msgstr "" +#: project/forms/user.py:9 project/templates/admin/admin.html:31 +#: project/templates/admin/newsletter.html:4 +#: project/templates/admin/newsletter.html:93 +msgid "Newsletter" +msgstr "" + +#: project/forms/user.py:10 +msgid "Information about new features and improvements." +msgstr "" + #: project/forms/widgets.py:154 msgid "This field is required." msgstr "" -#: project/templates/_macros.html:147 +#: project/templates/_macros.html:149 msgid "Show on Google Maps" msgstr "" -#: project/templates/_macros.html:226 +#: project/templates/_macros.html:228 msgid "Link" msgstr "" -#: project/templates/_macros.html:282 +#: project/templates/_macros.html:284 msgid "Verified" msgstr "" -#: project/templates/_macros.html:346 -#, python-format -msgid "Created at %(created_at)s by %(created_by)s." -msgstr "" - #: project/templates/_macros.html:348 #, python-format -msgid "Created at %(created_at)s." +msgid "Created at %(created_at)s by %(created_by)s." msgstr "" -#: project/templates/_macros.html:353 +#: project/templates/_macros.html:350 #, python-format -msgid "Last updated at %(updated_at)s by %(updated_by)s." +msgid "Created at %(created_at)s." msgstr "" #: project/templates/_macros.html:355 #, python-format +msgid "Last updated at %(updated_at)s by %(updated_by)s." +msgstr "" + +#: project/templates/_macros.html:357 +#, python-format msgid "Last updated at %(updated_at)s." msgstr "" -#: project/templates/_macros.html:385 project/templates/_macros.html:555 +#: project/templates/_macros.html:387 project/templates/_macros.html:557 #: project/templates/event/actions.html:25 #: project/templates/event/create.html:230 #: project/templates/event/update.html:122 @@ -1207,63 +1235,63 @@ msgstr "" msgid "Event" msgstr "" -#: project/templates/_macros.html:391 project/templates/_macros.html:920 +#: project/templates/_macros.html:393 project/templates/_macros.html:922 msgid "Date" msgstr "" -#: project/templates/_macros.html:418 project/templates/_macros.html:577 -#: project/templates/_macros.html:1476 project/templates/event/actions.html:51 +#: project/templates/_macros.html:420 project/templates/_macros.html:579 +#: project/templates/_macros.html:1478 project/templates/event/actions.html:51 msgid "Share" msgstr "" -#: project/templates/_macros.html:422 project/templates/_macros.html:581 -#: project/templates/_macros.html:1506 +#: project/templates/_macros.html:424 project/templates/_macros.html:583 +#: project/templates/_macros.html:1508 msgid "Add to calendar" msgstr "" -#: project/templates/_macros.html:430 project/templates/_macros.html:592 +#: project/templates/_macros.html:432 project/templates/_macros.html:594 #: project/templates/event/report.html:4 msgid "Report event" msgstr "" -#: project/templates/_macros.html:457 project/templates/_macros.html:618 +#: project/templates/_macros.html:459 project/templates/_macros.html:620 msgid "Show directions" msgstr "" -#: project/templates/_macros.html:462 project/templates/_macros.html:623 +#: project/templates/_macros.html:464 project/templates/_macros.html:625 msgid "The event takes place online." msgstr "" -#: project/templates/_macros.html:464 project/templates/_macros.html:625 +#: project/templates/_macros.html:466 project/templates/_macros.html:627 msgid "The event takes place both offline and online." msgstr "" -#: project/templates/_macros.html:585 project/templates/layout.html:168 +#: project/templates/_macros.html:587 project/templates/layout.html:168 #: project/templates/user/favorite_events.html:4 msgid "Favorite events" msgstr "" -#: project/templates/_macros.html:679 project/templates/event_date/list.html:5 +#: project/templates/_macros.html:681 project/templates/event_date/list.html:5 #: project/templates/event_date/list.html:299 #: project/templates/reference_request/review.html:32 msgid "Event Dates" msgstr "" -#: project/templates/_macros.html:771 +#: project/templates/_macros.html:773 msgid "Search location on Google" msgstr "" -#: project/templates/_macros.html:837 +#: project/templates/_macros.html:839 #, python-format msgid "%(count)d event dates" msgstr "" -#: project/templates/_macros.html:860 project/templates/_macros.html:862 +#: project/templates/_macros.html:862 project/templates/_macros.html:864 #: project/templates/event_date/list.html:321 msgid "First" msgstr "" -#: project/templates/_macros.html:865 project/templates/_macros.html:867 +#: project/templates/_macros.html:867 project/templates/_macros.html:869 #: project/templates/event_date/list.html:322 #: project/templates/widget/event_suggestion/create.html:193 #: project/templates/widget/event_suggestion/create.html:218 @@ -1274,12 +1302,12 @@ msgstr "" msgid "Previous" msgstr "" -#: project/templates/_macros.html:869 +#: project/templates/_macros.html:871 #, python-format msgid "Page %(page)d of %(pages)d (%(total)d total)" msgstr "" -#: project/templates/_macros.html:871 project/templates/_macros.html:873 +#: project/templates/_macros.html:873 project/templates/_macros.html:875 #: project/templates/event_date/list.html:324 #: project/templates/widget/event_suggestion/create.html:194 #: project/templates/widget/event_suggestion/create.html:219 @@ -1289,88 +1317,88 @@ msgstr "" msgid "Next" msgstr "" -#: project/templates/_macros.html:876 project/templates/_macros.html:878 +#: project/templates/_macros.html:878 project/templates/_macros.html:880 #: project/templates/event_date/list.html:325 msgid "Last" msgstr "" -#: project/templates/_macros.html:943 +#: project/templates/_macros.html:945 msgid "Radius" msgstr "" -#: project/templates/_macros.html:1153 +#: project/templates/_macros.html:1155 msgid "Edit image" msgstr "" -#: project/templates/_macros.html:1174 +#: project/templates/_macros.html:1176 msgid "Close" msgstr "" -#: project/templates/_macros.html:1175 +#: project/templates/_macros.html:1177 msgid "Okay" msgstr "" -#: project/templates/_macros.html:1187 +#: project/templates/_macros.html:1189 msgid "Choose image file" msgstr "" -#: project/templates/_macros.html:1223 project/templates/event/actions.html:65 +#: project/templates/_macros.html:1225 project/templates/event/actions.html:65 #: project/templates/event/delete.html:12 msgid "Edit event" msgstr "" -#: project/templates/_macros.html:1226 project/templates/manage/events.html:66 +#: project/templates/_macros.html:1228 project/templates/manage/events.html:66 msgid "More" msgstr "" -#: project/templates/_macros.html:1273 +#: project/templates/_macros.html:1275 msgid "Please enter a valid time, between 00:00 and 23:59." msgstr "" -#: project/templates/_macros.html:1301 +#: project/templates/_macros.html:1303 #, python-format msgid "Just use %(term)s" msgstr "" -#: project/templates/_macros.html:1367 +#: project/templates/_macros.html:1369 msgid "Event suggestion" msgstr "" -#: project/templates/_macros.html:1485 +#: project/templates/_macros.html:1487 msgid "Link copied" msgstr "" -#: project/templates/_macros.html:1485 +#: project/templates/_macros.html:1487 msgid "Copy link" msgstr "" -#: project/templates/_macros.html:1514 +#: project/templates/_macros.html:1516 msgid "Google calendar" msgstr "" -#: project/templates/_macros.html:1515 +#: project/templates/_macros.html:1517 msgid "Apple calendar" msgstr "" -#: project/templates/_macros.html:1516 +#: project/templates/_macros.html:1518 msgid "Yahoo calendar" msgstr "" -#: project/templates/_macros.html:1517 +#: project/templates/_macros.html:1519 msgid "Other calendar" msgstr "" -#: project/templates/_macros.html:1712 +#: project/templates/_macros.html:1714 msgid "Remove event date" msgstr "" -#: project/templates/_macros.html:1741 project/templates/event/create.html:176 +#: project/templates/_macros.html:1743 project/templates/event/create.html:176 #: project/templates/event/update.html:99 #: project/templates/widget/event_suggestion/create.html:129 msgid "Enter organizer" msgstr "" -#: project/templates/_macros.html:1765 +#: project/templates/_macros.html:1767 msgid "Enter list name" msgstr "" @@ -1414,6 +1442,7 @@ msgstr "" #: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9 #: project/templates/admin/admin_units.html:10 #: project/templates/admin/email.html:65 +#: project/templates/admin/newsletter.html:92 #: project/templates/admin/settings.html:10 #: project/templates/admin/users.html:10 project/templates/layout.html:171 msgid "Admin" @@ -1501,8 +1530,7 @@ msgstr "" msgid "Organization invitations" msgstr "" -#: project/templates/admin/admin.html:15 project/templates/admin/email.html:4 -#: project/templates/admin/email.html:66 +#: project/templates/admin/admin.html:15 #: project/templates/admin/settings.html:4 #: project/templates/admin/settings.html:11 #: project/templates/admin_unit/update.html:6 @@ -1528,18 +1556,24 @@ msgid "Switch organization" msgstr "" #: project/templates/developer/read.html:4 project/templates/layout.html:310 -#: project/templates/profile.html:29 +#: project/templates/profile.html:33 msgid "Developer" msgstr "" #: project/templates/profile.html:23 +#: project/templates/user/notifications.html:4 +#: project/templates/user/notifications.html:8 +msgid "Notifications" +msgstr "" + +#: project/templates/profile.html:27 msgid "Applications" msgstr "" #: project/templates/oauth2_client/list.html:4 #: project/templates/oauth2_client/list.html:11 #: project/templates/oauth2_client/read.html:11 -#: project/templates/profile.html:33 +#: project/templates/profile.html:37 msgid "OAuth2 clients" msgstr "" @@ -1560,7 +1594,7 @@ msgstr "" msgid "Edit" msgstr "" -#: project/templates/admin/email.html:47 project/views/admin.py:119 +#: project/templates/admin/email.html:47 project/views/admin.py:122 msgid "Mail sent successfully" msgstr "" @@ -1572,6 +1606,10 @@ msgstr "" msgid "Send test mail asynchronously" msgstr "" +#: project/templates/admin/newsletter.html:59 +msgid "Mails sent successfully" +msgstr "" + #: project/templates/admin_unit/create.html:58 #: project/templates/admin_unit/update.html:59 #: project/templates/event/create.html:347 @@ -1626,6 +1664,10 @@ msgstr "" msgid "this is a message from %(site_name)s." msgstr "" +#: project/templates/email/newsletter.html:7 +msgid "Notification settings" +msgstr "" + #: project/templates/email/organization_invitation_accepted_notice.html:4 #, python-format msgid "" @@ -2035,20 +2077,26 @@ msgstr "" msgid "Preview" msgstr "" -#: project/views/admin.py:55 +#: project/views/admin.py:58 msgid "Organization successfully updated" msgstr "" -#: project/views/admin.py:79 project/views/manage.py:361 +#: project/views/admin.py:82 project/views/manage.py:361 +#: project/views/user.py:27 msgid "Settings successfully updated" msgstr "" -#: project/views/admin.py:108 +#: project/views/admin.py:111 #, python-format msgid "Test mail from %(site_name)s" msgstr "" -#: project/views/admin.py:152 +#: project/views/admin.py:150 +#, python-format +msgid "Newsletter from %(site_name)s" +msgstr "" + +#: project/views/admin.py:200 msgid "User successfully updated" msgstr "" diff --git a/migrations/versions/47c334ba5b86_.py b/migrations/versions/47c334ba5b86_.py new file mode 100644 index 0000000..db18259 --- /dev/null +++ b/migrations/versions/47c334ba5b86_.py @@ -0,0 +1,31 @@ +"""empty message + +Revision ID: 47c334ba5b86 +Revises: 3f77c8693ae3 +Create Date: 2023-03-26 23:03:44.678745 + +""" +import sqlalchemy as sa +import sqlalchemy_utils +from alembic import op + +from project import dbtypes + +# revision identifiers, used by Alembic. +revision = "47c334ba5b86" +down_revision = "3f77c8693ae3" +branch_labels = None +depends_on = None + + +def upgrade(): + op.add_column( + "user", + sa.Column( + "newsletter_enabled", sa.Boolean(), server_default="1", nullable=False + ), + ) + + +def downgrade(): + op.drop_column("user", "newsletter_enabled") diff --git a/project/base_tasks.py b/project/base_tasks.py index 0280a39..cbdf04c 100644 --- a/project/base_tasks.py +++ b/project/base_tasks.py @@ -7,6 +7,6 @@ from project.views.utils import send_mail base=getattr(app, "celery_http_task_cls"), priority=0, ) -def send_mail_task(recipient, subject, template): +def send_mail_task(recipient, subject, template, **context): with force_locale(): - send_mail(recipient, subject, template) + send_mail(recipient, subject, template, **context) diff --git a/project/forms/admin.py b/project/forms/admin.py index e7251f3..2899fa8 100644 --- a/project/forms/admin.py +++ b/project/forms/admin.py @@ -1,6 +1,6 @@ from flask_babelex import lazy_gettext from flask_wtf import FlaskForm -from wtforms import BooleanField, SubmitField, TextAreaField +from wtforms import BooleanField, RadioField, SubmitField, TextAreaField from wtforms.fields.html5 import EmailField from wtforms.validators import DataRequired, Optional @@ -63,3 +63,18 @@ class AdminTestEmailForm(FlaskForm): recipient = EmailField(lazy_gettext("Recipient"), validators=[DataRequired()]) submit = SubmitField(lazy_gettext("Send test mail synchronously")) + + +class AdminNewsletterForm(FlaskForm): + recipient_choice = RadioField( + lazy_gettext("Recipient"), + choices=[ + (1, lazy_gettext("Test recipient")), + (2, lazy_gettext("All users with enabled newsletter setting")), + ], + default=1, + coerce=int, + ) + test_recipient = EmailField(lazy_gettext("Test recipient"), validators=[Optional()]) + message = TextAreaField(lazy_gettext("Message"), validators=[DataRequired()]) + submit = SubmitField(lazy_gettext("Send newsletter")) diff --git a/project/forms/user.py b/project/forms/user.py new file mode 100644 index 0000000..cd56c5b --- /dev/null +++ b/project/forms/user.py @@ -0,0 +1,13 @@ +from flask_babelex import lazy_gettext +from flask_wtf import FlaskForm +from wtforms import BooleanField, SubmitField +from wtforms.validators import Optional + + +class NotificationForm(FlaskForm): + newsletter_enabled = BooleanField( + lazy_gettext("Newsletter"), + description=lazy_gettext("Information about new features and improvements."), + validators=[Optional()], + ) + submit = SubmitField(lazy_gettext("Save")) diff --git a/project/models.py b/project/models.py index c361b2e..0d19a43 100644 --- a/project/models.py +++ b/project/models.py @@ -199,6 +199,14 @@ class User(db.Model, UserMixin): secondary="user_favoriteevents", backref=backref("favored_by_users", lazy=True), ) + newsletter_enabled = deferred( + Column( + Boolean(), + nullable=True, + default=True, + server_default="1", + ) + ) def get_user_id(self): return self.id diff --git a/project/templates/_macros.html b/project/templates/_macros.html index d535743..8b3140c 100644 --- a/project/templates/_macros.html +++ b/project/templates/_macros.html @@ -70,6 +70,8 @@ {% endfor %} + {% elif 'ri' in kwargs and kwargs['ri'] == 'radio' %} + {{ render_radio_buttons(field) }} {% else %} {% if 'class' in kwargs %} {% set _dummy=kwargs.pop('class') %} diff --git a/project/templates/admin/admin.html b/project/templates/admin/admin.html index 024b0e1..adff26d 100644 --- a/project/templates/admin/admin.html +++ b/project/templates/admin/admin.html @@ -27,6 +27,10 @@ {{ _('Email') }} + + {{ _('Newsletter') }} + + {% endblock %} \ No newline at end of file diff --git a/project/templates/admin/email.html b/project/templates/admin/email.html index 88ad55c..3b3297c 100644 --- a/project/templates/admin/email.html +++ b/project/templates/admin/email.html @@ -1,7 +1,7 @@ {% extends "layout.html" %} {% from "_macros.html" import render_field, render_field_with_errors %} {%- block title -%} -{{ _('Settings') }} +{{ _('Email') }} {%- endblock -%} {% block header %} +{% endblock %} +{% block content %} + + + +
+ {{ form.hidden_tag() }} +
+ {{ render_field_with_errors(form.recipient_choice, ri='radio') }} +
+
+ {{ render_field_with_errors(form.test_recipient) }} +
+ {{ render_field_with_errors(form.message) }} + {{ render_field(form.submit) }} +
+ +

+

+ + +

+ + + +{% endblock %} \ No newline at end of file diff --git a/project/templates/email/newsletter.html b/project/templates/email/newsletter.html new file mode 100644 index 0000000..fdedd25 --- /dev/null +++ b/project/templates/email/newsletter.html @@ -0,0 +1,9 @@ +{% extends "email/layout.html" %} +{% block content %} +

+ {{ message|safe }} +

+

+ {{ _('Notification settings') }} +

+{% endblock %} \ No newline at end of file diff --git a/project/templates/email/newsletter.txt b/project/templates/email/newsletter.txt new file mode 100644 index 0000000..5e788d3 --- /dev/null +++ b/project/templates/email/newsletter.txt @@ -0,0 +1,3 @@ +{{ message|safe }} + +{{ _('Notification settings') }}: {{ url_for('user_notifications', _external=True) }} diff --git a/project/templates/profile.html b/project/templates/profile.html index 4472bcb..c864fcb 100644 --- a/project/templates/profile.html +++ b/project/templates/profile.html @@ -19,6 +19,10 @@

{{ _('Settings') }}

+ + {{ _('Notifications') }} + + {{ _('Applications') }} diff --git a/project/templates/user/notifications.html b/project/templates/user/notifications.html new file mode 100644 index 0000000..04fdc24 --- /dev/null +++ b/project/templates/user/notifications.html @@ -0,0 +1,16 @@ +{% extends "layout.html" %} +{% from "_macros.html" import render_field_with_errors, render_field %} +{%- block title -%} +{{ _('Notifications') }} +{%- endblock -%} +{% block content %} + +

{{ _('Notifications') }}

+ +
+ {{ form.hidden_tag() }} + {{ render_field_with_errors(form.newsletter_enabled, ri="switch") }} + {{ render_field(form.submit) }} +
+ +{% endblock %} diff --git a/project/translations/de/LC_MESSAGES/messages.mo b/project/translations/de/LC_MESSAGES/messages.mo index 0f63114..43c9722 100644 Binary files a/project/translations/de/LC_MESSAGES/messages.mo and b/project/translations/de/LC_MESSAGES/messages.mo differ diff --git a/project/translations/de/LC_MESSAGES/messages.po b/project/translations/de/LC_MESSAGES/messages.po index a94fbfa..9ff9549 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: 2023-03-24 21:24+0100\n" +"POT-Creation-Date: 2023-03-28 17:04+0200\n" "PO-Revision-Date: 2020-06-07 18:51+0200\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -209,7 +209,7 @@ msgstr "Nutzungsbedingungen" msgid "Legal notice" msgstr "Impressum" -#: project/forms/admin.py:13 project/templates/_macros.html:1395 +#: project/forms/admin.py:13 project/templates/_macros.html:1397 #: project/templates/layout.html:302 #: project/templates/widget/event_suggestion/create.html:204 #: project/views/admin_unit.py:73 project/views/root.py:69 @@ -226,6 +226,7 @@ msgid "Start page" msgstr "Startseite" #: project/forms/admin.py:17 project/forms/oauth2_client.py:24 +#: project/forms/user.py:13 msgid "Save" msgstr "Speichern" @@ -294,7 +295,7 @@ msgstr "" msgid "Update organization" msgstr "Organisation aktualisieren" -#: project/forms/admin.py:63 +#: project/forms/admin.py:63 project/forms/admin.py:70 msgid "Recipient" msgstr "Empfänger" @@ -302,6 +303,22 @@ msgstr "Empfänger" msgid "Send test mail synchronously" msgstr "Test-Mail synchron senden" +#: project/forms/admin.py:72 project/forms/admin.py:78 +msgid "Test recipient" +msgstr "Test-Empfänger" + +#: project/forms/admin.py:73 +msgid "All users with enabled newsletter setting" +msgstr "Alle Nutzer mit aktiviertem Newsletter" + +#: project/forms/admin.py:79 +msgid "Message" +msgstr "Nachricht" + +#: project/forms/admin.py:80 +msgid "Send newsletter" +msgstr "Newsletter senden" + #: project/forms/admin_unit.py:15 project/forms/event_place.py:12 #: project/forms/organizer.py:12 msgid "Street" @@ -354,7 +371,7 @@ msgstr "" "eindeutig zu identifizieren. Der Kurzname darf nur Buchstaben, Nummern " "und Unterstriche enthalten." -#: project/forms/admin_unit.py:41 project/templates/_macros.html:1531 +#: project/forms/admin_unit.py:41 project/templates/_macros.html:1533 msgid "Short name must contain only letters numbers or underscore" msgstr "Der Kurzname darf nur Buchstaben, Nummern und Unterstriche enthalten" @@ -367,20 +384,21 @@ msgstr "Link URL" #: project/forms/admin_unit.py:48 project/forms/admin_unit_member.py:11 #: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28 #: project/forms/event.py:107 project/forms/event_suggestion.py:38 -#: project/forms/organizer.py:27 project/templates/_macros.html:235 -#: project/templates/_macros.html:1491 project/templates/admin/admin.html:27 +#: project/forms/organizer.py:27 project/templates/_macros.html:237 +#: project/templates/_macros.html:1493 project/templates/admin/admin.html:27 +#: project/templates/admin/email.html:4 project/templates/admin/email.html:66 #: project/templates/admin/users.html:19 msgid "Email" msgstr "Email" #: project/forms/admin_unit.py:49 project/forms/event.py:108 #: project/forms/event_suggestion.py:31 project/forms/organizer.py:28 -#: project/templates/_macros.html:288 +#: project/templates/_macros.html:290 msgid "Phone" msgstr "Telefon" #: project/forms/admin_unit.py:50 project/forms/event.py:109 -#: project/forms/organizer.py:29 project/templates/_macros.html:296 +#: project/forms/organizer.py:29 project/templates/_macros.html:298 msgid "Fax" msgstr "Fax" @@ -589,16 +607,16 @@ msgstr "Gib an, wann der Termin endet. Ein Termin darf maximal 14 Tage dauern." msgid "All-day" msgstr "Ganztägig" -#: project/forms/event.py:54 project/templates/_macros.html:1711 +#: project/forms/event.py:54 project/templates/_macros.html:1713 #: project/templates/widget/event_suggestion/create.html:240 msgid "Recurring event" msgstr "Serientermin" -#: project/forms/event.py:61 project/templates/_macros.html:1252 +#: project/forms/event.py:61 project/templates/_macros.html:1254 msgid "The start must be before the end." msgstr "Der Start muss vor dem Ende sein." -#: project/forms/event.py:67 project/templates/_macros.html:1269 +#: project/forms/event.py:67 project/templates/_macros.html:1271 msgid "An event can last a maximum of 14 days." msgstr "Eine Veranstaltung darf maximal 14 Tage dauern." @@ -634,7 +652,7 @@ msgstr "Ticket Link" msgid "Enter a link where tickets can be purchased." msgstr "Gib einen Link ein, über den Tickets gekauft werden können." -#: project/forms/event.py:136 project/templates/_macros.html:217 +#: project/forms/event.py:136 project/templates/_macros.html:219 msgid "Tags" msgstr "Stichworte" @@ -687,7 +705,7 @@ msgstr "Anmeldung erforderlich" msgid "If the participants needs to register for the event." msgstr "Wenn sich die Teilnehmer für die Veranstaltung anmelden müssen." -#: project/forms/event.py:170 project/templates/_macros.html:249 +#: project/forms/event.py:170 project/templates/_macros.html:251 #: project/templates/layout.html:110 msgid "Booked up" msgstr "Ausgebucht" @@ -773,8 +791,8 @@ msgstr "" "Wir empfehlen dir, ein Foto für die Veranstaltung hochzuladen. Es macht " "schon deutlich mehr her, aber es geht natürlich auch ohne." -#: project/forms/event.py:242 project/templates/_macros.html:396 -#: project/templates/_macros.html:559 +#: project/forms/event.py:242 project/templates/_macros.html:398 +#: project/templates/_macros.html:561 msgid "Previous start date" msgstr "Vorheriges Startdatum" @@ -826,7 +844,7 @@ msgstr "Ungültiger Mitveranstalter." #: project/forms/event.py:286 project/forms/event.py:295 #: project/forms/event.py:368 project/forms/event_suggestion.py:50 -#: project/templates/_macros.html:436 project/templates/_macros.html:599 +#: project/templates/_macros.html:438 project/templates/_macros.html:601 #: project/templates/event/create.html:284 #: project/templates/event/update.html:166 #: project/templates/event_place/create.html:31 @@ -845,8 +863,8 @@ msgstr "Neuen Ort eingeben" #: project/forms/event.py:302 project/forms/event.py:311 #: project/forms/event.py:376 project/forms/event.py:439 -#: project/forms/event_suggestion.py:60 project/templates/_macros.html:473 -#: project/templates/_macros.html:636 project/templates/event/create.html:253 +#: project/forms/event_suggestion.py:60 project/templates/_macros.html:475 +#: project/templates/_macros.html:638 project/templates/event/create.html:253 #: project/templates/event/update.html:156 #: project/templates/organizer/create.html:27 #: project/templates/organizer/delete.html:13 @@ -935,7 +953,7 @@ msgstr "Öffentlicher Status" msgid "PublicStatus.published" msgstr "Veröffentlicht" -#: project/forms/event.py:402 project/templates/_macros.html:255 +#: project/forms/event.py:402 project/templates/_macros.html:257 msgid "PublicStatus.draft" msgstr "Entwurf" @@ -948,7 +966,7 @@ msgstr "Wähle den öffentlichen Status der Veranstaltung." msgid "Update event" msgstr "Veranstaltung aktualisieren" -#: project/forms/event.py:423 project/templates/_macros.html:1224 +#: project/forms/event.py:423 project/templates/_macros.html:1226 #: project/templates/event/actions.html:66 #: project/templates/event/delete.html:6 msgid "Delete event" @@ -969,7 +987,7 @@ msgid "Keyword" msgstr "Stichwort" #: project/forms/event.py:436 project/forms/event_date.py:21 -#: project/forms/planing.py:19 project/templates/_macros.html:369 +#: project/forms/planing.py:19 project/templates/_macros.html:371 msgid "Category" msgstr "Kategorie" @@ -978,7 +996,7 @@ msgid "Find events" msgstr "Veranstaltungen finden" #: project/forms/event_date.py:24 project/forms/planing.py:22 -#: project/templates/_macros.html:303 +#: project/templates/_macros.html:305 #: project/templates/admin_unit/create.html:38 #: project/templates/admin_unit/update.html:39 #: project/templates/event_place/create.html:40 @@ -1125,7 +1143,7 @@ msgid "Weekdays" msgstr "Wochentage" #: project/forms/reference.py:11 project/forms/reference_request.py:16 -#: project/templates/_macros.html:489 project/templates/_macros.html:652 +#: project/templates/_macros.html:491 project/templates/_macros.html:654 #: project/templates/admin_unit/create.html:28 #: project/templates/admin_unit/update.html:29 #: project/templates/layout.html:242 @@ -1153,7 +1171,7 @@ msgstr "Anfrage speichern" msgid "Delete request" msgstr "Anfrage löschen" -#: project/forms/reference_request.py:28 project/templates/_macros.html:1407 +#: project/forms/reference_request.py:28 project/templates/_macros.html:1409 #: project/templates/event_suggestion/review_status.html:18 #: project/templates/reference_request/review_status.html:12 msgid "Review status" @@ -1211,43 +1229,53 @@ msgstr "Erlauben" msgid "Deny" msgstr "Ablehnen" +#: project/forms/user.py:9 project/templates/admin/admin.html:31 +#: project/templates/admin/newsletter.html:4 +#: project/templates/admin/newsletter.html:93 +msgid "Newsletter" +msgstr "Newsletter" + +#: project/forms/user.py:10 +msgid "Information about new features and improvements." +msgstr "Informationen über neue Features und Verbesserungen." + #: project/forms/widgets.py:154 msgid "This field is required." msgstr "Dieses Feld ist erforderlich." -#: project/templates/_macros.html:147 +#: project/templates/_macros.html:149 msgid "Show on Google Maps" msgstr "Auf Google Maps anzeigen" -#: project/templates/_macros.html:226 +#: project/templates/_macros.html:228 msgid "Link" msgstr "Link" -#: project/templates/_macros.html:282 +#: project/templates/_macros.html:284 msgid "Verified" msgstr "Verifiziert" -#: project/templates/_macros.html:346 +#: project/templates/_macros.html:348 #, python-format msgid "Created at %(created_at)s by %(created_by)s." msgstr "Erstellt am %(created_at)s von %(created_by)s." -#: project/templates/_macros.html:348 +#: project/templates/_macros.html:350 #, python-format msgid "Created at %(created_at)s." msgstr "Erstellt am %(created_at)s." -#: project/templates/_macros.html:353 +#: project/templates/_macros.html:355 #, python-format msgid "Last updated at %(updated_at)s by %(updated_by)s." msgstr "Zuletzt aktualisiert am %(updated_at)s von %(updated_by)s." -#: project/templates/_macros.html:355 +#: project/templates/_macros.html:357 #, python-format msgid "Last updated at %(updated_at)s." msgstr "Zuletzt aktualisiert am %(updated_at)s." -#: project/templates/_macros.html:385 project/templates/_macros.html:555 +#: project/templates/_macros.html:387 project/templates/_macros.html:557 #: project/templates/event/actions.html:25 #: project/templates/event/create.html:230 #: project/templates/event/update.html:122 @@ -1255,65 +1283,65 @@ msgstr "Zuletzt aktualisiert am %(updated_at)s." msgid "Event" msgstr "Veranstaltung" -#: project/templates/_macros.html:391 project/templates/_macros.html:920 +#: project/templates/_macros.html:393 project/templates/_macros.html:922 msgid "Date" msgstr "Datum" -#: project/templates/_macros.html:418 project/templates/_macros.html:577 -#: project/templates/_macros.html:1476 project/templates/event/actions.html:51 +#: project/templates/_macros.html:420 project/templates/_macros.html:579 +#: project/templates/_macros.html:1478 project/templates/event/actions.html:51 msgid "Share" msgstr "Teilen" -#: project/templates/_macros.html:422 project/templates/_macros.html:581 -#: project/templates/_macros.html:1506 +#: project/templates/_macros.html:424 project/templates/_macros.html:583 +#: project/templates/_macros.html:1508 msgid "Add to calendar" msgstr "Zum Kalender" -#: project/templates/_macros.html:430 project/templates/_macros.html:592 +#: project/templates/_macros.html:432 project/templates/_macros.html:594 #: project/templates/event/report.html:4 msgid "Report event" msgstr "Veranstaltung melden" -#: project/templates/_macros.html:457 project/templates/_macros.html:618 +#: project/templates/_macros.html:459 project/templates/_macros.html:620 msgid "Show directions" msgstr "Anreise planen" -#: project/templates/_macros.html:462 project/templates/_macros.html:623 +#: project/templates/_macros.html:464 project/templates/_macros.html:625 msgid "The event takes place online." msgstr "Die Veranstaltung findet online statt." -#: project/templates/_macros.html:464 project/templates/_macros.html:625 +#: project/templates/_macros.html:466 project/templates/_macros.html:627 msgid "The event takes place both offline and online." msgstr "" "Die Veranstaltung findet sowohl als Präsenzveranstaltung als auch online " "statt." -#: project/templates/_macros.html:585 project/templates/layout.html:168 +#: project/templates/_macros.html:587 project/templates/layout.html:168 #: project/templates/user/favorite_events.html:4 msgid "Favorite events" msgstr "Merkzettel" -#: project/templates/_macros.html:679 project/templates/event_date/list.html:5 +#: project/templates/_macros.html:681 project/templates/event_date/list.html:5 #: project/templates/event_date/list.html:299 #: project/templates/reference_request/review.html:32 msgid "Event Dates" msgstr "Termine" -#: project/templates/_macros.html:771 +#: project/templates/_macros.html:773 msgid "Search location on Google" msgstr "Ort bei Google suchen" -#: project/templates/_macros.html:837 +#: project/templates/_macros.html:839 #, python-format msgid "%(count)d event dates" msgstr "%(count)d Termine" -#: project/templates/_macros.html:860 project/templates/_macros.html:862 +#: project/templates/_macros.html:862 project/templates/_macros.html:864 #: project/templates/event_date/list.html:321 msgid "First" msgstr "Letzte" -#: project/templates/_macros.html:865 project/templates/_macros.html:867 +#: project/templates/_macros.html:867 project/templates/_macros.html:869 #: project/templates/event_date/list.html:322 #: project/templates/widget/event_suggestion/create.html:193 #: project/templates/widget/event_suggestion/create.html:218 @@ -1324,12 +1352,12 @@ msgstr "Letzte" msgid "Previous" msgstr "Zurück" -#: project/templates/_macros.html:869 +#: project/templates/_macros.html:871 #, python-format msgid "Page %(page)d of %(pages)d (%(total)d total)" msgstr "Seite %(page)d von %(pages)d (%(total)d insgesamt)" -#: project/templates/_macros.html:871 project/templates/_macros.html:873 +#: project/templates/_macros.html:873 project/templates/_macros.html:875 #: project/templates/event_date/list.html:324 #: project/templates/widget/event_suggestion/create.html:194 #: project/templates/widget/event_suggestion/create.html:219 @@ -1339,88 +1367,88 @@ msgstr "Seite %(page)d von %(pages)d (%(total)d insgesamt)" msgid "Next" msgstr "Weiter" -#: project/templates/_macros.html:876 project/templates/_macros.html:878 +#: project/templates/_macros.html:878 project/templates/_macros.html:880 #: project/templates/event_date/list.html:325 msgid "Last" msgstr "Erste" -#: project/templates/_macros.html:943 +#: project/templates/_macros.html:945 msgid "Radius" msgstr "Umkreis" -#: project/templates/_macros.html:1153 +#: project/templates/_macros.html:1155 msgid "Edit image" msgstr "Bild bearbeiten" -#: project/templates/_macros.html:1174 +#: project/templates/_macros.html:1176 msgid "Close" msgstr "Schließen" -#: project/templates/_macros.html:1175 +#: project/templates/_macros.html:1177 msgid "Okay" msgstr "OK" -#: project/templates/_macros.html:1187 +#: project/templates/_macros.html:1189 msgid "Choose image file" msgstr "Bild-Datei auswählen" -#: project/templates/_macros.html:1223 project/templates/event/actions.html:65 +#: project/templates/_macros.html:1225 project/templates/event/actions.html:65 #: project/templates/event/delete.html:12 msgid "Edit event" msgstr "Veranstaltung bearbeiten" -#: project/templates/_macros.html:1226 project/templates/manage/events.html:66 +#: project/templates/_macros.html:1228 project/templates/manage/events.html:66 msgid "More" msgstr "Mehr" -#: project/templates/_macros.html:1273 +#: project/templates/_macros.html:1275 msgid "Please enter a valid time, between 00:00 and 23:59." msgstr "Bitte gib eine gültige Uhrzeit zwischen 00:00 und 23:59 ein." -#: project/templates/_macros.html:1301 +#: project/templates/_macros.html:1303 #, python-format msgid "Just use %(term)s" msgstr "Verwende einfach %(term)s" -#: project/templates/_macros.html:1367 +#: project/templates/_macros.html:1369 msgid "Event suggestion" msgstr "Veranstaltungsvorschlag" -#: project/templates/_macros.html:1485 +#: project/templates/_macros.html:1487 msgid "Link copied" msgstr "Link kopiert" -#: project/templates/_macros.html:1485 +#: project/templates/_macros.html:1487 msgid "Copy link" msgstr "Link kopieren" -#: project/templates/_macros.html:1514 +#: project/templates/_macros.html:1516 msgid "Google calendar" msgstr "Google Kalender" -#: project/templates/_macros.html:1515 +#: project/templates/_macros.html:1517 msgid "Apple calendar" msgstr "Apple Kalender" -#: project/templates/_macros.html:1516 +#: project/templates/_macros.html:1518 msgid "Yahoo calendar" msgstr "Yahoo Kalender" -#: project/templates/_macros.html:1517 +#: project/templates/_macros.html:1519 msgid "Other calendar" msgstr "Anderer Kalender" -#: project/templates/_macros.html:1712 +#: project/templates/_macros.html:1714 msgid "Remove event date" msgstr "Termin entfernen" -#: project/templates/_macros.html:1741 project/templates/event/create.html:176 +#: project/templates/_macros.html:1743 project/templates/event/create.html:176 #: project/templates/event/update.html:99 #: project/templates/widget/event_suggestion/create.html:129 msgid "Enter organizer" msgstr "Veranstalter eingeben" -#: project/templates/_macros.html:1765 +#: project/templates/_macros.html:1767 msgid "Enter list name" msgstr "Listenname eingeben" @@ -1464,6 +1492,7 @@ msgstr "Profil" #: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9 #: project/templates/admin/admin_units.html:10 #: project/templates/admin/email.html:65 +#: project/templates/admin/newsletter.html:92 #: project/templates/admin/settings.html:10 #: project/templates/admin/users.html:10 project/templates/layout.html:171 msgid "Admin" @@ -1551,8 +1580,7 @@ msgstr "Beziehungen" msgid "Organization invitations" msgstr "Organisationseinladungen" -#: project/templates/admin/admin.html:15 project/templates/admin/email.html:4 -#: project/templates/admin/email.html:66 +#: project/templates/admin/admin.html:15 #: project/templates/admin/settings.html:4 #: project/templates/admin/settings.html:11 #: project/templates/admin_unit/update.html:6 @@ -1578,18 +1606,24 @@ msgid "Switch organization" msgstr "Organisation wechseln" #: project/templates/developer/read.html:4 project/templates/layout.html:310 -#: project/templates/profile.html:29 +#: project/templates/profile.html:33 msgid "Developer" msgstr "Entwickler" #: project/templates/profile.html:23 +#: project/templates/user/notifications.html:4 +#: project/templates/user/notifications.html:8 +msgid "Notifications" +msgstr "Benachrichtigungen" + +#: project/templates/profile.html:27 msgid "Applications" msgstr "Apps" #: project/templates/oauth2_client/list.html:4 #: project/templates/oauth2_client/list.html:11 #: project/templates/oauth2_client/read.html:11 -#: project/templates/profile.html:33 +#: project/templates/profile.html:37 msgid "OAuth2 clients" msgstr "OAuth2 Clients" @@ -1610,7 +1644,7 @@ msgstr "Benutzer" msgid "Edit" msgstr "Bearbeiten" -#: project/templates/admin/email.html:47 project/views/admin.py:119 +#: project/templates/admin/email.html:47 project/views/admin.py:122 msgid "Mail sent successfully" msgstr "Mail erfolgreich gesendet" @@ -1622,6 +1656,10 @@ msgstr "Test-Mail" msgid "Send test mail asynchronously" msgstr "Test-Mail asynchron senden" +#: project/templates/admin/newsletter.html:59 +msgid "Mails sent successfully" +msgstr "Mails erfolgreich gesendet" + #: project/templates/admin_unit/create.html:58 #: project/templates/admin_unit/update.html:59 #: project/templates/event/create.html:347 @@ -1676,6 +1714,10 @@ msgstr "Moin" msgid "this is a message from %(site_name)s." msgstr "das ist eine Nachricht von %(site_name)s." +#: project/templates/email/newsletter.html:7 +msgid "Notification settings" +msgstr "Benachrichtigungseinstellungen" + #: project/templates/email/organization_invitation_accepted_notice.html:4 #, python-format msgid "" @@ -2096,20 +2138,26 @@ msgstr "Optionale Details" msgid "Preview" msgstr "Vorschau" -#: project/views/admin.py:55 +#: project/views/admin.py:58 msgid "Organization successfully updated" msgstr "Organisation erfolgreich aktualisiert" -#: project/views/admin.py:79 project/views/manage.py:361 +#: project/views/admin.py:82 project/views/manage.py:361 +#: project/views/user.py:27 msgid "Settings successfully updated" msgstr "Einstellungen erfolgreich aktualisiert" -#: project/views/admin.py:108 +#: project/views/admin.py:111 #, python-format msgid "Test mail from %(site_name)s" msgstr "Test-Mail von %(site_name)s" -#: project/views/admin.py:152 +#: project/views/admin.py:150 +#, python-format +msgid "Newsletter from %(site_name)s" +msgstr "Newsletter von %(site_name)s" + +#: project/views/admin.py:200 msgid "User successfully updated" msgstr "Nutzer erfolgreich aktualisiert" diff --git a/project/translations/en/LC_MESSAGES/messages.mo b/project/translations/en/LC_MESSAGES/messages.mo index f1fcd1d..bab21ee 100644 Binary files a/project/translations/en/LC_MESSAGES/messages.mo and b/project/translations/en/LC_MESSAGES/messages.mo differ diff --git a/project/translations/en/LC_MESSAGES/messages.po b/project/translations/en/LC_MESSAGES/messages.po index e38fe4b..fc96199 100644 --- a/project/translations/en/LC_MESSAGES/messages.po +++ b/project/translations/en/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: 2023-03-24 21:24+0100\n" +"POT-Creation-Date: 2023-03-28 17:04+0200\n" "PO-Revision-Date: 2021-04-30 15:04+0200\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -209,7 +209,7 @@ msgstr "" msgid "Legal notice" msgstr "" -#: project/forms/admin.py:13 project/templates/_macros.html:1395 +#: project/forms/admin.py:13 project/templates/_macros.html:1397 #: project/templates/layout.html:302 #: project/templates/widget/event_suggestion/create.html:204 #: project/views/admin_unit.py:73 project/views/root.py:69 @@ -226,6 +226,7 @@ msgid "Start page" msgstr "" #: project/forms/admin.py:17 project/forms/oauth2_client.py:24 +#: project/forms/user.py:13 msgid "Save" msgstr "" @@ -286,7 +287,7 @@ msgstr "" msgid "Update organization" msgstr "" -#: project/forms/admin.py:63 +#: project/forms/admin.py:63 project/forms/admin.py:70 msgid "Recipient" msgstr "" @@ -294,6 +295,22 @@ msgstr "" msgid "Send test mail synchronously" msgstr "" +#: project/forms/admin.py:72 project/forms/admin.py:78 +msgid "Test recipient" +msgstr "" + +#: project/forms/admin.py:73 +msgid "All users with enabled newsletter setting" +msgstr "" + +#: project/forms/admin.py:79 +msgid "Message" +msgstr "" + +#: project/forms/admin.py:80 +msgid "Send newsletter" +msgstr "" + #: project/forms/admin_unit.py:15 project/forms/event_place.py:12 #: project/forms/organizer.py:12 msgid "Street" @@ -343,7 +360,7 @@ msgstr "" msgid "The short name is used to create a unique identifier for your events" msgstr "" -#: project/forms/admin_unit.py:41 project/templates/_macros.html:1531 +#: project/forms/admin_unit.py:41 project/templates/_macros.html:1533 msgid "Short name must contain only letters numbers or underscore" msgstr "" @@ -356,20 +373,21 @@ msgstr "" #: project/forms/admin_unit.py:48 project/forms/admin_unit_member.py:11 #: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28 #: project/forms/event.py:107 project/forms/event_suggestion.py:38 -#: project/forms/organizer.py:27 project/templates/_macros.html:235 -#: project/templates/_macros.html:1491 project/templates/admin/admin.html:27 +#: project/forms/organizer.py:27 project/templates/_macros.html:237 +#: project/templates/_macros.html:1493 project/templates/admin/admin.html:27 +#: project/templates/admin/email.html:4 project/templates/admin/email.html:66 #: project/templates/admin/users.html:19 msgid "Email" msgstr "" #: project/forms/admin_unit.py:49 project/forms/event.py:108 #: project/forms/event_suggestion.py:31 project/forms/organizer.py:28 -#: project/templates/_macros.html:288 +#: project/templates/_macros.html:290 msgid "Phone" msgstr "" #: project/forms/admin_unit.py:50 project/forms/event.py:109 -#: project/forms/organizer.py:29 project/templates/_macros.html:296 +#: project/forms/organizer.py:29 project/templates/_macros.html:298 msgid "Fax" msgstr "" @@ -567,16 +585,16 @@ msgstr "" msgid "All-day" msgstr "" -#: project/forms/event.py:54 project/templates/_macros.html:1711 +#: project/forms/event.py:54 project/templates/_macros.html:1713 #: project/templates/widget/event_suggestion/create.html:240 msgid "Recurring event" msgstr "" -#: project/forms/event.py:61 project/templates/_macros.html:1252 +#: project/forms/event.py:61 project/templates/_macros.html:1254 msgid "The start must be before the end." msgstr "" -#: project/forms/event.py:67 project/templates/_macros.html:1269 +#: project/forms/event.py:67 project/templates/_macros.html:1271 msgid "An event can last a maximum of 14 days." msgstr "" @@ -610,7 +628,7 @@ msgstr "" msgid "Enter a link where tickets can be purchased." msgstr "" -#: project/forms/event.py:136 project/templates/_macros.html:217 +#: project/forms/event.py:136 project/templates/_macros.html:219 msgid "Tags" msgstr "" @@ -660,7 +678,7 @@ msgstr "" msgid "If the participants needs to register for the event." msgstr "" -#: project/forms/event.py:170 project/templates/_macros.html:249 +#: project/forms/event.py:170 project/templates/_macros.html:251 #: project/templates/layout.html:110 msgid "Booked up" msgstr "" @@ -740,8 +758,8 @@ msgid "" " course it works without it." msgstr "" -#: project/forms/event.py:242 project/templates/_macros.html:396 -#: project/templates/_macros.html:559 +#: project/forms/event.py:242 project/templates/_macros.html:398 +#: project/templates/_macros.html:561 msgid "Previous start date" msgstr "" @@ -787,7 +805,7 @@ msgstr "" #: project/forms/event.py:286 project/forms/event.py:295 #: project/forms/event.py:368 project/forms/event_suggestion.py:50 -#: project/templates/_macros.html:436 project/templates/_macros.html:599 +#: project/templates/_macros.html:438 project/templates/_macros.html:601 #: project/templates/event/create.html:284 #: project/templates/event/update.html:166 #: project/templates/event_place/create.html:31 @@ -806,8 +824,8 @@ msgstr "" #: project/forms/event.py:302 project/forms/event.py:311 #: project/forms/event.py:376 project/forms/event.py:439 -#: project/forms/event_suggestion.py:60 project/templates/_macros.html:473 -#: project/templates/_macros.html:636 project/templates/event/create.html:253 +#: project/forms/event_suggestion.py:60 project/templates/_macros.html:475 +#: project/templates/_macros.html:638 project/templates/event/create.html:253 #: project/templates/event/update.html:156 #: project/templates/organizer/create.html:27 #: project/templates/organizer/delete.html:13 @@ -892,7 +910,7 @@ msgstr "" msgid "PublicStatus.published" msgstr "" -#: project/forms/event.py:402 project/templates/_macros.html:255 +#: project/forms/event.py:402 project/templates/_macros.html:257 msgid "PublicStatus.draft" msgstr "" @@ -905,7 +923,7 @@ msgstr "" msgid "Update event" msgstr "" -#: project/forms/event.py:423 project/templates/_macros.html:1224 +#: project/forms/event.py:423 project/templates/_macros.html:1226 #: project/templates/event/actions.html:66 #: project/templates/event/delete.html:6 msgid "Delete event" @@ -926,7 +944,7 @@ msgid "Keyword" msgstr "" #: project/forms/event.py:436 project/forms/event_date.py:21 -#: project/forms/planing.py:19 project/templates/_macros.html:369 +#: project/forms/planing.py:19 project/templates/_macros.html:371 msgid "Category" msgstr "" @@ -935,7 +953,7 @@ msgid "Find events" msgstr "" #: project/forms/event_date.py:24 project/forms/planing.py:22 -#: project/templates/_macros.html:303 +#: project/templates/_macros.html:305 #: project/templates/admin_unit/create.html:38 #: project/templates/admin_unit/update.html:39 #: project/templates/event_place/create.html:40 @@ -1078,7 +1096,7 @@ msgid "Weekdays" msgstr "" #: project/forms/reference.py:11 project/forms/reference_request.py:16 -#: project/templates/_macros.html:489 project/templates/_macros.html:652 +#: project/templates/_macros.html:491 project/templates/_macros.html:654 #: project/templates/admin_unit/create.html:28 #: project/templates/admin_unit/update.html:29 #: project/templates/layout.html:242 @@ -1106,7 +1124,7 @@ msgstr "" msgid "Delete request" msgstr "" -#: project/forms/reference_request.py:28 project/templates/_macros.html:1407 +#: project/forms/reference_request.py:28 project/templates/_macros.html:1409 #: project/templates/event_suggestion/review_status.html:18 #: project/templates/reference_request/review_status.html:12 msgid "Review status" @@ -1164,43 +1182,53 @@ msgstr "" msgid "Deny" msgstr "" +#: project/forms/user.py:9 project/templates/admin/admin.html:31 +#: project/templates/admin/newsletter.html:4 +#: project/templates/admin/newsletter.html:93 +msgid "Newsletter" +msgstr "" + +#: project/forms/user.py:10 +msgid "Information about new features and improvements." +msgstr "" + #: project/forms/widgets.py:154 msgid "This field is required." msgstr "" -#: project/templates/_macros.html:147 +#: project/templates/_macros.html:149 msgid "Show on Google Maps" msgstr "" -#: project/templates/_macros.html:226 +#: project/templates/_macros.html:228 msgid "Link" msgstr "" -#: project/templates/_macros.html:282 +#: project/templates/_macros.html:284 msgid "Verified" msgstr "" -#: project/templates/_macros.html:346 -#, python-format -msgid "Created at %(created_at)s by %(created_by)s." -msgstr "" - #: project/templates/_macros.html:348 #, python-format -msgid "Created at %(created_at)s." +msgid "Created at %(created_at)s by %(created_by)s." msgstr "" -#: project/templates/_macros.html:353 +#: project/templates/_macros.html:350 #, python-format -msgid "Last updated at %(updated_at)s by %(updated_by)s." +msgid "Created at %(created_at)s." msgstr "" #: project/templates/_macros.html:355 #, python-format +msgid "Last updated at %(updated_at)s by %(updated_by)s." +msgstr "" + +#: project/templates/_macros.html:357 +#, python-format msgid "Last updated at %(updated_at)s." msgstr "" -#: project/templates/_macros.html:385 project/templates/_macros.html:555 +#: project/templates/_macros.html:387 project/templates/_macros.html:557 #: project/templates/event/actions.html:25 #: project/templates/event/create.html:230 #: project/templates/event/update.html:122 @@ -1208,63 +1236,63 @@ msgstr "" msgid "Event" msgstr "" -#: project/templates/_macros.html:391 project/templates/_macros.html:920 +#: project/templates/_macros.html:393 project/templates/_macros.html:922 msgid "Date" msgstr "" -#: project/templates/_macros.html:418 project/templates/_macros.html:577 -#: project/templates/_macros.html:1476 project/templates/event/actions.html:51 +#: project/templates/_macros.html:420 project/templates/_macros.html:579 +#: project/templates/_macros.html:1478 project/templates/event/actions.html:51 msgid "Share" msgstr "" -#: project/templates/_macros.html:422 project/templates/_macros.html:581 -#: project/templates/_macros.html:1506 +#: project/templates/_macros.html:424 project/templates/_macros.html:583 +#: project/templates/_macros.html:1508 msgid "Add to calendar" msgstr "" -#: project/templates/_macros.html:430 project/templates/_macros.html:592 +#: project/templates/_macros.html:432 project/templates/_macros.html:594 #: project/templates/event/report.html:4 msgid "Report event" msgstr "" -#: project/templates/_macros.html:457 project/templates/_macros.html:618 +#: project/templates/_macros.html:459 project/templates/_macros.html:620 msgid "Show directions" msgstr "" -#: project/templates/_macros.html:462 project/templates/_macros.html:623 +#: project/templates/_macros.html:464 project/templates/_macros.html:625 msgid "The event takes place online." msgstr "" -#: project/templates/_macros.html:464 project/templates/_macros.html:625 +#: project/templates/_macros.html:466 project/templates/_macros.html:627 msgid "The event takes place both offline and online." msgstr "" -#: project/templates/_macros.html:585 project/templates/layout.html:168 +#: project/templates/_macros.html:587 project/templates/layout.html:168 #: project/templates/user/favorite_events.html:4 msgid "Favorite events" msgstr "" -#: project/templates/_macros.html:679 project/templates/event_date/list.html:5 +#: project/templates/_macros.html:681 project/templates/event_date/list.html:5 #: project/templates/event_date/list.html:299 #: project/templates/reference_request/review.html:32 msgid "Event Dates" msgstr "" -#: project/templates/_macros.html:771 +#: project/templates/_macros.html:773 msgid "Search location on Google" msgstr "" -#: project/templates/_macros.html:837 +#: project/templates/_macros.html:839 #, python-format msgid "%(count)d event dates" msgstr "" -#: project/templates/_macros.html:860 project/templates/_macros.html:862 +#: project/templates/_macros.html:862 project/templates/_macros.html:864 #: project/templates/event_date/list.html:321 msgid "First" msgstr "" -#: project/templates/_macros.html:865 project/templates/_macros.html:867 +#: project/templates/_macros.html:867 project/templates/_macros.html:869 #: project/templates/event_date/list.html:322 #: project/templates/widget/event_suggestion/create.html:193 #: project/templates/widget/event_suggestion/create.html:218 @@ -1275,12 +1303,12 @@ msgstr "" msgid "Previous" msgstr "" -#: project/templates/_macros.html:869 +#: project/templates/_macros.html:871 #, python-format msgid "Page %(page)d of %(pages)d (%(total)d total)" msgstr "" -#: project/templates/_macros.html:871 project/templates/_macros.html:873 +#: project/templates/_macros.html:873 project/templates/_macros.html:875 #: project/templates/event_date/list.html:324 #: project/templates/widget/event_suggestion/create.html:194 #: project/templates/widget/event_suggestion/create.html:219 @@ -1290,88 +1318,88 @@ msgstr "" msgid "Next" msgstr "" -#: project/templates/_macros.html:876 project/templates/_macros.html:878 +#: project/templates/_macros.html:878 project/templates/_macros.html:880 #: project/templates/event_date/list.html:325 msgid "Last" msgstr "" -#: project/templates/_macros.html:943 +#: project/templates/_macros.html:945 msgid "Radius" msgstr "" -#: project/templates/_macros.html:1153 +#: project/templates/_macros.html:1155 msgid "Edit image" msgstr "" -#: project/templates/_macros.html:1174 +#: project/templates/_macros.html:1176 msgid "Close" msgstr "" -#: project/templates/_macros.html:1175 +#: project/templates/_macros.html:1177 msgid "Okay" msgstr "" -#: project/templates/_macros.html:1187 +#: project/templates/_macros.html:1189 msgid "Choose image file" msgstr "" -#: project/templates/_macros.html:1223 project/templates/event/actions.html:65 +#: project/templates/_macros.html:1225 project/templates/event/actions.html:65 #: project/templates/event/delete.html:12 msgid "Edit event" msgstr "" -#: project/templates/_macros.html:1226 project/templates/manage/events.html:66 +#: project/templates/_macros.html:1228 project/templates/manage/events.html:66 msgid "More" msgstr "" -#: project/templates/_macros.html:1273 +#: project/templates/_macros.html:1275 msgid "Please enter a valid time, between 00:00 and 23:59." msgstr "" -#: project/templates/_macros.html:1301 +#: project/templates/_macros.html:1303 #, python-format msgid "Just use %(term)s" msgstr "" -#: project/templates/_macros.html:1367 +#: project/templates/_macros.html:1369 msgid "Event suggestion" msgstr "" -#: project/templates/_macros.html:1485 +#: project/templates/_macros.html:1487 msgid "Link copied" msgstr "" -#: project/templates/_macros.html:1485 +#: project/templates/_macros.html:1487 msgid "Copy link" msgstr "" -#: project/templates/_macros.html:1514 +#: project/templates/_macros.html:1516 msgid "Google calendar" msgstr "" -#: project/templates/_macros.html:1515 +#: project/templates/_macros.html:1517 msgid "Apple calendar" msgstr "" -#: project/templates/_macros.html:1516 +#: project/templates/_macros.html:1518 msgid "Yahoo calendar" msgstr "" -#: project/templates/_macros.html:1517 +#: project/templates/_macros.html:1519 msgid "Other calendar" msgstr "" -#: project/templates/_macros.html:1712 +#: project/templates/_macros.html:1714 msgid "Remove event date" msgstr "" -#: project/templates/_macros.html:1741 project/templates/event/create.html:176 +#: project/templates/_macros.html:1743 project/templates/event/create.html:176 #: project/templates/event/update.html:99 #: project/templates/widget/event_suggestion/create.html:129 msgid "Enter organizer" msgstr "" -#: project/templates/_macros.html:1765 +#: project/templates/_macros.html:1767 msgid "Enter list name" msgstr "" @@ -1415,6 +1443,7 @@ msgstr "" #: project/templates/admin/admin.html:3 project/templates/admin/admin.html:9 #: project/templates/admin/admin_units.html:10 #: project/templates/admin/email.html:65 +#: project/templates/admin/newsletter.html:92 #: project/templates/admin/settings.html:10 #: project/templates/admin/users.html:10 project/templates/layout.html:171 msgid "Admin" @@ -1502,8 +1531,7 @@ msgstr "" msgid "Organization invitations" msgstr "" -#: project/templates/admin/admin.html:15 project/templates/admin/email.html:4 -#: project/templates/admin/email.html:66 +#: project/templates/admin/admin.html:15 #: project/templates/admin/settings.html:4 #: project/templates/admin/settings.html:11 #: project/templates/admin_unit/update.html:6 @@ -1529,18 +1557,24 @@ msgid "Switch organization" msgstr "" #: project/templates/developer/read.html:4 project/templates/layout.html:310 -#: project/templates/profile.html:29 +#: project/templates/profile.html:33 msgid "Developer" msgstr "" #: project/templates/profile.html:23 +#: project/templates/user/notifications.html:4 +#: project/templates/user/notifications.html:8 +msgid "Notifications" +msgstr "" + +#: project/templates/profile.html:27 msgid "Applications" msgstr "" #: project/templates/oauth2_client/list.html:4 #: project/templates/oauth2_client/list.html:11 #: project/templates/oauth2_client/read.html:11 -#: project/templates/profile.html:33 +#: project/templates/profile.html:37 msgid "OAuth2 clients" msgstr "" @@ -1561,7 +1595,7 @@ msgstr "" msgid "Edit" msgstr "" -#: project/templates/admin/email.html:47 project/views/admin.py:119 +#: project/templates/admin/email.html:47 project/views/admin.py:122 msgid "Mail sent successfully" msgstr "" @@ -1573,6 +1607,10 @@ msgstr "" msgid "Send test mail asynchronously" msgstr "" +#: project/templates/admin/newsletter.html:59 +msgid "Mails sent successfully" +msgstr "" + #: project/templates/admin_unit/create.html:58 #: project/templates/admin_unit/update.html:59 #: project/templates/event/create.html:347 @@ -1627,6 +1665,10 @@ msgstr "" msgid "this is a message from %(site_name)s." msgstr "" +#: project/templates/email/newsletter.html:7 +msgid "Notification settings" +msgstr "" + #: project/templates/email/organization_invitation_accepted_notice.html:4 #, python-format msgid "" @@ -2036,20 +2078,26 @@ msgstr "" msgid "Preview" msgstr "" -#: project/views/admin.py:55 +#: project/views/admin.py:58 msgid "Organization successfully updated" msgstr "" -#: project/views/admin.py:79 project/views/manage.py:361 +#: project/views/admin.py:82 project/views/manage.py:361 +#: project/views/user.py:27 msgid "Settings successfully updated" msgstr "" -#: project/views/admin.py:108 +#: project/views/admin.py:111 #, python-format msgid "Test mail from %(site_name)s" msgstr "" -#: project/views/admin.py:152 +#: project/views/admin.py:150 +#, python-format +msgid "Newsletter from %(site_name)s" +msgstr "" + +#: project/views/admin.py:200 msgid "User successfully updated" msgstr "" diff --git a/project/views/admin.py b/project/views/admin.py index b31ba16..e36c89e 100644 --- a/project/views/admin.py +++ b/project/views/admin.py @@ -1,3 +1,4 @@ +from celery import group from flask import flash, redirect, render_template, request, url_for from flask_babelex import gettext from flask_security import roles_required @@ -7,6 +8,7 @@ from sqlalchemy.sql import func from project import app, celery, db from project.base_tasks import send_mail_task from project.forms.admin import ( + AdminNewsletterForm, AdminSettingsForm, AdminTestEmailForm, UpdateAdminUnitForm, @@ -125,6 +127,51 @@ def admin_email(): return render_template("admin/email.html", form=form) +@app.route("/admin/newsletter", methods=["GET", "POST"]) +@roles_required("admin") +def admin_newsletter(): + form = AdminNewsletterForm() + + if "poll" in request.args: # pragma: no cover + try: + result = celery.GroupResult.restore(request.args["poll"]) + ready = result.ready() + return { + "ready": ready, + "count": len(result.children), + "completed": result.completed_count(), + "successful": result.successful() if ready else None, + } + except Exception as e: + return {"ready": True, "successful": False, "error": str(e)} + + if form.validate_on_submit(): + subject = gettext( + "Newsletter from %(site_name)s", + site_name=app.config["SITE_NAME"], + ) + + if form.recipient_choice.data == 1: # pragma: no cover + recipients = [form.test_recipient.data] + else: + users = ( + User.query.filter(User.email != None) + .filter(User.confirmed_at != None) + .filter(User.newsletter_enabled) + .all() + ) + recipients = [u.email for u in users] + + result = group( + send_mail_task.s(r, subject, "newsletter", message=form.message.data) + for r in recipients + ).delay() + result.save() + return {"result_id": result.id} + + return render_template("admin/newsletter.html", form=form) + + @app.route("/admin/users") @roles_required("admin") def admin_users(): diff --git a/project/views/user.py b/project/views/user.py index f75e21d..4878dda 100644 --- a/project/views/user.py +++ b/project/views/user.py @@ -1,9 +1,12 @@ -from flask import render_template -from flask_security import auth_required +from flask import flash, redirect, render_template, url_for +from flask_babelex import gettext +from flask_security import auth_required, current_user +from sqlalchemy.exc import SQLAlchemyError -from project import app -from project.models import AdminUnitInvitation -from project.views.utils import get_invitation_access_result +from project import app, db +from project.forms.user import NotificationForm +from project.models import AdminUnitInvitation, User +from project.views.utils import get_invitation_access_result, handleSqlError @app.route("/profile") @@ -12,6 +15,25 @@ def profile(): return render_template("profile.html") +@app.route("/user/notifications", methods=("GET", "POST")) +@auth_required() +def user_notifications(): + user = User.query.get_or_404(current_user.id) + form = NotificationForm(obj=user) + + if form.validate_on_submit(): + try: + form.populate_obj(user) + db.session.commit() + flash(gettext("Settings successfully updated"), "success") + return redirect(url_for("profile")) + except SQLAlchemyError as e: # pragma: no cover + db.session.rollback() + flash(handleSqlError(e), "danger") + + return render_template("user/notifications.html", form=form) + + @app.route("/user/organization-invitations/") def user_organization_invitation(id): invitation = AdminUnitInvitation.query.get_or_404(id) diff --git a/tests/conftest.py b/tests/conftest.py index d13c2df..fc462ab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,6 +14,7 @@ def pytest_generate_tests(metafunc): os.environ["DATABASE_URL"] = os.environ.get( "TEST_DATABASE_URL", "postgresql://postgres@localhost/eventcally_tests" ) + os.environ["REDIS_URL"] = os.environ.get("TEST_REDIS_URL", "redis://") os.environ["AUTHLIB_INSECURE_TRANSPORT"] = "1" os.environ[ "JWT_PRIVATE_KEY" diff --git a/tests/views/test_admin.py b/tests/views/test_admin.py index 058971d..37aec2a 100644 --- a/tests/views/test_admin.py +++ b/tests/views/test_admin.py @@ -79,6 +79,28 @@ def test_admin_email(client, seeder, utils, app, mocker): utils.assert_send_mail_called(mail_mock, "test@test.de") +def test_newsletter(app, utils, seeder): + user_id, admin_unit_id = seeder.setup_base(True) + + for i in range(10): + seeder.create_user(f"test{i}@test.de") + + url = utils.get_url("admin_newsletter") + response = utils.get_ok(url) + + response = utils.post_form( + url, + response, + { + "recipient_choice": 2, + "message": "Message", + }, + ) + + utils.assert_response_ok(response) + assert "result_id" in response.json + + def test_admin_users(client, seeder, utils, app): seeder.create_user(admin=True) user = utils.login() diff --git a/tests/views/test_user.py b/tests/views/test_user.py index b709df2..d9add97 100644 --- a/tests/views/test_user.py +++ b/tests/views/test_user.py @@ -65,3 +65,26 @@ def test_user_favorite_events(client, seeder, utils): url = utils.get_url("user_favorite_events") utils.get_ok(url) + + +def test_user_notifications(client, seeder, utils, app): + user_id, admin_unit_id = seeder.setup_base() + + url = utils.get_url("user_notifications") + response = utils.get_ok(url) + + response = utils.post_form( + url, + response, + { + "newsletter_enabled": None, + }, + ) + + utils.assert_response_redirect(response, "profile") + + with app.app_context(): + from project.models import User + + place = User.query.get(user_id) + assert not place.newsletter_enabled