Introduce draft for events #265

This commit is contained in:
Daniel Grams 2021-08-15 19:06:27 +02:00
parent d5f8c9cfd8
commit 0295da717f
42 changed files with 1041 additions and 598 deletions

View File

@ -28,5 +28,8 @@
},
"[yaml]": {
"editor.formatOnSave": false
},
"[sql]": {
"editor.formatOnSave": false
}
}

View File

@ -22,7 +22,7 @@ describe("Event", () => {
cy.url().should("include", "/actions");
cy.get("div.alert").should(
"contain",
"Veranstaltung erfolgreich erstellt"
"Veranstaltung erfolgreich veröffentlicht"
);
cy.contains("a", "Veranstaltung bearbeiten").click();
@ -40,4 +40,39 @@ describe("Event", () => {
});
});
});
it("saves draft", () => {
cy.login();
cy.createAdminUnit().then(function (adminUnitId) {
cy.visit("/admin_unit/" + adminUnitId + "/events/create");
cy.get("#name").type("Stadtfest");
cy.select2("event_place_id", "Gos", "Goslar, 38640 Goslar");
cy.select2("organizer_id", "Mei", "Meine Crew");
cy.get("#submit_draft").click();
cy.url().should("include", "/actions");
cy.get("div.alert").should(
"contain",
"Entwurf erfolgreich gespeichert"
);
cy.contains("a", "Veranstaltung bearbeiten").click();
cy.url().should("include", "/update");
cy.get("#public_status").should('have.value', '1')
cy.get("#submit").click();
cy.url().should(
"include",
"/manage/admin_unit/" + adminUnitId + "/events"
);
cy.get("div.alert").should(
"contain",
"Veranstaltung erfolgreich aktualisiert"
);
cy.visit("/manage/admin_unit/" + adminUnitId + "/events");
cy.get('main .badge-pill').should('contain', 'Entwurf')
});
});
});

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-08-12 23:45+0200\n"
"POT-Creation-Date: 2021-08-15 14:50+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -175,7 +175,7 @@ msgstr ""
msgid "Legal notice"
msgstr ""
#: project/forms/admin.py:12 project/templates/_macros.html:1322
#: project/forms/admin.py:12 project/templates/_macros.html:1328
#: project/templates/layout.html:339
#: project/templates/widget/event_suggestion/create.html:199
#: project/views/admin_unit.py:36 project/views/root.py:58
@ -246,8 +246,8 @@ msgstr ""
msgid "Longitude"
msgstr ""
#: project/forms/admin_unit.py:28 project/forms/event.py:35
#: project/forms/event.py:64 project/forms/event.py:359
#: project/forms/admin_unit.py:28 project/forms/event.py:36
#: project/forms/event.py:65 project/forms/event.py:375
#: project/forms/event_place.py:25 project/forms/event_place.py:50
#: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66
#: project/forms/organizer.py:25 project/forms/organizer.py:52
@ -268,32 +268,32 @@ msgstr ""
msgid "The short name is used to create a unique identifier for your events"
msgstr ""
#: project/forms/admin_unit.py:40 project/templates/_macros.html:1452
#: project/forms/admin_unit.py:40 project/templates/_macros.html:1458
msgid "Short name must contain only letters numbers or underscore"
msgstr ""
#: project/forms/admin_unit.py:46 project/forms/event.py:56
#: project/forms/event.py:90 project/forms/event_place.py:26
#: project/forms/admin_unit.py:46 project/forms/event.py:57
#: project/forms/event.py:91 project/forms/event_place.py:26
#: project/forms/organizer.py:26
msgid "Link URL"
msgstr ""
#: project/forms/admin_unit.py:47 project/forms/admin_unit_member.py:11
#: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28
#: project/forms/event.py:57 project/forms/event_suggestion.py:38
#: project/forms/event.py:58 project/forms/event_suggestion.py:38
#: project/forms/organizer.py:27 project/templates/_macros.html:262
#: project/templates/_macros.html:1412 project/templates/admin/users.html:19
#: project/templates/_macros.html:1418 project/templates/admin/users.html:19
msgid "Email"
msgstr ""
#: project/forms/admin_unit.py:48 project/forms/event.py:58
#: project/forms/admin_unit.py:48 project/forms/event.py:59
#: project/forms/event_suggestion.py:31 project/forms/organizer.py:28
#: project/templates/_macros.html:305
#: project/templates/_macros.html:311
msgid "Phone"
msgstr ""
#: project/forms/admin_unit.py:49 project/forms/event.py:59
#: project/forms/organizer.py:29 project/templates/_macros.html:313
#: project/forms/admin_unit.py:49 project/forms/event.py:60
#: project/forms/organizer.py:29 project/templates/_macros.html:319
msgid "Fax"
msgstr ""
@ -432,230 +432,230 @@ msgstr ""
msgid "100 km"
msgstr ""
#: project/forms/event.py:53
#: project/forms/event.py:54
msgid "Organizator"
msgstr ""
#: project/forms/event.py:66
#: project/forms/event.py:67
msgid "Enter a short, meaningful name for the event."
msgstr ""
#: project/forms/event.py:69
#: project/forms/event.py:70
msgid "Start"
msgstr ""
#: project/forms/event.py:71
#: project/forms/event.py:72
msgid "Indicate when the event will take place."
msgstr ""
#: project/forms/event.py:74
#: project/forms/event.py:75
msgid "End"
msgstr ""
#: project/forms/event.py:76
#: project/forms/event.py:77
msgid "Indicate when the event will end. An event can last a maximum of 14 days."
msgstr ""
#: project/forms/event.py:81 project/templates/event/create.html:244
#: project/forms/event.py:82 project/templates/event/create.html:244
#: project/templates/event/update.html:135
#: project/templates/widget/event_suggestion/create.html:234
msgid "Recurring event"
msgstr ""
#: project/forms/event.py:85 project/forms/event_place.py:28
#: project/forms/event.py:86 project/forms/event_place.py:28
msgid "Description"
msgstr ""
#: project/forms/event.py:87
#: project/forms/event.py:88
msgid "Add an description of the event."
msgstr ""
#: project/forms/event.py:92
#: project/forms/event.py:93
msgid ""
"Enter a link to an external website containing more information about the"
" event."
msgstr ""
#: project/forms/event.py:97
#: project/forms/event.py:98
msgid "Ticket Link URL"
msgstr ""
#: project/forms/event.py:99
#: project/forms/event.py:100
msgid "Enter a link where tickets can be purchased."
msgstr ""
#: project/forms/event.py:102 project/templates/_macros.html:244
#: project/forms/event.py:103 project/templates/_macros.html:244
msgid "Tags"
msgstr ""
#: project/forms/event.py:104
#: project/forms/event.py:105
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:109
#: project/forms/event.py:110
msgid "Kid friendly"
msgstr ""
#: project/forms/event.py:111
#: project/forms/event.py:112
msgid "If the event is particularly suitable for children."
msgstr ""
#: project/forms/event.py:114
#: project/forms/event.py:115
msgid "Accessible for free"
msgstr ""
#: project/forms/event.py:116
#: project/forms/event.py:117
msgid "If the event is accessible for free."
msgstr ""
#: project/forms/event.py:119
#: project/forms/event.py:120
msgid "Typical Age from"
msgstr ""
#: project/forms/event.py:121
#: project/forms/event.py:122
msgid "The minimum age that participants should be."
msgstr ""
#: project/forms/event.py:124
#: project/forms/event.py:125
msgid "Typical Age to"
msgstr ""
#: project/forms/event.py:126
#: project/forms/event.py:127
msgid "The maximum age that participants should be."
msgstr ""
#: project/forms/event.py:129
#: project/forms/event.py:130
msgid "Registration required"
msgstr ""
#: project/forms/event.py:131
#: project/forms/event.py:132
msgid "If the participants needs to register for the event."
msgstr ""
#: project/forms/event.py:136 project/templates/_macros.html:276
#: project/forms/event.py:137 project/templates/_macros.html:276
#: project/templates/layout.html:159
msgid "Booked up"
msgstr ""
#: project/forms/event.py:138
#: project/forms/event.py:139
msgid "If the event is booked up or sold out."
msgstr ""
#: project/forms/event.py:141
#: project/forms/event.py:142
msgid "Expected number of participants"
msgstr ""
#: project/forms/event.py:143
#: project/forms/event.py:144
msgid "The estimated expected attendance."
msgstr ""
#: project/forms/event.py:146
#: project/forms/event.py:147
msgid "Price info"
msgstr ""
#: project/forms/event.py:148
#: project/forms/event.py:149
msgid ""
"Enter price information in textual form. E.g., different prices for "
"adults and children."
msgstr ""
#: project/forms/event.py:153
#: project/forms/event.py:154
msgid "Target group origin"
msgstr ""
#: project/forms/event.py:158
#: project/forms/event.py:159
msgid "EventTargetGroupOrigin.both"
msgstr ""
#: project/forms/event.py:162
#: project/forms/event.py:163
msgid "EventTargetGroupOrigin.tourist"
msgstr ""
#: project/forms/event.py:166
#: project/forms/event.py:167
msgid "EventTargetGroupOrigin.resident"
msgstr ""
#: project/forms/event.py:169
#: project/forms/event.py:170
msgid ""
"Choose whether the event is particularly suitable for tourists or "
"residents."
msgstr ""
#: project/forms/event.py:174
#: project/forms/event.py:175
msgid "Attendance mode"
msgstr ""
#: project/forms/event.py:179
#: project/forms/event.py:180
msgid "EventAttendanceMode.offline"
msgstr ""
#: project/forms/event.py:183 project/templates/layout.html:147
#: project/forms/event.py:184 project/templates/layout.html:147
msgid "EventAttendanceMode.online"
msgstr ""
#: project/forms/event.py:185 project/templates/layout.html:150
#: project/forms/event.py:186 project/templates/layout.html:150
msgid "EventAttendanceMode.mixed"
msgstr ""
#: project/forms/event.py:187
#: project/forms/event.py:188
msgid "Choose how people can attend the event."
msgstr ""
#: project/forms/event.py:191 project/forms/event_place.py:27
#: project/forms/event.py:192 project/forms/event_place.py:27
#: project/templates/widget/event_suggestion/create.html:252
msgid "Photo"
msgstr ""
#: project/forms/event.py:193
#: project/forms/event.py:194
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:203 project/templates/_macros.html:1193
#: project/forms/event.py:204 project/templates/_macros.html:1199
msgid "The start must be before the end."
msgstr ""
#: project/forms/event.py:209 project/templates/_macros.html:1210
#: project/forms/event.py:210 project/templates/_macros.html:1216
msgid "An event can last a maximum of 14 days."
msgstr ""
#: project/forms/event.py:217 project/templates/_macros.html:423
#: project/templates/_macros.html:582
#: project/forms/event.py:218 project/templates/_macros.html:429
#: project/templates/_macros.html:588
msgid "Previous start date"
msgstr ""
#: project/forms/event.py:219
#: project/forms/event.py:220
msgid "Enter when the event should have taken place before it was postponed."
msgstr ""
#: project/forms/event.py:224 project/forms/event_suggestion.py:71
#: project/forms/event.py:225 project/forms/event_suggestion.py:71
msgid "Categories"
msgstr ""
#: project/forms/event.py:227 project/forms/event_suggestion.py:74
#: project/forms/event.py:228 project/forms/event_suggestion.py:74
msgid "Choose categories that fit the event."
msgstr ""
#: project/forms/event.py:230 project/forms/reference.py:14
#: project/forms/event.py:231 project/forms/reference.py:14
#: project/forms/reference.py:27 project/forms/reference_request.py:75
#: project/templates/event/create.html:358
#: project/templates/event/update.html:214
msgid "Rating"
msgstr ""
#: project/forms/event.py:234 project/forms/reference.py:18
#: project/forms/event.py:235 project/forms/reference.py:18
#: project/forms/reference.py:31 project/forms/reference_request.py:79
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:242 project/forms/event.py:251
#: project/forms/event.py:315 project/forms/event_suggestion.py:50
#: project/templates/_macros.html:462 project/templates/_macros.html:618
#: project/forms/event.py:243 project/forms/event.py:252
#: project/forms/event.py:321 project/forms/event_suggestion.py:50
#: project/templates/_macros.html:468 project/templates/_macros.html:624
#: project/templates/event/create.html:283
#: project/templates/event/update.html:164
#: project/templates/event_place/create.html:21
@ -664,18 +664,18 @@ msgstr ""
msgid "Place"
msgstr ""
#: project/forms/event.py:244
#: project/forms/event.py:245
msgid "Select existing place"
msgstr ""
#: project/forms/event.py:245
#: project/forms/event.py:246
msgid "Enter new place"
msgstr ""
#: project/forms/event.py:258 project/forms/event.py:267
#: project/forms/event.py:323 project/forms/event.py:373
#: project/forms/event_suggestion.py:60 project/templates/_macros.html:500
#: project/templates/_macros.html:655 project/templates/event/create.html:254
#: project/forms/event.py:259 project/forms/event.py:268
#: project/forms/event.py:329 project/forms/event.py:389
#: project/forms/event_suggestion.py:60 project/templates/_macros.html:506
#: project/templates/_macros.html:661 project/templates/event/create.html:254
#: project/templates/event/update.html:155
#: project/templates/organizer/create.html:17
#: project/templates/organizer/delete.html:13
@ -683,110 +683,127 @@ msgstr ""
msgid "Organizer"
msgstr ""
#: project/forms/event.py:260
#: project/forms/event.py:261
msgid "Select existing organizer"
msgstr ""
#: project/forms/event.py:261
#: project/forms/event.py:262
msgid "Enter new organizer"
msgstr ""
#: project/forms/event.py:273 project/templates/event/create.html:4
#: project/templates/event/create.html:221 project/templates/layout.html:256
#: project/templates/manage/events.html:12
#: project/templates/manage/organizers.html:21
msgid "Create event"
#: project/forms/event.py:274
msgid "Save as draft"
msgstr ""
#: project/forms/event.py:299
#: project/forms/event.py:275
msgid "Publish event"
msgstr ""
#: project/forms/event.py:305
msgid "Select existing place or enter new place"
msgstr ""
#: project/forms/event.py:306
#: project/forms/event.py:312
msgid "Select existing organizer or enter new organizer"
msgstr ""
#: project/forms/event.py:318
#: project/forms/event.py:324
msgid ""
"Choose where the event takes place. You can add and modify places at "
"Manage > Places."
msgstr ""
#: project/forms/event.py:326
#: project/forms/event.py:332
msgid ""
"Select the organizer. You can add and modify organizers at Manage > "
"Organizers."
msgstr ""
#: project/forms/event.py:332 project/templates/event/update.html:145
#: project/forms/event.py:338 project/templates/event/update.html:145
#: project/templates/oauth2_token/list.html:21
msgid "Status"
msgstr ""
#: project/forms/event.py:335
#: project/forms/event.py:341
msgid "EventStatus.scheduled"
msgstr ""
#: project/forms/event.py:336 project/templates/layout.html:113
#: project/forms/event.py:342 project/templates/layout.html:113
#: project/templates/layout.html:128
msgid "EventStatus.cancelled"
msgstr ""
#: project/forms/event.py:337 project/templates/layout.html:116
#: project/forms/event.py:343 project/templates/layout.html:116
#: project/templates/layout.html:131
msgid "EventStatus.movedOnline"
msgstr ""
#: project/forms/event.py:338 project/templates/layout.html:119
#: project/forms/event.py:344 project/templates/layout.html:119
#: project/templates/layout.html:134
msgid "EventStatus.postponed"
msgstr ""
#: project/forms/event.py:339 project/templates/layout.html:122
#: project/forms/event.py:345 project/templates/layout.html:122
#: project/templates/layout.html:137
msgid "EventStatus.rescheduled"
msgstr ""
#: project/forms/event.py:341
#: project/forms/event.py:347
msgid "Select the status of the event."
msgstr ""
#: project/forms/event.py:344 project/templates/event/update.html:4
#: project/forms/event.py:351
msgid "Public status"
msgstr ""
#: project/forms/event.py:354
msgid "PublicStatus.published"
msgstr ""
#: project/forms/event.py:355 project/templates/_macros.html:282
msgid "PublicStatus.draft"
msgstr ""
#: project/forms/event.py:357
msgid "Select the public status of the event."
msgstr ""
#: project/forms/event.py:360 project/templates/event/update.html:4
#: project/templates/event/update.html:112
msgid "Update event"
msgstr ""
#: project/forms/event.py:358 project/templates/_macros.html:1165
#: project/forms/event.py:374 project/templates/_macros.html:1171
#: project/templates/event/actions.html:47
#: project/templates/event/delete.html:6
msgid "Delete event"
msgstr ""
#: project/forms/event.py:366 project/forms/event_date.py:15
#: project/forms/event.py:382 project/forms/event_date.py:15
#: project/forms/planing.py:14
msgid "From"
msgstr ""
#: project/forms/event.py:367 project/forms/event_date.py:16
#: project/forms/event.py:383 project/forms/event_date.py:16
#: project/forms/planing.py:15
msgid "to"
msgstr ""
#: project/forms/event.py:368 project/forms/event_date.py:17
#: project/forms/event.py:384 project/forms/event_date.py:17
msgid "Keyword"
msgstr ""
#: project/forms/event.py:370 project/forms/event_date.py:19
#: project/forms/planing.py:17 project/templates/_macros.html:386
#: project/forms/event.py:386 project/forms/event_date.py:19
#: project/forms/planing.py:17 project/templates/_macros.html:392
msgid "Category"
msgstr ""
#: project/forms/event.py:376
#: project/forms/event.py:392
msgid "Find events"
msgstr ""
#: project/forms/event_date.py:22 project/forms/planing.py:20
#: project/templates/_macros.html:137 project/templates/_macros.html:320
#: project/templates/_macros.html:137 project/templates/_macros.html:326
#: project/templates/admin_unit/create.html:29
#: project/templates/admin_unit/update.html:30
#: project/templates/event_place/create.html:30
@ -926,7 +943,7 @@ msgid "Weekdays"
msgstr ""
#: project/forms/reference.py:11 project/forms/reference_request.py:15
#: project/templates/_macros.html:521 project/templates/_macros.html:681
#: project/templates/_macros.html:527 project/templates/_macros.html:687
#: project/templates/admin_unit/create.html:19
#: project/templates/admin_unit/update.html:20
#: project/templates/layout.html:286
@ -954,7 +971,7 @@ msgstr ""
msgid "Delete request"
msgstr ""
#: project/forms/reference_request.py:27 project/templates/_macros.html:1334
#: project/forms/reference_request.py:27 project/templates/_macros.html:1340
#: project/templates/event_suggestion/review_status.html:18
#: project/templates/reference_request/review_status.html:12
msgid "Review status"
@ -1016,8 +1033,8 @@ msgstr ""
msgid "This field is required."
msgstr ""
#: project/templates/_macros.html:134 project/templates/_macros.html:409
#: project/templates/_macros.html:416 project/templates/_macros.html:861
#: project/templates/_macros.html:134 project/templates/_macros.html:415
#: project/templates/_macros.html:422 project/templates/_macros.html:867
msgid "Date"
msgstr ""
@ -1037,27 +1054,27 @@ msgstr ""
msgid "Link"
msgstr ""
#: project/templates/_macros.html:363
#: project/templates/_macros.html:369
#, python-format
msgid "Created at %(created_at)s by %(created_by)s."
msgstr ""
#: project/templates/_macros.html:365
#: project/templates/_macros.html:371
#, python-format
msgid "Created at %(created_at)s."
msgstr ""
#: project/templates/_macros.html:370
#: project/templates/_macros.html:376
#, python-format
msgid "Last updated at %(updated_at)s by %(updated_by)s."
msgstr ""
#: project/templates/_macros.html:372
#: project/templates/_macros.html:378
#, python-format
msgid "Last updated at %(updated_at)s."
msgstr ""
#: project/templates/_macros.html:402 project/templates/_macros.html:578
#: project/templates/_macros.html:408 project/templates/_macros.html:584
#: project/templates/event/actions.html:12
#: project/templates/event/create.html:228
#: project/templates/event/delete.html:13
@ -1067,45 +1084,45 @@ msgstr ""
msgid "Event"
msgstr ""
#: project/templates/_macros.html:412 project/templates/_macros.html:564
#: project/templates/_macros.html:418 project/templates/_macros.html:570
#, python-format
msgid "%(count)d event dates"
msgstr ""
#: project/templates/_macros.html:445 project/templates/_macros.html:600
#: project/templates/_macros.html:1397 project/templates/event/actions.html:32
#: project/templates/_macros.html:451 project/templates/_macros.html:606
#: project/templates/_macros.html:1403 project/templates/event/actions.html:32
msgid "Share"
msgstr ""
#: project/templates/_macros.html:449 project/templates/_macros.html:604
#: project/templates/_macros.html:1427
#: project/templates/_macros.html:455 project/templates/_macros.html:610
#: project/templates/_macros.html:1433
msgid "Add to calendar"
msgstr ""
#: project/templates/_macros.html:483 project/templates/_macros.html:637
#: project/templates/_macros.html:489 project/templates/_macros.html:643
msgid "Show directions"
msgstr ""
#: project/templates/_macros.html:488 project/templates/_macros.html:642
#: project/templates/_macros.html:494 project/templates/_macros.html:648
msgid "The event takes place online."
msgstr ""
#: project/templates/_macros.html:490 project/templates/_macros.html:644
#: project/templates/_macros.html:496 project/templates/_macros.html:650
msgid "The event takes place both offline and online."
msgstr ""
#: project/templates/_macros.html:705 project/templates/event_date/list.html:4
#: project/templates/_macros.html:711 project/templates/event_date/list.html:4
#: project/templates/event_date/list.html:258
#: project/templates/event_date/search.html:3
#: project/templates/reference_request/review.html:32
msgid "Event Dates"
msgstr ""
#: project/templates/_macros.html:778
#: project/templates/_macros.html:784
msgid "Search location on Google"
msgstr ""
#: project/templates/_macros.html:811 project/templates/_macros.html:813
#: project/templates/_macros.html:817 project/templates/_macros.html:819
#: project/templates/event_date/list.html:279
#: project/templates/widget/event_suggestion/create.html:188
#: project/templates/widget/event_suggestion/create.html:213
@ -1116,12 +1133,12 @@ msgstr ""
msgid "Previous"
msgstr ""
#: project/templates/_macros.html:815
#: project/templates/_macros.html:821
#, python-format
msgid "Page %(page)d of %(pages)d (%(total)d total)"
msgstr ""
#: project/templates/_macros.html:817 project/templates/_macros.html:819
#: project/templates/_macros.html:823 project/templates/_macros.html:825
#: project/templates/event_date/list.html:281
#: project/templates/widget/event_suggestion/create.html:189
#: project/templates/widget/event_suggestion/create.html:214
@ -1131,68 +1148,68 @@ msgstr ""
msgid "Next"
msgstr ""
#: project/templates/_macros.html:884
#: project/templates/_macros.html:890
msgid "Radius"
msgstr ""
#: project/templates/_macros.html:1094
#: project/templates/_macros.html:1100
msgid "Edit image"
msgstr ""
#: project/templates/_macros.html:1115
#: project/templates/_macros.html:1121
msgid "Close"
msgstr ""
#: project/templates/_macros.html:1116
#: project/templates/_macros.html:1122
msgid "Okay"
msgstr ""
#: project/templates/_macros.html:1128
#: project/templates/_macros.html:1134
msgid "Choose image file"
msgstr ""
#: project/templates/_macros.html:1164 project/templates/event/actions.html:46
#: project/templates/_macros.html:1170 project/templates/event/actions.html:46
msgid "Edit event"
msgstr ""
#: project/templates/_macros.html:1167 project/templates/manage/events.html:30
#: project/templates/_macros.html:1173 project/templates/manage/events.html:30
msgid "More"
msgstr ""
#: project/templates/_macros.html:1214
#: project/templates/_macros.html:1220
msgid "Please enter a valid time, between 00:00 and 23:59."
msgstr ""
#: project/templates/_macros.html:1242
#: project/templates/_macros.html:1248
#, python-format
msgid "Just use %(term)s"
msgstr ""
#: project/templates/_macros.html:1294
#: project/templates/_macros.html:1300
msgid "Event suggestion"
msgstr ""
#: project/templates/_macros.html:1406
#: project/templates/_macros.html:1412
msgid "Link copied"
msgstr ""
#: project/templates/_macros.html:1406
#: project/templates/_macros.html:1412
msgid "Copy link"
msgstr ""
#: project/templates/_macros.html:1435
#: project/templates/_macros.html:1441
msgid "Google calendar"
msgstr ""
#: project/templates/_macros.html:1436
#: project/templates/_macros.html:1442
msgid "Apple calendar"
msgstr ""
#: project/templates/_macros.html:1437
#: project/templates/_macros.html:1443
msgid "Yahoo calendar"
msgstr ""
#: project/templates/_macros.html:1438
#: project/templates/_macros.html:1444
msgid "Other calendar"
msgstr ""
@ -1201,7 +1218,7 @@ msgid "Manage"
msgstr ""
#: project/templates/home.html:29 project/templates/security/login_user.html:35
#: project/views/widget.py:179
#: project/views/widget.py:180
msgid "Register for free"
msgstr ""
@ -1251,6 +1268,13 @@ msgstr ""
msgid "Show events"
msgstr ""
#: project/templates/event/create.html:4
#: project/templates/event/create.html:221 project/templates/layout.html:256
#: project/templates/manage/events.html:12
#: project/templates/manage/organizers.html:21
msgid "Create event"
msgstr ""
#: project/templates/layout.html:258
msgid "Review suggestions"
msgstr ""
@ -1725,7 +1749,7 @@ msgstr ""
msgid "Organization successfully updated"
msgstr ""
#: project/views/admin.py:68 project/views/manage.py:259
#: project/views/admin.py:68 project/views/manage.py:260
msgid "Settings successfully updated"
msgstr ""
@ -1783,23 +1807,27 @@ msgstr ""
msgid "Invitation successfully deleted"
msgstr ""
#: project/views/event.py:167
msgid "Event successfully created"
#: project/views/event.py:171
msgid "Event successfully published"
msgstr ""
#: project/views/event.py:207
#: project/views/event.py:173
msgid "Draft successfully saved"
msgstr ""
#: project/views/event.py:216
msgid "Event successfully updated"
msgstr ""
#: project/views/event.py:230 project/views/reference.py:162
#: project/views/event.py:239 project/views/reference.py:162
msgid "Entered name does not match event name"
msgstr ""
#: project/views/event.py:236
#: project/views/event.py:245
msgid "Event successfully deleted"
msgstr ""
#: project/views/event.py:383
#: project/views/event.py:392
msgid "Referenced event changed"
msgstr ""
@ -1933,17 +1961,17 @@ msgstr ""
msgid "You do not have permission for this action"
msgstr ""
#: project/views/widget.py:171
#: project/views/widget.py:172
msgid "Thank you so much! The event is being verified."
msgstr ""
#: project/views/widget.py:175
#: project/views/widget.py:176
msgid ""
"For more options and your own calendar of events, you can register for "
"free."
msgstr ""
#: project/views/widget.py:238
#: project/views/widget.py:239
msgid "New event review"
msgstr ""

