Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions backend/api/grants/mutations.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def validate(self, conference: Conference, user: User) -> GrantErrors:
"python_usage",
"been_to_other_events",
"why",
"grant_type",
)

for field in non_empty_fields:
Expand All @@ -110,7 +111,7 @@ class SendGrantInput(BaseGrantInput):
age_group: AgeGroup
gender: str
occupation: Occupation
grant_type: GrantType
grant_type: list[GrantType]
python_usage: str
been_to_other_events: str
community_contribution: str
Expand Down Expand Up @@ -149,7 +150,7 @@ class UpdateGrantInput(BaseGrantInput):
age_group: AgeGroup
gender: str
occupation: Occupation
grant_type: GrantType
grant_type: list[GrantType]
python_usage: str
been_to_other_events: str
community_contribution: str
Expand Down
4 changes: 2 additions & 2 deletions backend/api/grants/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Grant:
age_group: Optional[AgeGroup]
gender: str
occupation: Occupation
grant_type: GrantType
grant_type: list[GrantType]
python_usage: str
community_contribution: str
been_to_other_events: str
Expand All @@ -46,7 +46,7 @@ def from_model(cls, grant: GrantModel) -> Grant:
age_group=AgeGroup(grant.age_group) if grant.age_group else None,
gender=grant.gender,
occupation=Occupation(grant.occupation),
grant_type=GrantType(grant.grant_type),
grant_type=[GrantType(g) for g in grant.grant_type],
python_usage=grant.python_usage,
community_contribution=grant.community_contribution,
been_to_other_events=grant.been_to_other_events,
Expand Down
50 changes: 50 additions & 0 deletions backend/grants/migrations/0023_alter_grant_grant_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Generated by Django 5.1.1 on 2024-12-01 17:59

from django.db import migrations, models
import json

def forwards_func(apps, schema_editor):
Grant = apps.get_model('grants', 'Grant')
for grant in Grant.objects.all():
old_value = grant.grant_type
# Convert the old string value into a list
grant.grant_type_json = [old_value] if old_value else []
grant.save(update_fields=['grant_type_json'])

def reverse_func(apps, schema_editor):
Grant = apps.get_model('grants', 'Grant')
for grant in Grant.objects.all():
value_list = grant.grant_type
# Convert the list back to a single string
if value_list:
grant.grant_type = value_list[0]
else:
grant.grant_type = ''
grant.save(update_fields=['grant_type'])

class Migration(migrations.Migration):
dependencies = [
("grants", "0022_grant_departure_city_grant_nationality_and_more"),
]

operations = [
# Step 1: Add a temporary JSONField
migrations.AddField(
model_name='grant',
name='grant_type_json',
field=models.JSONField(default=list, verbose_name="grant type"),
),
# Step 2: Backfill data into the temporary field
migrations.RunPython(forwards_func, reverse_func),
# Step 3: Remove the old field
migrations.RemoveField(
model_name='grant',
name='grant_type',
),
# Step 4: Rename the temporary field to grant_type
migrations.RenameField(
model_name='grant',
old_name='grant_type_json',
new_name='grant_type',
),
]
4 changes: 1 addition & 3 deletions backend/grants/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,7 @@ class ApprovedType(models.TextChoices):
)

