Skip to content

Commit b901915

Browse files
authored
Convert grant_type to be a multiple choice (#4200)
1 parent 18ac707 commit b901915

File tree

11 files changed

+112
-38
lines changed

11 files changed

+112
-38
lines changed

backend/api/grants/mutations.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ def validate(self, conference: Conference, user: User) -> GrantErrors:
9090
"python_usage",
9191
"been_to_other_events",
9292
"why",
93+
"grant_type",
9394
)
9495

9596
for field in non_empty_fields:
@@ -110,7 +111,7 @@ class SendGrantInput(BaseGrantInput):
110111
age_group: AgeGroup
111112
gender: str
112113
occupation: Occupation
113-
grant_type: GrantType
114+
grant_type: list[GrantType]
114115
python_usage: str
115116
been_to_other_events: str
116117
community_contribution: str
@@ -149,7 +150,7 @@ class UpdateGrantInput(BaseGrantInput):
149150
age_group: AgeGroup
150151
gender: str
151152
occupation: Occupation
152-
grant_type: GrantType
153+
grant_type: list[GrantType]
153154
python_usage: str
154155
been_to_other_events: str
155156
community_contribution: str

backend/api/grants/types.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Grant:
2222
age_group: Optional[AgeGroup]
2323
gender: str
2424
occupation: Occupation
25-
grant_type: GrantType
25+
grant_type: list[GrantType]
2626
python_usage: str
2727
community_contribution: str
2828
been_to_other_events: str
@@ -46,7 +46,7 @@ def from_model(cls, grant: GrantModel) -> Grant:
4646
age_group=AgeGroup(grant.age_group) if grant.age_group else None,
4747
gender=grant.gender,
4848
occupation=Occupation(grant.occupation),
49-
grant_type=GrantType(grant.grant_type),
49+
grant_type=[GrantType(g) for g in grant.grant_type],
5050
python_usage=grant.python_usage,
5151
community_contribution=grant.community_contribution,
5252
been_to_other_events=grant.been_to_other_events,
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Generated by Django 5.1.1 on 2024-12-01 17:59
2+
3+
from django.db import migrations, models
4+
import json
5+
6+
def forwards_func(apps, schema_editor):
7+
Grant = apps.get_model('grants', 'Grant')
8+
for grant in Grant.objects.all():
9+
old_value = grant.grant_type
10+
# Convert the old string value into a list
11+
grant.grant_type_json = [old_value] if old_value else []
12+
grant.save(update_fields=['grant_type_json'])
13+
14+
def reverse_func(apps, schema_editor):
15+
Grant = apps.get_model('grants', 'Grant')
16+
for grant in Grant.objects.all():
17+
value_list = grant.grant_type
18+
# Convert the list back to a single string
19+
if value_list:
20+
grant.grant_type = value_list[0]
21+
else:
22+
grant.grant_type = ''
23+
grant.save(update_fields=['grant_type'])
24+
25+
class Migration(migrations.Migration):
26+
dependencies = [
27+
("grants", "0022_grant_departure_city_grant_nationality_and_more"),
28+
]
29+
30+
operations = [
31+
# Step 1: Add a temporary JSONField
32+
migrations.AddField(
33+
model_name='grant',
34+
name='grant_type_json',
35+
field=models.JSONField(default=list, verbose_name="grant type"),
36+
),
37+
# Step 2: Backfill data into the temporary field
38+
migrations.RunPython(forwards_func, reverse_func),
39+
# Step 3: Remove the old field
40+
migrations.RemoveField(
41+
model_name='grant',
42+
name='grant_type',
43+
),
44+
# Step 4: Rename the temporary field to grant_type
45+
migrations.RenameField(
46+
model_name='grant',
47+
old_name='grant_type_json',
48+
new_name='grant_type',
49+
),
50+
]

backend/grants/models.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,7 @@ class ApprovedType(models.TextChoices):
9797
)
9898