View File

@ -0,0 +1,35 @@
"""empty message
Revision ID: 6893de0cb15b
Revises: 1fb9f679defb
Create Date: 2021-08-13 08:28:00.156404
"""
import sqlalchemy as sa
import sqlalchemy_utils
from alembic import op
from project import dbtypes
from project.models import PublicStatus
# revision identifiers, used by Alembic.
revision = "6893de0cb15b"
down_revision = "1fb9f679defb"
branch_labels = None
depends_on = None
def upgrade():
op.add_column(
"event",
sa.Column(
"public_status",
dbtypes.IntegerEnum(PublicStatus),
server_default=str(PublicStatus.published.value),
nullable=False,
),
)
def downgrade():
op.drop_column("event", "public_status")

View File

@ -170,7 +170,6 @@ from project.views import (
admin_unit,
admin_unit_member,
admin_unit_member_invitation,
api,
dump,
event,
event_date,

View File

@ -6,7 +6,7 @@ from flask_security.utils import FsPermNeed
from sqlalchemy import and_
from project import app
from project.models import AdminUnit, AdminUnitMember
from project.models import AdminUnit, AdminUnitMember, Event, PublicStatus
from project.services.admin_unit import get_member_for_admin_unit_by_user_id
@ -29,8 +29,12 @@ def owner_access_or_401(user_id):
abort(401)
def login_api_user_or_401(user):
if not login_user(user):
def login_api_user(token) -> bool:
return token and login_user(token.user)
def login_api_user_or_401(token) -> bool:
if not login_api_user(token):
abort(401)
@ -175,3 +179,19 @@ def can_create_admin_unit():
return True
return has_current_user_role("admin")
def can_read_event(event: Event) -> bool:
if event.public_status == PublicStatus.published:
return True
return has_access(event.admin_unit, "event:read")
def can_read_event_or_401(event: Event):
if not can_read_event(event):
abort(401)
def can_read_private_events(admin_unit: AdminUnit) -> bool:
return has_access(admin_unit, "event:read")

View File

@ -4,7 +4,13 @@ from flask_apispec import doc, marshal_with, use_kwargs
from sqlalchemy.orm import lazyload, load_only
from project import db
from project.access import access_or_401, login_api_user_or_401
from project.access import (
access_or_401,
can_read_event_or_401,
can_read_private_events,
login_api_user,
login_api_user_or_401,
)
from project.api import add_api_resource
from project.api.event.schemas import (
EventListRequestSchema,
@ -20,7 +26,7 @@ from project.api.event_date.schemas import (
EventDateListResponseSchema,
)
from project.api.resources import BaseResource
from project.models import Event, EventDate
from project.models import AdminUnit, Event, EventDate, PublicStatus
from project.oauth2 import require_oauth
from project.services.event import (
get_event_with_details_or_404,
@ -32,20 +38,36 @@ from project.services.event_search import EventSearchParams
from project.views.event import send_referenced_event_changed_mails
def api_can_read_event_or_401(event: Event):
if event.public_status != PublicStatus.published:
login_api_user(current_token)
can_read_event_or_401(event)
def api_can_read_private_events(admin_unit: AdminUnit):
login_api_user(current_token)
return can_read_private_events(admin_unit)
class EventListResource(BaseResource):
@doc(summary="List events", tags=["Events"])
@use_kwargs(EventListRequestSchema, location=("query"))
@marshal_with(EventListResponseSchema)
def get(self, **kwargs):
pagination = Event.query.paginate()
pagination = Event.query.filter(
Event.public_status == PublicStatus.published
).paginate()
return pagination
class EventResource(BaseResource):
@doc(summary="Get event", tags=["Events"])
@marshal_with(EventSchema)
@require_oauth(optional=True)
def get(self, id):
return get_event_with_details_or_404(id)
event = get_event_with_details_or_404(id)
api_can_read_event_or_401(event)
return event
@doc(
summary="Update event", tags=["Events"], security=[{"oauth2": ["event:write"]}]
@ -54,7 +76,7 @@ class EventResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("event:write")
def put(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
event = Event.query.get_or_404(id)
access_or_401(event.admin_unit, "event:update")
@ -73,7 +95,7 @@ class EventResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("event:write")
def patch(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
event = Event.query.get_or_404(id)
access_or_401(event.admin_unit, "event:update")
@ -93,7 +115,7 @@ class EventResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("event:write")
def delete(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
event = Event.query.get_or_404(id)
access_or_401(event.admin_unit, "event:delete")
@ -107,8 +129,13 @@ class EventDatesResource(BaseResource):
@doc(summary="List dates for event", tags=["Events", "Event Dates"])
@use_kwargs(EventDateListRequestSchema, location=("query"))
@marshal_with(EventDateListResponseSchema)
@require_oauth(optional=True)
def get(self, id):
event = Event.query.options(load_only(Event.id)).get_or_404(id)
event = Event.query.options(
load_only(Event.id, Event.public_status)
).get_or_404(id)
api_can_read_event_or_401(event)
return (
EventDate.query.options(lazyload(EventDate.event))
.filter(EventDate.event_id == event.id)

View File

@ -34,6 +34,7 @@ from project.models import (
EventAttendanceMode,
EventStatus,
EventTargetGroupOrigin,
PublicStatus,
)
@ -149,6 +150,11 @@ class EventBaseSchemaMixin(TrackableSchemaMixin):
"description": "When the event will end. An event can last a maximum of 14 days. If the event takes place regularly, enter when the first date will end."
},
)
public_status = EnumField(
PublicStatus,
missing=PublicStatus.published,
metadata={"description": "Public status of the event."},
)
class EventSchema(EventIdSchema, EventBaseSchemaMixin):
@ -186,6 +192,7 @@ class EventSearchItemSchema(EventRefSchema):
organization = fields.Nested(OrganizationRefSchema, attribute="admin_unit")
categories = fields.List(fields.Nested(EventCategoryRefSchema))
attendance_mode = EnumField(EventAttendanceMode)
public_status = EnumField(PublicStatus)
class EventListRequestSchema(PaginationRequestSchema):

View File

@ -2,6 +2,7 @@ from flask_apispec import doc, marshal_with, use_kwargs
from sqlalchemy.orm import defaultload, lazyload
from project.api import add_api_resource
from project.api.event.resources import api_can_read_event_or_401
from project.api.event_date.schemas import (
EventDateListRequestSchema,
EventDateListResponseSchema,
@ -10,7 +11,8 @@ from project.api.event_date.schemas import (
EventDateSearchResponseSchema,
)
from project.api.resources import BaseResource
from project.models import Event, EventDate
from project.models import Event, EventDate, PublicStatus
from project.oauth2 import require_oauth
from project.services.event import get_event_dates_query
from project.services.event_search import EventSearchParams
@ -20,17 +22,27 @@ class EventDateListResource(BaseResource):
@use_kwargs(EventDateListRequestSchema, location=("query"))
@marshal_with(EventDateListResponseSchema)
def get(self, **kwargs):
pagination = EventDate.query.options(lazyload(EventDate.event)).paginate()
pagination = (
EventDate.query.join(EventDate.event)
.options(lazyload(EventDate.event))
.filter(Event.public_status == PublicStatus.published)
.paginate()
)
return pagination
class EventDateResource(BaseResource):
@doc(summary="Get event date", tags=["Event Dates"])
@marshal_with(EventDateSchema)
@require_oauth(optional=True)
def get(self, id):
return EventDate.query.options(
defaultload(EventDate.event).load_only(Event.id, Event.name)
event_date = EventDate.query.options(
defaultload(EventDate.event).load_only(
Event.id, Event.name, Event.public_status
)
).get_or_404(id)
api_can_read_event_or_401(event_date.event)
return event_date
class EventDateSearchResource(BaseResource):

View File

@ -1,3 +1,5 @@
from operator import and_
from authlib.integrations.flask_oauth2 import current_token
from flask_apispec import doc, marshal_with, use_kwargs
@ -8,6 +10,7 @@ from project.access import (
login_api_user_or_401,
)
from project.api import add_api_resource
from project.api.event.resources import api_can_read_private_events
from project.api.event.schemas import (
EventIdSchema,
EventListRequestSchema,
@ -42,7 +45,7 @@ from project.api.place.schemas import (
PlacePostRequestSchema,
)
from project.api.resources import BaseResource
from project.models import AdminUnit, Event
from project.models import AdminUnit, Event, PublicStatus
from project.oauth2 import require_oauth
from project.services.admin_unit import (
get_admin_unit_query,
@ -72,12 +75,14 @@ class OrganizationEventDateSearchResource(BaseResource):
)
@use_kwargs(EventDateSearchRequestSchema, location=("query"))
@marshal_with(EventDateSearchResponseSchema)
@require_oauth(optional=True)
def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id)
params = EventSearchParams()
params.load_from_request()
params.admin_unit_id = admin_unit.id
params.can_read_private_events = api_can_read_private_events(admin_unit)
pagination = get_event_dates_query(params).paginate()
return pagination
@ -87,12 +92,14 @@ class OrganizationEventSearchResource(BaseResource):
@doc(summary="Search for events of organization", tags=["Organizations", "Events"])
@use_kwargs(EventSearchRequestSchema, location=("query"))
@marshal_with(EventSearchResponseSchema)
@require_oauth(optional=True)
def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id)
params = EventSearchParams()
params.load_from_request()
params.admin_unit_id = admin_unit.id
params.can_read_private_events = api_can_read_private_events(admin_unit)
pagination = get_events_query(params).paginate()
return pagination
@ -102,9 +109,18 @@ class OrganizationEventListResource(BaseResource):
@doc(summary="List events of organization", tags=["Organizations", "Events"])
@use_kwargs(EventListRequestSchema, location=("query"))
@marshal_with(EventListResponseSchema)
@require_oauth(optional=True)
def get(self, id, **kwargs):
admin_unit = AdminUnit.query.get_or_404(id)
pagination = Event.query.filter(Event.admin_unit_id == admin_unit.id).paginate()
event_filter = Event.admin_unit_id == admin_unit.id
if not api_can_read_private_events(admin_unit):
event_filter = and_(
event_filter, Event.public_status == PublicStatus.published
)
pagination = Event.query.filter(event_filter).paginate()
return pagination
@doc(
@ -116,7 +132,7 @@ class OrganizationEventListResource(BaseResource):
@marshal_with(EventIdSchema, 201)
@require_oauth("event:write")
def post(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
admin_unit = get_admin_unit_for_manage_or_404(id)
access_or_401(admin_unit, "event:create")
@ -161,7 +177,7 @@ class OrganizationOrganizerListResource(BaseResource):
@marshal_with(OrganizerIdSchema, 201)
@require_oauth("organizer:write")
def post(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
admin_unit = get_admin_unit_for_manage_or_404(id)
access_or_401(admin_unit, "organizer:create")
@ -194,7 +210,7 @@ class OrganizationPlaceListResource(BaseResource):
@marshal_with(PlaceIdSchema, 201)
@require_oauth("place:write")
def post(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
admin_unit = get_admin_unit_for_manage_or_404(id)
access_or_401(admin_unit, "place:create")

View File

@ -30,7 +30,7 @@ class OrganizerResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("organizer:write")
def put(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
organizer = EventOrganizer.query.get_or_404(id)
access_or_401(organizer.adminunit, "organizer:update")
@ -48,7 +48,7 @@ class OrganizerResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("organizer:write")
def patch(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
organizer = EventOrganizer.query.get_or_404(id)
access_or_401(organizer.adminunit, "organizer:update")
@ -67,7 +67,7 @@ class OrganizerResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("organizer:write")
def delete(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
organizer = EventOrganizer.query.get_or_404(id)
access_or_401(organizer.adminunit, "organizer:delete")

View File

@ -28,7 +28,7 @@ class PlaceResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("place:write")
def put(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
place = EventPlace.query.get_or_404(id)
access_or_401(place.adminunit, "place:update")
@ -42,7 +42,7 @@ class PlaceResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("place:write")
def patch(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
place = EventPlace.query.get_or_404(id)
access_or_401(place.adminunit, "place:update")
@ -57,7 +57,7 @@ class PlaceResource(BaseResource):
@marshal_with(None, 204)
@require_oauth("place:write")
def delete(self, id):
login_api_user_or_401(current_token.user)
login_api_user_or_401(current_token)
place = EventPlace.query.get_or_404(id)
access_or_401(place.adminunit, "place:delete")

View File

@ -20,6 +20,7 @@ from project.models import (
EventOrganizer,
EventPlace,
EventReference,
PublicStatus,
)
from project.utils import make_dir
@ -43,7 +44,11 @@ def dump_all():
make_dir(tmp_path)
# Events
events = Event.query.options(joinedload(Event.categories)).all()
events = (
Event.query.options(joinedload(Event.categories))
.filter(Event.public_status == PublicStatus.published)
.all()
)
dump_items(events, EventDumpSchema(many=True), "events", tmp_path)
# Places

View File

@ -10,7 +10,7 @@ from sqlalchemy.orm import load_only
from project import app, cache_path, robots_txt_path, sitemap_path
from project.dateutils import get_today
from project.models import Event, EventDate
from project.models import Event, EventDate, PublicStatus
from project.utils import make_dir
seo_cli = AppGroup("seo")
@ -31,6 +31,7 @@ def generate_sitemap(pinggoogle):
events = (
Event.query.options(load_only(Event.id, Event.updated_at))
.filter(Event.dates.any(EventDate.start >= today))
.filter(Event.public_status == PublicStatus.published)
.all()
)
click.echo(f"Found {len(events)} events")

View File

@ -27,6 +27,7 @@ from project.models import (
EventTargetGroupOrigin,
Image,
Location,
PublicStatus,
)
@ -270,7 +271,8 @@ class CreateEventForm(BaseEventForm):
)
new_organizer = FormField(OrganizerForm, default=lambda: EventOrganizer())
submit = SubmitField(lazy_gettext("Create event"))
submit_draft = SubmitField(lazy_gettext("Save as draft"))
submit = SubmitField(lazy_gettext("Publish event"))
def populate_obj(self, obj):
for name, field in self._fields.items():
@ -290,6 +292,10 @@ class CreateEventForm(BaseEventForm):
obj.photo = Image()
field.populate_obj(obj, name)
obj.public_status = (
PublicStatus.published if self.submit.data else PublicStatus.draft
)
def validate(self):
if not super(BaseEventForm, self).validate():
return False
@ -341,6 +347,16 @@ class UpdateEventForm(BaseEventForm):
description=lazy_gettext("Select the status of the event."),
)
public_status = SelectField(
lazy_gettext("Public status"),
coerce=int,
choices=[
(int(PublicStatus.published), lazy_gettext("PublicStatus.published")),
(int(PublicStatus.draft), lazy_gettext("PublicStatus.draft")),
],
description=lazy_gettext("Select the public status of the event."),
)
submit = SubmitField(lazy_gettext("Update event"))
def populate_obj(self, obj):

View File

@ -469,6 +469,11 @@ class EventReferenceRequestRejectionReason(IntEnum):
irrelevant = 4
class PublicStatus(IntEnum):
draft = 1
published = 2
class EventOrganizer(db.Model, TrackableMixin):
__tablename__ = "eventorganizer"
__table_args__ = (UniqueConstraint("name", "admin_unit_id"),)
@ -643,6 +648,12 @@ class Event(db.Model, TrackableMixin, EventMixin):
categories = relationship("EventCategory", secondary="event_eventcategories")
public_status = Column(
IntegerEnum(PublicStatus),
nullable=False,
default=PublicStatus.published.value,
server_default=str(PublicStatus.published.value),
)
status = Column(IntegerEnum(EventStatus))
previous_start_date = db.Column(db.DateTime(timezone=True), nullable=True)
rating = Column(Integer())

View File

@ -28,6 +28,7 @@ from project.models import (
EventStatus,
Image,
Location,
PublicStatus,
)
from project.utils import get_pending_changes, get_place_str
from project.views.utils import truncate
@ -101,6 +102,13 @@ def get_event_dates_query(params):
),
)
if not params.can_read_private_events:
event_filter = and_(
event_filter, Event.public_status == PublicStatus.published
)
else:
event_filter = and_(event_filter, Event.public_status == PublicStatus.published)
if params.date_from:
date_filter = EventDate.start >= params.date_from
@ -251,6 +259,13 @@ def get_events_query(params):
if params.admin_unit_id:
event_filter = and_(event_filter, Event.admin_unit_id == params.admin_unit_id)
if not params.can_read_private_events:
event_filter = and_(
event_filter, Event.public_status == PublicStatus.published
)
else:
event_filter = and_(event_filter, Event.public_status == PublicStatus.published)
if params.date_from:
date_filter = EventDate.start >= params.date_from
@ -325,6 +340,10 @@ def update_event_dates_with_recurrence_rule(event):
def insert_event(event):
if not event.status:
event.status = EventStatus.scheduled
if not event.public_status:
event.public_status = PublicStatus.published
update_event_dates_with_recurrence_rule(event)
db.session.add(event)

View File

@ -17,6 +17,7 @@ class EventSearchParams(object):
self._date_to_str = None
self._coordinate = None
self.admin_unit_id = None
self.can_read_private_events = None
self.keyword = None
self.latitude = None
self.longitude = None

View File

@ -277,6 +277,12 @@
{% endif %}
{% endmacro %}
{% macro render_public_status_pill(event) %}
{% if event.public_status and event.public_status == 1 %}
<span class="badge badge-pill badge-info">{{ _('PublicStatus.draft') }}</span>
{% endif %}
{% endmacro %}
{% macro render_attendance_mode_pill(event) %}
{% if event.attendance_mode and event.attendance_mode.value != 1 %}
<span class="badge badge-pill badge-info">{{ event.attendance_mode | loc_enum }}</span>
@ -284,7 +290,7 @@
{% endmacro %}
{% macro render_event_warning_pills(event) %}
{{ render_event_status_pill(event) }} {{ render_booked_up_pill(event) }} {{ render_attendance_mode_pill(event) }}
{{ render_public_status_pill(event) }} {{ render_event_status_pill(event) }} {{ render_booked_up_pill(event) }} {{ render_attendance_mode_pill(event) }}
{% endmacro %}
{% macro render_event_review_status_pill(event) %}

View File

@ -363,7 +363,10 @@ $( function() {
</div>
{% endif %}
{{ render_field(form.submit) }}
<div class="d-flex flex-column flex-sm-row">
{{ form.submit(class="btn btn-primary m-1")|safe }}
{{ form.submit_draft(class="btn btn-secondary m-1")|safe }}
</div>
</form>

View File

@ -145,6 +145,7 @@
{{ _('Status') }}
</div>
<div class="card-body">
{{ render_field_with_errors(form.public_status, class="autocomplete w-100") }}
{{ render_field_with_errors(form.status, class="autocomplete w-100") }}
{{ render_field_with_errors(form.previous_start_date) }}
</div>

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-08-12 23:45+0200\n"
"POT-Creation-Date: 2021-08-15 14:50+0200\n"
"PO-Revision-Date: 2020-06-07 18:51+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@ -176,7 +176,7 @@ msgstr "Nutzungsbedingungen"
msgid "Legal notice"
msgstr "Impressum"
#: project/forms/admin.py:12 project/templates/_macros.html:1322
#: project/forms/admin.py:12 project/templates/_macros.html:1328
#: project/templates/layout.html:339
#: project/templates/widget/event_suggestion/create.html:199
#: project/views/admin_unit.py:36 project/views/root.py:58
@ -249,8 +249,8 @@ msgstr "Breitengrad"
msgid "Longitude"
msgstr "Längengrad"
#: project/forms/admin_unit.py:28 project/forms/event.py:35
#: project/forms/event.py:64 project/forms/event.py:359
#: project/forms/admin_unit.py:28 project/forms/event.py:36
#: project/forms/event.py:65 project/forms/event.py:375
#: project/forms/event_place.py:25 project/forms/event_place.py:50
#: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66
#: project/forms/organizer.py:25 project/forms/organizer.py:52
@ -274,32 +274,32 @@ msgstr ""
"eindeutig zu identifizieren. Der Kurzname darf nur Buchstaben, Nummern "
"und Unterstriche enthalten."
#: project/forms/admin_unit.py:40 project/templates/_macros.html:1452
#: project/forms/admin_unit.py:40 project/templates/_macros.html:1458
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:46 project/forms/event.py:56
#: project/forms/event.py:90 project/forms/event_place.py:26
#: project/forms/admin_unit.py:46 project/forms/event.py:57
#: project/forms/event.py:91 project/forms/event_place.py:26
#: project/forms/organizer.py:26
msgid "Link URL"
msgstr "Link URL"
#: project/forms/admin_unit.py:47 project/forms/admin_unit_member.py:11
#: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28
#: project/forms/event.py:57 project/forms/event_suggestion.py:38
#: project/forms/event.py:58 project/forms/event_suggestion.py:38
#: project/forms/organizer.py:27 project/templates/_macros.html:262
#: project/templates/_macros.html:1412 project/templates/admin/users.html:19
#: project/templates/_macros.html:1418 project/templates/admin/users.html:19
msgid "Email"
msgstr "Email"
#: project/forms/admin_unit.py:48 project/forms/event.py:58
#: project/forms/admin_unit.py:48 project/forms/event.py:59
#: project/forms/event_suggestion.py:31 project/forms/organizer.py:28
#: project/templates/_macros.html:305
#: project/templates/_macros.html:311
msgid "Phone"
msgstr "Telefon"
#: project/forms/admin_unit.py:49 project/forms/event.py:59
#: project/forms/organizer.py:29 project/templates/_macros.html:313
#: project/forms/admin_unit.py:49 project/forms/event.py:60
#: project/forms/organizer.py:29 project/templates/_macros.html:319
msgid "Fax"
msgstr "Fax"
@ -441,47 +441,47 @@ msgstr "50 km"
msgid "100 km"
msgstr "100 km"
#: project/forms/event.py:53
#: project/forms/event.py:54
msgid "Organizator"
msgstr "Veranstalter"
#: project/forms/event.py:66
#: project/forms/event.py:67
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:69
#: project/forms/event.py:70
msgid "Start"
msgstr "Beginn"
#: project/forms/event.py:71
#: project/forms/event.py:72
msgid "Indicate when the event will take place."
msgstr "Gib an, wann die Veranstaltung stattfindet."
#: project/forms/event.py:74
#: project/forms/event.py:75
msgid "End"
msgstr "Ende"
#: project/forms/event.py:76
#: project/forms/event.py:77
msgid "Indicate when the event will end. An event can last a maximum of 14 days."
msgstr ""
"Gib an, wann die Veranstaltung endet. Eine Veranstaltung darf maximal 14 "
"Tage dauern."
#: project/forms/event.py:81 project/templates/event/create.html:244
#: project/forms/event.py:82 project/templates/event/create.html:244
#: project/templates/event/update.html:135
#: project/templates/widget/event_suggestion/create.html:234
msgid "Recurring event"
msgstr "Regelmäßige Veranstaltung"
#: project/forms/event.py:85 project/forms/event_place.py:28
#: project/forms/event.py:86 project/forms/event_place.py:28
msgid "Description"
msgstr "Beschreibung"
#: project/forms/event.py:87
#: project/forms/event.py:88
msgid "Add an description of the event."
msgstr "Füge der Veranstaltung eine Beschreibung hinzu."
#: project/forms/event.py:92
#: project/forms/event.py:93
msgid ""
"Enter a link to an external website containing more information about the"
" event."
@ -489,19 +489,19 @@ msgstr ""
"Gib einen Link zu einer externen Website ein, die weitere Informationen "
"zur Veranstaltung enthält."
#: project/forms/event.py:97
#: project/forms/event.py:98
msgid "Ticket Link URL"
msgstr "Ticket Link"
#: project/forms/event.py:99
#: project/forms/event.py:100
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:102 project/templates/_macros.html:244
#: project/forms/event.py:103 project/templates/_macros.html:244
msgid "Tags"
msgstr "Stichworte"
#: project/forms/event.py:104
#: project/forms/event.py:105
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."
@ -510,68 +510,68 @@ msgstr ""
"Worte müssen nicht eingegeben werden, wenn sie bereits im Namen oder in "
"der Beschreibung enthalten sind."
#: project/forms/event.py:109
#: project/forms/event.py:110
msgid "Kid friendly"
msgstr "Für Kinder geeignet"
#: project/forms/event.py:111
#: project/forms/event.py:112
msgid "If the event is particularly suitable for children."
msgstr "Wenn die Veranstaltung besonders für Kinder geeignet ist."
#: project/forms/event.py:114
#: project/forms/event.py:115
msgid "Accessible for free"
msgstr "Kostenlos zugänglich"
#: project/forms/event.py:116
#: project/forms/event.py:117
msgid "If the event is accessible for free."
msgstr "Wenn die Veranstaltung kostenlos zugänglich ist."
#: project/forms/event.py:119
#: project/forms/event.py:120
msgid "Typical Age from"
msgstr "Typisches Alter von"
#: project/forms/event.py:121
#: project/forms/event.py:122
msgid "The minimum age that participants should be."
msgstr "Das Mindestalter, das die Teilnehmer haben sollten."
#: project/forms/event.py:124
#: project/forms/event.py:125
msgid "Typical Age to"
msgstr "Typisches Alter bis"
#: project/forms/event.py:126
#: project/forms/event.py:127
msgid "The maximum age that participants should be."
msgstr "Das maximale Alter, das die Teilnehmer haben sollten."
#: project/forms/event.py:129
#: project/forms/event.py:130
msgid "Registration required"
msgstr "Anmeldung erforderlich"
#: project/forms/event.py:131
#: project/forms/event.py:132
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:136 project/templates/_macros.html:276
#: project/forms/event.py:137 project/templates/_macros.html:276
#: project/templates/layout.html:159
msgid "Booked up"
msgstr "Ausgebucht"
#: project/forms/event.py:138
#: project/forms/event.py:139
msgid "If the event is booked up or sold out."
msgstr "Wenn die Veranstaltung ausgebucht oder ausverkauft ist."
#: project/forms/event.py:141
#: project/forms/event.py:142
msgid "Expected number of participants"
msgstr "Erwartete Teilnehmerzahl"
#: project/forms/event.py:143
#: project/forms/event.py:144
msgid "The estimated expected attendance."
msgstr "Die geschätzte erwartete Teilnehmerzahl."
#: project/forms/event.py:146
#: project/forms/event.py:147
msgid "Price info"
msgstr "Preisinformation"
#: project/forms/event.py:148
#: project/forms/event.py:149
msgid ""
"Enter price information in textual form. E.g., different prices for "
"adults and children."
@ -579,23 +579,23 @@ msgstr ""
"Gib die Preisinformationen in Textform ein. Z.B. unterschiedliche Preise "
"für Erwachsene und Kinder."
#: project/forms/event.py:153
#: project/forms/event.py:154
msgid "Target group origin"
msgstr "Für Touristen/Einwohner geeignet"
#: project/forms/event.py:158
#: project/forms/event.py:159
msgid "EventTargetGroupOrigin.both"
msgstr "Für Touristen und Einwohner"
#: project/forms/event.py:162
#: project/forms/event.py:163
msgid "EventTargetGroupOrigin.tourist"
msgstr "Hauptsächlich für Touristen"
#: project/forms/event.py:166
#: project/forms/event.py:167
msgid "EventTargetGroupOrigin.resident"
msgstr "Hauptsächlich für Einwohner"
#: project/forms/event.py:169
#: project/forms/event.py:170
msgid ""
"Choose whether the event is particularly suitable for tourists or "
"residents."
@ -603,32 +603,32 @@ msgstr ""
"Wähle, ob die Veranstaltung besonders für Touristen oder Einwohner "
"geeignet ist."
#: project/forms/event.py:174
#: project/forms/event.py:175
msgid "Attendance mode"
msgstr "Teilnahme"
#: project/forms/event.py:179
#: project/forms/event.py:180
msgid "EventAttendanceMode.offline"
msgstr "Präsenzveranstaltung"
#: project/forms/event.py:183 project/templates/layout.html:147
#: project/forms/event.py:184 project/templates/layout.html:147
msgid "EventAttendanceMode.online"
msgstr "Online"
#: project/forms/event.py:185 project/templates/layout.html:150
#: project/forms/event.py:186 project/templates/layout.html:150
msgid "EventAttendanceMode.mixed"
msgstr "Präsenzveranstaltung und online"
#: project/forms/event.py:187
#: project/forms/event.py:188
msgid "Choose how people can attend the event."
msgstr "Wähle aus, wie Personen an der Veranstaltung teilnehmen können."
#: project/forms/event.py:191 project/forms/event_place.py:27
#: project/forms/event.py:192 project/forms/event_place.py:27
#: project/templates/widget/event_suggestion/create.html:252
msgid "Photo"
msgstr "Foto"
#: project/forms/event.py:193
#: project/forms/event.py:194
msgid ""
"We recommend uploading a photo for the event. It looks a lot more, but of"
" course it works without it."
@ -636,41 +636,41 @@ 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:203 project/templates/_macros.html:1193
#: project/forms/event.py:204 project/templates/_macros.html:1199
msgid "The start must be before the end."
msgstr "Der Start muss vor dem Ende sein."
#: project/forms/event.py:209 project/templates/_macros.html:1210
#: project/forms/event.py:210 project/templates/_macros.html:1216
msgid "An event can last a maximum of 14 days."
msgstr "Eine Veranstaltung darf maximal 14 Tage dauern."
#: project/forms/event.py:217 project/templates/_macros.html:423
#: project/templates/_macros.html:582
#: project/forms/event.py:218 project/templates/_macros.html:429
#: project/templates/_macros.html:588
msgid "Previous start date"
msgstr "Vorheriges Startdatum"
#: project/forms/event.py:219
#: project/forms/event.py:220
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:224 project/forms/event_suggestion.py:71
#: project/forms/event.py:225 project/forms/event_suggestion.py:71
msgid "Categories"
msgstr "Kategorien"
#: project/forms/event.py:227 project/forms/event_suggestion.py:74
#: project/forms/event.py:228 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:230 project/forms/reference.py:14
#: project/forms/event.py:231 project/forms/reference.py:14
#: project/forms/reference.py:27 project/forms/reference_request.py:75
#: project/templates/event/create.html:358
#: project/templates/event/update.html:214
msgid "Rating"
msgstr "Bewertung"
#: project/forms/event.py:234 project/forms/reference.py:18
#: project/forms/event.py:235 project/forms/reference.py:18
#: project/forms/reference.py:31 project/forms/reference_request.py:79
msgid ""
"Choose how relevant the event is to your organization. The value is not "
@ -679,9 +679,9 @@ 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:242 project/forms/event.py:251
#: project/forms/event.py:315 project/forms/event_suggestion.py:50
#: project/templates/_macros.html:462 project/templates/_macros.html:618
#: project/forms/event.py:243 project/forms/event.py:252
#: project/forms/event.py:321 project/forms/event_suggestion.py:50
#: project/templates/_macros.html:468 project/templates/_macros.html:624
#: project/templates/event/create.html:283
#: project/templates/event/update.html:164
#: project/templates/event_place/create.html:21
@ -690,18 +690,18 @@ msgstr ""
msgid "Place"
msgstr "Ort"
#: project/forms/event.py:244
#: project/forms/event.py:245
msgid "Select existing place"
msgstr "Vorhandenen Ort auswählen"
#: project/forms/event.py:245
#: project/forms/event.py:246
msgid "Enter new place"
msgstr "Neuen Ort eingeben"
#: project/forms/event.py:258 project/forms/event.py:267
#: project/forms/event.py:323 project/forms/event.py:373
#: project/forms/event_suggestion.py:60 project/templates/_macros.html:500
#: project/templates/_macros.html:655 project/templates/event/create.html:254
#: project/forms/event.py:259 project/forms/event.py:268
#: project/forms/event.py:329 project/forms/event.py:389
#: project/forms/event_suggestion.py:60 project/templates/_macros.html:506
#: project/templates/_macros.html:661 project/templates/event/create.html:254
#: project/templates/event/update.html:155
#: project/templates/organizer/create.html:17
#: project/templates/organizer/delete.html:13
@ -709,30 +709,31 @@ msgstr "Neuen Ort eingeben"
msgid "Organizer"
msgstr "Veranstalter"
#: project/forms/event.py:260
#: project/forms/event.py:261
msgid "Select existing organizer"
msgstr "Vorhandenen Veranstalter auswählen"
#: project/forms/event.py:261
#: project/forms/event.py:262
msgid "Enter new organizer"
msgstr "Neuen Veranstalter eingeben"
#: project/forms/event.py:273 project/templates/event/create.html:4
#: project/templates/event/create.html:221 project/templates/layout.html:256
#: project/templates/manage/events.html:12
#: project/templates/manage/organizers.html:21
msgid "Create event"
msgstr "Veranstaltung erstellen"
#: project/forms/event.py:274
msgid "Save as draft"
msgstr "Als Entwurf speicher"
#: project/forms/event.py:299
#: project/forms/event.py:275
msgid "Publish event"
msgstr "Veranstaltung veröffentlichen"
#: project/forms/event.py:305
msgid "Select existing place or enter new place"
msgstr "Existierenden Ort wählen oder neuen Ort eingeben"
#: project/forms/event.py:306
#: project/forms/event.py:312
msgid "Select existing organizer or enter new organizer"
msgstr "Wähle einen vorhandenen Veranstalter oder gib einen neuen Veranstalter ein"
#: project/forms/event.py:318
#: project/forms/event.py:324
msgid ""
"Choose where the event takes place. You can add and modify places at "
"Manage > Places."
@ -740,7 +741,7 @@ msgstr ""
"Wähle, wo die Veranstaltung stattfindet. Du kannst Orte unter Verwaltung "
"> Orte hinzufügen und ändern."
#: project/forms/event.py:326
#: project/forms/event.py:332
msgid ""
"Select the organizer. You can add and modify organizers at Manage > "
"Organizers."
@ -748,75 +749,91 @@ msgstr ""
"Wähle den Veranstalter. Du kannst Veranstalter unter Verwaltung > "
"Veranstalter hinzufügen und ändern."
#: project/forms/event.py:332 project/templates/event/update.html:145
#: project/forms/event.py:338 project/templates/event/update.html:145
#: project/templates/oauth2_token/list.html:21
msgid "Status"
msgstr "Status"
#: project/forms/event.py:335
#: project/forms/event.py:341
msgid "EventStatus.scheduled"
msgstr "Geplant"
#: project/forms/event.py:336 project/templates/layout.html:113
#: project/forms/event.py:342 project/templates/layout.html:113
#: project/templates/layout.html:128
msgid "EventStatus.cancelled"
msgstr "Abgesagt"
#: project/forms/event.py:337 project/templates/layout.html:116
#: project/forms/event.py:343 project/templates/layout.html:116
#: project/templates/layout.html:131
msgid "EventStatus.movedOnline"
msgstr "Online verschoben"
#: project/forms/event.py:338 project/templates/layout.html:119
#: project/forms/event.py:344 project/templates/layout.html:119
#: project/templates/layout.html:134
msgid "EventStatus.postponed"
msgstr "Verschoben"
#: project/forms/event.py:339 project/templates/layout.html:122
#: project/forms/event.py:345 project/templates/layout.html:122
#: project/templates/layout.html:137
msgid "EventStatus.rescheduled"
msgstr "Neu angesetzt"
#: project/forms/event.py:341
#: project/forms/event.py:347
msgid "Select the status of the event."
msgstr "Wähle den Status der Veranstaltung."
#: project/forms/event.py:344 project/templates/event/update.html:4
#: project/forms/event.py:351
msgid "Public status"
msgstr "Öffentlicher Status"
#: project/forms/event.py:354
msgid "PublicStatus.published"
msgstr "Veröffentlicht"
#: project/forms/event.py:355 project/templates/_macros.html:282
msgid "PublicStatus.draft"
msgstr "Entwurf"
#: project/forms/event.py:357
msgid "Select the public status of the event."
msgstr "Wähle den öffentlichen Status der Veranstaltung."
#: project/forms/event.py:360 project/templates/event/update.html:4
#: project/templates/event/update.html:112
msgid "Update event"
msgstr "Veranstaltung aktualisieren"
#: project/forms/event.py:358 project/templates/_macros.html:1165
#: project/forms/event.py:374 project/templates/_macros.html:1171
#: project/templates/event/actions.html:47
#: project/templates/event/delete.html:6
msgid "Delete event"
msgstr "Veranstaltung löschen"
#: project/forms/event.py:366 project/forms/event_date.py:15
#: project/forms/event.py:382 project/forms/event_date.py:15
#: project/forms/planing.py:14
msgid "From"
msgstr "Von"
#: project/forms/event.py:367 project/forms/event_date.py:16
#: project/forms/event.py:383 project/forms/event_date.py:16
#: project/forms/planing.py:15
msgid "to"
msgstr "bis"
#: project/forms/event.py:368 project/forms/event_date.py:17
#: project/forms/event.py:384 project/forms/event_date.py:17
msgid "Keyword"
msgstr "Stichwort"
#: project/forms/event.py:370 project/forms/event_date.py:19
#: project/forms/planing.py:17 project/templates/_macros.html:386
#: project/forms/event.py:386 project/forms/event_date.py:19
#: project/forms/planing.py:17 project/templates/_macros.html:392
msgid "Category"
msgstr "Kategorie"
#: project/forms/event.py:376
#: project/forms/event.py:392
msgid "Find events"
msgstr "Veranstaltungen finden"
#: project/forms/event_date.py:22 project/forms/planing.py:20
#: project/templates/_macros.html:137 project/templates/_macros.html:320
#: project/templates/_macros.html:137 project/templates/_macros.html:326
#: project/templates/admin_unit/create.html:29
#: project/templates/admin_unit/update.html:30
#: project/templates/event_place/create.html:30
@ -960,7 +977,7 @@ msgid "Weekdays"
msgstr "Wochentage"
#: project/forms/reference.py:11 project/forms/reference_request.py:15
#: project/templates/_macros.html:521 project/templates/_macros.html:681
#: project/templates/_macros.html:527 project/templates/_macros.html:687
#: project/templates/admin_unit/create.html:19
#: project/templates/admin_unit/update.html:20
#: project/templates/layout.html:286
@ -988,7 +1005,7 @@ msgstr "Anfrage speichern"
msgid "Delete request"
msgstr "Anfrage löschen"
#: project/forms/reference_request.py:27 project/templates/_macros.html:1334
#: project/forms/reference_request.py:27 project/templates/_macros.html:1340
#: project/templates/event_suggestion/review_status.html:18
#: project/templates/reference_request/review_status.html:12
msgid "Review status"
@ -1050,8 +1067,8 @@ msgstr "Ablehnen"
msgid "This field is required."
msgstr "Dieses Feld ist erforderlich."
#: project/templates/_macros.html:134 project/templates/_macros.html:409
#: project/templates/_macros.html:416 project/templates/_macros.html:861
#: project/templates/_macros.html:134 project/templates/_macros.html:415
#: project/templates/_macros.html:422 project/templates/_macros.html:867
msgid "Date"
msgstr "Datum"
@ -1071,27 +1088,27 @@ msgstr "Auf Google Maps anzeigen"
msgid "Link"
msgstr "Link"
#: project/templates/_macros.html:363
#: project/templates/_macros.html:369
#, python-format
msgid "Created at %(created_at)s by %(created_by)s."
msgstr "Erstellt am %(created_at)s von %(created_by)s."
#: project/templates/_macros.html:365
#: project/templates/_macros.html:371
#, python-format
msgid "Created at %(created_at)s."
msgstr "Erstellt am %(created_at)s."
#: project/templates/_macros.html:370
#: project/templates/_macros.html:376
#, python-format
msgid "Last updated at %(updated_at)s by %(updated_by)s."
msgstr "Zuletzt aktualisiert am %(updated_at)s von %(updated_by)s."
#: project/templates/_macros.html:372
#: project/templates/_macros.html:378
#, python-format
msgid "Last updated at %(updated_at)s."
msgstr "Zuletzt aktualisiert am %(updated_at)s."
#: project/templates/_macros.html:402 project/templates/_macros.html:578
#: project/templates/_macros.html:408 project/templates/_macros.html:584
#: project/templates/event/actions.html:12
#: project/templates/event/create.html:228
#: project/templates/event/delete.html:13
@ -1101,47 +1118,47 @@ msgstr "Zuletzt aktualisiert am %(updated_at)s."
msgid "Event"
msgstr "Veranstaltung"
#: project/templates/_macros.html:412 project/templates/_macros.html:564
#: project/templates/_macros.html:418 project/templates/_macros.html:570
#, python-format
msgid "%(count)d event dates"
msgstr "%(count)d Termine"
#: project/templates/_macros.html:445 project/templates/_macros.html:600
#: project/templates/_macros.html:1397 project/templates/event/actions.html:32
#: project/templates/_macros.html:451 project/templates/_macros.html:606
#: project/templates/_macros.html:1403 project/templates/event/actions.html:32
msgid "Share"
msgstr "Teilen"
#: project/templates/_macros.html:449 project/templates/_macros.html:604
#: project/templates/_macros.html:1427
#: project/templates/_macros.html:455 project/templates/_macros.html:610
#: project/templates/_macros.html:1433
msgid "Add to calendar"
msgstr "Zum Kalender"
#: project/templates/_macros.html:483 project/templates/_macros.html:637
#: project/templates/_macros.html:489 project/templates/_macros.html:643
msgid "Show directions"
msgstr "Anreise planen"
#: project/templates/_macros.html:488 project/templates/_macros.html:642
#: project/templates/_macros.html:494 project/templates/_macros.html:648
msgid "The event takes place online."
msgstr "Die Veranstaltung findet online statt."
#: project/templates/_macros.html:490 project/templates/_macros.html:644
#: project/templates/_macros.html:496 project/templates/_macros.html:650
msgid "The event takes place both offline and online."
msgstr ""
"Die Veranstaltung findet sowohl als Präsenzveranstaltung als auch online "
"statt."
#: project/templates/_macros.html:705 project/templates/event_date/list.html:4
#: project/templates/_macros.html:711 project/templates/event_date/list.html:4
#: project/templates/event_date/list.html:258
#: project/templates/event_date/search.html:3
#: project/templates/reference_request/review.html:32
msgid "Event Dates"
msgstr "Termine"
#: project/templates/_macros.html:778
#: project/templates/_macros.html:784
msgid "Search location on Google"
msgstr "Ort bei Google suchen"
#: project/templates/_macros.html:811 project/templates/_macros.html:813
#: project/templates/_macros.html:817 project/templates/_macros.html:819
#: project/templates/event_date/list.html:279
#: project/templates/widget/event_suggestion/create.html:188
#: project/templates/widget/event_suggestion/create.html:213
@ -1152,12 +1169,12 @@ msgstr "Ort bei Google suchen"
msgid "Previous"
msgstr "Zurück"
#: project/templates/_macros.html:815
#: project/templates/_macros.html:821
#, python-format
msgid "Page %(page)d of %(pages)d (%(total)d total)"
msgstr "Seite %(page)d von %(pages)d (%(total)d insgesamt)"
#: project/templates/_macros.html:817 project/templates/_macros.html:819
#: project/templates/_macros.html:823 project/templates/_macros.html:825
#: project/templates/event_date/list.html:281
#: project/templates/widget/event_suggestion/create.html:189
#: project/templates/widget/event_suggestion/create.html:214
@ -1167,68 +1184,68 @@ msgstr "Seite %(page)d von %(pages)d (%(total)d insgesamt)"
msgid "Next"
msgstr "Weiter"
#: project/templates/_macros.html:884
#: project/templates/_macros.html:890
msgid "Radius"
msgstr "Umkreis"
#: project/templates/_macros.html:1094
#: project/templates/_macros.html:1100
msgid "Edit image"
msgstr "Bild bearbeiten"
#: project/templates/_macros.html:1115
#: project/templates/_macros.html:1121
msgid "Close"
msgstr "Schließen"
#: project/templates/_macros.html:1116
#: project/templates/_macros.html:1122
msgid "Okay"
msgstr "OK"
#: project/templates/_macros.html:1128
#: project/templates/_macros.html:1134
msgid "Choose image file"
msgstr "Bild-Datei auswählen"
#: project/templates/_macros.html:1164 project/templates/event/actions.html:46
#: project/templates/_macros.html:1170 project/templates/event/actions.html:46
msgid "Edit event"
msgstr "Veranstaltung bearbeiten"
#: project/templates/_macros.html:1167 project/templates/manage/events.html:30
#: project/templates/_macros.html:1173 project/templates/manage/events.html:30
msgid "More"
msgstr "Mehr"
#: project/templates/_macros.html:1214
#: project/templates/_macros.html:1220
msgid "Please enter a valid time, between 00:00 and 23:59."
msgstr "Bitte gib eine gültige Uhrzeit zwischen 00:00 und 23:59 ein."
#: project/templates/_macros.html:1242
#: project/templates/_macros.html:1248
#, python-format
msgid "Just use %(term)s"
msgstr "Verwende einfach %(term)s"
#: project/templates/_macros.html:1294
#: project/templates/_macros.html:1300
msgid "Event suggestion"
msgstr "Veranstaltungsvorschlag"
#: project/templates/_macros.html:1406
#: project/templates/_macros.html:1412
msgid "Link copied"
msgstr "Link kopiert"
#: project/templates/_macros.html:1406
#: project/templates/_macros.html:1412
msgid "Copy link"
msgstr "Link kopieren"
#: project/templates/_macros.html:1435
#: project/templates/_macros.html:1441
msgid "Google calendar"
msgstr "Google Kalender"
#: project/templates/_macros.html:1436
#: project/templates/_macros.html:1442
msgid "Apple calendar"
msgstr "Apple Kalender"
#: project/templates/_macros.html:1437
#: project/templates/_macros.html:1443
msgid "Yahoo calendar"
msgstr "Yahoo Kalender"
#: project/templates/_macros.html:1438
#: project/templates/_macros.html:1444
msgid "Other calendar"
msgstr "Anderer Kalender"
@ -1237,7 +1254,7 @@ msgid "Manage"
msgstr "Verwaltung"
#: project/templates/home.html:29 project/templates/security/login_user.html:35
#: project/views/widget.py:179
#: project/views/widget.py:180
msgid "Register for free"
msgstr "Kostenlos registrieren"
@ -1287,6 +1304,13 @@ msgstr "Ausloggen"
msgid "Show events"
msgstr "Veranstaltungen anzeigen"
#: project/templates/event/create.html:4
#: project/templates/event/create.html:221 project/templates/layout.html:256
#: project/templates/manage/events.html:12
#: project/templates/manage/organizers.html:21
msgid "Create event"
msgstr "Veranstaltung erstellen"
#: project/templates/layout.html:258
msgid "Review suggestions"
msgstr "Vorschläge prüfen"
@ -1763,7 +1787,7 @@ msgstr "Vorschau"
msgid "Organization successfully updated"
msgstr "Organisation erfolgreich aktualisiert"
#: project/views/admin.py:68 project/views/manage.py:259
#: project/views/admin.py:68 project/views/manage.py:260
msgid "Settings successfully updated"
msgstr "Einstellungen erfolgreich aktualisiert"
@ -1824,23 +1848,27 @@ msgstr "Die eingegebene Email passt nicht zur Email der Einladung"
msgid "Invitation successfully deleted"
msgstr "Einladung erfolgreich gelöscht"
#: project/views/event.py:167
msgid "Event successfully created"
msgstr "Veranstaltung erfolgreich erstellt"
#: project/views/event.py:171
msgid "Event successfully published"
msgstr "Veranstaltung erfolgreich veröffentlicht"
#: project/views/event.py:207
#: project/views/event.py:173
msgid "Draft successfully saved"
msgstr "Entwurf erfolgreich gespeichert"
#: project/views/event.py:216
msgid "Event successfully updated"
msgstr "Veranstaltung erfolgreich aktualisiert"
#: project/views/event.py:230 project/views/reference.py:162
#: project/views/event.py:239 project/views/reference.py:162
msgid "Entered name does not match event name"
msgstr "Der eingegebene Name entspricht nicht dem Namen der Veranstaltung"
#: project/views/event.py:236
#: project/views/event.py:245
msgid "Event successfully deleted"
msgstr "Veranstaltung erfolgreich gelöscht"
#: project/views/event.py:383
#: project/views/event.py:392
msgid "Referenced event changed"
msgstr "Empfohlene Veranstaltung wurde geändert"
@ -1978,11 +2006,11 @@ msgstr "Anzeigen"
msgid "You do not have permission for this action"
msgstr "Du hast keine Berechtigung für diese Aktion"
#: project/views/widget.py:171
#: project/views/widget.py:172
msgid "Thank you so much! The event is being verified."
msgstr "Vielen Dank! Die Veranstaltung wird geprüft."
#: project/views/widget.py:175
#: project/views/widget.py:176
msgid ""
"For more options and your own calendar of events, you can register for "
"free."
@ -1990,7 +2018,7 @@ msgstr ""
"Für mehr Optionen und einen eigenen Veranstaltungskalender, kannst du "
"dich kostenlos registrieren."
#: project/views/widget.py:238
#: project/views/widget.py:239
msgid "New event review"
msgstr "Neue Veranstaltung zu prüfen"
@ -2019,3 +2047,9 @@ msgstr "Neue Veranstaltung zu prüfen"
#~ msgid "Enter if the event takes place regularly."
#~ msgstr "Gib an, ob die Veranstaltung regelmäßig stattfindet."
#~ msgid "Event successfully created"
#~ msgstr "Veranstaltung erfolgreich erstellt"
#~ msgid "Draft"
#~ msgstr "Entwurf"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-08-12 23:45+0200\n"
"POT-Creation-Date: 2021-08-15 14:50+0200\n"
"PO-Revision-Date: 2021-04-30 15:04+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: en\n"
@ -176,7 +176,7 @@ msgstr ""
msgid "Legal notice"
msgstr ""
#: project/forms/admin.py:12 project/templates/_macros.html:1322
#: project/forms/admin.py:12 project/templates/_macros.html:1328
#: project/templates/layout.html:339
#: project/templates/widget/event_suggestion/create.html:199
#: project/views/admin_unit.py:36 project/views/root.py:58
@ -247,8 +247,8 @@ msgstr ""
msgid "Longitude"
msgstr ""
#: project/forms/admin_unit.py:28 project/forms/event.py:35
#: project/forms/event.py:64 project/forms/event.py:359
#: project/forms/admin_unit.py:28 project/forms/event.py:36
#: project/forms/event.py:65 project/forms/event.py:375
#: project/forms/event_place.py:25 project/forms/event_place.py:50
#: project/forms/event_suggestion.py:26 project/forms/oauth2_client.py:66
#: project/forms/organizer.py:25 project/forms/organizer.py:52
@ -269,32 +269,32 @@ msgstr ""
msgid "The short name is used to create a unique identifier for your events"
msgstr ""
#: project/forms/admin_unit.py:40 project/templates/_macros.html:1452
#: project/forms/admin_unit.py:40 project/templates/_macros.html:1458
msgid "Short name must contain only letters numbers or underscore"
msgstr ""
#: project/forms/admin_unit.py:46 project/forms/event.py:56
#: project/forms/event.py:90 project/forms/event_place.py:26
#: project/forms/admin_unit.py:46 project/forms/event.py:57
#: project/forms/event.py:91 project/forms/event_place.py:26
#: project/forms/organizer.py:26
msgid "Link URL"
msgstr ""
#: project/forms/admin_unit.py:47 project/forms/admin_unit_member.py:11
#: project/forms/admin_unit_member.py:23 project/forms/admin_unit_member.py:28
#: project/forms/event.py:57 project/forms/event_suggestion.py:38
#: project/forms/event.py:58 project/forms/event_suggestion.py:38
#: project/forms/organizer.py:27 project/templates/_macros.html:262
#: project/templates/_macros.html:1412 project/templates/admin/users.html:19
#: project/templates/_macros.html:1418 project/templates/admin/users.html:19
msgid "Email"
msgstr ""
#: project/forms/admin_unit.py:48 project/forms/event.py:58
#: project/forms/admin_unit.py:48 project/forms/event.py:59
#: project/forms/event_suggestion.py:31 project/forms/organizer.py:28
#: project/templates/_macros.html:305
#: project/templates/_macros.html:311
msgid "Phone"
msgstr ""
#: project/forms/admin_unit.py:49 project/forms/event.py:59
#: project/forms/organizer.py:29 project/templates/_macros.html:313
#: project/forms/admin_unit.py:49 project/forms/event.py:60
#: project/forms/organizer.py:29 project/templates/_macros.html:319
msgid "Fax"
msgstr ""
@ -433,230 +433,230 @@ msgstr ""
msgid "100 km"
msgstr ""
#: project/forms/event.py:53
#: project/forms/event.py:54
msgid "Organizator"
msgstr ""
#: project/forms/event.py:66
#: project/forms/event.py:67
msgid "Enter a short, meaningful name for the event."
msgstr ""
#: project/forms/event.py:69
#: project/forms/event.py:70
msgid "Start"
msgstr ""
#: project/forms/event.py:71
#: project/forms/event.py:72
msgid "Indicate when the event will take place."
msgstr ""
#: project/forms/event.py:74
#: project/forms/event.py:75
msgid "End"
msgstr ""
#: project/forms/event.py:76
#: project/forms/event.py:77
msgid "Indicate when the event will end. An event can last a maximum of 14 days."
msgstr ""
#: project/forms/event.py:81 project/templates/event/create.html:244
#: project/forms/event.py:82 project/templates/event/create.html:244
#: project/templates/event/update.html:135
#: project/templates/widget/event_suggestion/create.html:234
msgid "Recurring event"
msgstr ""
#: project/forms/event.py:85 project/forms/event_place.py:28
#: project/forms/event.py:86 project/forms/event_place.py:28
msgid "Description"
msgstr ""
#: project/forms/event.py:87
#: project/forms/event.py:88
msgid "Add an description of the event."
msgstr ""
#: project/forms/event.py:92
#: project/forms/event.py:93
msgid ""
"Enter a link to an external website containing more information about the"
" event."
msgstr ""
#: project/forms/event.py:97
#: project/forms/event.py:98
msgid "Ticket Link URL"
msgstr ""
#: project/forms/event.py:99
#: project/forms/event.py:100
msgid "Enter a link where tickets can be purchased."
msgstr ""
#: project/forms/event.py:102 project/templates/_macros.html:244
#: project/forms/event.py:103 project/templates/_macros.html:244
msgid "Tags"
msgstr ""
#: project/forms/event.py:104
#: project/forms/event.py:105
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:109
#: project/forms/event.py:110
msgid "Kid friendly"
msgstr ""
#: project/forms/event.py:111
#: project/forms/event.py:112
msgid "If the event is particularly suitable for children."
msgstr ""
#: project/forms/event.py:114
#: project/forms/event.py:115
msgid "Accessible for free"
msgstr ""
#: project/forms/event.py:116
#: project/forms/event.py:117
msgid "If the event is accessible for free."
msgstr ""
#: project/forms/event.py:119
#: project/forms/event.py:120
msgid "Typical Age from"
msgstr ""
#: project/forms/event.py:121
#: project/forms/event.py:122
msgid "The minimum age that participants should be."
msgstr ""
#: project/forms/event.py:124
#: project/forms/event.py:125
msgid "Typical Age to"
msgstr ""
#: project/forms/event.py:126
#: project/forms/event.py:127
msgid "The maximum age that participants should be."
msgstr ""
#: project/forms/event.py:129
#: project/forms/event.py:130
msgid "Registration required"
msgstr ""
#: project/forms/event.py:131
#: project/forms/event.py:132
msgid "If the participants needs to register for the event."
msgstr ""
#: project/forms/event.py:136 project/templates/_macros.html:276
#: project/forms/event.py:137 project/templates/_macros.html:276
#: project/templates/layout.html:159
msgid "Booked up"
msgstr ""
#: project/forms/event.py:138
#: project/forms/event.py:139
msgid "If the event is booked up or sold out."
msgstr ""
#: project/forms/event.py:141
#: project/forms/event.py:142
msgid "Expected number of participants"
msgstr ""
#: project/forms/event.py:143
#: project/forms/event.py:144
msgid "The estimated expected attendance."
msgstr ""
#: project/forms/event.py:146
#: project/forms/event.py:147
msgid "Price info"
msgstr ""
#: project/forms/event.py:148
#: project/forms/event.py:149
msgid ""
"Enter price information in textual form. E.g., different prices for "
"adults and children."
msgstr ""
#: project/forms/event.py:153
#: project/forms/event.py:154
msgid "Target group origin"
msgstr "Suitable for tourists / residents"
#: project/forms/event.py:158
#: project/forms/event.py:159
msgid "EventTargetGroupOrigin.both"
msgstr "For tourists and residents"
#: project/forms/event.py:162
#: project/forms/event.py:163
msgid "EventTargetGroupOrigin.tourist"
msgstr "Mainly for tourists"
#: project/forms/event.py:166
#: project/forms/event.py:167
msgid "EventTargetGroupOrigin.resident"
msgstr "Mainly for residents"
#: project/forms/event.py:169
#: project/forms/event.py:170
msgid ""
"Choose whether the event is particularly suitable for tourists or "
"residents."
msgstr ""
#: project/forms/event.py:174
#: project/forms/event.py:175
msgid "Attendance mode"
msgstr ""
#: project/forms/event.py:179
#: project/forms/event.py:180
msgid "EventAttendanceMode.offline"
msgstr "Normal (Offline)"
#: project/forms/event.py:183 project/templates/layout.html:147
#: project/forms/event.py:184 project/templates/layout.html:147
msgid "EventAttendanceMode.online"
msgstr "Online"
#: project/forms/event.py:185 project/templates/layout.html:150
#: project/forms/event.py:186 project/templates/layout.html:150
msgid "EventAttendanceMode.mixed"
msgstr "Online and offline"
#: project/forms/event.py:187
#: project/forms/event.py:188
msgid "Choose how people can attend the event."
msgstr ""
#: project/forms/event.py:191 project/forms/event_place.py:27
#: project/forms/event.py:192 project/forms/event_place.py:27
#: project/templates/widget/event_suggestion/create.html:252
msgid "Photo"
msgstr ""
#: project/forms/event.py:193
#: project/forms/event.py:194
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:203 project/templates/_macros.html:1193
#: project/forms/event.py:204 project/templates/_macros.html:1199
msgid "The start must be before the end."
msgstr ""
#: project/forms/event.py:209 project/templates/_macros.html:1210
#: project/forms/event.py:210 project/templates/_macros.html:1216
msgid "An event can last a maximum of 14 days."
msgstr ""
#: project/forms/event.py:217 project/templates/_macros.html:423
#: project/templates/_macros.html:582
#: project/forms/event.py:218 project/templates/_macros.html:429
#: project/templates/_macros.html:588
msgid "Previous start date"
msgstr ""
#: project/forms/event.py:219
#: project/forms/event.py:220
msgid "Enter when the event should have taken place before it was postponed."
msgstr ""
#: project/forms/event.py:224 project/forms/event_suggestion.py:71
#: project/forms/event.py:225 project/forms/event_suggestion.py:71
msgid "Categories"
msgstr ""
#: project/forms/event.py:227 project/forms/event_suggestion.py:74
#: project/forms/event.py:228 project/forms/event_suggestion.py:74
msgid "Choose categories that fit the event."
msgstr ""
#: project/forms/event.py:230 project/forms/reference.py:14
#: project/forms/event.py:231 project/forms/reference.py:14
#: project/forms/reference.py:27 project/forms/reference_request.py:75
#: project/templates/event/create.html:358
#: project/templates/event/update.html:214
msgid "Rating"
msgstr ""
#: project/forms/event.py:234 project/forms/reference.py:18
#: project/forms/event.py:235 project/forms/reference.py:18
#: project/forms/reference.py:31 project/forms/reference_request.py:79
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:242 project/forms/event.py:251
#: project/forms/event.py:315 project/forms/event_suggestion.py:50
#: project/templates/_macros.html:462 project/templates/_macros.html:618
#: project/forms/event.py:243 project/forms/event.py:252
#: project/forms/event.py:321 project/forms/event_suggestion.py:50
#: project/templates/_macros.html:468 project/templates/_macros.html:624
#: project/templates/event/create.html:283
#: project/templates/event/update.html:164
#: project/templates/event_place/create.html:21
@ -665,18 +665,18 @@ msgstr ""
msgid "Place"
msgstr ""
#: project/forms/event.py:244
#: project/forms/event.py:245
msgid "Select existing place"
msgstr ""
#: project/forms/event.py:245
#: project/forms/event.py:246
msgid "Enter new place"
msgstr ""
#: project/forms/event.py:258 project/forms/event.py:267
#: project/forms/event.py:323 project/forms/event.py:373
#: project/forms/event_suggestion.py:60 project/templates/_macros.html:500
#: project/templates/_macros.html:655 project/templates/event/create.html:254
#: project/forms/event.py:259 project/forms/event.py:268
#: project/forms/event.py:329 project/forms/event.py:389
#: project/forms/event_suggestion.py:60 project/templates/_macros.html:506
#: project/templates/_macros.html:661 project/templates/event/create.html:254
#: project/templates/event/update.html:155
#: project/templates/organizer/create.html:17
#: project/templates/organizer/delete.html:13
@ -684,110 +684,127 @@ msgstr ""
msgid "Organizer"
msgstr ""
#: project/forms/event.py:260
#: project/forms/event.py:261
msgid "Select existing organizer"
msgstr ""
#: project/forms/event.py:261
#: project/forms/event.py:262
msgid "Enter new organizer"
msgstr ""
#: project/forms/event.py:273 project/templates/event/create.html:4
#: project/templates/event/create.html:221 project/templates/layout.html:256
#: project/templates/manage/events.html:12
#: project/templates/manage/organizers.html:21
msgid "Create event"
#: project/forms/event.py:274
msgid "Save as draft"
msgstr ""
#: project/forms/event.py:299
#: project/forms/event.py:275
msgid "Publish event"
msgstr ""
#: project/forms/event.py:305
msgid "Select existing place or enter new place"
msgstr ""
#: project/forms/event.py:306
#: project/forms/event.py:312
msgid "Select existing organizer or enter new organizer"
msgstr ""
#: project/forms/event.py:318
#: project/forms/event.py:324
msgid ""
"Choose where the event takes place. You can add and modify places at "
"Manage > Places."
msgstr ""
#: project/forms/event.py:326
#: project/forms/event.py:332
msgid ""
"Select the organizer. You can add and modify organizers at Manage > "
"Organizers."
msgstr ""
#: project/forms/event.py:332 project/templates/event/update.html:145
#: project/forms/event.py:338 project/templates/event/update.html:145
#: project/templates/oauth2_token/list.html:21
msgid "Status"
msgstr ""
#: project/forms/event.py:335
#: project/forms/event.py:341
msgid "EventStatus.scheduled"
msgstr "Scheduled"
#: project/forms/event.py:336 project/templates/layout.html:113
#: project/forms/event.py:342 project/templates/layout.html:113
#: project/templates/layout.html:128
msgid "EventStatus.cancelled"
msgstr "Cancelled"
#: project/forms/event.py:337 project/templates/layout.html:116
#: project/forms/event.py:343 project/templates/layout.html:116
#: project/templates/layout.html:131
msgid "EventStatus.movedOnline"
msgstr "Moved online"
#: project/forms/event.py:338 project/templates/layout.html:119
#: project/forms/event.py:344 project/templates/layout.html:119
#: project/templates/layout.html:134
msgid "EventStatus.postponed"
msgstr "Postponed"
#: project/forms/event.py:339 project/templates/layout.html:122
#: project/forms/event.py:345 project/templates/layout.html:122
#: project/templates/layout.html:137
msgid "EventStatus.rescheduled"
msgstr "Rescheduled"
#: project/forms/event.py:341
#: project/forms/event.py:347
msgid "Select the status of the event."
msgstr ""
#: project/forms/event.py:344 project/templates/event/update.html:4
#: project/forms/event.py:351
msgid "Public status"
msgstr ""
#: project/forms/event.py:354
msgid "PublicStatus.published"
msgstr ""
#: project/forms/event.py:355 project/templates/_macros.html:282
msgid "PublicStatus.draft"
msgstr ""
#: project/forms/event.py:357
msgid "Select the public status of the event."
msgstr ""
#: project/forms/event.py:360 project/templates/event/update.html:4
#: project/templates/event/update.html:112
msgid "Update event"
msgstr ""
#: project/forms/event.py:358 project/templates/_macros.html:1165
#: project/forms/event.py:374 project/templates/_macros.html:1171
#: project/templates/event/actions.html:47
#: project/templates/event/delete.html:6
msgid "Delete event"
msgstr ""
#: project/forms/event.py:366 project/forms/event_date.py:15
#: project/forms/event.py:382 project/forms/event_date.py:15
#: project/forms/planing.py:14
msgid "From"
msgstr ""
#: project/forms/event.py:367 project/forms/event_date.py:16
#: project/forms/event.py:383 project/forms/event_date.py:16
#: project/forms/planing.py:15
msgid "to"
msgstr ""
#: project/forms/event.py:368 project/forms/event_date.py:17
#: project/forms/event.py:384 project/forms/event_date.py:17
msgid "Keyword"
msgstr ""
#: project/forms/event.py:370 project/forms/event_date.py:19
#: project/forms/planing.py:17 project/templates/_macros.html:386
#: project/forms/event.py:386 project/forms/event_date.py:19
#: project/forms/planing.py:17 project/templates/_macros.html:392
msgid "Category"
msgstr ""
#: project/forms/event.py:376
#: project/forms/event.py:392
msgid "Find events"
msgstr ""
#: project/forms/event_date.py:22 project/forms/planing.py:20
#: project/templates/_macros.html:137 project/templates/_macros.html:320
#: project/templates/_macros.html:137 project/templates/_macros.html:326
#: project/templates/admin_unit/create.html:29
#: project/templates/admin_unit/update.html:30
#: project/templates/event_place/create.html:30
@ -927,7 +944,7 @@ msgid "Weekdays"
msgstr ""
#: project/forms/reference.py:11 project/forms/reference_request.py:15
#: project/templates/_macros.html:521 project/templates/_macros.html:681
#: project/templates/_macros.html:527 project/templates/_macros.html:687
#: project/templates/admin_unit/create.html:19
#: project/templates/admin_unit/update.html:20
#: project/templates/layout.html:286
@ -955,7 +972,7 @@ msgstr ""
msgid "Delete request"
msgstr ""
#: project/forms/reference_request.py:27 project/templates/_macros.html:1334
#: project/forms/reference_request.py:27 project/templates/_macros.html:1340
#: project/templates/event_suggestion/review_status.html:18
#: project/templates/reference_request/review_status.html:12
msgid "Review status"
@ -1017,8 +1034,8 @@ msgstr ""
msgid "This field is required."
msgstr ""
#: project/templates/_macros.html:134 project/templates/_macros.html:409
#: project/templates/_macros.html:416 project/templates/_macros.html:861
#: project/templates/_macros.html:134 project/templates/_macros.html:415
#: project/templates/_macros.html:422 project/templates/_macros.html:867
msgid "Date"
msgstr ""
@ -1038,27 +1055,27 @@ msgstr ""
msgid "Link"
msgstr ""
#: project/templates/_macros.html:363
#: project/templates/_macros.html:369
#, python-format
msgid "Created at %(created_at)s by %(created_by)s."
msgstr ""
#: project/templates/_macros.html:365
#: project/templates/_macros.html:371
#, python-format
msgid "Created at %(created_at)s."
msgstr ""
#: project/templates/_macros.html:370
#: project/templates/_macros.html:376
#, python-format
msgid "Last updated at %(updated_at)s by %(updated_by)s."
msgstr ""
#: project/templates/_macros.html:372
#: project/templates/_macros.html:378
#, python-format
msgid "Last updated at %(updated_at)s."
msgstr ""
#: project/templates/_macros.html:402 project/templates/_macros.html:578
#: project/templates/_macros.html:408 project/templates/_macros.html:584
#: project/templates/event/actions.html:12
#: project/templates/event/create.html:228
#: project/templates/event/delete.html:13
@ -1068,45 +1085,45 @@ msgstr ""
msgid "Event"
msgstr ""
#: project/templates/_macros.html:412 project/templates/_macros.html:564
#: project/templates/_macros.html:418 project/templates/_macros.html:570
#, python-format
msgid "%(count)d event dates"
msgstr ""
#: project/templates/_macros.html:445 project/templates/_macros.html:600
#: project/templates/_macros.html:1397 project/templates/event/actions.html:32
#: project/templates/_macros.html:451 project/templates/_macros.html:606
#: project/templates/_macros.html:1403 project/templates/event/actions.html:32
msgid "Share"
msgstr ""
#: project/templates/_macros.html:449 project/templates/_macros.html:604
#: project/templates/_macros.html:1427
#: project/templates/_macros.html:455 project/templates/_macros.html:610
#: project/templates/_macros.html:1433
msgid "Add to calendar"
msgstr ""
#: project/templates/_macros.html:483 project/templates/_macros.html:637
#: project/templates/_macros.html:489 project/templates/_macros.html:643
msgid "Show directions"
msgstr ""
#: project/templates/_macros.html:488 project/templates/_macros.html:642
#: project/templates/_macros.html:494 project/templates/_macros.html:648
msgid "The event takes place online."
msgstr ""
#: project/templates/_macros.html:490 project/templates/_macros.html:644
#: project/templates/_macros.html:496 project/templates/_macros.html:650
msgid "The event takes place both offline and online."
msgstr ""
#: project/templates/_macros.html:705 project/templates/event_date/list.html:4
#: project/templates/_macros.html:711 project/templates/event_date/list.html:4
#: project/templates/event_date/list.html:258
#: project/templates/event_date/search.html:3
#: project/templates/reference_request/review.html:32
msgid "Event Dates"
msgstr ""
#: project/templates/_macros.html:778
#: project/templates/_macros.html:784
msgid "Search location on Google"
msgstr ""
#: project/templates/_macros.html:811 project/templates/_macros.html:813
#: project/templates/_macros.html:817 project/templates/_macros.html:819
#: project/templates/event_date/list.html:279
#: project/templates/widget/event_suggestion/create.html:188
#: project/templates/widget/event_suggestion/create.html:213
@ -1117,12 +1134,12 @@ msgstr ""
msgid "Previous"
msgstr ""
#: project/templates/_macros.html:815
#: project/templates/_macros.html:821
#, python-format
msgid "Page %(page)d of %(pages)d (%(total)d total)"
msgstr ""
#: project/templates/_macros.html:817 project/templates/_macros.html:819
#: project/templates/_macros.html:823 project/templates/_macros.html:825
#: project/templates/event_date/list.html:281
#: project/templates/widget/event_suggestion/create.html:189
#: project/templates/widget/event_suggestion/create.html:214
@ -1132,68 +1149,68 @@ msgstr ""
msgid "Next"
msgstr ""
#: project/templates/_macros.html:884
#: project/templates/_macros.html:890
msgid "Radius"
msgstr ""
#: project/templates/_macros.html:1094
#: project/templates/_macros.html:1100
msgid "Edit image"
msgstr ""
#: project/templates/_macros.html:1115
#: project/templates/_macros.html:1121
msgid "Close"
msgstr ""
#: project/templates/_macros.html:1116
#: project/templates/_macros.html:1122
msgid "Okay"
msgstr ""
#: project/templates/_macros.html:1128
#: project/templates/_macros.html:1134
msgid "Choose image file"
msgstr ""
#: project/templates/_macros.html:1164 project/templates/event/actions.html:46
#: project/templates/_macros.html:1170 project/templates/event/actions.html:46
msgid "Edit event"
msgstr ""
#: project/templates/_macros.html:1167 project/templates/manage/events.html:30
#: project/templates/_macros.html:1173 project/templates/manage/events.html:30
msgid "More"
msgstr ""
#: project/templates/_macros.html:1214
#: project/templates/_macros.html:1220
msgid "Please enter a valid time, between 00:00 and 23:59."
msgstr ""
#: project/templates/_macros.html:1242
#: project/templates/_macros.html:1248
#, python-format
msgid "Just use %(term)s"
msgstr ""
#: project/templates/_macros.html:1294
#: project/templates/_macros.html:1300
msgid "Event suggestion"
msgstr ""
#: project/templates/_macros.html:1406
#: project/templates/_macros.html:1412
msgid "Link copied"
msgstr ""
#: project/templates/_macros.html:1406
#: project/templates/_macros.html:1412
msgid "Copy link"
msgstr ""
#: project/templates/_macros.html:1435
#: project/templates/_macros.html:1441
msgid "Google calendar"
msgstr ""
#: project/templates/_macros.html:1436
#: project/templates/_macros.html:1442
msgid "Apple calendar"
msgstr ""
#: project/templates/_macros.html:1437
#: project/templates/_macros.html:1443
msgid "Yahoo calendar"
msgstr ""
#: project/templates/_macros.html:1438
#: project/templates/_macros.html:1444
msgid "Other calendar"
msgstr ""
@ -1202,7 +1219,7 @@ msgid "Manage"
msgstr ""
#: project/templates/home.html:29 project/templates/security/login_user.html:35
#: project/views/widget.py:179
#: project/views/widget.py:180
msgid "Register for free"
msgstr ""
@ -1252,6 +1269,13 @@ msgstr ""
msgid "Show events"
msgstr ""
#: project/templates/event/create.html:4
#: project/templates/event/create.html:221 project/templates/layout.html:256
#: project/templates/manage/events.html:12
#: project/templates/manage/organizers.html:21
msgid "Create event"
msgstr ""
#: project/templates/layout.html:258
msgid "Review suggestions"
msgstr ""
@ -1726,7 +1750,7 @@ msgstr ""
msgid "Organization successfully updated"
msgstr ""
#: project/views/admin.py:68 project/views/manage.py:259
#: project/views/admin.py:68 project/views/manage.py:260
msgid "Settings successfully updated"
msgstr ""
@ -1784,23 +1808,27 @@ msgstr ""
msgid "Invitation successfully deleted"
msgstr ""
#: project/views/event.py:167
msgid "Event successfully created"
#: project/views/event.py:171
msgid "Event successfully published"
msgstr ""
#: project/views/event.py:207
#: project/views/event.py:173
msgid "Draft successfully saved"
msgstr ""
#: project/views/event.py:216
msgid "Event successfully updated"
msgstr ""
#: project/views/event.py:230 project/views/reference.py:162
#: project/views/event.py:239 project/views/reference.py:162
msgid "Entered name does not match event name"
msgstr ""
#: project/views/event.py:236
#: project/views/event.py:245
msgid "Event successfully deleted"
msgstr ""
#: project/views/event.py:383
#: project/views/event.py:392
msgid "Referenced event changed"
msgstr ""
@ -1934,17 +1962,17 @@ msgstr ""
msgid "You do not have permission for this action"
msgstr ""
#: project/views/widget.py:171
#: project/views/widget.py:172
msgid "Thank you so much! The event is being verified."
msgstr ""
#: project/views/widget.py:175
#: project/views/widget.py:176
msgid ""
"For more options and your own calendar of events, you can register for "
"free."
msgstr ""
#: project/views/widget.py:238
#: project/views/widget.py:239
msgid "New event review"
msgstr ""
@ -1968,3 +1996,9 @@ msgstr ""
#~ msgid "Enter if the event takes place regularly."
#~ msgstr ""
#~ msgid "Event successfully created"
#~ msgstr ""
#~ msgid "Draft"
#~ msgstr ""

View File

@ -1,44 +0,0 @@
from flask import jsonify
from project import app
from project.dateutils import get_today
from project.jsonld import get_sd_for_event_date
from project.models import Event, EventDate
from project.services.event import get_event_dates_query
from project.services.event_search import EventSearchParams
@app.route("/api/events")
def api_events():
today = today = get_today()
dates = (
EventDate.query.join(Event)
.filter(EventDate.start >= today)
.order_by(EventDate.start)
.all()
)
return json_from_event_dates(dates)
@app.route("/api/event_dates")
def api_event_dates():
params = EventSearchParams()
params.load_from_request()
dates = get_event_dates_query(params).paginate()
return json_from_event_dates(dates.items)
def json_from_event_dates(dates):
structured_events = list()
for event_date in dates:
structured_event = get_sd_for_event_date(event_date)
structured_event.pop("@context", None)
structured_events.append(structured_event)
result = {}
result["@context"] = "https://schema.org"
result["@type"] = "Project"
result["name"] = "Prototyp"
result["event"] = structured_events
return jsonify(result)

View File

@ -9,6 +9,7 @@ from sqlalchemy.exc import SQLAlchemyError
from project import app, db
from project.access import (
access_or_401,
can_read_event_or_401,
can_reference_event,
can_request_event_reference,
has_access,
@ -27,6 +28,7 @@ from project.models import (
EventReference,
EventReviewStatus,
EventSuggestion,
PublicStatus,
User,
)
from project.services.event import (
@ -53,6 +55,7 @@ from project.views.utils import (
@app.route("/event/<int:event_id>")
def event(event_id):
event = get_event_with_details_or_404(event_id)
can_read_event_or_401(event)
user_rights = get_menu_user_rights(event)
dates = get_upcoming_event_dates(event.id)
url = url_for("event", event_id=event_id, _external=True)
@ -80,6 +83,7 @@ def event(event_id):
@app.route("/event/<int:event_id>/actions")
def event_actions(event_id):
event = Event.query.get_or_404(event_id)
can_read_event_or_401(event)
user_rights = get_user_rights(event)
url = url_for("event", event_id=event_id, _external=True)
share_links = get_share_links(url, event.name)
@ -163,8 +167,13 @@ def event_create_for_admin_unit_id(id):
if event_suggestion:
send_event_suggestion_review_status_mail(event_suggestion)
success_msg = (
gettext("Event successfully published")
if event.public_status == PublicStatus.published
else gettext("Draft successfully saved")
)
flash_message(
gettext("Event successfully created"),
success_msg,
url_for("event", event_id=event.id),
)
return redirect(url_for("event_actions", event_id=event.id))

View File

@ -4,6 +4,7 @@ from flask import redirect, render_template, request, url_for
from flask.wrappers import Response
from project import app
from project.access import can_read_event_or_401
from project.dateutils import create_icalendar
from project.forms.event_date import FindEventDateForm
from project.jsonld import DateTimeEncoder, get_sd_for_event_date
@ -52,6 +53,7 @@ def event_date_search():
@app.route("/eventdate/<int:id>")
def event_date(id):
event_date = get_event_date_with_details_or_404(id)
can_read_event_or_401(event_date.event)
if "src" in request.args:
track_analytics("event_date", str(id), request.args["src"])
@ -81,6 +83,7 @@ def event_date(id):
@app.route("/eventdate/<int:id>/ical")
def event_date_ical(id):
event_date = get_event_date_with_details_or_404(id)
can_read_event_or_401(event_date.event)
event = create_ical_event_for_date(event_date)
cal = create_icalendar()

View File

@ -140,6 +140,7 @@ def manage_admin_unit_events(id):
form.populate_obj(params)
params.admin_unit_id = admin_unit.id
params.can_read_private_events = True
events = get_events_query(params).paginate()
return render_template(
"manage/events.html",

View File

@ -7,7 +7,7 @@ from sqlalchemy.exc import SQLAlchemyError
from sqlalchemy.sql import func
from project import app, db
from project.access import has_admin_unit_member_permission
from project.access import can_read_event_or_401, has_admin_unit_member_permission
from project.dateutils import get_next_full_hour
from project.forms.event_date import FindEventDateForm
from project.forms.event_suggestion import CreateEventSuggestionForm
@ -75,6 +75,7 @@ def widget_event_date(au_short_name, id):
AdminUnit.short_name == au_short_name
).first_or_404()
event_date = get_event_date_with_details_or_404(id)
can_read_event_or_401(event_date.event)
structured_data = json.dumps(
get_sd_for_event_date(event_date), indent=2, cls=DateTimeEncoder
)

View File

@ -1,5 +1,7 @@
import base64
from project.models import PublicStatus
def test_read(client, app, db, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
@ -20,12 +22,34 @@ def test_read(client, app, db, seeder, utils):
assert response.json["status"] == "scheduled"
def test_read_otherDraft(client, app, db, seeder, utils):
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event", id=event_id)
response = utils.get(url)
utils.assert_response_unauthorized(response)
def test_read_myDraft(client, app, db, seeder, utils):
user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event", id=event_id)
response = utils.get_json(url)
utils.assert_response_ok(response)
assert response.json["public_status"] == "draft"
def test_list(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_list")
utils.get_ok(url)
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id
def test_search(client, seeder, utils):
@ -33,18 +57,34 @@ def test_search(client, seeder, utils):
event_id = seeder.create_event(admin_unit_id)
image_id = seeder.upsert_default_image()
seeder.assign_image_to_event(event_id, image_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_search")
utils.get_ok(url)
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id
def test_dates(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id)
url = utils.get_url("api_v1_event_dates", id=event_id)
utils.get_ok(url)
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_dates", id=event_id)
response = utils.get(url)
utils.assert_response_unauthorized(response)
def test_dates_myDraft(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_api_access()
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_dates", id=event_id)
response = utils.get_json(url)
utils.assert_response_ok(response)
def create_put(
place_id, organizer_id, name="Neuer Name", start="2021-02-07T11:00:00.000Z"
@ -84,6 +124,7 @@ def test_put(client, seeder, utils, app, mocker):
put["expected_participants"] = 500
put["price_info"] = "Erwachsene 5€, Kinder 2€."
put["recurrence_rule"] = "RRULE:FREQ=DAILY;COUNT=7"
put["public_status"] = "draft"
url = utils.get_url("api_v1_event", id=event_id)
response = utils.put_json(url, put)
@ -120,6 +161,7 @@ def test_put(client, seeder, utils, app, mocker):
assert event.expected_participants == put["expected_participants"]
assert event.price_info == put["price_info"]
assert event.recurrence_rule == put["recurrence_rule"]
assert event.public_status == PublicStatus.draft
len_dates = len(event.dates)
assert len_dates == 7

View File

@ -1,23 +1,37 @@
def test_read(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
seeder.create_event(admin_unit_id)
url = utils.get_url("api_v1_event_date", id=1)
utils.get_ok(url)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_date", id=2)
response = utils.get(url)
utils.assert_response_unauthorized(response)
seeder.authorize_api_access(user_id, admin_unit_id)
response = utils.get_json(url)
utils.assert_response_ok(response)
def test_list(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_date_list")
utils.get_ok(url)
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == 1
def test_search(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_event_date_search", sort="-rating")
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == event_id
assert response.json["items"][0]["start"].endswith("+02:00")

View File

@ -13,21 +13,39 @@ def test_list(client, seeder, utils):
def test_event_date_search(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url(
"api_v1_organization_event_date_search", id=admin_unit_id, sort="-rating"
)
utils.get_ok(url)
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["event"]["id"] == event_id
seeder.authorize_api_access(user_id, admin_unit_id)
response = utils.get_json(url)
utils.assert_response_ok(response)
assert len(response.json["items"]) == 2
assert response.json["items"][1]["event"]["public_status"] == "draft"
def test_event_search(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_organization_event_search", id=admin_unit_id)
utils.get_ok(url)
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id
seeder.authorize_api_access(user_id, admin_unit_id)
response = utils.get_json(url)
utils.assert_response_ok(response)
assert len(response.json["items"]) == 2
assert response.json["items"][1]["public_status"] == "draft"
def test_organizers(client, seeder, utils):
@ -60,11 +78,19 @@ def test_organizers_post(client, seeder, utils, app):
def test_events(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("api_v1_organization_event_list", id=admin_unit_id)
utils.get_ok(url)
response = utils.get_ok(url)
assert len(response.json["items"]) == 1
assert response.json["items"][0]["id"] == event_id
seeder.authorize_api_access(user_id, admin_unit_id)
response = utils.get_json(url)
utils.assert_response_ok(response)
assert len(response.json["items"]) == 2
def prepare_events_post_data(seeder, utils):
@ -92,7 +118,7 @@ def test_events_post(client, seeder, utils, app):
assert "id" in response.json
with app.app_context():
from project.models import Event
from project.models import Event, PublicStatus
event = (
Event.query.filter(Event.admin_unit_id == admin_unit_id)
@ -104,6 +130,7 @@ def test_events_post(client, seeder, utils, app):
assert event.organizer_id == organizer_id
assert event.photo is not None
assert event.photo.encoding_format == "image/png"
assert event.public_status == PublicStatus.published
def test_events_post_photo_no_data(client, seeder, utils, app):

View File

@ -156,7 +156,10 @@ class Seeder(object):
return client_id
def setup_api_access(self):
user_id, admin_unit_id = self.setup_base(admin=True)
user_id, admin_unit_id = self.setup_base(admin=True, log_in=False)
return self.authorize_api_access(user_id, admin_unit_id)
def authorize_api_access(self, user_id, admin_unit_id):
oauth2_client_id = self.insert_default_oauth2_client(user_id)
with self._app.app_context():
@ -167,7 +170,9 @@ class Seeder(object):
client_secret = oauth2_client.client_secret
scope = oauth2_client.scope
self._utils.login()
self._utils.authorize(client_id, client_secret, scope)
self._utils.logout()
return (user_id, admin_unit_id)
def get_event_category_id(self, category_name):
@ -177,16 +182,22 @@ class Seeder(object):
return category.id
def create_event(
self, admin_unit_id, recurrence_rule="", external_link="", end=None
self,
admin_unit_id,
recurrence_rule="",
external_link="",
end=None,
draft=False,
name="Name",
):
from project.models import Event, EventAttendanceMode
from project.models import Event, EventAttendanceMode, PublicStatus
from project.services.event import insert_event, upsert_event_category
with self._app.app_context():
event = Event()
event.admin_unit_id = admin_unit_id
event.categories = [upsert_event_category("Other")]
event.name = "Name"
event.name = name
event.description = "Beschreibung"
event.start = self.get_now_by_minute()
event.end = end
@ -198,6 +209,10 @@ class Seeder(object):
event.tags = ""
event.price_info = ""
event.attendance_mode = EventAttendanceMode.offline
if draft:
event.public_status = PublicStatus.draft
insert_event(event)
self._db.session.commit()
event_id = event.id

View File

@ -1,3 +1,6 @@
import sqlalchemy
def test_mail_server():
import os
@ -29,3 +32,38 @@ def test_migrations(app, seeder):
seeder.create_any_reference(admin_unit_id)
seeder.create_reference_request(event_id, admin_unit_id)
downgrade()
def test_migration_public_status(app, seeder):
from flask_migrate import upgrade
from project import db
from project.models import Event, PublicStatus
with app.app_context():
db.drop_all()
db.engine.execute("DROP TABLE IF EXISTS alembic_version;")
upgrade(revision="1fb9f679defb")
sql = """
DO $$
DECLARE
admin_unit_id adminunit.id%TYPE;
event_place_id eventplace.id%TYPE;
organizer_id eventorganizer.id%TYPE;
event_id event.id%TYPE;
BEGIN
INSERT INTO adminunit (name) VALUES ('Org') RETURNING id INTO admin_unit_id;
INSERT INTO eventplace (name, admin_unit_id) VALUES ('Place', admin_unit_id) RETURNING id INTO event_place_id;
INSERT INTO eventorganizer (name, admin_unit_id) VALUES ('Organizer', admin_unit_id) RETURNING id INTO organizer_id;
INSERT INTO event (name, admin_unit_id, event_place_id, organizer_id, start) VALUES ('Event', admin_unit_id, event_place_id, organizer_id, current_timestamp) RETURNING id INTO event_id;
END $$;
"""
db.engine.execute(sqlalchemy.text(sql).execution_options(autocommit=True))
upgrade()
events = Event.query.all()
assert len(events) > 0
for event in events:
assert event.public_status == PublicStatus.published

View File

@ -246,6 +246,10 @@ class UtilActions(object):
def assert_response_unauthorized(self, response):
assert response.status_code == 401
return response
def assert_response_forbidden(self, response):
assert response.status_code == 403
def assert_response_notFound(self, response):
assert response.status_code == 404
@ -277,6 +281,12 @@ class UtilActions(object):
def assert_response_permission_missing(self, response, endpoint, **values):
self.assert_response_redirect(response, endpoint, **values)
def assert_response_contains(self, response, needle):
assert needle.encode("UTF-8") in response.data
def assert_response_contains_not(self, response, needle):
assert needle.encode("UTF-8") not in response.data
def parse_query_parameters(self, url):
query = urlsplit(url).query
params = parse_qs(query)

View File

@ -1,38 +0,0 @@
def test_events(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
url = utils.get_url("api_events")
utils.get_ok(url)
def test_event_dates(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
url = utils.get_url("api_event_dates")
utils.get_ok(url)
url = utils.get_url("api_event_dates", keyword="name")
utils.get_ok(url)
url = utils.get_url("api_event_dates", category_id=2000)
utils.get_ok(url)
url = utils.get_url("api_event_dates", category_id=0)
utils.get_ok(url)
url = utils.get_url("api_event_dates", weekday=1)
utils.get_ok(url)
url = utils.get_url(
"api_event_dates", coordinate="51.9077888,10.4333312", distance=500
)
utils.get_ok(url)
url = utils.get_url("api_event_dates", date_from="2020-10-03", date_to="2021-10-03")
utils.get_ok(url)
organizer_id = seeder.upsert_default_event_organizer(admin_unit_id)
url = utils.get_url("api_event_dates", organizer_id=organizer_id)
utils.get_ok(url)

View File

@ -6,12 +6,20 @@ from psycopg2.errors import UniqueViolation
"external_link", [None, "https://example.com", "www.example.com"]
)
def test_read(client, seeder, utils, external_link):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id, external_link=external_link)
url = utils.get_url("event", event_id=event_id)
utils.get_ok(url)
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("event", event_id=event_id)
response = utils.get(url)
utils.assert_response_unauthorized(response)
utils.login()
utils.get_ok(url)
def test_read_containsActionLink(seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
@ -305,7 +313,7 @@ def test_create_verifiedSuggestionRedirectsToReviewStatus(
def test_actions(seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
event_id = seeder.create_event(admin_unit_id)
url = utils.get_url("event_actions", event_id=event_id)
@ -315,6 +323,14 @@ def test_actions(seeder, utils):
assert b"Empfehlung anfragen" not in response.data
assert b"Veranstaltung empfehlen" not in response.data
event_id = seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("event_actions", event_id=event_id)
response = utils.get(url)
utils.assert_response_unauthorized(response)
utils.login()
utils.get_ok(url)
def test_actions_withReferenceRequestLink(seeder, utils):
user_id, admin_unit_id = seeder.setup_base()

View File

@ -1,5 +1,5 @@
def test_read(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
seeder.create_event(admin_unit_id, end=seeder.get_now_by_minute())
url = utils.get_url("event_date", id=1)
@ -9,14 +9,30 @@ def test_read(client, seeder, utils):
response = client.get(url)
utils.assert_response_redirect(response, "event_date", id=1)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("event_date", id=2)
response = utils.get(url)
utils.assert_response_unauthorized(response)
utils.login()
utils.get_ok(url)
def test_ical(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
user_id, admin_unit_id = seeder.setup_base(log_in=False)
seeder.create_event(admin_unit_id, end=seeder.get_now_by_minute())
url = utils.get_url("event_date_ical", id=1)
utils.get_ok(url)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("event_date_ical", id=2)
response = utils.get(url)
utils.assert_response_unauthorized(response)
utils.login()
utils.get_ok(url)
def test_list(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()

View File

@ -78,6 +78,12 @@ def test_admin_unit_events(client, seeder, utils):
date_to="2021-10-03",
)
event_id = seeder.create_event(admin_unit_id, draft=True)
response = utils.get_endpoint_ok("manage_admin_unit_events", id=admin_unit_id)
event_url = utils.get_url("event", event_id=event_id)
utils.assert_response_contains(response, event_url)
def test_admin_unit_events_invalidDateFormat(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()

View File

@ -3,6 +3,7 @@ import pytest
def test_list(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_api_access()
utils.login()
url = utils.get_url("oauth2_tokens")
utils.get_ok(url)
@ -11,6 +12,7 @@ def test_list(client, seeder, utils):
@pytest.mark.parametrize("db_error", [True, False])
def test_revoke(client, seeder, utils, app, mocker, db_error):
user_id, admin_unit_id = seeder.setup_api_access()
utils.login()
with app.app_context():
from project.models import OAuth2Token

View File

@ -4,10 +4,17 @@ import pytest
def test_event_dates(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()
seeder.create_event(admin_unit_id)
seeder.create_event(admin_unit_id, draft=True)
au_short_name = "meinecrew"
url = utils.get_url("widget_event_dates", au_short_name=au_short_name)
utils.get_ok(url)
response = utils.get_ok(url)
event_url = utils.get_url("widget_event_date", au_short_name=au_short_name, id=1)
utils.assert_response_contains(response, event_url)
draft_url = utils.get_url("widget_event_date", au_short_name=au_short_name, id=2)
utils.assert_response_contains_not(response, draft_url)
url = utils.get_url(
"widget_event_dates", au_short_name=au_short_name, keyword="name"
@ -37,8 +44,8 @@ def test_event_dates(client, seeder, utils):
def test_event_date(client, seeder, utils, app, db):
user_id, admin_unit_id = seeder.setup_base()
event_id = seeder.create_event(admin_unit_id)
user_id, admin_unit_id = seeder.setup_base(log_in=False)
seeder.create_event(admin_unit_id)
au_short_name = "meinecrew"
with app.app_context():
@ -53,9 +60,14 @@ def test_event_date(client, seeder, utils, app, db):
admin_unit.widget_link_color = Color("#FF0000")
db.session.commit()
url = utils.get_url("widget_event_date", au_short_name=au_short_name, id=event_id)
url = utils.get_url("widget_event_date", au_short_name=au_short_name, id=1)
utils.get_ok(url)
seeder.create_event(admin_unit_id, draft=True)
url = utils.get_url("widget_event_date", au_short_name=au_short_name, id=2)
response = utils.get(url)
utils.assert_response_unauthorized(response)
def test_infoscreen(client, seeder, utils):
user_id, admin_unit_id = seeder.setup_base()