Skip to content

Commit e8e1491

Browse files
authored
Add speaker availability support in the BE (#4188)
1 parent 6d5c60e commit e8e1491

File tree

8 files changed

+107
-24
lines changed

8 files changed

+107
-24
lines changed

backend/api/grants/types.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
from typing import Optional
55

66
import strawberry
7-
from api.participants.types import Participant
8-
from participants.models import Participant as ParticipantModel
97

108
from grants.models import Grant as GrantModel
119

@@ -36,15 +34,8 @@ class Grant:
3634
travelling_from: Optional[str]
3735
applicant_reply_deadline: Optional[datetime]
3836

39-
participant: Participant
40-
4137
@classmethod
4238
def from_model(cls, grant: GrantModel) -> Grant:
43-
participant = ParticipantModel.objects.filter(
44-
user_id=grant.user_id,
45-
conference=grant.conference,
46-
).first()
47-
4839
return cls(
4940
id=grant.id,
5041
status=Status(grant.status),
@@ -64,5 +55,4 @@ def from_model(cls, grant: GrantModel) -> Grant:
6455
notes=grant.notes,
6556
travelling_from=grant.travelling_from,
6657
applicant_reply_deadline=grant.applicant_reply_deadline,
67-
participant=Participant.from_model(participant),
6858
)

backend/api/participants/types.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from typing import Optional
22

3+
from strawberry.scalars import JSON
34
import strawberry
45
from strawberry import ID
56

@@ -22,6 +23,7 @@ class Participant:
2223
mastodon_handle: str
2324
speaker_id: strawberry.Private[int]
2425
fullname: str
26+
speaker_availabilities: JSON
2527

2628
_speaker_level: strawberry.Private[str]
2729
_previous_talk_video: strawberry.Private[str]
@@ -59,4 +61,5 @@ def from_model(cls, instance):
5961
linkedin_url=instance.linkedin_url,
6062
facebook_url=instance.facebook_url,
6163
mastodon_handle=instance.mastodon_handle,
64+
speaker_availabilities=instance.speaker_availabilities or {},
6265
)

backend/api/submissions/mutations.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from strawberry.scalars import JSON
2+
13
from django.db import transaction
24
import math
35
import re
@@ -208,6 +210,7 @@ class SendSubmissionInput(BaseSubmissionInput):
208210
speaker_linkedin_url: str
209211
speaker_facebook_url: str
210212
speaker_mastodon_handle: str
213+
speaker_availabilities: JSON
211214

212215
topic: Optional[ID] = strawberry.field(default=None)
213216
tags: list[ID] = strawberry.field(default_factory=list)
@@ -236,6 +239,7 @@ class UpdateSubmissionInput(BaseSubmissionInput):
236239
speaker_linkedin_url: str
237240
speaker_facebook_url: str
238241
speaker_mastodon_handle: str
242+
speaker_availabilities: JSON
239243

240244
topic: Optional[ID] = strawberry.field(default=None)
241245
tags: list[ID] = strawberry.field(default_factory=list)
@@ -307,6 +311,7 @@ def update_submission(
307311
"linkedin_url": input.speaker_linkedin_url,
308312
"facebook_url": input.speaker_facebook_url,
309313
"mastodon_handle": input.speaker_mastodon_handle,
314+
"speaker_availabilities": input.speaker_availabilities,
310315
},
311316
)
312317

@@ -368,6 +373,7 @@ def send_submission(
368373
"linkedin_url": input.speaker_linkedin_url,
369374
"facebook_url": input.speaker_facebook_url,
370375
"mastodon_handle": input.speaker_mastodon_handle,
376+
"speaker_availabilities": input.speaker_availabilities,
371377
},
372378
)
373379

backend/api/submissions/tests/test_edit_submission.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ def _update_submission(
3333
new_speaker_linkedin_url="",
3434
new_speaker_facebook_url="",
3535
new_speaker_mastodon_handle="",
36+
new_speaker_availabilities=None,
3637
):
3738
new_title = new_title or {"en": "new title to use"}
3839
new_elevator_pitch = new_elevator_pitch or {"en": "This is an elevator pitch"}
3940
new_abstract = new_abstract or {"en": "abstract here"}
4041
short_social_summary = new_short_social_summary or ""
4142
new_speaker_photo = new_speaker_photo or FileFactory().id
43+
new_speaker_availabilities = new_speaker_availabilities or {}
4244