9999
# Your Grant Section
100-
grant_type = models.CharField(
101-
_("grant type"), choices=GrantType.choices, max_length=10
102-
)
100+
grant_type = models.JSONField(_("grant type"), default=list)
103101
departure_country = models.CharField(
104102
_("Departure Country"),
105103
max_length=100,

backend/grants/tests/factories.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from countries import countries
99
from participants.tests.factories import ParticipantFactory
1010
from participants.models import Participant
11+
import random
1112

1213

1314
class GrantFactory(DjangoModelFactory):
@@ -22,7 +23,12 @@ class Meta:
2223
age_group = factory.fuzzy.FuzzyChoice(Grant.AgeGroup)
2324
gender = factory.fuzzy.FuzzyChoice([gender[0] for gender in GENDERS])
2425
occupation = factory.fuzzy.FuzzyChoice(Grant.Occupation)
25-
grant_type = factory.fuzzy.FuzzyChoice(Grant.GrantType)
26+
grant_type = factory.LazyFunction(
27+
lambda: random.sample(
28+
[choice[0] for choice in Grant.GrantType.choices],
29+
k=random.randint(1, len(Grant.GrantType.choices)),
30+
)
31+
)
2632

2733
python_usage = factory.Faker("text")
2834
been_to_other_events = factory.Faker("text")

backend/reviews/templates/grant-review.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,11 @@ <h2>Grant</h2>
112112

113113
<div class="review-row">
114114
<strong>Grant type</strong>
115-
<div>{{grant.get_grant_type_display}}</div>
115+
<div>
116+
{% for type_ in grant.grant_type %}
117+
{{type_}}
118+
{% endfor %}
119+
</div>
116120
</div>
117121

118122
<div class="review-row">

backend/reviews/templates/grants-recap.html

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,11 @@ <h3>
507507
</li>
508508
<li>
509509
<strong>Grant type:</strong>
510-
<span>{{ item.get_grant_type_display }}</span>
510+
<span>
511+
{% for type_ in item.grant_type %}
512+
{{type_}}
513+
{% endfor %}
514+
</span>
511515
</li>
512516
<li>
513517
<strong>Needs:</strong>

frontend/src/components/grant-form/index.tsx

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export type GrantFormFields = ParticipantFormFields & {
5858
ageGroup: AgeGroup;
5959
gender: string;
6060
occupation: Occupation;
61-
grantType: GrantType;
61+
grantType: GrantType[];
6262
pythonUsage: string;
6363
communityContribution: string;
6464
beenToOtherEvents: string;
@@ -458,21 +458,27 @@ export const GrantForm = ({
458458
<FormattedMessage id="grants.form.fields.grantType.description" />
459459
}
460460
>
461-
<Select
462-
{...select("grantType")}
463-
required={true}
464-
errors={getErrors("grantType")}
465-
>
461+
<HorizontalStack gap="small">
466462
{GRANT_TYPE_OPTIONS.map(({ value, disabled, messageId }) => (
467-
<FormattedMessage id={messageId} key={messageId}>
468-
{(msg) => (
469-
<option disabled={disabled} value={value}>
470-
{msg}
471-
</option>
472-
)}
473-
</FormattedMessage>
463+
<label key={value}>
464+
<HorizontalStack gap="small" alignItems="center">
465+
<Checkbox
466+
size="small"
467+
{...checkbox("grantType", value)}
468+
disabled={disabled}
469+
/>
470+
471+
<FormattedMessage id={messageId} key={messageId}>
472+
{(msg) => <Text size={2}>{msg}</Text>}
473+
</FormattedMessage>
474+
</HorizontalStack>
475+
</label>
474476
))}
475-
</Select>
477+
</HorizontalStack>
478+
<Spacer size="xs" />
479+
<Text as="p" size="label4" color="error" uppercase>
480+
{getErrors("grantType").join(", ")}
481+
</Text>
476482
</InputWrapper>
477483

478484
<InputWrapper

frontend/src/components/grant-form/options.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ export const OCCUPATION_OPTIONS = [
6262
];
6363

6464
export const GRANT_TYPE_OPTIONS = [
65-
{
66-
value: "",
67-
disabled: true,
68-
messageId: "global.selectOption",
69-
},
7065
{
7166
disabled: false,
7267
value: GrantType.Diversity,

frontend/src/components/my-grant-profile-page-handler/sidebar.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,16 @@ export const Sidebar = ({
3434
</GrantInfo>
3535

3636
<GrantInfo label={<FormattedMessage id="profile.myGrant.grantType" />}>
37-
<FormattedMessage
38-
id={`grants.form.fields.grantType.values.${grantType}`}
39-
/>
37+
<VerticalStack gap="small">
38+
{grantType.map((type, index) => (
39+
<Text size="label2" weight="strong">
40+
<FormattedMessage
41+
key={index}
42+
id={`grants.form.fields.grantType.values.${type}`}
43+
/>
44+
</Text>
45+
))}
46+
</VerticalStack>
4047
</GrantInfo>
4148

4249
<GrantInfo label={<FormattedMessage id="profile.myGrant.appliedFor" />}>

0 commit comments

Comments
 (0)