Skip to content

Commit b8a46f6

Browse files
authored
Use Participant model in grant form (#4169)
1 parent fddae2a commit b8a46f6

File tree

17 files changed

+266
-166
lines changed

17 files changed

+266
-166
lines changed

backend/api/grants/mutations.py

Lines changed: 67 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from dataclasses import asdict
22
from enum import Enum
33
from typing import Annotated, Union, Optional
4+
from participants.models import Participant
45

56
from privacy_policy.record import record_privacy_policy_acceptance
67
import strawberry
@@ -42,11 +43,13 @@ class _GrantErrors:
4243
notes: list[str] = strawberry.field(default_factory=list)
4344
travelling_from: list[str] = strawberry.field(default_factory=list)
4445
non_field_errors: list[str] = strawberry.field(default_factory=list)
45-
website: list[str] = strawberry.field(default_factory=list)
46-
twitter_handle: list[str] = strawberry.field(default_factory=list)
47-
github_handle: list[str] = strawberry.field(default_factory=list)
48-
linkedin_url: list[str] = strawberry.field(default_factory=list)
49-
mastodon_handle: list[str] = strawberry.field(default_factory=list)
46+
participant_bio: list[str] = strawberry.field(default_factory=list)
47+
participant_website: list[str] = strawberry.field(default_factory=list)
48+
participant_twitter_handle: list[str] = strawberry.field(default_factory=list)
49+
participant_instagram_handle: list[str] = strawberry.field(default_factory=list)
50+
participant_linkedin_url: list[str] = strawberry.field(default_factory=list)
51+
participant_facebook_url: list[str] = strawberry.field(default_factory=list)
52+
participant_mastodon_handle: list[str] = strawberry.field(default_factory=list)
5053

5154
errors: _GrantErrors = None
5255

@@ -113,11 +116,14 @@ class SendGrantInput(BaseGrantInput):
113116
why: str
114117
notes: str
115118
travelling_from: str
116-
website: str
117-
twitter_handle: str
118-
github_handle: str
119-
linkedin_url: str
120-
mastodon_handle: str
119+
120+
participant_bio: str
121+
participant_website: str
122+
participant_twitter_handle: str
123+
participant_instagram_handle: str
124+
participant_linkedin_url: str
125+
participant_facebook_url: str
126+
participant_mastodon_handle: str
121127

122128
def validate(self, conference: Conference, user: User) -> GrantErrors | None:
123129
errors = super().validate(conference=conference, user=user)
@@ -147,11 +153,14 @@ class UpdateGrantInput(BaseGrantInput):
147153
why: str
148154
notes: str
149155
travelling_from: str
150-
website: str
151-
twitter_handle: str
152-
github_handle: str
153-
linkedin_url: str
154-
mastodon_handle: str
156+
157+
participant_bio: str
158+
participant_website: str
159+
participant_twitter_handle: str
160+
participant_instagram_handle: str
161+
participant_linkedin_url: str
162+
participant_facebook_url: str
163+
participant_mastodon_handle: str
155164

156165
def validate(self, conference: Conference, user: User) -> GrantErrors | None:
157166
return super().validate(conference=conference, user=user).if_has_errors
@@ -205,9 +214,23 @@ def send_grant(self, info: Info, input: SendGrantInput) -> SendGrantResult:
205214
with transaction.atomic():
206215
instance = GrantModel.objects.create(
207216
**{
208-
**asdict(input),
209217
"user_id": request.user.id,
210218
"conference": conference,
219+
"name": input.name,
220+
"full_name": input.full_name,
221+
"age_group": input.age_group,
222+
"gender": input.gender,
223+
"occupation": input.occupation,
224+
"grant_type": input.grant_type,
225+
"python_usage": input.python_usage,
226+
"been_to_other_events": input.been_to_other_events,
227+
"community_contribution": input.community_contribution,
228+
"needs_funds_for_travel": input.needs_funds_for_travel,
229+
"need_visa": input.need_visa,
230+
"need_accommodation": input.need_accommodation,
231+
"why": input.why,
232+
"notes": input.notes,
233+
"travelling_from": input.travelling_from,
211234
}
212235
)
213236

@@ -217,6 +240,20 @@ def send_grant(self, info: Info, input: SendGrantInput) -> SendGrantResult:
217240
"grant",
218241
)
219242

243+
Participant.objects.update_or_create(
244+
user_id=request.user.id,
245+
conference=instance.conference,
246+
defaults={
247+
"bio": input.participant_bio,
248+
"website": input.participant_website,
249+
"twitter_handle": input.participant_twitter_handle,
250+
"instagram_handle": input.participant_instagram_handle,
251+
"linkedin_url": input.participant_linkedin_url,
252+
"facebook_url": input.participant_facebook_url,
253+
"mastodon_handle": input.participant_mastodon_handle,
254+
},
255+
)
256+
220257
# hack because we return django models
221258
instance.__strawberry_definition__ = Grant.__strawberry_definition__
222259
return instance
@@ -239,6 +276,20 @@ def update_grant(self, info: Info, input: UpdateGrantInput) -> UpdateGrantResult
239276
setattr(instance, attr, value)
240277
instance.save()
241278

