Skip to content
This repository was archived by the owner on Apr 29, 2022. It is now read-only.

Commit 6e078a7

Browse files
authored
Add a checkbox to the Talk submission page (#1368)
* initial * renamed to something more sensible * Add a required checkbox to the CfP proposal submission page. The checkbox content is not stored in the database, but submission will fail unless checked. * added test to verify that speakers do have to agree to the speaker release agreement
1 parent 34d5f35 commit 6e078a7

File tree

4 files changed

+117
-1
lines changed

4 files changed

+117
-1
lines changed

conference/forms/forms.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
from p3 import utils as p3utils
1515
from conference import models
1616

17+
18+
REL_AGR_URL = 'https://epstage.europython.eu/events/speaker-release-agreement/'
19+
RELEASE_AGREEMENT_CHECKBOX = (
20+
"I agree with the terms outlined in the " +
21+
f"<a href='{REL_AGR_URL}' target='_blank'>" +
22+
"EuroPython Speaker Release Agreement</a>"
23+
)
24+
1725
log = logging.getLogger('conference.tags')
1826

1927
### Helpers
@@ -149,6 +157,10 @@ class TalkBaseForm(forms.Form):
149157
help_text=_('<p>Please add anything you may find useful for the review of your session proposal, e.g. references of where you have held talks, blogs, YouTube channels, books you have written, etc. This information will only be shown for talk review purposes.</p>'),
150158
widget=forms.Textarea,
151159
required=False)
160+
i_accept_speaker_release = forms.BooleanField(
161+
label=RELEASE_AGREEMENT_CHECKBOX,
162+
required=True
163+
)
152164

153165

154166
class TrackForm(forms.ModelForm):

conference/forms/talks.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from taggit_labels.widgets import LabelWidget
66

77
from conference.forms import TalkBaseForm
8-
from conference.models import (Conference, ConferenceTag, Talk, TALK_TYPE,
8+
from conference.models import (Conference, ConferenceTag, Talk, TALK_TYPE,
99
CFP_TALK_TYPE)
1010

1111

@@ -20,6 +20,9 @@ class TalkUpdateForm(forms.ModelForm):
2020
prerequisites = TalkBaseForm.base_fields["prerequisites"]
2121
level = TalkBaseForm.base_fields["level"]
2222
domain_level = TalkBaseForm.base_fields["domain_level"]
23+
i_accept_speaker_release = TalkBaseForm.base_fields[
24+
'i_accept_speaker_release'
25+
]
2326

2427
class Meta:
2528
model = Talk

tests/test_cfp.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def test_if_user_can_submit_talk_details_and_is_redirect_to_step2(user_client):
152152
"tags": "abc, defg",
153153
"level": TALK_LEVEL.beginner,
154154
"domain_level": TALK_LEVEL.advanced,
155+
"i_accept_speaker_release": True,
155156
},
156157
)
157158

@@ -174,6 +175,36 @@ def test_if_user_can_submit_talk_details_and_is_redirect_to_step2(user_client):
174175
)
175176

176177

