Skip to content

Commit

Permalink
Merge pull request #476 from tamuhack-org/sandeep-dev
Browse files Browse the repository at this point in the history
Potentially fixed blank wave bug
  • Loading branch information
skandrigi authored Nov 24, 2024
2 parents 62b2696 + aaf4eca commit 68742b7
Show file tree
Hide file tree
Showing 29 changed files with 1,441 additions and 178 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ RUN python3 -m pip install -r requirements.txt

RUN python3 manage.py collectstatic --no-input

CMD gunicorn -b :$PORT hiss.wsgi:application --capture-output
CMD gunicorn -b :$PORT hiss.wsgi:application --log-file=- --capture-output --log-level=debug
13 changes: 9 additions & 4 deletions hiss/application/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ class ApplicationAdmin(admin.ModelAdmin):
readonly_fields = [
"datetime_submitted",
"user",
"is_adult",
# "is_adult",
"gender",
"race",
"major",
Expand All @@ -203,13 +203,15 @@ class ApplicationAdmin(admin.ModelAdmin):
("status", ChoiceDropdownFilter),
("classification", ChoiceDropdownFilter),
("gender", ChoiceDropdownFilter),
("major", ChoiceDropdownFilter),
("grad_year", ChoiceDropdownFilter),
("num_hackathons_attended", ChoiceDropdownFilter),
("wares", ChoiceDropdownFilter),
# ("wares", ChoiceDropdownFilter),
# ("technology_experience", ChoiceDropdownFilter),
# ("dietary_restrictions", ChoiceDropdownFilter),
("shirt_size", ChoiceDropdownFilter),
("datetime_submitted", DateRangeFilter),
("accessibility_requirements", ChoiceDropdownFilter),
RaceFilter,
)
list_display = (
Expand All @@ -232,6 +234,7 @@ class ApplicationAdmin(admin.ModelAdmin):
"fields": [
"first_name",
"last_name",
"tamu_email",
"age",
"phone_number",
"country",
Expand All @@ -250,6 +253,7 @@ class ApplicationAdmin(admin.ModelAdmin):
"school",
"school_other",
"major",
"major_other",
"classification",
"gender",
"gender_other",
Expand All @@ -266,9 +270,10 @@ class ApplicationAdmin(admin.ModelAdmin):
"Logistical Information",
{
"fields": [
"wares",
# "wares",
"shirt_size",
"dietary_restrictions",
"meal_group",
"additional_accommodations",
# "address",
"emergency_contact_name",
Expand All @@ -279,7 +284,7 @@ class ApplicationAdmin(admin.ModelAdmin):
},
),
("Confirmation Deadline", {"fields": ["confirmation_deadline"]}),
("Miscellaneous", {"fields": ["notes"]}),
("Miscellaneous", {"fields": ["notes", "is_adult", "accessibility_requirements"]}),
]
formfield_overrides = {
AddressField: {"widget": AddressWidget(attrs={"style": "width: 300px;"})}
Expand Down
51 changes: 38 additions & 13 deletions hiss/application/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,35 @@
from application.models import Application
from application.apple_wallet import get_apple_wallet_pass_url

import threading
from django.core.mail import EmailMessage

#create separate threading class for confirmation email since it has a QR code

class EmailQRThread(threading.Thread):
def __init__(self, subject, msg, html_msg, recipient_email, qr_stream):
self.subject = subject
self.msg = msg
self.html_msg = html_msg
self.recipient_email = recipient_email
self.qr_stream = qr_stream
threading.Thread.__init__(self)

def run(self):
qr_code = pyqrcode.create(self.qr_content)
qr_stream = BytesIO()
qr_code.png(qr_stream, scale=5)

email = mail.EmailMultiAlternatives(
self.subject, self.msg, from_email=None, to=[self.recipient_email]
)
email.attach_alternative(self.html_msg, "text/html")
email.attach("code.png", self.qr_stream.getvalue(), "text/png")

# if above code is defined directly in function, it will run synchronously
# therefore need to directly define in threading class to run asynchronously

email.send()

def send_creation_email(app: Application) -> None:
"""
Expand All @@ -27,8 +56,11 @@ def send_creation_email(app: Application) -> None:
"organizer_email": settings.ORGANIZER_EMAIL,
}

app.user.send_html_email(template_name, context, subject)
# send_html_email is threaded from the User class
# see user/models.py

app.user.send_html_email(template_name, context, subject)


def send_confirmation_email(app: Application) -> None:
"""
Expand All @@ -37,7 +69,7 @@ def send_confirmation_email(app: Application) -> None:
:type app: Application
:return: None
"""
subject = f"TAMUhack Waitlist: Important Day-Of Information"
subject = f"HowdyHack Waitlist: Important Day-Of Information"
email_template = "application/emails/confirmed.html"
context = {
"first_name": app.first_name,
Expand All @@ -48,11 +80,7 @@ def send_confirmation_email(app: Application) -> None:
"apple_wallet_url": get_apple_wallet_pass_url(app.user.email),
}
html_msg = render_to_string(email_template, context)
msg = html.strip_tags(html_msg)
email = mail.EmailMultiAlternatives(
subject, msg, from_email=None, to=[app.user.email]
)
email.attach_alternative(html_msg, "text/html")
plain_msg = html.strip_tags(html_msg)

qr_content = json.dumps(
{
Expand All @@ -62,9 +90,6 @@ def send_confirmation_email(app: Application) -> None:
"university": app.school.name,
}
)
qr_code = pyqrcode.create(qr_content)
qr_stream = BytesIO()
qr_code.png(qr_stream, scale=5)
email.attach("code.png", qr_stream.getvalue(), "text/png")
print(f"sending confirmation email to {app.user.email}")
email.send()

email_thread = EmailQRThread(subject, plain_msg, html_msg, app.user.email, qr_content)
email_thread.start()
7 changes: 7 additions & 0 deletions hiss/application/fixtures/schools.json
Original file line number Diff line number Diff line change
Expand Up @@ -10982,6 +10982,13 @@
"name": "Texas A&M University - Kingsville"
}
},
{
"model": "application.school",
"pk": 2075,
"fields": {
"name": "Texas A&M University - San Antonio"
}
},
{
"model": "application.school",
"pk": 1570,
Expand Down
43 changes: 35 additions & 8 deletions hiss/application/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ class ApplicationModelForm(forms.ModelForm):
label='If you chose "Prefer to self-describe", please elaborate.',
required=False,
)
major_other = forms.CharField(
label='If you chose "Other", please specify your major.',
required=False,
)
school = forms.ModelChoiceField(
School.objects.all(),
label="What school do you go to?",
Expand All @@ -31,6 +35,10 @@ class ApplicationModelForm(forms.ModelForm):
label='If you chose "Other", please enter your school\'s name here.',
required=False,
)
tamu_email = forms.CharField(
label="TAMU Email if you are a Texas A&M student",
required=False,
)

# Languages
PYTHON = "Python"
Expand Down Expand Up @@ -178,7 +186,7 @@ class ApplicationModelForm(forms.ModelForm):
(TENSORFLOW, "Tensorflow"),
(PYTORCH, "PyTorch"),
(FLUTTER, "Flutter"),
(REACT_NATIVE, "React Native")
(REACT_NATIVE, "React Native"),
)
# SKILLS
technology_experience = forms.MultipleChoiceField(
Expand Down Expand Up @@ -207,9 +215,9 @@ class ApplicationModelForm(forms.ModelForm):
(KOSHER, "Kosher"),
(GLUTEN_FREE, "Gluten-Free"),
(FOOD_ALLERGY, "Food Allergy"),
(OTHER_DIETARY_RESTRICTION, "Other")
(OTHER_DIETARY_RESTRICTION, "Other"),
)

dietary_restrictions = forms.MultipleChoiceField(
label="Do you have any dietary restrictions?",
help_text="Select all that apply",
Expand All @@ -234,6 +242,13 @@ def __init__(self, *args, **kwargs):
}

super().__init__(*args, **kwargs)

photo_agreement = "Do you grant permission for TAMUhack to use your name, likeness, voice, and any photographs, video recordings, or audio recordings taken during the event 'TAMUhack 2025' for promotional and media purposes, including but not limited to publications, websites, social media, and press releases?"
accessibilities = "Please check this box if you require any accommodations to ensure accessibility during this event. Our team will follow up to discuss your needs."

self.fields["agree_to_photos"].label = mark_safe(photo_agreement)
self.fields["accessibility_requirements"].label = mark_safe(accessibilities)

self.fields["agree_to_coc"].label = mark_safe(
'I agree to the <a href="https://static.mlh.io/docs/mlh-code-of-conduct.pdf">MLH Code of Conduct</a>'
)
Expand All @@ -247,10 +262,7 @@ def __init__(self, *args, **kwargs):
' and the <a href="https://mlh.io/privacy">MLH Privacy Policy</a>'
)

mlh_newsletter = (
"I authorize MLH to send me occasional emails about relevant events, career opportunities, and community announcements."
)

mlh_newsletter = "I authorize MLH to send me occasional emails about relevant events, career opportunities, and community announcements."
self.fields["agree_to_mlh_stuff"].label = mark_safe(mlh_stuff)
self.fields["signup_to_mlh_newsletter"].label = mark_safe(mlh_newsletter)

Expand Down Expand Up @@ -287,6 +299,14 @@ def clean(self):
"Please fill out this field with the appropriate information."
)
self.add_error("race_other", msg)
major = self.cleaned_data.get("major")
if major:
major_other = self.cleaned_data.get("major_other")
if major == "Other" and not major_other:
msg = forms.ValidationError(
'Please fill out this field or choose "Other".'
)
self.add_error("major_other", msg)
return self.cleaned_data

class Meta:
Expand All @@ -296,7 +316,10 @@ class Meta:
"agree_to_coc": forms.CheckboxInput,
"agree_to_mlh_stuff": forms.CheckboxInput,
"signup_to_mlh_newsletter": forms.CheckboxInput,
"agree_to_photos": forms.CheckboxInput,
"accessibility_requirements": forms.CheckboxInput,
"travel_reimbursement": forms.CheckboxInput,
"tamu_email": forms.EmailInput(attrs={"placeholder": "[email protected]"}),
"extra_links": forms.TextInput(
attrs={
"placeholder": "ex. GitHub, Devpost, personal website, LinkedIn, etc."
Expand All @@ -312,7 +335,9 @@ class Meta:
"country",
"school",
"school_other",
"tamu_email",
"major",
"major_other",
"classification",
"grad_year",
"level_of_study",
Expand All @@ -322,7 +347,7 @@ class Meta:
"race_other",
"num_hackathons_attended",
"technology_experience",
"wares",
# "wares",
"dietary_restrictions",
"has_team",
"wants_team",
Expand All @@ -339,6 +364,8 @@ class Meta:
"emergency_contact_phone",
"emergency_contact_email",
"notes",
"agree_to_photos",
"accessibility_requirements",
"agree_to_coc",
"agree_to_mlh_stuff",
"signup_to_mlh_newsletter",
Expand Down
38 changes: 38 additions & 0 deletions hiss/application/migrations/0021_auto_20240620_1047.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Generated by Django 2.2.13 on 2024-06-20 15:47

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('application', '0020_auto_20231214_2259'),
]

operations = [
migrations.AddField(
model_name='application',
name='major_other',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Other'),
),
migrations.AddField(
model_name='application',
name='tamu_email',
field=models.EmailField(blank=True, max_length=75, null=True, verbose_name='TAMU Email if you are a Texas A&M student'),
),
migrations.AlterField(
model_name='application',
name='grad_year',
field=models.IntegerField(choices=[(2024, 2024), (2025, 2025), (2026, 2026), (2027, 2027), (2028, 2028), (2029, 2029)], verbose_name='What is your anticipated graduation year?'),
),
migrations.AlterField(
model_name='application',
name='major',
field=models.CharField(choices=[('Computer Science', 'Computer Science'), ('Software Engineering', 'Software Engineering'), ('Computer Engineering', 'Computer Engineering'), ('Electrical Engineering', 'Electrical Engineering'), ('Information Technology', 'Information Technology'), ('Data Science', 'Data Science'), ('major_other', 'Other')], default='NA', max_length=100, verbose_name="What's your major?"),
),
migrations.AlterField(
model_name='application',
name='shirt_size',
field=models.CharField(choices=[('XXS', 'XXS'), ('XS', 'XS'), ('S', 'S'), ('M', 'M'), ('L', 'L'), ('XL', 'XL'), ('XXL', 'XXL')], max_length=4, verbose_name='What size shirt do you wear?'),
),
]
18 changes: 18 additions & 0 deletions hiss/application/migrations/0022_auto_20240627_1606.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.13 on 2024-06-27 21:06

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('application', '0021_auto_20240620_1047'),
]

operations = [
migrations.AlterField(
model_name='application',
name='major',
field=models.CharField(choices=[('Computer Science', 'Computer Science'), ('Software Engineering', 'Software Engineering'), ('Computer Engineering', 'Computer Engineering'), ('Electrical Engineering', 'Electrical Engineering'), ('Information Technology', 'Information Technology'), ('Data Science', 'Data Science'), ('Other', 'Other')], default='NA', max_length=100, verbose_name="What's your major?"),
),
]
18 changes: 18 additions & 0 deletions hiss/application/migrations/0023_auto_20240810_1843.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 2.2.13 on 2024-08-10 23:43

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('application', '0022_auto_20240627_1606'),
]

operations = [
migrations.AlterField(
model_name='application',
name='wants_team',
field=models.CharField(choices=[('Friend', 'From a friend'), ('Tabling', 'Tabling outside Zachry'), ('Howdy Week', 'From Howdy Week'), ('Yard Sign', 'Yard sign'), ('Social Media', 'Social media'), ('Student Orgs', 'Though another student org'), ('TH Organizer', 'From a TAMUhack organizer'), ('ENGR Newsletter', 'From the TAMU Engineering Newsletter'), ('MLH', 'Major League Hacking (MLH)'), ('Attended Before', "I've attended TAMUhack before")], max_length=16, verbose_name='How did you hear about TAMUhack?'),
),
]
23 changes: 23 additions & 0 deletions hiss/application/migrations/0024_auto_20240823_1038.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 2.2.13 on 2024-08-23 15:38

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('application', '0023_auto_20240810_1843'),
]

operations = [
migrations.AddField(
model_name='application',
name='meal_group',
field=models.CharField(blank=True, default=None, max_length=255, null=True),
),
migrations.AlterField(
model_name='application',
name='status',
field=models.CharField(choices=[('P', 'Under Review'), ('R', 'Rejected'), ('A', 'Admitted'), ('C', 'Confirmed'), ('X', 'Declined'), ('I', 'Checked in'), ('E', 'Waitlisted (Expired, internally)')], default='P', max_length=1),
),
]
Loading

0 comments on commit 68742b7

Please sign in to comment.