Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add field to profile for user to specify type #421

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
27 changes: 27 additions & 0 deletions backend/clubs/migrations/0078_profile_affiliation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.1.6 on 2021-04-11 17:46

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("clubs", "0077_auto_20210219_2014"),
]

operations = [
migrations.AddField(
model_name="profile",
name="affiliation",
field=models.PositiveSmallIntegerField(
choices=[
(0, "Undergraduate"),
(1, "Masters"),
(2, "Professional"),
(3, "Doctoral"),
(4, "Staff"),
],
default=0,
),
),
]
47 changes: 47 additions & 0 deletions backend/clubs/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1415,9 +1415,26 @@ class Profile(models.Model):
Additional information attached to a user account.
"""

UNDERGRADUATE = 0
MASTERS = 1
PROFESSIONAL = 2
PHD = 3
STAFF = 4

AFFILIATION_CHOICES = (
(UNDERGRADUATE, "Undergraduate"),
(MASTERS, "Masters"),
(PROFESSIONAL, "Professional"),
(PHD, "Doctoral"),
(STAFF, "Staff"),
)

user = models.OneToOneField(
get_user_model(), on_delete=models.CASCADE, primary_key=True
)
affiliation = models.PositiveSmallIntegerField(
choices=AFFILIATION_CHOICES, default=UNDERGRADUATE
)
image = models.ImageField(upload_to=get_user_file_name, null=True, blank=True)
uuid_secret = models.UUIDField(default=uuid.uuid4)

Expand All @@ -1428,6 +1445,36 @@ class Profile(models.Model):
school = models.ManyToManyField(School, blank=True)
major = models.ManyToManyField(Major, blank=True)

def detect_information(self):
"""
Try to detect appropriate values for profile fields based on what platform has
returned. Currently only supports detecting the affiliation.
This method is not very accurate and should only be used to provide the user
an initial guess.

Overwrites existing information.
"""

# detect the affilation
if self.user.groups.filter(name="platform_student").exists():
# if the user has the student group from platform, they're probably student
domain = self.user.email.split("@", 1)[-1].lower()
if domain in {
"nursing.upenn.edu",
"sas.upenn.edu",
"seas.upenn.edu",
"upenn.edu",
"wharton.upenn.edu",
}:
# domains commonly associated with undergrad schools marked as undergrad
self.affiliation = Profile.UNDERGRADUATE
else:
self.affiliation = Profile.MASTERS
else:
self.affiliation = Profile.STAFF

self.save(update_fields=["affiliation"])

def __str__(self):
return self.user.username

Expand Down
2 changes: 2 additions & 0 deletions backend/clubs/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,7 @@ class UserSerializer(serializers.ModelSerializer):
graduation_year = serializers.IntegerField(
source="profile.graduation_year", allow_null=True
)
affiliation = serializers.IntegerField(source="profile.affiliation")
school = SchoolSerializer(many=True, source="profile.school")
major = MajorSerializer(many=True, source="profile.major")

Expand Down Expand Up @@ -1841,6 +1842,7 @@ def update(self, instance, validated_data):
class Meta:
model = get_user_model()
fields = [
"affiliation",
"email",
"graduation_year",
"has_been_prompted",
Expand Down
16 changes: 16 additions & 0 deletions frontend/components/Settings/ProfileForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ const ProfileForm = ({
}
}

const affiliations = [
{ value: 0, label: 'Undergraduate Student' },
{ value: 1, label: 'Masters Student' },
{ value: 2, label: 'Professional Student' },
{ value: 3, label: 'Doctoral Student' },
{ value: 4, label: 'Faculty or Staff Member' },
Copy link
Member Author

Choose a reason for hiding this comment

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

@ArmaanT Rerequesting review so I can get your opinion on these labels. Are there better labels that we can use? What is the difference between a masters and a professional student? They generally seem very intertwined when Penn refers to them, would everyone be able to tell which one they should select?

Copy link
Member

Choose a reason for hiding this comment

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

On platform we're using the labels that Penn used to label degrees (link). I'm sure Penn isn't very consistent in their naming, but I think this should be good enough for us. There are definitely conflicts (for example an Accounting MBA is both a Master's and a Professional degree) so we just choose the first label that applies. Bachelor's, then Master's, then PhD, then Professional

]

return (
<>
<Formik
Expand All @@ -97,6 +105,14 @@ const ProfileForm = ({
isImage
/>
<Field name="graduation_year" as={TextField} type="number" />
<Field
name="affiliation"
as={SelectField}
choices={affiliations}
valueDeserialize={(val) =>
affiliations.find((item) => item.value === val)
}
/>
<Field name="school" as={SelectField} choices={schools} isMulti />
<Field name="major" as={SelectField} choices={majors} isMulti />
<Field
Expand Down