4345
return graphql_client.query(
4446
"""
@@ -141,6 +143,7 @@ def _update_submission(
141143
"speakerLinkedinUrl": new_speaker_linkedin_url,
142144
"speakerFacebookUrl": new_speaker_facebook_url,
143145
"speakerMastodonHandle": new_speaker_mastodon_handle,
146+
"speakerAvailabilities": new_speaker_availabilities,
144147
}
145148
},
146149
)
@@ -201,6 +204,67 @@ def test_update_submission(graphql_client, user):
201204
assert participant.linkedin_url == "http://linkedin.com/company/pythonpizza"
202205

203206

207+
def test_update_submission_speaker_availabilities(graphql_client, user):
208+
conference = ConferenceFactory(
209+
topics=("life", "diy"),
210+
languages=("it", "en"),
211+
durations=("10", "20"),
212+
active_cfp=True,
213+
audience_levels=("adult", "senior"),
214+
submission_types=("talk", "workshop"),
215+
)
216+
217+
submission = SubmissionFactory(
218+
speaker_id=user.id,
219+
custom_topic="life",
220+
custom_duration="10m",
221+
custom_audience_level="adult",
222+
custom_submission_type="talk",
223+
languages=["it"],
224+
tags=["python", "ml"],
225+
conference=conference,
226+
speaker_level=Submission.SPEAKER_LEVELS.intermediate,
227+
previous_talk_video="https://www.youtube.com/watch?v=SlPhMPnQ58k",
228+
)
229+
230+
graphql_client.force_login(user)
231+
232+
new_topic = conference.topics.filter(name="diy").first()
233+
new_audience = conference.audience_levels.filter(name="senior").first()
234+
new_tag = SubmissionTagFactory(name="yello")
235+
new_duration = conference.durations.filter(name="20m").first()
236+
new_type = conference.submission_types.filter(name="workshop").first()
237+
238+
response = _update_submission(
239+
graphql_client,
240+
submission=submission,
241+
new_topic=new_topic,
242+
new_audience=new_audience,
243+
new_tag=new_tag,
244+
new_duration=new_duration,
245+
new_type=new_type,
246+
new_speaker_level=Submission.SPEAKER_LEVELS.experienced,
247+
new_speaker_availabilities={
248+
"2023-12-10@am": "unavailable",
249+
"2023-12-11@pm": "unavailable",
250+
"2023-12-12@am": "preferred",
251+
"2023-12-13@am": None,
252+
},
253+
)
254+
255+
submission.refresh_from_db()
256+
257+
assert response["data"]["updateSubmission"]["__typename"] == "Submission"
258+
259+
participant = Participant.objects.first()
260+
assert participant.speaker_availabilities == {
261+
"2023-12-10@am": "unavailable",
262+
"2023-12-11@pm": "unavailable",
263+
"2023-12-12@am": "preferred",
264+
"2023-12-13@am": None,
265+
}
266+
267+
204268
def test_update_submission_with_invalid_facebook_social_url(graphql_client, user):
205269
conference = ConferenceFactory(
206270
topics=("life", "diy"),

backend/api/submissions/tests/test_send_submission.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ def _submit_proposal(client, conference, submission, **kwargs):
6767
"speakerFacebookUrl": "https://facebook.com/fake-link",
6868
"speakerMastodonHandle": "[email protected]",
6969
"tags": [tag.id],
70+
"speakerAvailabilities": {},
7071
}
7172

7273
override_conference = kwargs.pop("override_conference", None)
@@ -163,6 +164,11 @@ def test_submit_talk(graphql_client, user, django_capture_on_commit_callbacks, m
163164
shortSocialSummary="summary",
164165
speakerBio="my bio",
165166
speakerPhoto=speaker_photo,
167+
speakerAvailabilities={
168+
"2023-10-10@am": "preferred",
169+
"2023-10-11@pm": "unavailable",
170+
"2023-10-12@am": "available",
171+
},
166172
)
167173

168174
assert resp["data"]["sendSubmission"]["__typename"] == "Submission"
@@ -190,6 +196,11 @@ def test_submit_talk(graphql_client, user, django_capture_on_commit_callbacks, m
190196
participant = Participant.objects.get(conference=conference, user_id=user.id)
191197
assert participant.bio == "my bio"
192198
assert participant.photo_file_id == speaker_photo
199+
assert participant.speaker_availabilities == {
200+
"2023-10-10@am": "preferred",
201+
"2023-10-11@pm": "unavailable",
202+
"2023-10-12@am": "available",
203+
}
193204

194205
assert PrivacyPolicyAcceptanceRecord.objects.filter(
195206
user=user, conference=conference, privacy_policy="cfp"

backend/participants/admin.py

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,7 @@
88
class ParticipantForm(forms.ModelForm):
99
class Meta:
1010
model = Participant
11-
fields = [
12-
"conference",
13-
"user",
14-
"photo",
15-
"bio",
16-
"website",
17-
"twitter_handle",
18-
"instagram_handle",
19-
"linkedin_url",
20-
"facebook_url",
21-
"mastodon_handle",
22-
"speaker_level",
23-
"previous_talk_video",
24-
]
11+
fields = "__all__"
2512

2613

2714
@admin.register(Participant)
@@ -54,6 +41,7 @@ class ParticipantAdmin(admin.ModelAdmin):
5441
"mastodon_handle",
5542
"speaker_level",
5643
"previous_talk_video",
44+
"speaker_availabilities",
5745
),
5846
},
5947
),
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.1.1 on 2024-11-28 22:08
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('participants', '0011_alter_participant_photo'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='participant',
15+
name='speaker_availabilities',
16+
field=models.JSONField(blank=True, null=True, verbose_name='speaker availabilities'),
17+
),
18+
]

backend/participants/models.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ class SpeakerLevels(models.TextChoices):
5454
previous_talk_video = models.URLField(
5555
_("previous talk video"), blank=True, max_length=2049
5656
)
57+
speaker_availabilities = models.JSONField(
58+
_("speaker availabilities"), null=True, blank=True
59+
)
5760

5861
objects = ParticipantQuerySet().as_manager()
5962

0 commit comments

Comments
 (0)