178+
def test_if_user_cannot_submit_talk_if_release_not_selected(user_client):
179+
STEP1_VALIDATION_FAIL_200 = 200
180+
181+
Conference.objects.create(
182+
code=settings.CONFERENCE_CONFERENCE,
183+
name=settings.CONFERENCE_CONFERENCE,
184+
cfp_start=timezone.now().date() - timedelta(days=2),
185+
cfp_end=timezone.now().date() + timedelta(days=1),
186+
)
187+
step1_url = reverse("cfp:step1_submit_proposal")
188+
189+
response = user_client.post(
190+
step1_url,
191+
{
192+
"type": TALK_TYPE_CHOICES.t_30,
193+
"abstract": "Abstract goes here",
194+
"title": "A title",
195+
"sub_title": "A sub title",
196+
"abstract_short": "Short abstract",
197+
"abstract_extra": "Abstract _extra",
198+
"tags": "abc, defg",
199+
"level": TALK_LEVEL.beginner,
200+
"domain_level": TALK_LEVEL.advanced,
201+
"i_accept_speaker_release": False,
202+
},
203+
)
204+
205+
assert response.status_code == STEP1_VALIDATION_FAIL_200
206+
207+
177208
def test_validation_errors_are_handled_on_step2(user_client):
178209
"""
179210
NOTE(artcz)
@@ -450,6 +481,7 @@ def test_update_proposal_updates_proposal(user_client):
450481
"title": "New title",
451482
"sub_title": "New sub title",
452483
"tags": "Some, tags",
484+
"i_accept_speaker_release": True,
453485
},
454486
)
455487

@@ -470,6 +502,42 @@ def test_update_proposal_updates_proposal(user_client):
470502
assert talk_dict["speakers"] == []
471503

472504

505+
def test_update_proposal_fails_if_missing_release_agreement(user_client):
506+
create_conference_with_open_cfp()
507+
talk = TalkFactory()
508+
talk.setAbstract("some abstract")
509+
talk.created_by = user_client.user
510+
talk.save()
511+
512+
edit_url = reverse("cfp:update", args=[talk.uuid])
513+
514+
response = user_client.post(
515+
edit_url,
516+
{
517+
"type": TALK_TYPE_CHOICES.t_45,
518+
"abstract": "New abstract",
519+
"abstract_short": "New short abstract",
520+
"abstract_extra": "New extra abstract",
521+
"level": TALK_LEVEL.intermediate,
522+
"domain_level": TALK_LEVEL.advanced,
523+
"title": "New title",
524+
"sub_title": "New sub title",
525+
"tags": "Some, tags",
526+
"i_accept_speaker_release": False
527+
},
528+
)
529+
530+
# We do not advance and talk should be unchanged in DB
531+
assert response.status_code == 200
532+
533+
# Make sure that nothing changed.
534+
orig_talk_dict = dump_relevant_talk_information_to_dict(talk)
535+
talk.refresh_from_db()
536+
new_talk_dict = dump_relevant_talk_information_to_dict(talk)
537+
538+
assert orig_talk_dict == new_talk_dict
539+
540+
473541
def test_update_speaker_updated_speaker(user_client):
474542
create_conference_with_open_cfp()
475543
talk = TalkFactory()

tests/test_talks.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.core.files.uploadedfile import SimpleUploadedFile
77
from django.utils import timezone
88

9+
from conference.cfp import dump_relevant_talk_information_to_dict
910
from conference.models import TALK_STATUS, TALK_LEVEL
1011
from tests.factories import (
1112
EventFactory,
@@ -133,6 +134,7 @@ def test_update_talk_post(user_client):
133134
"level": TALK_LEVEL.advanced,
134135
"domain_level": TALK_LEVEL.advanced,
135136
"tags": ",".join(tag.name for tag in tags),
137+
"i_accept_speaker_release": True,
136138
}
137139
resp = user_client.post(url, data=post_data)
138140

@@ -150,6 +152,37 @@ def test_update_talk_post(user_client):
150152
)
151153

152154

155+
def test_update_talk_post_fails_if_release_not_agreed(user_client):
156+
tomorrow = timezone.now().date() + timedelta(days=1)
157+
get_default_conference(conference_end=tomorrow)
158+
talk = TalkFactory(created_by=user_client.user, status=TALK_STATUS.accepted)
159+
url = reverse("talks:update_talk", args=[talk.slug])
160+
161+
tags = ConferenceTagFactory.create_batch(size=3)
162+
post_data = {
163+
"title": "new title",
164+
"sub_title": "new sub title",
165+
"abstract": "new abstract",
166+
"abstract_short": "new short abstract",
167+
"prerequisites": "new prerequisites",
168+
"level": TALK_LEVEL.advanced,
169+
"domain_level": TALK_LEVEL.advanced,
170+
"tags": ",".join(tag.name for tag in tags),
171+
"i_accept_speaker_release": False,
172+
}
173+
resp = user_client.post(url, data=post_data)
174+
175+
# We do not advance and talk should be unchanged in DB
176+
assert resp.status_code == 200
177+
178+
# Make sure that nothing changed.
179+
orig_talk_dict = dump_relevant_talk_information_to_dict(talk)
180+
talk.refresh_from_db()
181+
new_talk_dict = dump_relevant_talk_information_to_dict(talk)
182+
183+
assert orig_talk_dict == new_talk_dict
184+
185+
153186
def test_anonymous_cannot_get_submit_slides(client):
154187
get_default_conference()
155188
talk = TalkFactory(status=TALK_STATUS.accepted)

0 commit comments

Comments
 (0)