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 98a7269..2469f8a 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 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 a7dd873..0a27c17 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 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)