From baa612b22656bc3058a0ef89e6a6cb7b7c192f86 Mon Sep 17 00:00:00 2001 From: Daniel Grams Date: Tue, 13 Jun 2023 13:14:09 +0200 Subject: [PATCH] Reference requests when creating an event #495 --- messages.pot | 254 ++++++++-------- project/access.py | 16 +- project/forms/event.py | 11 +- project/services/admin_unit.py | 47 +++ project/services/reference.py | 59 +++- project/templates/event/create.html | 15 + .../translations/de/LC_MESSAGES/messages.mo | Bin 45395 -> 45881 bytes .../translations/de/LC_MESSAGES/messages.po | 270 ++++++++++-------- .../translations/en/LC_MESSAGES/messages.mo | Bin 4079 -> 4079 bytes .../translations/en/LC_MESSAGES/messages.po | 260 +++++++++-------- project/views/event.py | 81 ++++++ project/views/reference_request.py | 46 +-- tests/seeder.py | 11 + tests/views/test_event.py | 132 ++++++++- 14 files changed, 802 insertions(+), 400 deletions(-) diff --git a/messages.pot b/messages.pot index 207b6c8..8b59471 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-06-09 13:32+0200\n" +"POT-Creation-Date: 2023-06-12 14:29+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -257,7 +257,7 @@ msgstr "" #: project/forms/admin.py:34 project/forms/admin_unit.py:60 #: project/forms/admin_unit_member.py:12 project/forms/admin_unit_member.py:25 -#: project/forms/admin_unit_member.py:30 project/forms/event.py:107 +#: project/forms/admin_unit_member.py:30 project/forms/event.py:112 #: project/forms/event_suggestion.py:38 project/forms/organizer.py:33 #: project/forms/user.py:18 project/forms/user.py:23 #: project/templates/_macros.html:246 project/templates/_macros.html:1561 @@ -322,7 +322,7 @@ msgstr "" #: project/forms/admin.py:76 project/forms/admin_unit.py:149 #: project/forms/admin_unit.py:154 project/forms/admin_unit.py:159 -#: project/forms/event.py:85 project/forms/event.py:114 +#: project/forms/event.py:90 project/forms/event.py:119 #: project/forms/event_place.py:30 project/forms/event_place.py:56 #: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66 #: project/forms/organizer.py:30 project/forms/organizer.py:58 @@ -365,7 +365,7 @@ msgstr "" msgid "Street" msgstr "" -#: project/forms/admin_unit.py:18 project/forms/event.py:461 +#: project/forms/admin_unit.py:18 project/forms/event.py:470 #: project/forms/event_date.py:52 project/forms/event_place.py:16 #: project/forms/organizer.py:16 project/forms/planning.py:44 msgid "Postal code" @@ -411,7 +411,7 @@ msgstr "" msgid "Short name must contain only letters numbers or underscore" msgstr "" -#: project/forms/admin_unit.py:55 project/forms/event.py:119 +#: project/forms/admin_unit.py:55 project/forms/event.py:124 #: project/forms/event_place.py:34 msgid "Description" msgstr "" @@ -420,20 +420,20 @@ msgstr "" msgid "Describe the organization in a few words" msgstr "" -#: project/forms/admin_unit.py:59 project/forms/event.py:106 -#: project/forms/event.py:124 project/forms/event_place.py:32 +#: project/forms/admin_unit.py:59 project/forms/event.py:111 +#: project/forms/event.py:129 project/forms/event_place.py:32 #: project/forms/organizer.py:32 project/templates/manage/organizers.html:21 msgid "Link URL" msgstr "" -#: project/forms/admin_unit.py:61 project/forms/event.py:108 +#: project/forms/admin_unit.py:61 project/forms/event.py:113 #: project/forms/event_suggestion.py:31 project/forms/organizer.py:34 #: project/templates/_macros.html:309 #: project/templates/manage/organizers.html:20 msgid "Phone" msgstr "" -#: project/forms/admin_unit.py:62 project/forms/event.py:109 +#: project/forms/admin_unit.py:62 project/forms/event.py:114 #: project/forms/organizer.py:35 project/templates/_macros.html:317 msgid "Fax" msgstr "" @@ -635,187 +635,187 @@ msgstr "" msgid "100 km" msgstr "" -#: project/forms/event.py:38 project/templates/manage/events.html:102 +#: project/forms/event.py:43 project/templates/manage/events.html:102 msgid "Start" msgstr "" -#: project/forms/event.py:40 +#: project/forms/event.py:45 msgid "Indicate when the event date will start." msgstr "" -#: project/forms/event.py:43 +#: project/forms/event.py:48 msgid "End" msgstr "" -#: project/forms/event.py:45 +#: project/forms/event.py:50 msgid "" "Indicate when the event date will end. An event can last a maximum of 14 " "days." msgstr "" -#: project/forms/event.py:50 +#: project/forms/event.py:55 msgid "All-day" msgstr "" -#: project/forms/event.py:54 project/templates/_macros.html:1773 +#: project/forms/event.py:59 project/templates/_macros.html:1773 #: project/templates/widget/event_suggestion/create.html:240 msgid "Recurring event" msgstr "" -#: project/forms/event.py:61 project/templates/_macros.html:1322 +#: project/forms/event.py:66 project/templates/_macros.html:1322 msgid "The start must be before the end." msgstr "" -#: project/forms/event.py:67 project/templates/_macros.html:1339 +#: project/forms/event.py:72 project/templates/_macros.html:1339 msgid "An event can last a maximum of 14 days." msgstr "" -#: project/forms/event.py:103 +#: project/forms/event.py:108 msgid "Organizator" msgstr "" -#: project/forms/event.py:116 +#: project/forms/event.py:121 msgid "Enter a short, meaningful name for the event." msgstr "" -#: project/forms/event.py:121 +#: project/forms/event.py:126 msgid "Add an description of the event." msgstr "" -#: project/forms/event.py:126 +#: project/forms/event.py:131 msgid "" "Enter a link to an external website containing more information about the" " event." msgstr "" -#: project/forms/event.py:131 +#: project/forms/event.py:136 msgid "Ticket Link URL" msgstr "" -#: project/forms/event.py:133 +#: project/forms/event.py:138 msgid "Enter a link where tickets can be purchased." msgstr "" -#: project/forms/event.py:136 project/templates/_macros.html:228 +#: project/forms/event.py:141 project/templates/_macros.html:228 msgid "Tags" msgstr "" -#: project/forms/event.py:138 +#: project/forms/event.py:143 msgid "" "Enter keywords with which the event should be found. Words do not need to" " be entered if they are already in the name or description." msgstr "" -#: project/forms/event.py:143 +#: project/forms/event.py:148 msgid "Kid friendly" msgstr "" -#: project/forms/event.py:145 +#: project/forms/event.py:150 msgid "If the event is particularly suitable for children." msgstr "" -#: project/forms/event.py:148 +#: project/forms/event.py:153 msgid "Accessible for free" msgstr "" -#: project/forms/event.py:150 +#: project/forms/event.py:155 msgid "If the event is accessible for free." msgstr "" -#: project/forms/event.py:153 +#: project/forms/event.py:158 msgid "Typical Age from" msgstr "" -#: project/forms/event.py:155 +#: project/forms/event.py:160 msgid "The minimum age that participants should be." msgstr "" -#: project/forms/event.py:158 +#: project/forms/event.py:163 msgid "Typical Age to" msgstr "" -#: project/forms/event.py:160 +#: project/forms/event.py:165 msgid "The maximum age that participants should be." msgstr "" -#: project/forms/event.py:163 +#: project/forms/event.py:168 msgid "Registration required" msgstr "" -#: project/forms/event.py:165 +#: project/forms/event.py:170 msgid "If the participants needs to register for the event." msgstr "" -#: project/forms/event.py:170 project/templates/_macros.html:260 +#: project/forms/event.py:175 project/templates/_macros.html:260 #: project/templates/layout.html:118 msgid "Booked up" msgstr "" -#: project/forms/event.py:172 +#: project/forms/event.py:177 msgid "If the event is booked up or sold out." msgstr "" -#: project/forms/event.py:175 +#: project/forms/event.py:180 msgid "Expected number of participants" msgstr "" -#: project/forms/event.py:177 +#: project/forms/event.py:182 msgid "The estimated expected attendance." msgstr "" -#: project/forms/event.py:180 +#: project/forms/event.py:185 msgid "Price info" msgstr "" -#: project/forms/event.py:182 +#: project/forms/event.py:187 msgid "" "Enter price information in textual form. E.g., different prices for " "adults and children." msgstr "" -#: project/forms/event.py:187 +#: project/forms/event.py:192 msgid "Target group origin" msgstr "" -#: project/forms/event.py:192 +#: project/forms/event.py:197 msgid "EventTargetGroupOrigin.both" msgstr "" -#: project/forms/event.py:196 +#: project/forms/event.py:201 msgid "EventTargetGroupOrigin.tourist" msgstr "" -#: project/forms/event.py:200 +#: project/forms/event.py:205 msgid "EventTargetGroupOrigin.resident" msgstr "" -#: project/forms/event.py:203 +#: project/forms/event.py:208 msgid "" "Choose whether the event is particularly suitable for tourists or " "residents." msgstr "" -#: project/forms/event.py:208 +#: project/forms/event.py:213 msgid "Attendance mode" msgstr "" -#: project/forms/event.py:213 +#: project/forms/event.py:218 msgid "EventAttendanceMode.offline" msgstr "" -#: project/forms/event.py:217 project/templates/layout.html:106 +#: project/forms/event.py:222 project/templates/layout.html:106 msgid "EventAttendanceMode.online" msgstr "" -#: project/forms/event.py:219 project/templates/layout.html:109 +#: project/forms/event.py:224 project/templates/layout.html:109 msgid "EventAttendanceMode.mixed" msgstr "" -#: project/forms/event.py:221 +#: project/forms/event.py:226 msgid "Choose how people can attend the event." msgstr "" -#: project/forms/event.py:225 project/forms/event_place.py:33 +#: project/forms/event.py:230 project/forms/event_place.py:33 #: project/templates/manage/events.html:106 #: project/templates/manage/events.html:141 #: project/templates/manage/places.html:21 @@ -824,59 +824,59 @@ msgstr "" msgid "Photo" msgstr "" -#: project/forms/event.py:227 +#: project/forms/event.py:232 msgid "" "We recommend uploading a photo for the event. It looks a lot more, but of" " course it works without it." msgstr "" -#: project/forms/event.py:242 project/templates/_macros.html:422 +#: project/forms/event.py:247 project/templates/_macros.html:422 #: project/templates/_macros.html:585 msgid "Previous start date" msgstr "" -#: project/forms/event.py:244 +#: project/forms/event.py:249 msgid "Enter when the event should have taken place before it was postponed." msgstr "" -#: project/forms/event.py:249 project/forms/event_suggestion.py:71 +#: project/forms/event.py:254 project/forms/event_suggestion.py:71 msgid "Categories" msgstr "" -#: project/forms/event.py:252 project/forms/event_suggestion.py:74 +#: project/forms/event.py:257 project/forms/event_suggestion.py:74 msgid "Choose categories that fit the event." msgstr "" -#: project/forms/event.py:255 project/forms/reference.py:14 +#: project/forms/event.py:260 project/forms/reference.py:14 #: project/forms/reference.py:27 project/forms/reference_request.py:76 #: project/templates/event/create.html:363 #: project/templates/event/update.html:220 msgid "Rating" msgstr "" -#: project/forms/event.py:259 project/forms/reference.py:18 +#: project/forms/event.py:264 project/forms/reference.py:18 #: project/forms/reference.py:31 project/forms/reference_request.py:80 msgid "" "Choose how relevant the event is to your organization. The value is not " "visible and is used for sorting." msgstr "" -#: project/forms/event.py:264 +#: project/forms/event.py:269 msgid "Co-organizers" msgstr "" -#: project/forms/event.py:267 +#: project/forms/event.py:272 msgid "" "Select optional co-organizers. You can add and modify organizers at " "Organization > Organizers." msgstr "" -#: project/forms/event.py:277 +#: project/forms/event.py:282 msgid "Invalid co-organizer." msgstr "" -#: project/forms/event.py:286 project/forms/event.py:295 -#: project/forms/event.py:373 project/forms/event.py:450 +#: project/forms/event.py:291 project/forms/event.py:300 +#: project/forms/event.py:382 project/forms/event.py:459 #: project/forms/event_suggestion.py:50 project/templates/_macros.html:462 #: project/templates/_macros.html:628 project/templates/event/create.html:288 #: project/templates/event/update.html:170 @@ -887,16 +887,16 @@ msgstr "" msgid "Place" msgstr "" -#: project/forms/event.py:288 +#: project/forms/event.py:293 msgid "Select existing place" msgstr "" -#: project/forms/event.py:289 +#: project/forms/event.py:294 msgid "Enter new place" msgstr "" -#: project/forms/event.py:302 project/forms/event.py:311 -#: project/forms/event.py:381 project/forms/event.py:447 +#: project/forms/event.py:307 project/forms/event.py:316 +#: project/forms/event.py:390 project/forms/event.py:456 #: project/forms/event_date.py:40 project/forms/event_suggestion.py:60 #: project/templates/_macros.html:499 project/templates/_macros.html:671 #: project/templates/event/create.html:257 @@ -908,130 +908,137 @@ msgstr "" msgid "Organizer" msgstr "" -#: project/forms/event.py:304 +#: project/forms/event.py:309 msgid "Select existing organizer" msgstr "" -#: project/forms/event.py:305 +#: project/forms/event.py:310 msgid "Enter new organizer" msgstr "" -#: project/forms/event.py:317 +#: project/forms/event.py:323 project/templates/_macros.html:736 +#: project/templates/event/create.html:374 +#: project/templates/manage/reference_requests_incoming.html:5 +#: project/templates/manage/reference_requests_outgoing.html:5 +msgid "Reference requests" +msgstr "" + +#: project/forms/event.py:326 msgid "Save as draft" msgstr "" -#: project/forms/event.py:318 +#: project/forms/event.py:327 msgid "Save as planned" msgstr "" -#: project/forms/event.py:319 +#: project/forms/event.py:328 msgid "Publish event" msgstr "" -#: project/forms/event.py:355 +#: project/forms/event.py:364 msgid "Select existing place or enter new place" msgstr "" -#: project/forms/event.py:363 +#: project/forms/event.py:372 msgid "Select existing organizer or enter new organizer" msgstr "" -#: project/forms/event.py:376 +#: project/forms/event.py:385 msgid "" "Choose where the event takes place. You can add and modify places at " "Organization > Places." msgstr "" -#: project/forms/event.py:384 +#: project/forms/event.py:393 msgid "" "Select the organizer. You can add and modify organizers at Organization >" " Organizers." msgstr "" -#: project/forms/event.py:390 project/templates/event/update.html:149 +#: project/forms/event.py:399 project/templates/event/update.html:149 #: project/templates/oauth2_token/list.html:21 msgid "Status" msgstr "" -#: project/forms/event.py:393 +#: project/forms/event.py:402 msgid "EventStatus.scheduled" msgstr "" -#: project/forms/event.py:394 project/templates/layout.html:72 +#: project/forms/event.py:403 project/templates/layout.html:72 #: project/templates/layout.html:87 msgid "EventStatus.cancelled" msgstr "" -#: project/forms/event.py:395 project/templates/layout.html:75 +#: project/forms/event.py:404 project/templates/layout.html:75 #: project/templates/layout.html:90 msgid "EventStatus.movedOnline" msgstr "" -#: project/forms/event.py:396 project/templates/layout.html:78 +#: project/forms/event.py:405 project/templates/layout.html:78 #: project/templates/layout.html:93 msgid "EventStatus.postponed" msgstr "" -#: project/forms/event.py:397 project/templates/layout.html:81 +#: project/forms/event.py:406 project/templates/layout.html:81 #: project/templates/layout.html:96 msgid "EventStatus.rescheduled" msgstr "" -#: project/forms/event.py:399 +#: project/forms/event.py:408 msgid "Select the status of the event." msgstr "" -#: project/forms/event.py:403 +#: project/forms/event.py:412 msgid "Public status" msgstr "" -#: project/forms/event.py:406 +#: project/forms/event.py:415 msgid "PublicStatus.published" msgstr "" -#: project/forms/event.py:407 project/templates/_macros.html:269 +#: project/forms/event.py:416 project/templates/_macros.html:269 msgid "PublicStatus.planned" msgstr "" -#: project/forms/event.py:408 project/templates/_macros.html:267 +#: project/forms/event.py:417 project/templates/_macros.html:267 msgid "PublicStatus.draft" msgstr "" -#: project/forms/event.py:410 project/templates/event/create.html:371 +#: project/forms/event.py:419 project/templates/event/create.html:386 msgid "Planned events appear in the scheduling view, but not on public calendars." msgstr "" -#: project/forms/event.py:415 project/templates/event/update.html:5 +#: project/forms/event.py:424 project/templates/event/update.html:5 #: project/templates/event/update.html:117 msgid "Update event" msgstr "" -#: project/forms/event.py:431 project/templates/_macros.html:1279 +#: project/forms/event.py:440 project/templates/_macros.html:1279 #: project/templates/event/actions.html:66 #: project/templates/event/delete.html:6 msgid "Delete event" msgstr "" -#: project/forms/event.py:438 project/forms/event_date.py:14 +#: project/forms/event.py:447 project/forms/event_date.py:14 #: project/forms/planning.py:21 msgid "From" msgstr "" -#: project/forms/event.py:440 project/forms/event_date.py:16 +#: project/forms/event.py:449 project/forms/event_date.py:16 #: project/forms/planning.py:22 msgid "to" msgstr "" -#: project/forms/event.py:442 project/forms/event_date.py:18 +#: project/forms/event.py:451 project/forms/event_date.py:18 msgid "Keyword" msgstr "" -#: project/forms/event.py:444 project/forms/event_date.py:20 +#: project/forms/event.py:453 project/forms/event_date.py:20 #: project/forms/planning.py:24 project/templates/_macros.html:395 msgid "Category" msgstr "" -#: project/forms/event.py:454 project/forms/event_date.py:26 +#: project/forms/event.py:463 project/forms/event_date.py:26 #: project/forms/planning.py:27 project/templates/_macros.html:324 #: project/templates/admin_unit/create.html:39 #: project/templates/admin_unit/update.html:47 @@ -1044,17 +1051,17 @@ msgstr "" msgid "Location" msgstr "" -#: project/forms/event.py:456 project/forms/event_date.py:28 +#: project/forms/event.py:465 project/forms/event_date.py:28 #: project/forms/planning.py:29 msgid "Distance" msgstr "" -#: project/forms/event.py:463 project/forms/event_date.py:49 +#: project/forms/event.py:472 project/forms/event_date.py:49 #: project/forms/planning.py:41 msgid "Exclude recurring events" msgstr "" -#: project/forms/event.py:467 project/forms/event_date.py:54 +#: project/forms/event.py:476 project/forms/event_date.py:54 msgid "Find events" msgstr "" @@ -1477,12 +1484,6 @@ msgstr "" msgid "Reference event" msgstr "" -#: project/templates/_macros.html:736 -#: project/templates/manage/reference_requests_incoming.html:5 -#: project/templates/manage/reference_requests_outgoing.html:5 -msgid "Reference requests" -msgstr "" - #: project/templates/_macros.html:747 project/templates/_macros.html:1286 #: project/templates/event/actions.html:32 #: project/templates/manage/events.html:123 @@ -2201,6 +2202,14 @@ msgstr "" msgid "Target group" msgstr "" +#: project/templates/event/create.html:378 +msgid "References are important for the visibility of your events." +msgstr "" + +#: project/templates/event/create.html:379 +msgid "Select organizations to display your event on their calendars." +msgstr "" + #: project/templates/event/delete.html:10 msgid "" "You are about to delete an event with multiple dates. If you want to " @@ -2630,31 +2639,31 @@ msgstr "" msgid "Invitation successfully deleted" msgstr "" -#: project/views/event.py:181 +#: project/views/event.py:251 msgid "Event successfully published" msgstr "" -#: project/views/event.py:183 +#: project/views/event.py:253 msgid "Draft successfully saved" msgstr "" -#: project/views/event.py:185 +#: project/views/event.py:255 msgid "Event successfully planned" msgstr "" -#: project/views/event.py:228 +#: project/views/event.py:312 msgid "Event successfully updated" msgstr "" -#: project/views/event.py:254 +#: project/views/event.py:338 msgid "Event successfully deleted" msgstr "" -#: project/views/event.py:419 +#: project/views/event.py:503 msgid "Referenced event changed" msgstr "" -#: project/views/event.py:442 +#: project/views/event.py:526 msgid "New event report" msgstr "" @@ -2763,22 +2772,23 @@ msgstr "" msgid "Reference successfully deleted" msgstr "" -#: project/views/reference_request.py:104 -#: project/views/reference_request_review.py:57 -msgid "Reference successfully created" +#: project/views/reference_request.py:124 +#, python-format +msgid "%(organization)s accepted your reference request" msgstr "" -#: project/views/reference_request.py:108 +#: project/views/reference_request.py:131 +#, python-format msgid "" -"Request successfully created. You will be notified after the other " -"organization reviews the event." +"Reference request to %(organization)s successfully created. You will be " +"notified after the other organization reviews the event." msgstr "" -#: project/views/reference_request.py:144 +#: project/views/reference_request.py:154 msgid "New reference request" msgstr "" -#: project/views/reference_request.py:153 +#: project/views/reference_request.py:163 msgid "New reference automatically verified" msgstr "" @@ -2787,6 +2797,10 @@ msgstr "" msgid "Request already verified" msgstr "" +#: project/views/reference_request_review.py:57 +msgid "Reference successfully created" +msgstr "" + #: project/views/reference_request_review.py:65 msgid "Request successfully updated" msgstr "" diff --git a/project/access.py b/project/access.py index 11049f4..6e7fb67 100644 --- a/project/access.py +++ b/project/access.py @@ -128,11 +128,21 @@ def get_admin_units_for_event_reference(event): return result -def can_request_event_reference(event): - if not has_access(event.admin_unit, "reference_request:create"): +def can_request_event_reference_from_admin_unit(admin_unit): + if not has_access(admin_unit, "reference_request:create"): return False - if not event.admin_unit.is_verified: + if not admin_unit.is_verified: + return False + + return True + + +def can_request_event_reference(event): + if not can_request_event_reference_from_admin_unit(event.admin_unit): + return False + + if event.public_status != PublicStatus.published: return False return len(get_admin_units_for_event_reference_request(event)) > 0 diff --git a/project/forms/event.py b/project/forms/event.py index becf03f..6f71902 100644 --- a/project/forms/event.py +++ b/project/forms/event.py @@ -19,7 +19,12 @@ from wtforms.validators import DataRequired, Length, Optional from project.forms.common import Base64ImageForm, distance_choices, event_rating_choices from project.forms.event_place import EventPlaceLocationForm -from project.forms.widgets import CustomDateField, CustomDateTimeField, HTML5StringField +from project.forms.widgets import ( + CustomDateField, + CustomDateTimeField, + HTML5StringField, + MultiCheckboxField, +) from project.models import ( EventAttendanceMode, EventDateDefinition, @@ -314,6 +319,10 @@ class CreateEventForm(BaseEventForm): ) new_organizer = FormField(OrganizerForm, default=lambda: EventOrganizer()) + reference_request_admin_unit_id = MultiCheckboxField( + lazy_gettext("Reference requests"), validators=[Optional()], coerce=int + ) + submit_draft = SubmitField(lazy_gettext("Save as draft")) submit_planned = SubmitField(lazy_gettext("Save as planned")) submit = SubmitField(lazy_gettext("Publish event")) diff --git a/project/services/admin_unit.py b/project/services/admin_unit.py index c2ef1c7..a506ea4 100644 --- a/project/services/admin_unit.py +++ b/project/services/admin_unit.py @@ -1,6 +1,7 @@ import datetime from sqlalchemy import and_, func, or_ +from sqlalchemy.orm import joinedload, load_only from project import db from project.models import ( @@ -296,6 +297,52 @@ def upsert_admin_unit_relation(source_admin_unit_id: int, target_admin_unit_id: return result +def get_admin_unit_relations_for_reference_requests( + target_admin_unit_id: int, limit: int +): + return ( + AdminUnitRelation.query.join( + AdminUnit, + AdminUnitRelation.source_admin_unit_id == AdminUnit.id, + ) + .options( + joinedload(AdminUnitRelation.source_admin_unit).load_only( + AdminUnit.id, AdminUnit.name + ), + ) + .filter( + and_( + AdminUnitRelation.target_admin_unit_id == target_admin_unit_id, + AdminUnit.incoming_reference_requests_allowed, + ) + ) + .order_by( + AdminUnitRelation.auto_verify_event_reference_requests.desc(), + AdminUnitRelation.verify.desc(), + AdminUnitRelation.invited.desc(), + AdminUnitRelation.created_at.desc(), + ) + .limit(limit) + .all() + ) + + +def get_admin_units_for_reference_requests(admin_unit_id: int, limit: int): + return ( + AdminUnit.query.options( + load_only(AdminUnit.id, AdminUnit.name), + ) + .filter( + and_( + AdminUnit.id != admin_unit_id, + AdminUnit.incoming_reference_requests_allowed, + ) + ) + .limit(limit) + .all() + ) + + def get_admin_unit_invitation_query(admin_unit): return AdminUnitInvitation.query.filter( AdminUnitInvitation.admin_unit_id == admin_unit.id diff --git a/project/services/reference.py b/project/services/reference.py index 7c9ed29..1302c64 100644 --- a/project/services/reference.py +++ b/project/services/reference.py @@ -1,5 +1,5 @@ from sqlalchemy import and_ -from sqlalchemy.orm import load_only +from sqlalchemy.orm import defaultload, joinedload, load_only from project import db from project.models import ( @@ -9,6 +9,7 @@ from project.models import ( EventReferenceRequest, EventReferenceRequestReviewStatus, ) +from project.models.admin_unit import AdminUnit def create_event_reference_for_request(request): @@ -69,3 +70,59 @@ def get_relation_outgoing_query(admin_unit): return AdminUnitRelation.query.filter( AdminUnitRelation.source_admin_unit_id == admin_unit.id ) + + +def get_newest_reference_requests(admin_unit_id: int, limit: int): + return ( + EventReferenceRequest.query.join( + Event, EventReferenceRequest.event_id == Event.id + ) + .join( + AdminUnit, + EventReferenceRequest.admin_unit_id == AdminUnit.id, + ) + .options( + load_only(EventReferenceRequest.id), + defaultload(EventReferenceRequest.event).load_only(Event.id), + joinedload(EventReferenceRequest.admin_unit).load_only( + AdminUnit.id, AdminUnit.name + ), + ) + .filter( + and_( + Event.admin_unit_id == admin_unit_id, + AdminUnit.id != admin_unit_id, + AdminUnit.incoming_reference_requests_allowed, + ) + ) + .order_by(EventReferenceRequest.created_at.desc()) + .limit(limit) + .all() + ) + + +def get_newest_references(admin_unit_id: int, limit: int): + return ( + EventReference.query.join(Event, EventReference.event_id == Event.id) + .join( + AdminUnit, + EventReference.admin_unit_id == AdminUnit.id, + ) + .options( + load_only(EventReference.id), + defaultload(EventReference.event).load_only(Event.id), + joinedload(EventReference.admin_unit).load_only( + AdminUnit.id, AdminUnit.name + ), + ) + .filter( + and_( + Event.admin_unit_id == admin_unit_id, + AdminUnit.id != admin_unit_id, + AdminUnit.incoming_reference_requests_allowed, + ) + ) + .order_by(EventReference.created_at.desc()) + .limit(limit) + .all() + ) diff --git a/project/templates/event/create.html b/project/templates/event/create.html index a07a4f5..915daf7 100644 --- a/project/templates/event/create.html +++ b/project/templates/event/create.html @@ -368,6 +368,21 @@ $( function() { {% endif %} + {% if form.reference_request_admin_unit_id.choices|length > 0 %} +
+
+ {{ _('Reference requests') }} +
+
+