# Your Grant Section
grant_type = models.CharField(
_("grant type"), choices=GrantType.choices, max_length=10
)
grant_type = models.JSONField(_("grant type"), default=list)
departure_country = models.CharField(
_("Departure Country"),
max_length=100,
Expand Down
8 changes: 7 additions & 1 deletion backend/grants/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from countries import countries
from participants.tests.factories import ParticipantFactory
from participants.models import Participant
import random


class GrantFactory(DjangoModelFactory):
Expand All @@ -22,7 +23,12 @@ class Meta:
age_group = factory.fuzzy.FuzzyChoice(Grant.AgeGroup)
gender = factory.fuzzy.FuzzyChoice([gender[0] for gender in GENDERS])
occupation = factory.fuzzy.FuzzyChoice(Grant.Occupation)
grant_type = factory.fuzzy.FuzzyChoice(Grant.GrantType)
grant_type = factory.LazyFunction(
lambda: random.sample(
[choice[0] for choice in Grant.GrantType.choices],
k=random.randint(1, len(Grant.GrantType.choices)),
)
)

python_usage = factory.Faker("text")
been_to_other_events = factory.Faker("text")
Expand Down
34 changes: 20 additions & 14 deletions frontend/src/components/grant-form/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export type GrantFormFields = ParticipantFormFields & {
ageGroup: AgeGroup;
gender: string;
occupation: Occupation;
grantType: GrantType;
grantType: GrantType[];
pythonUsage: string;
communityContribution: string;
beenToOtherEvents: string;
Expand Down Expand Up @@ -458,21 +458,27 @@ export const GrantForm = ({
<FormattedMessage id="grants.form.fields.grantType.description" />
}
>
<Select
{...select("grantType")}
required={true}
errors={getErrors("grantType")}
>
<HorizontalStack gap="small">
{GRANT_TYPE_OPTIONS.map(({ value, disabled, messageId }) => (
<FormattedMessage id={messageId} key={messageId}>
{(msg) => (
<option disabled={disabled} value={value}>
{msg}
</option>
)}
</FormattedMessage>
<label key={value}>
<HorizontalStack gap="small" alignItems="center">
<Checkbox
size="small"
{...checkbox("grantType", value)}
disabled={disabled}
/>

<FormattedMessage id={messageId} key={messageId}>
{(msg) => <Text size={2}>{msg}</Text>}
</FormattedMessage>
</HorizontalStack>
</label>
))}
</Select>
</HorizontalStack>
<Spacer size="xs" />
<Text as="p" size="label4" color="error" uppercase>
{getErrors("grantType").join(", ")}
</Text>
</InputWrapper>

<InputWrapper
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/components/grant-form/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,6 @@ export const OCCUPATION_OPTIONS = [
];

export const GRANT_TYPE_OPTIONS = [
{
value: "",
disabled: true,
messageId: "global.selectOption",
},
{
disabled: false,
value: GrantType.Diversity,
Expand Down
14 changes: 11 additions & 3 deletions frontend/src/components/my-grant-profile-page-handler/sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,17 @@ export const Sidebar = ({
</GrantInfo>

<GrantInfo label={<FormattedMessage id="profile.myGrant.grantType" />}>
<FormattedMessage
id={`grants.form.fields.grantType.values.${grantType}`}
/>
<VerticalStack gap="small">
{grantType.map((type, index) => (
<Text size="label2" weight="strong">
{" "}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the empty space? maybe a vertical Spacer works better?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no was a mistake, think my editor put it somehow

<FormattedMessage
key={index}
id={`grants.form.fields.grantType.values.${type}`}
/>
</Text>
))}
</VerticalStack>
</GrantInfo>

<GrantInfo label={<FormattedMessage id="profile.myGrant.appliedFor" />}>
Expand Down
15 changes: 9 additions & 6 deletions frontend/src/locale/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,7 @@ We look forward to reading about you and hope to see you at PyCon Italia 2024!
"grants.form.yourGrant": "Your grant",
"grants.form.travel": "Travel",
"grants.form.youAndPython": "You and Python",
"grants.form.validationErrors": "The submitted form is not correct",

"grants.form.optionalInformation": "Optional information",
"grants.form.optionalInformation.description":
Expand Down Expand Up @@ -730,9 +731,10 @@ We look forward to reading about you and hope to see you at PyCon Italia 2024!
"grants.form.fields.occupation.values.researcher": "Researcher",
"grants.form.fields.occupation.values.unemployed": "Unemployed",
"grants.form.fields.occupation.values.other": "Other",
"grants.form.fields.grantType": "What type of grant are you applying for?",
"grants.form.fields.grantType.description":
"Note: If you have submitted a talk/workshop proposal, you do not need to apply for a grant to receive a refund. If your proposal is accepted, we will contact you regarding the ticket refund.",
"grants.form.fields.grantType":
"Select all grant categories that apply to you",
"grants.form.fields.grantType.description": `You can choose more than one option if applicable.
Note: If you have submitted a talk/workshop proposal, you do not need to apply for a grant to receive a refund. If your proposal is accepted, we will contact you regarding the ticket refund.`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to be more specific, we need to make sure it is clear we are only talking about the ticket. Otherwise people might think we are going to refund all their expenses

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I adjusted the text slightly

"grants.form.fields.grantType.values.diversity": "Diversity",
"grants.form.fields.grantType.values.unemployed": "Unemployed",
"grants.form.fields.grantType.values.speaker": "Speaker",
Expand Down Expand Up @@ -1456,9 +1458,10 @@ Non vediamo l'ora di leggere la tua storia e speriamo di vederti a PyCon Italia
"grants.form.fields.occupation.values.researcher": "Ricerca",
"grants.form.fields.occupation.values.unemployed": "Disoccupato/a",
"grants.form.fields.occupation.values.other": "Altro",
"grants.form.fields.grantType": "Che tipo di grant stai richiedendo?",
"grants.form.fields.grantType.description":
"Nota: Se hai inviato una proposta di talk/workshop, non è necessario fare domanda per un grant per ricevere un rimborso. Se la tua proposta viene accettata, ti contatteremo riguardo al rimborso del biglietto.",
"grants.form.fields.grantType":
"Seleziona tutte le categorie di grant che si applicano a te",
"grants.form.fields.grantType.description": `Puoi scegliere più di un'opzione se necessario.
Nota: Se hai inviato una proposta di talk/workshop, non è necessario fare domanda per un grant per ricevere un rimborso. Se la tua proposta viene accettata, ti contatteremo riguardo al rimborso del biglietto.`,
"grants.form.fields.grantType.values.diversity": "Diversity",
"grants.form.fields.grantType.values.unemployed": "Disoccupato",
"grants.form.fields.grantType.values.speaker": "Speaker",
Expand Down