279+
Participant.objects.update_or_create(
280+
user_id=request.user.id,
281+
conference=instance.conference,
282+
defaults={
283+
"bio": input.participant_bio,
284+
"website": input.participant_website,
285+
"twitter_handle": input.participant_twitter_handle,
286+
"instagram_handle": input.participant_instagram_handle,
287+
"linkedin_url": input.participant_linkedin_url,
288+
"facebook_url": input.participant_facebook_url,
289+
"mastodon_handle": input.participant_mastodon_handle,
290+
},
291+
)
292+
242293
instance.__strawberry_definition__ = Grant.__strawberry_definition__
243294
return instance
244295

backend/api/grants/tests/test_send_grant.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from conferences.tests.factories import ConferenceFactory
33
from grants.tests.factories import GrantFactory
44
import pytest
5+
from participants.models import Participant
6+
57

68
pytestmark = pytest.mark.django_db
79

@@ -35,11 +37,13 @@ def _send_grant(client, conference, conference_code=None, **kwargs):
3537
validationWhy: why
3638
validationNotes: notes
3739
validationTravellingFrom: travellingFrom
38-
validationWebsite: website
39-
validationTwitterHandle: twitterHandle
40-
validationGithubHandle: githubHandle
41-
validationLinkedinUrl: linkedinUrl
42-
validationMastodonHandle: mastodonHandle
40+
validationParticipantBio: participantBio
41+
validationParticipantWebsite: participantWebsite
42+
validationParticipantTwitterHandle: participantTwitterHandle
43+
validationparticipantInstagramHandle: participantInstagramHandle
44+
validationParticipantLinkedinUrl: participantLinkedinUrl
45+
validationParticipantFacebookUrl: participantFacebookUrl
46+
validationParticipantMastodonHandle: participantMastodonHandle
4347
nonFieldErrors
4448
}
4549
}
@@ -64,11 +68,13 @@ def _send_grant(client, conference, conference_code=None, **kwargs):
6468
"why": grant.why,
6569
"notes": grant.notes,
6670
"travellingFrom": grant.travelling_from,
67-
"website": grant.website,
68-
"twitterHandle": grant.twitter_handle,
69-
"githubHandle": grant.github_handle,
70-
"linkedinUrl": grant.linkedin_url,
71-
"mastodonHandle": grant.mastodon_handle,
71+
"participantBio": "my bio",
72+
"participantWebsite": "http://website.it",
73+
"participantTwitterHandle": "handle",
74+
"participantInstagramHandle": "handleinsta",
75+
"participantLinkedinUrl": "https://linkedin.com/fake-link",
76+
"participantFacebookUrl": "https://facebook.com/fake-link",
77+
"participantMastodonHandle": "[email protected]",
7278
}
7379

7480
variables = {**defaults, **kwargs}
@@ -87,6 +93,9 @@ def test_send_grant(graphql_client, user):
8793
assert response["data"]["sendGrant"]["__typename"] == "Grant"
8894
assert response["data"]["sendGrant"]["id"]
8995

96+
participant = Participant.objects.get(conference=conference, user_id=user.id)
97+
assert participant.bio == "my bio"
98+
9099
assert PrivacyPolicyAcceptanceRecord.objects.filter(
91100
user=user, conference=conference, privacy_policy="grant"
92101
).exists()

backend/api/grants/tests/test_update_grant.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from conferences.tests.factories import ConferenceFactory
33
from grants.tests.factories import GrantFactory
44
import pytest
5+
from participants.models import Participant
56

67
pytestmark = pytest.mark.django_db
78