+ {{ _('References are important for the visibility of your events.') }} + {{ _('Select organizations to display your event on their calendars.') }} +

+ {{ render_field_with_errors(form.reference_request_admin_unit_id, ri="multicheckbox", label_hidden=True) }} +
+
+ {% endif %} +

{{ _('Planned events appear in the scheduling view, but not on public calendars.') }}

diff --git a/project/translations/de/LC_MESSAGES/messages.mo b/project/translations/de/LC_MESSAGES/messages.mo index 98a72692f04be95bb1940035067c9bead06fdb5a..2469f8aed2c4b61586f9a8c796384a63326f699e 100644 GIT binary patch delta 10148 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 bRtFWwu76M_|Mcdd{6`zh6wldwEcpKbZB`Gw diff --git a/project/translations/de/LC_MESSAGES/messages.po b/project/translations/de/LC_MESSAGES/messages.po index a7a43a1..67a7f99 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-06-09 13:32+0200\n" +"POT-Creation-Date: 2023-06-12 14:29+0200\n" "PO-Revision-Date: 2020-06-07 18:51+0200\n" "Last-Translator: FULL NAME \n" "Language: de\n" @@ -258,7 +258,7 @@ msgstr "Nutzer löschen" #: project/forms/admin.py:34 project/forms/admin_unit.py:60 #: project/forms/admin_unit_member.py:12 project/forms/admin_unit_member.py:25 -#: project/forms/admin_unit_member.py:30 project/forms/event.py:107 +#: project/forms/admin_unit_member.py:30 project/forms/event.py:112 #: project/forms/event_suggestion.py:38 project/forms/organizer.py:33 #: project/forms/user.py:18 project/forms/user.py:23 #: project/templates/_macros.html:246 project/templates/_macros.html:1561 @@ -331,7 +331,7 @@ msgstr "Organisation löschen" #: project/forms/admin.py:76 project/forms/admin_unit.py:149 #: project/forms/admin_unit.py:154 project/forms/admin_unit.py:159 -#: project/forms/event.py:85 project/forms/event.py:114 +#: project/forms/event.py:90 project/forms/event.py:119 #: project/forms/event_place.py:30 project/forms/event_place.py:56 #: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66 #: project/forms/organizer.py:30 project/forms/organizer.py:58 @@ -374,7 +374,7 @@ msgstr "Newsletter senden" msgid "Street" msgstr "Straße" -#: project/forms/admin_unit.py:18 project/forms/event.py:461 +#: project/forms/admin_unit.py:18 project/forms/event.py:470 #: project/forms/event_date.py:52 project/forms/event_place.py:16 #: project/forms/organizer.py:16 project/forms/planning.py:44 msgid "Postal code" @@ -423,7 +423,7 @@ msgstr "" msgid "Short name must contain only letters numbers or underscore" msgstr "Der Kurzname darf nur Buchstaben, Nummern und Unterstriche enthalten" -#: project/forms/admin_unit.py:55 project/forms/event.py:119 +#: project/forms/admin_unit.py:55 project/forms/event.py:124 #: project/forms/event_place.py:34 msgid "Description" msgstr "Beschreibung" @@ -432,20 +432,20 @@ msgstr "Beschreibung" msgid "Describe the organization in a few words" msgstr "Beschreibe die Organisation in wenigen Worten" -#: project/forms/admin_unit.py:59 project/forms/event.py:106 -#: project/forms/event.py:124 project/forms/event_place.py:32 +#: project/forms/admin_unit.py:59 project/forms/event.py:111 +#: project/forms/event.py:129 project/forms/event_place.py:32 #: project/forms/organizer.py:32 project/templates/manage/organizers.html:21 msgid "Link URL" msgstr "Link URL" -#: project/forms/admin_unit.py:61 project/forms/event.py:108 +#: project/forms/admin_unit.py:61 project/forms/event.py:113 #: project/forms/event_suggestion.py:31 project/forms/organizer.py:34 #: project/templates/_macros.html:309 #: project/templates/manage/organizers.html:20 msgid "Phone" msgstr "Telefon" -#: project/forms/admin_unit.py:62 project/forms/event.py:109 +#: project/forms/admin_unit.py:62 project/forms/event.py:114 #: project/forms/organizer.py:35 project/templates/_macros.html:317 msgid "Fax" msgstr "Fax" @@ -660,54 +660,54 @@ msgstr "50 km" msgid "100 km" msgstr "100 km" -#: project/forms/event.py:38 project/templates/manage/events.html:102 +#: project/forms/event.py:43 project/templates/manage/events.html:102 msgid "Start" msgstr "Beginn" -#: project/forms/event.py:40 +#: project/forms/event.py:45 msgid "Indicate when the event date will start." msgstr "Gib an, wann der Termin beginnt." -#: project/forms/event.py:43 +#: project/forms/event.py:48 msgid "End" msgstr "Ende" -#: project/forms/event.py:45 +#: project/forms/event.py:50 msgid "" "Indicate when the event date will end. An event can last a maximum of 14 " "days." msgstr "Gib an, wann der Termin endet. Ein Termin darf maximal 14 Tage dauern." -#: project/forms/event.py:50 +#: project/forms/event.py:55 msgid "All-day" msgstr "Ganztägig" -#: project/forms/event.py:54 project/templates/_macros.html:1773 +#: project/forms/event.py:59 project/templates/_macros.html:1773 #: project/templates/widget/event_suggestion/create.html:240 msgid "Recurring event" msgstr "Serientermin" -#: project/forms/event.py:61 project/templates/_macros.html:1322 +#: project/forms/event.py:66 project/templates/_macros.html:1322 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:1339 +#: project/forms/event.py:72 project/templates/_macros.html:1339 msgid "An event can last a maximum of 14 days." msgstr "Eine Veranstaltung darf maximal 14 Tage dauern." -#: project/forms/event.py:103 +#: project/forms/event.py:108 msgid "Organizator" msgstr "Veranstalter" -#: project/forms/event.py:116 +#: project/forms/event.py:121 msgid "Enter a short, meaningful name for the event." msgstr "Gib einen kurzen, aussagekräftigen Namen für die Veranstaltung ein." -#: project/forms/event.py:121 +#: project/forms/event.py:126 msgid "Add an description of the event." msgstr "Füge der Veranstaltung eine Beschreibung hinzu." -#: project/forms/event.py:126 +#: project/forms/event.py:131 msgid "" "Enter a link to an external website containing more information about the" " event." @@ -715,19 +715,19 @@ msgstr "" "Gib einen Link zu einer externen Website ein, die weitere Informationen " "zur Veranstaltung enthält." -#: project/forms/event.py:131 +#: project/forms/event.py:136 msgid "Ticket Link URL" msgstr "Ticket Link" -#: project/forms/event.py:133 +#: project/forms/event.py:138 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:228 +#: project/forms/event.py:141 project/templates/_macros.html:228 msgid "Tags" msgstr "Stichworte" -#: project/forms/event.py:138 +#: project/forms/event.py:143 msgid "" "Enter keywords with which the event should be found. Words do not need to" " be entered if they are already in the name or description." @@ -736,68 +736,68 @@ msgstr "" "Worte müssen nicht eingegeben werden, wenn sie bereits im Namen oder in " "der Beschreibung enthalten sind." -#: project/forms/event.py:143 +#: project/forms/event.py:148 msgid "Kid friendly" msgstr "Für Kinder geeignet" -#: project/forms/event.py:145 +#: project/forms/event.py:150 msgid "If the event is particularly suitable for children." msgstr "Wenn die Veranstaltung besonders für Kinder geeignet ist." -#: project/forms/event.py:148 +#: project/forms/event.py:153 msgid "Accessible for free" msgstr "Kostenlos zugänglich" -#: project/forms/event.py:150 +#: project/forms/event.py:155 msgid "If the event is accessible for free." msgstr "Wenn die Veranstaltung kostenlos zugänglich ist." -#: project/forms/event.py:153 +#: project/forms/event.py:158 msgid "Typical Age from" msgstr "Typisches Alter von" -#: project/forms/event.py:155 +#: project/forms/event.py:160 msgid "The minimum age that participants should be." msgstr "Das Mindestalter, das die Teilnehmer haben sollten." -#: project/forms/event.py:158 +#: project/forms/event.py:163 msgid "Typical Age to" msgstr "Typisches Alter bis" -#: project/forms/event.py:160 +#: project/forms/event.py:165 msgid "The maximum age that participants should be." msgstr "Das maximale Alter, das die Teilnehmer haben sollten." -#: project/forms/event.py:163 +#: project/forms/event.py:168 msgid "Registration required" msgstr "Anmeldung erforderlich" -#: project/forms/event.py:165 +#: project/forms/event.py:170 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:260 +#: project/forms/event.py:175 project/templates/_macros.html:260 #: project/templates/layout.html:118 msgid "Booked up" msgstr "Ausgebucht" -#: project/forms/event.py:172 +#: project/forms/event.py:177 msgid "If the event is booked up or sold out." msgstr "Wenn die Veranstaltung ausgebucht oder ausverkauft ist." -#: project/forms/event.py:175 +#: project/forms/event.py:180 msgid "Expected number of participants" msgstr "Erwartete Teilnehmerzahl" -#: project/forms/event.py:177 +#: project/forms/event.py:182 msgid "The estimated expected attendance." msgstr "Die geschätzte erwartete Teilnehmerzahl." -#: project/forms/event.py:180 +#: project/forms/event.py:185 msgid "Price info" msgstr "Preisinformation" -#: project/forms/event.py:182 +#: project/forms/event.py:187 msgid "" "Enter price information in textual form. E.g., different prices for " "adults and children." @@ -805,23 +805,23 @@ msgstr "" "Gib die Preisinformationen in Textform ein. Z.B. unterschiedliche Preise " "für Erwachsene und Kinder." -#: project/forms/event.py:187 +#: project/forms/event.py:192 msgid "Target group origin" msgstr "Für Touristen/Einwohner geeignet" -#: project/forms/event.py:192 +#: project/forms/event.py:197 msgid "EventTargetGroupOrigin.both" msgstr "Für Touristen und Einwohner" -#: project/forms/event.py:196 +#: project/forms/event.py:201 msgid "EventTargetGroupOrigin.tourist" msgstr "Hauptsächlich für Touristen" -#: project/forms/event.py:200 +#: project/forms/event.py:205 msgid "EventTargetGroupOrigin.resident" msgstr "Hauptsächlich für Einwohner" -#: project/forms/event.py:203 +#: project/forms/event.py:208 msgid "" "Choose whether the event is particularly suitable for tourists or " "residents." @@ -829,27 +829,27 @@ msgstr "" "Wähle, ob die Veranstaltung besonders für Touristen oder Einwohner " "geeignet ist." -#: project/forms/event.py:208 +#: project/forms/event.py:213 msgid "Attendance mode" msgstr "Teilnahme" -#: project/forms/event.py:213 +#: project/forms/event.py:218 msgid "EventAttendanceMode.offline" msgstr "Präsenzveranstaltung" -#: project/forms/event.py:217 project/templates/layout.html:106 +#: project/forms/event.py:222 project/templates/layout.html:106 msgid "EventAttendanceMode.online" msgstr "Online" -#: project/forms/event.py:219 project/templates/layout.html:109 +#: project/forms/event.py:224 project/templates/layout.html:109 msgid "EventAttendanceMode.mixed" msgstr "Präsenzveranstaltung und online" -#: project/forms/event.py:221 +#: project/forms/event.py:226 msgid "Choose how people can attend the event." msgstr "Wähle aus, wie Personen an der Veranstaltung teilnehmen können." -#: project/forms/event.py:225 project/forms/event_place.py:33 +#: project/forms/event.py:230 project/forms/event_place.py:33 #: project/templates/manage/events.html:106 #: project/templates/manage/events.html:141 #: project/templates/manage/places.html:21 @@ -858,7 +858,7 @@ msgstr "Wähle aus, wie Personen an der Veranstaltung teilnehmen können." msgid "Photo" msgstr "Foto" -#: project/forms/event.py:227 +#: project/forms/event.py:232 msgid "" "We recommend uploading a photo for the event. It looks a lot more, but of" " course it works without it." @@ -866,33 +866,33 @@ 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:422 +#: project/forms/event.py:247 project/templates/_macros.html:422 #: project/templates/_macros.html:585 msgid "Previous start date" msgstr "Vorheriges Startdatum" -#: project/forms/event.py:244 +#: project/forms/event.py:249 msgid "Enter when the event should have taken place before it was postponed." msgstr "" "Gib ein, wann die Veranstaltung hätte stattfinden sollen, bevor sie " "verschoben wurde." -#: project/forms/event.py:249 project/forms/event_suggestion.py:71 +#: project/forms/event.py:254 project/forms/event_suggestion.py:71 msgid "Categories" msgstr "Kategorien" -#: project/forms/event.py:252 project/forms/event_suggestion.py:74 +#: project/forms/event.py:257 project/forms/event_suggestion.py:74 msgid "Choose categories that fit the event." msgstr "Wähle Kategorien, die zur Veranstaltung passen." -#: project/forms/event.py:255 project/forms/reference.py:14 +#: project/forms/event.py:260 project/forms/reference.py:14 #: project/forms/reference.py:27 project/forms/reference_request.py:76 #: project/templates/event/create.html:363 #: project/templates/event/update.html:220 msgid "Rating" msgstr "Bewertung" -#: project/forms/event.py:259 project/forms/reference.py:18 +#: project/forms/event.py:264 project/forms/reference.py:18 #: project/forms/reference.py:31 project/forms/reference_request.py:80 msgid "" "Choose how relevant the event is to your organization. The value is not " @@ -901,11 +901,11 @@ msgstr "" "Wähle aus, wie relevant die Veranstaltung für deine Organisation ist. Der" " Wert ist nicht sichtbar und dient der Sortierung." -#: project/forms/event.py:264 +#: project/forms/event.py:269 msgid "Co-organizers" msgstr "Mitveranstalter" -#: project/forms/event.py:267 +#: project/forms/event.py:272 msgid "" "Select optional co-organizers. You can add and modify organizers at " "Organization > Organizers." @@ -913,12 +913,12 @@ msgstr "" "Wähle optionale Mitveranstalter. Du kannst Veranstalter unter " "Organisation > Veranstalter hinzufügen und ändern." -#: project/forms/event.py:277 +#: project/forms/event.py:282 msgid "Invalid co-organizer." msgstr "Ungültiger Mitveranstalter." -#: project/forms/event.py:286 project/forms/event.py:295 -#: project/forms/event.py:373 project/forms/event.py:450 +#: project/forms/event.py:291 project/forms/event.py:300 +#: project/forms/event.py:382 project/forms/event.py:459 #: project/forms/event_suggestion.py:50 project/templates/_macros.html:462 #: project/templates/_macros.html:628 project/templates/event/create.html:288 #: project/templates/event/update.html:170 @@ -929,16 +929,16 @@ msgstr "Ungültiger Mitveranstalter." msgid "Place" msgstr "Ort" -#: project/forms/event.py:288 +#: project/forms/event.py:293 msgid "Select existing place" msgstr "Vorhandenen Ort auswählen" -#: project/forms/event.py:289 +#: project/forms/event.py:294 msgid "Enter new place" msgstr "Neuen Ort eingeben" -#: project/forms/event.py:302 project/forms/event.py:311 -#: project/forms/event.py:381 project/forms/event.py:447 +#: project/forms/event.py:307 project/forms/event.py:316 +#: project/forms/event.py:390 project/forms/event.py:456 #: project/forms/event_date.py:40 project/forms/event_suggestion.py:60 #: project/templates/_macros.html:499 project/templates/_macros.html:671 #: project/templates/event/create.html:257 @@ -950,35 +950,42 @@ msgstr "Neuen Ort eingeben" msgid "Organizer" msgstr "Veranstalter" -#: project/forms/event.py:304 +#: project/forms/event.py:309 msgid "Select existing organizer" msgstr "Vorhandenen Veranstalter auswählen" -#: project/forms/event.py:305 +#: project/forms/event.py:310 msgid "Enter new organizer" msgstr "Neuen Veranstalter eingeben" -#: project/forms/event.py:317 +#: project/forms/event.py:323 project/templates/_macros.html:736 +#: project/templates/event/create.html:374 +#: project/templates/manage/reference_requests_incoming.html:5 +#: project/templates/manage/reference_requests_outgoing.html:5 +msgid "Reference requests" +msgstr "Empfehlungsanfragen" + +#: project/forms/event.py:326 msgid "Save as draft" msgstr "Als Entwurf speichern" -#: project/forms/event.py:318 +#: project/forms/event.py:327 msgid "Save as planned" msgstr "Als geplant speichern" -#: project/forms/event.py:319 +#: project/forms/event.py:328 msgid "Publish event" msgstr "Veranstaltung veröffentlichen" -#: project/forms/event.py:355 +#: project/forms/event.py:364 msgid "Select existing place or enter new place" msgstr "Existierenden Ort wählen oder neuen Ort eingeben" -#: project/forms/event.py:363 +#: project/forms/event.py:372 msgid "Select existing organizer or enter new organizer" msgstr "Wähle einen vorhandenen Veranstalter oder gib einen neuen Veranstalter ein" -#: project/forms/event.py:376 +#: project/forms/event.py:385 msgid "" "Choose where the event takes place. You can add and modify places at " "Organization > Places." @@ -986,7 +993,7 @@ msgstr "" "Wähle, wo die Veranstaltung stattfindet. Du kannst Orte unter " "Organisation > Orte hinzufügen und ändern." -#: project/forms/event.py:384 +#: project/forms/event.py:393 msgid "" "Select the organizer. You can add and modify organizers at Organization >" " Organizers." @@ -994,92 +1001,92 @@ msgstr "" "Wähle den Veranstalter. Du kannst Veranstalter unter Organisation > " "Veranstalter hinzufügen und ändern." -#: project/forms/event.py:390 project/templates/event/update.html:149 +#: project/forms/event.py:399 project/templates/event/update.html:149 #: project/templates/oauth2_token/list.html:21 msgid "Status" msgstr "Status" -#: project/forms/event.py:393 +#: project/forms/event.py:402 msgid "EventStatus.scheduled" msgstr "Geplant" -#: project/forms/event.py:394 project/templates/layout.html:72 +#: project/forms/event.py:403 project/templates/layout.html:72 #: project/templates/layout.html:87 msgid "EventStatus.cancelled" msgstr "Abgesagt" -#: project/forms/event.py:395 project/templates/layout.html:75 +#: project/forms/event.py:404 project/templates/layout.html:75 #: project/templates/layout.html:90 msgid "EventStatus.movedOnline" msgstr "Online verschoben" -#: project/forms/event.py:396 project/templates/layout.html:78 +#: project/forms/event.py:405 project/templates/layout.html:78 #: project/templates/layout.html:93 msgid "EventStatus.postponed" msgstr "Verschoben" -#: project/forms/event.py:397 project/templates/layout.html:81 +#: project/forms/event.py:406 project/templates/layout.html:81 #: project/templates/layout.html:96 msgid "EventStatus.rescheduled" msgstr "Neu angesetzt" -#: project/forms/event.py:399 +#: project/forms/event.py:408 msgid "Select the status of the event." msgstr "Wähle den Status der Veranstaltung." -#: project/forms/event.py:403 +#: project/forms/event.py:412 msgid "Public status" msgstr "Öffentlicher Status" -#: project/forms/event.py:406 +#: project/forms/event.py:415 msgid "PublicStatus.published" msgstr "Veröffentlicht" -#: project/forms/event.py:407 project/templates/_macros.html:269 +#: project/forms/event.py:416 project/templates/_macros.html:269 msgid "PublicStatus.planned" msgstr "In Planung" -#: project/forms/event.py:408 project/templates/_macros.html:267 +#: project/forms/event.py:417 project/templates/_macros.html:267 msgid "PublicStatus.draft" msgstr "Entwurf" -#: project/forms/event.py:410 project/templates/event/create.html:371 +#: project/forms/event.py:419 project/templates/event/create.html:386 msgid "Planned events appear in the scheduling view, but not on public calendars." msgstr "" "Geplante Veranstaltungen werden in der Planungsansicht angezeigt, aber " "nicht in öffentlichen Kalendern." -#: project/forms/event.py:415 project/templates/event/update.html:5 +#: project/forms/event.py:424 project/templates/event/update.html:5 #: project/templates/event/update.html:117 msgid "Update event" msgstr "Veranstaltung aktualisieren" -#: project/forms/event.py:431 project/templates/_macros.html:1279 +#: project/forms/event.py:440 project/templates/_macros.html:1279 #: project/templates/event/actions.html:66 #: project/templates/event/delete.html:6 msgid "Delete event" msgstr "Veranstaltung löschen" -#: project/forms/event.py:438 project/forms/event_date.py:14 +#: project/forms/event.py:447 project/forms/event_date.py:14 #: project/forms/planning.py:21 msgid "From" msgstr "Von" -#: project/forms/event.py:440 project/forms/event_date.py:16 +#: project/forms/event.py:449 project/forms/event_date.py:16 #: project/forms/planning.py:22 msgid "to" msgstr "bis" -#: project/forms/event.py:442 project/forms/event_date.py:18 +#: project/forms/event.py:451 project/forms/event_date.py:18 msgid "Keyword" msgstr "Stichwort" -#: project/forms/event.py:444 project/forms/event_date.py:20 +#: project/forms/event.py:453 project/forms/event_date.py:20 #: project/forms/planning.py:24 project/templates/_macros.html:395 msgid "Category" msgstr "Kategorie" -#: project/forms/event.py:454 project/forms/event_date.py:26 +#: project/forms/event.py:463 project/forms/event_date.py:26 #: project/forms/planning.py:27 project/templates/_macros.html:324 #: project/templates/admin_unit/create.html:39 #: project/templates/admin_unit/update.html:47 @@ -1092,17 +1099,17 @@ msgstr "Kategorie" msgid "Location" msgstr "Standort" -#: project/forms/event.py:456 project/forms/event_date.py:28 +#: project/forms/event.py:465 project/forms/event_date.py:28 #: project/forms/planning.py:29 msgid "Distance" msgstr "Distanz" -#: project/forms/event.py:463 project/forms/event_date.py:49 +#: project/forms/event.py:472 project/forms/event_date.py:49 #: project/forms/planning.py:41 msgid "Exclude recurring events" msgstr "Serientermine nicht anzeigen" -#: project/forms/event.py:467 project/forms/event_date.py:54 +#: project/forms/event.py:476 project/forms/event_date.py:54 msgid "Find events" msgstr "Veranstaltungen finden" @@ -1538,12 +1545,6 @@ msgstr "Empfohlen von" msgid "Reference event" msgstr "Veranstaltung empfehlen" -#: project/templates/_macros.html:736 -#: project/templates/manage/reference_requests_incoming.html:5 -#: project/templates/manage/reference_requests_outgoing.html:5 -msgid "Reference requests" -msgstr "Empfehlungsanfragen" - #: project/templates/_macros.html:747 project/templates/_macros.html:1286 #: project/templates/event/actions.html:32 #: project/templates/manage/events.html:123 @@ -2268,6 +2269,14 @@ msgstr "Zugang" msgid "Target group" msgstr "Zielgruppe" +#: project/templates/event/create.html:378 +msgid "References are important for the visibility of your events." +msgstr "Empfehlungen sind wichtig für die Sichtbarkeit deiner Veranstaltungen." + +#: project/templates/event/create.html:379 +msgid "Select organizations to display your event on their calendars." +msgstr "Wähle Organisationen aus, die deine Veranstaltung in ihren Kalendern anzeigen sollen." + #: project/templates/event/delete.html:10 msgid "" "You are about to delete an event with multiple dates. If you want to " @@ -2709,31 +2718,31 @@ msgstr "Die eingegebene Email passt nicht zur Email der Einladung" msgid "Invitation successfully deleted" msgstr "Einladung erfolgreich gelöscht" -#: project/views/event.py:181 +#: project/views/event.py:251 msgid "Event successfully published" msgstr "Veranstaltung erfolgreich veröffentlicht" -#: project/views/event.py:183 +#: project/views/event.py:253 msgid "Draft successfully saved" msgstr "Entwurf erfolgreich gespeichert" -#: project/views/event.py:185 +#: project/views/event.py:255 msgid "Event successfully planned" msgstr "Veranstaltung erfolgreich geplant" -#: project/views/event.py:228 +#: project/views/event.py:312 msgid "Event successfully updated" msgstr "Veranstaltung erfolgreich aktualisiert" -#: project/views/event.py:254 +#: project/views/event.py:338 msgid "Event successfully deleted" msgstr "Veranstaltung erfolgreich gelöscht" -#: project/views/event.py:419 +#: project/views/event.py:503 msgid "Referenced event changed" msgstr "Empfohlene Veranstaltung wurde geändert" -#: project/views/event.py:442 +#: project/views/event.py:526 msgid "New event report" msgstr "Neue Meldung zu einer Veranstaltung" @@ -2844,24 +2853,26 @@ msgstr "Empfehlung erfolgreich empfohlen" msgid "Reference successfully deleted" msgstr "Empfehlung erfolgreich gelöscht" -#: project/views/reference_request.py:104 -#: project/views/reference_request_review.py:57 -msgid "Reference successfully created" -msgstr "Empfehlung erfolgreich erstellt" +#: project/views/reference_request.py:124 +#, python-format +msgid "%(organization)s accepted your reference request" +msgstr "%(organization)s hat deine Empfehlungsanfrage akzeptiert" -#: project/views/reference_request.py:108 +#: project/views/reference_request.py:131 +#, python-format msgid "" -"Request successfully created. You will be notified after the other " -"organization reviews the event." +"Reference request to %(organization)s successfully created. You will be " +"notified after the other organization reviews the event." msgstr "" -"Empfehlungsanfrage erfolgreich erstellt. Du wirst benachrichtigt, nachdem" -" die andere Organisation die Veranstaltung geprüft hat." +"Empfehlungsanfrage an %(organization)s erfolgreich erstellt. Du wirst " +"benachrichtigt, nachdem die andere Organisation die Veranstaltung geprüft" +" hat." -#: project/views/reference_request.py:144 +#: project/views/reference_request.py:154 msgid "New reference request" msgstr "Neue Empfehlungsanfrage" -#: project/views/reference_request.py:153 +#: project/views/reference_request.py:163 msgid "New reference automatically verified" msgstr "Neue automatisch verifizierte Empfehlung" @@ -2870,6 +2881,10 @@ msgstr "Neue automatisch verifizierte Empfehlung" msgid "Request already verified" msgstr "Empfehlungsanfrage ist bereits verifiziert" +#: project/views/reference_request_review.py:57 +msgid "Reference successfully created" +msgstr "Empfehlung erfolgreich erstellt" + #: project/views/reference_request_review.py:65 msgid "Request successfully updated" msgstr "Empfehlungsanfrage erfolgreich aktualisiert" @@ -3052,3 +3067,12 @@ msgstr "Neue Veranstaltung zu prüfen" #~ msgid "Select the public status of the event." #~ msgstr "Wähle den öffentlichen Status der Veranstaltung." +#~ msgid "" +#~ "Request successfully created. You will " +#~ "be notified after the other organization" +#~ " reviews the event." +#~ msgstr "" +#~ "Empfehlungsanfrage erfolgreich erstellt. Du " +#~ "wirst benachrichtigt, nachdem die andere " +#~ "Organisation die Veranstaltung geprüft hat." + diff --git a/project/translations/en/LC_MESSAGES/messages.mo b/project/translations/en/LC_MESSAGES/messages.mo index a7dd873343372b826b8078bde92bae337eec2a24..0a27c1794aeeacf2bdbd99b9a8b400bed65017e7 100644 GIT binary patch delta 21 dcmaDa|6YE>D^3nWBLzbfDD^3mrO9ew?D`TV0pE&=r0svh>2m}BC diff --git a/project/translations/en/LC_MESSAGES/messages.po b/project/translations/en/LC_MESSAGES/messages.po index a6928b3..51d2015 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-06-09 13:32+0200\n" +"POT-Creation-Date: 2023-06-12 14:29+0200\n" "PO-Revision-Date: 2021-04-30 15:04+0200\n" "Last-Translator: FULL NAME \n" "Language: en\n" @@ -258,7 +258,7 @@ msgstr "" #: project/forms/admin.py:34 project/forms/admin_unit.py:60 #: project/forms/admin_unit_member.py:12 project/forms/admin_unit_member.py:25 -#: project/forms/admin_unit_member.py:30 project/forms/event.py:107 +#: project/forms/admin_unit_member.py:30 project/forms/event.py:112 #: project/forms/event_suggestion.py:38 project/forms/organizer.py:33 #: project/forms/user.py:18 project/forms/user.py:23 #: project/templates/_macros.html:246 project/templates/_macros.html:1561 @@ -323,7 +323,7 @@ msgstr "" #: project/forms/admin.py:76 project/forms/admin_unit.py:149 #: project/forms/admin_unit.py:154 project/forms/admin_unit.py:159 -#: project/forms/event.py:85 project/forms/event.py:114 +#: project/forms/event.py:90 project/forms/event.py:119 #: project/forms/event_place.py:30 project/forms/event_place.py:56 #: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66 #: project/forms/organizer.py:30 project/forms/organizer.py:58 @@ -366,7 +366,7 @@ msgstr "" msgid "Street" msgstr "" -#: project/forms/admin_unit.py:18 project/forms/event.py:461 +#: project/forms/admin_unit.py:18 project/forms/event.py:470 #: project/forms/event_date.py:52 project/forms/event_place.py:16 #: project/forms/organizer.py:16 project/forms/planning.py:44 msgid "Postal code" @@ -412,7 +412,7 @@ msgstr "" msgid "Short name must contain only letters numbers or underscore" msgstr "" -#: project/forms/admin_unit.py:55 project/forms/event.py:119 +#: project/forms/admin_unit.py:55 project/forms/event.py:124 #: project/forms/event_place.py:34 msgid "Description" msgstr "" @@ -421,20 +421,20 @@ msgstr "" msgid "Describe the organization in a few words" msgstr "" -#: project/forms/admin_unit.py:59 project/forms/event.py:106 -#: project/forms/event.py:124 project/forms/event_place.py:32 +#: project/forms/admin_unit.py:59 project/forms/event.py:111 +#: project/forms/event.py:129 project/forms/event_place.py:32 #: project/forms/organizer.py:32 project/templates/manage/organizers.html:21 msgid "Link URL" msgstr "" -#: project/forms/admin_unit.py:61 project/forms/event.py:108 +#: project/forms/admin_unit.py:61 project/forms/event.py:113 #: project/forms/event_suggestion.py:31 project/forms/organizer.py:34 #: project/templates/_macros.html:309 #: project/templates/manage/organizers.html:20 msgid "Phone" msgstr "" -#: project/forms/admin_unit.py:62 project/forms/event.py:109 +#: project/forms/admin_unit.py:62 project/forms/event.py:114 #: project/forms/organizer.py:35 project/templates/_macros.html:317 msgid "Fax" msgstr "" @@ -636,187 +636,187 @@ msgstr "" msgid "100 km" msgstr "" -#: project/forms/event.py:38 project/templates/manage/events.html:102 +#: project/forms/event.py:43 project/templates/manage/events.html:102 msgid "Start" msgstr "" -#: project/forms/event.py:40 +#: project/forms/event.py:45 msgid "Indicate when the event date will start." msgstr "" -#: project/forms/event.py:43 +#: project/forms/event.py:48 msgid "End" msgstr "" -#: project/forms/event.py:45 +#: project/forms/event.py:50 msgid "" "Indicate when the event date will end. An event can last a maximum of 14 " "days." msgstr "" -#: project/forms/event.py:50 +#: project/forms/event.py:55 msgid "All-day" msgstr "" -#: project/forms/event.py:54 project/templates/_macros.html:1773 +#: project/forms/event.py:59 project/templates/_macros.html:1773 #: project/templates/widget/event_suggestion/create.html:240 msgid "Recurring event" msgstr "" -#: project/forms/event.py:61 project/templates/_macros.html:1322 +#: project/forms/event.py:66 project/templates/_macros.html:1322 msgid "The start must be before the end." msgstr "" -#: project/forms/event.py:67 project/templates/_macros.html:1339 +#: project/forms/event.py:72 project/templates/_macros.html:1339 msgid "An event can last a maximum of 14 days." msgstr "" -#: project/forms/event.py:103 +#: project/forms/event.py:108 msgid "Organizator" msgstr "" -#: project/forms/event.py:116 +#: project/forms/event.py:121 msgid "Enter a short, meaningful name for the event." msgstr "" -#: project/forms/event.py:121 +#: project/forms/event.py:126 msgid "Add an description of the event." msgstr "" -#: project/forms/event.py:126 +#: project/forms/event.py:131 msgid "" "Enter a link to an external website containing more information about the" " event." msgstr "" -#: project/forms/event.py:131 +#: project/forms/event.py:136 msgid "Ticket Link URL" msgstr "" -#: project/forms/event.py:133 +#: project/forms/event.py:138 msgid "Enter a link where tickets can be purchased." msgstr "" -#: project/forms/event.py:136 project/templates/_macros.html:228 +#: project/forms/event.py:141 project/templates/_macros.html:228 msgid "Tags" msgstr "" -#: project/forms/event.py:138 +#: project/forms/event.py:143 msgid "" "Enter keywords with which the event should be found. Words do not need to" " be entered if they are already in the name or description." msgstr "" -#: project/forms/event.py:143 +#: project/forms/event.py:148 msgid "Kid friendly" msgstr "" -#: project/forms/event.py:145 +#: project/forms/event.py:150 msgid "If the event is particularly suitable for children." msgstr "" -#: project/forms/event.py:148 +#: project/forms/event.py:153 msgid "Accessible for free" msgstr "" -#: project/forms/event.py:150 +#: project/forms/event.py:155 msgid "If the event is accessible for free." msgstr "" -#: project/forms/event.py:153 +#: project/forms/event.py:158 msgid "Typical Age from" msgstr "" -#: project/forms/event.py:155 +#: project/forms/event.py:160 msgid "The minimum age that participants should be." msgstr "" -#: project/forms/event.py:158 +#: project/forms/event.py:163 msgid "Typical Age to" msgstr "" -#: project/forms/event.py:160 +#: project/forms/event.py:165 msgid "The maximum age that participants should be." msgstr "" -#: project/forms/event.py:163 +#: project/forms/event.py:168 msgid "Registration required" msgstr "" -#: project/forms/event.py:165 +#: project/forms/event.py:170 msgid "If the participants needs to register for the event." msgstr "" -#: project/forms/event.py:170 project/templates/_macros.html:260 +#: project/forms/event.py:175 project/templates/_macros.html:260 #: project/templates/layout.html:118 msgid "Booked up" msgstr "" -#: project/forms/event.py:172 +#: project/forms/event.py:177 msgid "If the event is booked up or sold out." msgstr "" -#: project/forms/event.py:175 +#: project/forms/event.py:180 msgid "Expected number of participants" msgstr "" -#: project/forms/event.py:177 +#: project/forms/event.py:182 msgid "The estimated expected attendance." msgstr "" -#: project/forms/event.py:180 +#: project/forms/event.py:185 msgid "Price info" msgstr "" -#: project/forms/event.py:182 +#: project/forms/event.py:187 msgid "" "Enter price information in textual form. E.g., different prices for " "adults and children." msgstr "" -#: project/forms/event.py:187 +#: project/forms/event.py:192 msgid "Target group origin" msgstr "Suitable for tourists / residents" -#: project/forms/event.py:192 +#: project/forms/event.py:197 msgid "EventTargetGroupOrigin.both" msgstr "For tourists and residents" -#: project/forms/event.py:196 +#: project/forms/event.py:201 msgid "EventTargetGroupOrigin.tourist" msgstr "Mainly for tourists" -#: project/forms/event.py:200 +#: project/forms/event.py:205 msgid "EventTargetGroupOrigin.resident" msgstr "Mainly for residents" -#: project/forms/event.py:203 +#: project/forms/event.py:208 msgid "" "Choose whether the event is particularly suitable for tourists or " "residents." msgstr "" -#: project/forms/event.py:208 +#: project/forms/event.py:213 msgid "Attendance mode" msgstr "" -#: project/forms/event.py:213 +#: project/forms/event.py:218 msgid "EventAttendanceMode.offline" msgstr "Normal (Offline)" -#: project/forms/event.py:217 project/templates/layout.html:106 +#: project/forms/event.py:222 project/templates/layout.html:106 msgid "EventAttendanceMode.online" msgstr "Online" -#: project/forms/event.py:219 project/templates/layout.html:109 +#: project/forms/event.py:224 project/templates/layout.html:109 msgid "EventAttendanceMode.mixed" msgstr "Online and offline" -#: project/forms/event.py:221 +#: project/forms/event.py:226 msgid "Choose how people can attend the event." msgstr "" -#: project/forms/event.py:225 project/forms/event_place.py:33 +#: project/forms/event.py:230 project/forms/event_place.py:33 #: project/templates/manage/events.html:106 #: project/templates/manage/events.html:141 #: project/templates/manage/places.html:21 @@ -825,59 +825,59 @@ msgstr "" msgid "Photo" msgstr "" -#: project/forms/event.py:227 +#: project/forms/event.py:232 msgid "" "We recommend uploading a photo for the event. It looks a lot more, but of" " course it works without it." msgstr "" -#: project/forms/event.py:242 project/templates/_macros.html:422 +#: project/forms/event.py:247 project/templates/_macros.html:422 #: project/templates/_macros.html:585 msgid "Previous start date" msgstr "" -#: project/forms/event.py:244 +#: project/forms/event.py:249 msgid "Enter when the event should have taken place before it was postponed." msgstr "" -#: project/forms/event.py:249 project/forms/event_suggestion.py:71 +#: project/forms/event.py:254 project/forms/event_suggestion.py:71 msgid "Categories" msgstr "" -#: project/forms/event.py:252 project/forms/event_suggestion.py:74 +#: project/forms/event.py:257 project/forms/event_suggestion.py:74 msgid "Choose categories that fit the event." msgstr "" -#: project/forms/event.py:255 project/forms/reference.py:14 +#: project/forms/event.py:260 project/forms/reference.py:14 #: project/forms/reference.py:27 project/forms/reference_request.py:76 #: project/templates/event/create.html:363 #: project/templates/event/update.html:220 msgid "Rating" msgstr "" -#: project/forms/event.py:259 project/forms/reference.py:18 +#: project/forms/event.py:264 project/forms/reference.py:18 #: project/forms/reference.py:31 project/forms/reference_request.py:80 msgid "" "Choose how relevant the event is to your organization. The value is not " "visible and is used for sorting." msgstr "" -#: project/forms/event.py:264 +#: project/forms/event.py:269 msgid "Co-organizers" msgstr "" -#: project/forms/event.py:267 +#: project/forms/event.py:272 msgid "" "Select optional co-organizers. You can add and modify organizers at " "Organization > Organizers." msgstr "" -#: project/forms/event.py:277 +#: project/forms/event.py:282 msgid "Invalid co-organizer." msgstr "" -#: project/forms/event.py:286 project/forms/event.py:295 -#: project/forms/event.py:373 project/forms/event.py:450 +#: project/forms/event.py:291 project/forms/event.py:300 +#: project/forms/event.py:382 project/forms/event.py:459 #: project/forms/event_suggestion.py:50 project/templates/_macros.html:462 #: project/templates/_macros.html:628 project/templates/event/create.html:288 #: project/templates/event/update.html:170 @@ -888,16 +888,16 @@ msgstr "" msgid "Place" msgstr "" -#: project/forms/event.py:288 +#: project/forms/event.py:293 msgid "Select existing place" msgstr "" -#: project/forms/event.py:289 +#: project/forms/event.py:294 msgid "Enter new place" msgstr "" -#: project/forms/event.py:302 project/forms/event.py:311 -#: project/forms/event.py:381 project/forms/event.py:447 +#: project/forms/event.py:307 project/forms/event.py:316 +#: project/forms/event.py:390 project/forms/event.py:456 #: project/forms/event_date.py:40 project/forms/event_suggestion.py:60 #: project/templates/_macros.html:499 project/templates/_macros.html:671 #: project/templates/event/create.html:257 @@ -909,130 +909,137 @@ msgstr "" msgid "Organizer" msgstr "" -#: project/forms/event.py:304 +#: project/forms/event.py:309 msgid "Select existing organizer" msgstr "" -#: project/forms/event.py:305 +#: project/forms/event.py:310 msgid "Enter new organizer" msgstr "" -#: project/forms/event.py:317 +#: project/forms/event.py:323 project/templates/_macros.html:736 +#: project/templates/event/create.html:374 +#: project/templates/manage/reference_requests_incoming.html:5 +#: project/templates/manage/reference_requests_outgoing.html:5 +msgid "Reference requests" +msgstr "" + +#: project/forms/event.py:326 msgid "Save as draft" msgstr "" -#: project/forms/event.py:318 +#: project/forms/event.py:327 msgid "Save as planned" msgstr "" -#: project/forms/event.py:319 +#: project/forms/event.py:328 msgid "Publish event" msgstr "" -#: project/forms/event.py:355 +#: project/forms/event.py:364 msgid "Select existing place or enter new place" msgstr "" -#: project/forms/event.py:363 +#: project/forms/event.py:372 msgid "Select existing organizer or enter new organizer" msgstr "" -#: project/forms/event.py:376 +#: project/forms/event.py:385 msgid "" "Choose where the event takes place. You can add and modify places at " "Organization > Places." msgstr "" -#: project/forms/event.py:384 +#: project/forms/event.py:393 msgid "" "Select the organizer. You can add and modify organizers at Organization >" " Organizers." msgstr "" -#: project/forms/event.py:390 project/templates/event/update.html:149 +#: project/forms/event.py:399 project/templates/event/update.html:149 #: project/templates/oauth2_token/list.html:21 msgid "Status" msgstr "" -#: project/forms/event.py:393 +#: project/forms/event.py:402 msgid "EventStatus.scheduled" msgstr "Scheduled" -#: project/forms/event.py:394 project/templates/layout.html:72 +#: project/forms/event.py:403 project/templates/layout.html:72 #: project/templates/layout.html:87 msgid "EventStatus.cancelled" msgstr "Cancelled" -#: project/forms/event.py:395 project/templates/layout.html:75 +#: project/forms/event.py:404 project/templates/layout.html:75 #: project/templates/layout.html:90 msgid "EventStatus.movedOnline" msgstr "Moved online" -#: project/forms/event.py:396 project/templates/layout.html:78 +#: project/forms/event.py:405 project/templates/layout.html:78 #: project/templates/layout.html:93 msgid "EventStatus.postponed" msgstr "Postponed" -#: project/forms/event.py:397 project/templates/layout.html:81 +#: project/forms/event.py:406 project/templates/layout.html:81 #: project/templates/layout.html:96 msgid "EventStatus.rescheduled" msgstr "Rescheduled" -#: project/forms/event.py:399 +#: project/forms/event.py:408 msgid "Select the status of the event." msgstr "" -#: project/forms/event.py:403 +#: project/forms/event.py:412 msgid "Public status" msgstr "" -#: project/forms/event.py:406 +#: project/forms/event.py:415 msgid "PublicStatus.published" msgstr "" -#: project/forms/event.py:407 project/templates/_macros.html:269 +#: project/forms/event.py:416 project/templates/_macros.html:269 msgid "PublicStatus.planned" msgstr "" -#: project/forms/event.py:408 project/templates/_macros.html:267 +#: project/forms/event.py:417 project/templates/_macros.html:267 msgid "PublicStatus.draft" msgstr "" -#: project/forms/event.py:410 project/templates/event/create.html:371 +#: project/forms/event.py:419 project/templates/event/create.html:386 msgid "Planned events appear in the scheduling view, but not on public calendars." msgstr "" -#: project/forms/event.py:415 project/templates/event/update.html:5 +#: project/forms/event.py:424 project/templates/event/update.html:5 #: project/templates/event/update.html:117 msgid "Update event" msgstr "" -#: project/forms/event.py:431 project/templates/_macros.html:1279 +#: project/forms/event.py:440 project/templates/_macros.html:1279 #: project/templates/event/actions.html:66 #: project/templates/event/delete.html:6 msgid "Delete event" msgstr "" -#: project/forms/event.py:438 project/forms/event_date.py:14 +#: project/forms/event.py:447 project/forms/event_date.py:14 #: project/forms/planning.py:21 msgid "From" msgstr "" -#: project/forms/event.py:440 project/forms/event_date.py:16 +#: project/forms/event.py:449 project/forms/event_date.py:16 #: project/forms/planning.py:22 msgid "to" msgstr "" -#: project/forms/event.py:442 project/forms/event_date.py:18 +#: project/forms/event.py:451 project/forms/event_date.py:18 msgid "Keyword" msgstr "" -#: project/forms/event.py:444 project/forms/event_date.py:20 +#: project/forms/event.py:453 project/forms/event_date.py:20 #: project/forms/planning.py:24 project/templates/_macros.html:395 msgid "Category" msgstr "" -#: project/forms/event.py:454 project/forms/event_date.py:26 +#: project/forms/event.py:463 project/forms/event_date.py:26 #: project/forms/planning.py:27 project/templates/_macros.html:324 #: project/templates/admin_unit/create.html:39 #: project/templates/admin_unit/update.html:47 @@ -1045,17 +1052,17 @@ msgstr "" msgid "Location" msgstr "" -#: project/forms/event.py:456 project/forms/event_date.py:28 +#: project/forms/event.py:465 project/forms/event_date.py:28 #: project/forms/planning.py:29 msgid "Distance" msgstr "" -#: project/forms/event.py:463 project/forms/event_date.py:49 +#: project/forms/event.py:472 project/forms/event_date.py:49 #: project/forms/planning.py:41 msgid "Exclude recurring events" msgstr "" -#: project/forms/event.py:467 project/forms/event_date.py:54 +#: project/forms/event.py:476 project/forms/event_date.py:54 msgid "Find events" msgstr "" @@ -1485,12 +1492,6 @@ msgstr "" msgid "Reference event" msgstr "" -#: project/templates/_macros.html:736 -#: project/templates/manage/reference_requests_incoming.html:5 -#: project/templates/manage/reference_requests_outgoing.html:5 -msgid "Reference requests" -msgstr "" - #: project/templates/_macros.html:747 project/templates/_macros.html:1286 #: project/templates/event/actions.html:32 #: project/templates/manage/events.html:123 @@ -2209,6 +2210,14 @@ msgstr "" msgid "Target group" msgstr "" +#: project/templates/event/create.html:378 +msgid "References are important for the visibility of your events." +msgstr "" + +#: project/templates/event/create.html:379 +msgid "Select organizations to display your event on their calendars." +msgstr "" + #: project/templates/event/delete.html:10 msgid "" "You are about to delete an event with multiple dates. If you want to " @@ -2638,31 +2647,31 @@ msgstr "" msgid "Invitation successfully deleted" msgstr "" -#: project/views/event.py:181 +#: project/views/event.py:251 msgid "Event successfully published" msgstr "" -#: project/views/event.py:183 +#: project/views/event.py:253 msgid "Draft successfully saved" msgstr "" -#: project/views/event.py:185 +#: project/views/event.py:255 msgid "Event successfully planned" msgstr "" -#: project/views/event.py:228 +#: project/views/event.py:312 msgid "Event successfully updated" msgstr "" -#: project/views/event.py:254 +#: project/views/event.py:338 msgid "Event successfully deleted" msgstr "" -#: project/views/event.py:419 +#: project/views/event.py:503 msgid "Referenced event changed" msgstr "" -#: project/views/event.py:442 +#: project/views/event.py:526 msgid "New event report" msgstr "" @@ -2771,22 +2780,23 @@ msgstr "" msgid "Reference successfully deleted" msgstr "" -#: project/views/reference_request.py:104 -#: project/views/reference_request_review.py:57 -msgid "Reference successfully created" +#: project/views/reference_request.py:124 +#, python-format +msgid "%(organization)s accepted your reference request" msgstr "" -#: project/views/reference_request.py:108 +#: project/views/reference_request.py:131 +#, python-format msgid "" -"Request successfully created. You will be notified after the other " -"organization reviews the event." +"Reference request to %(organization)s successfully created. You will be " +"notified after the other organization reviews the event." msgstr "" -#: project/views/reference_request.py:144 +#: project/views/reference_request.py:154 msgid "New reference request" msgstr "" -#: project/views/reference_request.py:153 +#: project/views/reference_request.py:163 msgid "New reference automatically verified" msgstr "" @@ -2795,6 +2805,10 @@ msgstr "" msgid "Request already verified" msgstr "" +#: project/views/reference_request_review.py:57 +msgid "Reference successfully created" +msgstr "" + #: project/views/reference_request_review.py:65 msgid "Request successfully updated" msgstr "" @@ -2960,3 +2974,9 @@ msgstr "" #~ msgid "Select the public status of the event." #~ msgstr "" +#~ msgid "" +#~ "Request successfully created. You will " +#~ "be notified after the other organization" +#~ " reviews the event." +#~ msgstr "" + diff --git a/project/views/event.py b/project/views/event.py index 361ee16..0a26143 100644 --- a/project/views/event.py +++ b/project/views/event.py @@ -11,6 +11,7 @@ from project.access import ( can_read_event_or_401, can_reference_event, can_request_event_reference, + can_request_event_reference_from_admin_unit, get_admin_unit_members_with_permission, has_access, ) @@ -28,6 +29,11 @@ from project.models import ( EventSuggestion, PublicStatus, ) +from project.models.event_reference_request import EventReferenceRequest +from project.services.admin_unit import ( + get_admin_unit_relations_for_reference_requests, + get_admin_units_for_reference_requests, +) from project.services.event import ( create_ical_events_for_event, get_event_with_details_or_404, @@ -38,8 +44,13 @@ from project.services.event import ( update_event, upsert_event_category, ) +from project.services.reference import ( + get_newest_reference_requests, + get_newest_references, +) from project.utils import get_event_category_name, get_place_str from project.views.event_suggestion import send_event_suggestion_review_status_mail +from project.views.reference_request import handle_request_according_to_relation from project.views.utils import ( flash_errors, flash_message, @@ -103,6 +114,61 @@ def event_report(event_id): return render_template("event/report.html") +def prepare_form_reference_requests(form, admin_unit): + if not can_request_event_reference_from_admin_unit(admin_unit): + form.reference_request_admin_unit_id.choices = [] + return + + max_choices = 5 + admin_unit_ids = [] + admin_unit_choices = [] + selected_ids = [] + + def add_admin_units(admin_units, selected=True): + for admin_unit in admin_units: + if admin_unit.id in admin_unit_ids: + continue + + admin_unit_ids.append(admin_unit.id) + admin_unit_choices.append(admin_unit) + + if selected: + selected_ids.append(admin_unit.id) + + # Neuste ausgehende Empfehlungsanfragen + limit = max_choices - len(admin_unit_ids) + reference_requests = get_newest_reference_requests(admin_unit.id, limit) + add_admin_units([r.admin_unit for r in reference_requests]) + + # Neuste ausgehende Empfehlungen + limit = max_choices - len(admin_unit_ids) + if limit > 0: + references = get_newest_references(admin_unit.id, limit) + add_admin_units([r.admin_unit for r in references]) + + # Eingehende Beziehungen, die Organisation oder Events automatisch verifizieren + limit = max_choices - len(admin_unit_ids) + if limit > 0: + relations = get_admin_unit_relations_for_reference_requests( + admin_unit.id, limit + ) + add_admin_units([r.source_admin_unit for r in relations]) + + # Organisationen, die eingehende Empfehlungsanfragen erlauben + limit = max_choices - len(admin_unit_ids) + if limit > 0: + admin_units_for_reference = get_admin_units_for_reference_requests( + admin_unit.id, limit + ) + add_admin_units(admin_units_for_reference, False) + + form.reference_request_admin_unit_id.choices = sorted( + [(a.id, a.name) for a in admin_unit_choices], + key=lambda a: a[1], + ) + form.reference_request_admin_unit_id.data = selected_ids + + @app.route("/admin_unit//events/create", methods=("GET", "POST")) @auth_required() def event_create_for_admin_unit_id(id): @@ -114,6 +180,7 @@ def event_create_for_admin_unit_id(id): admin_unit_id=admin_unit.id, category_ids=[upsert_event_category("Other").id] ) prepare_event_form(form) + prepare_form_reference_requests(form, admin_unit) # Vorlagen event_suggestion = None @@ -188,6 +255,20 @@ def event_create_for_admin_unit_id(id): success_msg, url_for("event", event_id=event.id), ) + + if ( + event.public_status == PublicStatus.published + and form.reference_request_admin_unit_id.data + ): + for target_admin_unit_id in form.reference_request_admin_unit_id.data: + reference_request = EventReferenceRequest() + reference_request.event_id = event.id + reference_request.admin_unit_id = target_admin_unit_id + db.session.add(reference_request) + msg = handle_request_according_to_relation(reference_request, event) + db.session.commit() + flash(msg, "success") + return redirect(url_for("event_actions", event_id=event.id)) except SQLAlchemyError as e: db.session.rollback() diff --git a/project/views/reference_request.py b/project/views/reference_request.py index f52b1a5..0fd7c05 100644 --- a/project/views/reference_request.py +++ b/project/views/reference_request.py @@ -17,7 +17,7 @@ from project.models import ( EventReferenceRequest, EventReferenceRequestReviewStatus, ) -from project.services.admin_unit import get_admin_unit_relation +from project.services.admin_unit import get_admin_unit_by_id, get_admin_unit_relation from project.services.reference import ( create_event_reference_for_request, get_reference_requests_incoming_query, @@ -92,23 +92,7 @@ def event_reference_request_create(event_id): try: db.session.add(request) - relation = get_admin_unit_relation( - request.admin_unit_id, event.admin_unit_id - ) - auto_verify = relation and relation.auto_verify_event_reference_requests - - if auto_verify: - request.review_status = EventReferenceRequestReviewStatus.verified - reference = create_event_reference_for_request(request) - send_auto_reference_inbox_mails(reference) - msg = gettext("Reference successfully created") - else: - request.review_status = EventReferenceRequestReviewStatus.inbox - send_reference_request_inbox_mails(request) - msg = gettext( - "Request successfully created. You will be notified after the other organization reviews the event." - ) - + msg = handle_request_according_to_relation(request, event) db.session.commit() flash(msg, "success") return redirect( @@ -126,6 +110,32 @@ def event_reference_request_create(event_id): return render_template("event/reference_request.html", form=form, event=event) +def handle_request_according_to_relation( + request: EventReferenceRequest, event: Event +) -> str: + admin_unit = get_admin_unit_by_id(request.admin_unit_id) + relation = get_admin_unit_relation(request.admin_unit_id, event.admin_unit_id) + auto_verify = relation and relation.auto_verify_event_reference_requests + + if auto_verify: + request.review_status = EventReferenceRequestReviewStatus.verified + reference = create_event_reference_for_request(request) + send_auto_reference_inbox_mails(reference) + msg = gettext( + "%(organization)s accepted your reference request", + organization=admin_unit.name, + ) + else: + request.review_status = EventReferenceRequestReviewStatus.inbox + send_reference_request_inbox_mails(request) + msg = gettext( + "Reference request to %(organization)s successfully created. You will be notified after the other organization reviews the event.", + organization=admin_unit.name, + ) + + return msg + + def send_member_reference_request_verify_mails( admin_unit_id, subject, template, **context ): diff --git a/tests/seeder.py b/tests/seeder.py index c64121d..4fa27fd 100644 --- a/tests/seeder.py +++ b/tests/seeder.py @@ -77,6 +77,7 @@ class Seeder(object): can_verify_other=False, verified=False, can_invite_other=True, + incoming_verification_requests_allowed=False, **kwargs ): from project.models import AdminUnit, Location @@ -93,6 +94,9 @@ class Seeder(object): admin_unit.can_create_other = can_create_other admin_unit.can_verify_other = can_verify_other admin_unit.can_invite_other = can_invite_other + admin_unit.incoming_verification_requests_allowed = ( + incoming_verification_requests_allowed + ) location = Location() location.postalCode = "12345" @@ -109,6 +113,13 @@ class Seeder(object): return admin_unit_id + def get_eventcally_admin_unit_id(self): + from project.services.admin_unit import get_admin_unit_by_name + + with self._app.app_context(): + other_admin_unit = get_admin_unit_by_name("eventcally") + return other_admin_unit.id if other_admin_unit else None + def verify_admin_unit(self, admin_unit_id): from project.services.admin_unit import get_admin_unit_by_name diff --git a/tests/views/test_event.py b/tests/views/test_event.py index 523abd5..512a662 100644 --- a/tests/views/test_event.py +++ b/tests/views/test_event.py @@ -1,6 +1,9 @@ import pytest from psycopg2.errors import UniqueViolation +from tests.seeder import Seeder +from tests.utils import UtilActions + @pytest.mark.parametrize( "external_link", [None, "https://example.com", "www.example.com"] @@ -54,7 +57,7 @@ def test_read_co_organizers(seeder, utils): @pytest.mark.parametrize("variant", ["normal", "db_error", "two_date_definitions"]) -def test_create(client, app, utils, seeder, mocker, variant): +def test_create(client, app, utils: UtilActions, seeder: Seeder, mocker, variant): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) @@ -105,7 +108,7 @@ def test_create(client, app, utils, seeder, mocker, variant): assert len(event.date_definitions) == 1 -def test_create_allday(client, app, utils, seeder): +def test_create_allday(client, app, utils: UtilActions, seeder: Seeder): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) @@ -142,7 +145,100 @@ def test_create_allday(client, app, utils, seeder): assert event.date_definitions[0].allday -def test_create_newPlaceAndOrganizer(client, app, utils, seeder, mocker): +def test_create_with_reference_requests( + client, app, utils: UtilActions, seeder: Seeder +): + user_id, admin_unit_id = seeder.setup_base() + eventcally_admin_unit_id = seeder.get_eventcally_admin_unit_id() + place_id = seeder.upsert_default_event_place(admin_unit_id) + organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) + + other_user_id = seeder.create_user("other@test.de") + other_admin_unit_id = seeder.create_admin_unit( + other_user_id, + "Other Crew", + verified=True, + incoming_verification_requests_allowed=True, + ) + seeder.create_admin_unit_relation( + other_admin_unit_id, admin_unit_id, auto_verify_event_reference_requests=True + ) + + url = utils.get_url("event_create_for_admin_unit_id", id=admin_unit_id) + response = utils.get_ok(url) + + response = utils.post_form( + url, + response, + { + "name": "Name", + "description": "Beschreibung", + "date_definitions-0-start": ["2030-12-31", "00:00"], + "date_definitions-0-end": ["2030-12-31", "23:59"], + "event_place_id": place_id, + "organizer_id": organizer_id, + "reference_request_admin_unit_id": [ + eventcally_admin_unit_id, + other_admin_unit_id, + ], + }, + ) + + utils.assert_response_redirect(response, "event_actions", event_id=1) + + with app.app_context(): + from project.models import ( + Event, + EventReference, + EventReferenceRequest, + EventReferenceRequestReviewStatus, + ) + + event = ( + Event.query.filter(Event.admin_unit_id == admin_unit_id) + .filter(Event.name == "Name") + .first() + ) + assert event is not None + + reference_request = ( + EventReferenceRequest.query.filter( + EventReferenceRequest.admin_unit_id == eventcally_admin_unit_id + ) + .filter(EventReferenceRequest.event_id == event.id) + .first() + ) + assert reference_request is not None + assert ( + reference_request.review_status == EventReferenceRequestReviewStatus.inbox + ) + + reference_request = ( + EventReferenceRequest.query.filter( + EventReferenceRequest.admin_unit_id == other_admin_unit_id + ) + .filter(EventReferenceRequest.event_id == event.id) + .first() + ) + assert reference_request is not None + assert ( + reference_request.review_status + == EventReferenceRequestReviewStatus.verified + ) + + reference = ( + EventReference.query.filter( + EventReference.admin_unit_id == other_admin_unit_id + ) + .filter(EventReference.event_id == event.id) + .first() + ) + assert reference is not None + + +def test_create_newPlaceAndOrganizer( + client, app, utils: UtilActions, seeder: Seeder, mocker +): user_id, admin_unit_id = seeder.setup_base() url = utils.get_url("event_create_for_admin_unit_id", id=admin_unit_id) @@ -174,7 +270,7 @@ def test_create_newPlaceAndOrganizer(client, app, utils, seeder, mocker): assert event is not None -def test_create_missingName(client, app, utils, seeder, mocker): +def test_create_missingName(client, app, utils: UtilActions, seeder: Seeder, mocker): user_id, admin_unit_id = seeder.setup_base() url = utils.get_url("event_create_for_admin_unit_id", id=admin_unit_id) @@ -189,7 +285,7 @@ def test_create_missingName(client, app, utils, seeder, mocker): utils.assert_response_error_message(response) -def test_create_missingPlace(client, app, utils, seeder, mocker): +def test_create_missingPlace(client, app, utils: UtilActions, seeder: Seeder, mocker): user_id, admin_unit_id = seeder.setup_base() url = utils.get_url("event_create_for_admin_unit_id", id=admin_unit_id) @@ -208,7 +304,9 @@ def test_create_missingPlace(client, app, utils, seeder, mocker): utils.assert_response_error_message(response) -def test_create_missingOrganizer(client, app, utils, seeder, mocker): +def test_create_missingOrganizer( + client, app, utils: UtilActions, seeder: Seeder, mocker +): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) @@ -229,7 +327,9 @@ def test_create_missingOrganizer(client, app, utils, seeder, mocker): utils.assert_response_error_message(response) -def test_create_invalidOrganizer(client, app, utils, seeder, mocker): +def test_create_invalidOrganizer( + client, app, utils: UtilActions, seeder: Seeder, mocker +): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) @@ -254,7 +354,9 @@ def test_create_invalidOrganizer(client, app, utils, seeder, mocker): utils.assert_response_contains(response, "Ungültiger Mitveranstalter") -def test_create_invalidDateFormat(client, app, utils, seeder, mocker): +def test_create_invalidDateFormat( + client, app, utils: UtilActions, seeder: Seeder, mocker +): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) @@ -275,7 +377,7 @@ def test_create_invalidDateFormat(client, app, utils, seeder, mocker): utils.assert_response_error_message(response) -def test_create_startInvalid(client, app, utils, seeder, mocker): +def test_create_startInvalid(client, app, utils: UtilActions, seeder: Seeder, mocker): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) @@ -296,7 +398,7 @@ def test_create_startInvalid(client, app, utils, seeder, mocker): utils.assert_response_error_message(response) -def test_create_startAfterEnd(client, app, utils, seeder, mocker): +def test_create_startAfterEnd(client, app, utils: UtilActions, seeder: Seeder, mocker): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) organizer_id = seeder.upsert_default_event_organizer(admin_unit_id) @@ -322,7 +424,9 @@ def test_create_startAfterEnd(client, app, utils, seeder, mocker): ) -def test_create_durationMoreThanMaxAllowedDuration(client, app, utils, seeder, mocker): +def test_create_durationMoreThanMaxAllowedDuration( + client, app, utils: UtilActions, seeder: Seeder, mocker +): user_id, admin_unit_id = seeder.setup_base() place_id = seeder.upsert_default_event_place(admin_unit_id) @@ -347,7 +451,7 @@ def test_create_durationMoreThanMaxAllowedDuration(client, app, utils, seeder, m @pytest.mark.parametrize("allday", [True, False]) -def test_duplicate(client, app, utils, seeder, mocker, allday): +def test_duplicate(client, app, utils: UtilActions, seeder: Seeder, mocker, allday): user_id, admin_unit_id = seeder.setup_base() template_event_id = seeder.create_event(admin_unit_id, allday=allday) @@ -380,7 +484,7 @@ def test_duplicate(client, app, utils, seeder, mocker, allday): @pytest.mark.parametrize("free_text", [True, False]) @pytest.mark.parametrize("allday", [True, False]) def test_create_fromSuggestion( - client, app, db, utils, seeder, mocker, free_text, allday + client, app, db, utils: UtilActions, seeder: Seeder, mocker, free_text, allday ): user_id, admin_unit_id = seeder.setup_base() suggestion_id = seeder.create_event_suggestion(admin_unit_id, free_text, allday) @@ -413,7 +517,7 @@ def test_create_fromSuggestion( def test_create_verifiedSuggestionRedirectsToReviewStatus( - client, app, utils, seeder, mocker + client, app, utils: UtilActions, seeder: Seeder, mocker ): user_id, admin_unit_id = seeder.setup_base() suggestion_id = seeder.create_event_suggestion(admin_unit_id)