@@ -34,11 +35,13 @@ def _update_grant(graphql_client, grant, **kwargs):
3435
validationWhy: why
3536
validationNotes: notes
3637
validationTravellingFrom: travellingFrom
37-
validationWebsite: website
38-
validationTwitterHandle: twitterHandle
39-
validationGithubHandle: githubHandle
40-
validationLinkedinUrl: linkedinUrl
41-
validationMastodonHandle: mastodonHandle
38+
validationParticipantBio: participantBio
39+
validationParticipantWebsite: participantWebsite
40+
validationParticipantTwitterHandle: participantTwitterHandle
41+
validationParticipantInstagramHandle: participantInstagramHandle
42+
validationParticipantLinkedinUrl: participantLinkedinUrl
43+
validationParticipantFacebookUrl: participantFacebookUrl
44+
validationparticipantMastodonHandle: participantMastodonHandle
4245
nonFieldErrors
4346
}
4447
}
@@ -63,11 +66,13 @@ def _update_grant(graphql_client, grant, **kwargs):
6366
"why": grant.why,
6467
"notes": grant.notes,
6568
"travellingFrom": grant.travelling_from,
66-
"website": grant.website,
67-
"twitterHandle": grant.twitter_handle,
68-
"githubHandle": grant.github_handle,
69-
"linkedinUrl": grant.linkedin_url,
70-
"mastodonHandle": grant.mastodon_handle,
69+
"participantBio": "bio",
70+
"participantWebsite": "http://website.it",
71+
"participantTwitterHandle": "handle",
72+
"participantInstagramHandle": "handleinsta",
73+
"participantLinkedinUrl": "https://linkedin.com/fake-link",
74+
"participantFacebookUrl": "https://facebook.com/fake-link",
75+
"participantMastodonHandle": "[email protected]",
7176
}
7277

7378
variables = {
@@ -105,18 +110,19 @@ def test_update_grant(graphql_client, user):
105110
why="why not",
106111
notes="🧸",
107112
travellingFrom="GB",
108-
website="https://marcotte.house",
109-
twitterHandle="@marcottebear",
110-
githubHandle="marcottebear",
111-
linkedinUrl="www.linkedin.com/in/marcotteba",
112-
mastodonHandle="[email protected]",
113+
participantFacebookUrl="http://facebook.com/pythonpizza",
114+
participantLinkedinUrl="http://linkedin.com/company/pythonpizza",
113115
)
114116

115117
grant.refresh_from_db()
116118

117119
assert not response.get("errors")
118120
assert response["data"]["updateGrant"]["__typename"] == "Grant"
119121

122+
participant = Participant.objects.first()
123+
assert participant.facebook_url == "http://facebook.com/pythonpizza"
124+
assert participant.linkedin_url == "http://linkedin.com/company/pythonpizza"
125+
120126

121127
def test_cannot_update_a_grant_if_user_is_not_owner(
122128
graphql_client,

backend/api/grants/types.py

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

66
import strawberry
7+
from api.participants.types import Participant
8+
from participants.models import Participant as ParticipantModel
79

810
from grants.models import Grant as GrantModel
911

@@ -33,14 +35,16 @@ class Grant:
3335
notes: str
3436
travelling_from: Optional[str]
3537
applicant_reply_deadline: Optional[datetime]
36-
website: str
37-
twitter_handle: str
38-
github_handle: str
39-
linkedin_url: str
40-
mastodon_handle: str
38+
39+
participant: Participant
4140

4241
@classmethod
4342
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+
4448
return cls(
4549
id=grant.id,
4650
status=Status(grant.status),
@@ -60,9 +64,5 @@ def from_model(cls, grant: GrantModel) -> Grant:
6064
notes=grant.notes,
6165
travelling_from=grant.travelling_from,
6266
applicant_reply_deadline=grant.applicant_reply_deadline,
63-
website=grant.website,
64-
twitter_handle=grant.twitter_handle,
65-
github_handle=grant.github_handle,
66-
linkedin_url=grant.linkedin_url,
67-
mastodon_handle=grant.mastodon_handle,
67+
participant=Participant.from_model(participant),
6868
)

backend/api/participants/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Participant:
1212
user_id: ID
1313
bio: str
1414
website: str
15-
photo: str
15+
photo: str | None
1616
photo_id: str | None
1717
public_profile: bool
1818
twitter_handle: str

backend/grants/tests/factories.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
from helpers.constants import GENDERS
77
from users.tests.factories import UserFactory
88
from countries import countries
9+
from participants.tests.factories import ParticipantFactory
10+
from participants.models import Participant
911

1012

1113
class GrantFactory(DjangoModelFactory):
@@ -34,3 +36,14 @@ class Meta:
3436
github_handle = factory.Faker("user_name")
3537
linkedin_url = factory.Faker("user_name")
3638
mastodon_handle = factory.Faker("user_name")
39+
40+
@classmethod
41+
def _create(self, model_class, *args, **kwargs):
42+
grant = super()._create(model_class, *args, **kwargs)
43+
44+
if not Participant.objects.filter(
45+
user_id=grant.user.id, conference=grant.conference
46+
).exists():
47+
ParticipantFactory(user_id=grant.user.id, conference=grant.conference)
48+
49+
return grant

backend/participants/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ class ParticipantAdmin(admin.ModelAdmin):
2929
form = ParticipantForm
3030
search_fields = ("user__email", "user__full_name")
3131
list_display = (
32+
"id",
3233
"user_display_name",
3334
"conference",
3435
)

0 commit comments

Comments
 (0)