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

Rsvp support #23

Merged
merged 6 commits into from
Oct 20, 2024
Merged
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
87 changes: 75 additions & 12 deletions hackathon_site/event/jinja2/event/dashboard_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,7 @@
<h1 class="formH1">Dashboard</h1>

{% if application is none %}
{% if is_registration_open() and not is_application_open() %}
<h2 class="formH2">Applications are not open yet</h2>
<p style="margin-bottom: 20px;">{{ hackathon_name }} applications will open soon! Please follow our <a href="https://www.instagram.com/ieee_uoft/" class="hoverLink primaryText" target="_blank">Instagram</a> for the latest updates.</p>
<br />
<p style="margin-bottom: 20px;"><b>Note:</b> We are sorry to inform, but due to logistical changes, we will be updating our application form. To those that have previously submitted an application, you would need to refill a new one
when applications re-open. We will be sending an email soon to all those that are affected. Apologies for the inconvenience!</p>
<br />
<p style="margin-bottom: 20px;">If you have any questions or concerns, please <a href="mailto:{{ contact_email }}" class="hoverLink primaryText">contact us</a>.</p>

{% elif not is_application_open() %}
{% if not is_registration_open() %}
<h2 class="formH2">Applications have closed</h2>
<p>Unfortunately, the deadline to apply for {{ hackathon_name }} was {{ localtime(registration_close_date).strftime("%B %-d, %Y") }}.</p>
<br />
Expand All @@ -44,10 +35,82 @@ <h2 class="formH2">Complete your application</h2>
{% elif application is not none and review is not none %}
<br />
{% if review.status == "Accepted" %}
<h4 class="formH2"><b>Congratulations!</b> You've been accepted into {{ hackathon_name }}!</h4>
<p>Make sure you read the <a class="primaryText hoverLink" href="{{ participant_package_link }}" rel="noopener" target="_blank">participant package</a> for all the info regarding
{% if application.rsvp and using_rsvp %}
<h4 class="formH2"><b>Thanks for RSVP'ing!</b> See you at {{ hackathon_name }}!</h4>
{% elif application.rsvp is sameas false and using_rsvp%}
<h4 class="formH2"><b>Thanks for letting us know.</b> Hope to see you next year at {{ hackathon_name }}</h4>
{% else %}
<h4 class="formH2"><b>Congratulations!</b> You've been accepted into {{ hackathon_name }}!</h4>
{% endif %}

{% if using_rsvp %}
<p style="display: flex;">
<strong>Status:&nbsp;</strong>
{% if application.rsvp is sameas false %}
<span class="material-icons errorText" style="margin-right: 3px;">
highlight_off
</span>
{% elif application.rsvp %}
<span class="material-icons successText" style="margin-right: 3px;">
check_circle_outline
</span>
{% endif %}
{{ status }}
</p>
<br>
{% if not rsvp_passed %}
{% if application.rsvp is none %}
<p>To confirm your attendance at {{ hackathon_name }}, please RSVP using the accept or decline buttons below.</p> <br />
<p>RSVP by <b>{{ rsvp_deadline }}</b>, otherwise your spot will be given to other applicants.
Alternatively you can decline the offer. You can change your response at any time before <b>{{ rsvp_deadline }}</b>.
</p> <br />
{% else %}
<p>You can change your response at any time before <b>{{ rsvp_deadline }}</b>.</p> <br />
{% endif %}
{% endif %}
{% endif %}

{% if (application.rsvp and using_rsvp) or not using_rsvp %}
<p>Make sure you read the <a class="primaryText hoverLink" href="{{ participant_package_link }}" rel="noopener" target="_blank">participant package</a> for all the info regarding
the event, and join our <a class="primaryText hoverLink" href="{{ chat_room_link }}" rel="noopener" target="_blank">{{ chat_room_name }}</a>. Stay tuned for more updates regarding detailed event logistics, and we hope to see you soon!</p> <br />
<!-- TODO QR SCANNER CODE: <div style="margin-bottom: 15px; display: flex; flex-direction: column; align-items: center">
<p>Please show the QR code below to the front desk to sign-in. .</p>
<canvas id="qrcode" style="width: 150px; height: 150px; margin: 10px auto"></canvas>
</div> -->
{% endif %}
<p>If you have questions, read the <a class="primaryText hoverLink" href="#faq">FAQ</a>, or feel free to contact us.</p> <br />

{% if using_rsvp %}
{% if not rsvp_passed %}
<div style="display: flex; width: auto">
{% if application.rsvp is sameas false or application.rsvp is none %}
<a
href="{{ url("registration:rsvp", kwargs={"rsvp": "yes"}) }}"
class="btn-small waves-effect waves-light colorBtn"
style="margin-right: 30px;"
>
Will Attend (Accept)
</a>
{% endif %}
{% if application.rsvp or application.rsvp is none %}
<a
href="{{ url("registration:rsvp", kwargs={"rsvp": "no"})}}"
class="btn-small waves-effect waves-light redBtn"
>
Cannot Attend (Decline)
</a>
{% endif %}
</div>

{% elif rsvp_passed and application.rsvp %}
<p><b>The RSVP deadline has passed. Thanks for confirming your position at {{ hackathon_name }}! We look forward to seeing you there. Note that you cannot change your RSVP at this time.</b></p>
{% elif rsvp_passed and application.rsvp is sameas false %}
<p><b>The RSVP deadline has passed. We regret to see that you will not be joining us this year at {{ hackathon_name }}. Unfortunately you cannot change your RSVP at this time.</b></p>
{% else %}
<p><b>It appears you haven't RSVPed. Unfortunately the RSVP deadline has passed and you cannot change your RSVP at this time.</b></p>
{% endif %}
{% endif %}

{% elif review.status == "Waitlisted" %}
<h4 class="formH2">You've been waitlisted for {{ hackathon_name }}</h4>
<p>The {{ hackathon_name }} team has reviewed your application, and have decided not to grant you a guaranteed spot
Expand Down
10 changes: 5 additions & 5 deletions hackathon_site/event/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ def create(self, validated_data):
)
if not is_test_user:
try:
application = Application.objects.get(user=current_user)
# if not rsvp_status:
# raise serializers.ValidationError(
# "User has not RSVP'd to the hackathon. Please RSVP to access the Hardware Signout Site"
# )
rsvp_status = Application.objects.get(user=current_user).rsvp
if not rsvp_status and settings.RSVP:
raise serializers.ValidationError(
"User has not RSVP'd to the hackathon. Please RSVP to access the Hardware Signout Site"
)
except Application.DoesNotExist:
raise serializers.ValidationError(
"User has not completed their application to the hackathon. Please do so to access the Hardware Signout Site"
Expand Down
30 changes: 29 additions & 1 deletion hackathon_site/event/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,15 @@ def get_context_data(self, **kwargs):


class DashboardView(LoginRequiredMixin, FormView):
template_name = "event/dashboard_base.html"
# Form submits should take the user back to the dashboard
success_url = reverse_lazy("event:dashboard")

# TODO: QR Scanner CODE
def get_template_names(self):
# if self.request.user.is_staff:
# return "event/dashboard_admin.html"
return "event/dashboard_base.html"

def get_form(self, form_class=None):
"""
The dashboard can have different forms, but not at the same time:
Expand Down Expand Up @@ -117,6 +122,19 @@ def get_context_data(self, **kwargs):
review = self.request.user.application.review

context["review"] = review
if settings.RSVP:
context[
"rsvp_passed"
] = _now().date() > review.decision_sent_date + timedelta(
days=settings.RSVP_DAYS
)
rsvp_deadline = datetime.combine(
review.decision_sent_date + timedelta(days=settings.RSVP_DAYS),
datetime.max.time(), # 11:59PM
)
context["rsvp_deadline"] = settings.TZ_INFO.localize(
rsvp_deadline
).strftime("%B %-d, %Y, %-I:%M %p %Z")
else:
context["review"] = None

Expand All @@ -134,6 +152,12 @@ def get_context_data(self, **kwargs):
and self.request.user.application.review.decision_sent_date is None
):
context["status"] = "Application Complete"
elif (
hasattr(self.request.user.application, "review")
and self.request.user.application.review.status == "Accepted"
and self.request.user.application.rsvp is None
):
context["status"] = "Accepted, awaiting RSVP"
elif (
hasattr(self.request.user.application, "review")
and self.request.user.application.review.status == "Waitlisted"
Expand All @@ -144,6 +168,10 @@ def get_context_data(self, **kwargs):
and self.request.user.application.review.status == "Rejected"
):
context["status"] = "Rejected"
elif self.request.user.application.rsvp:
context["status"] = "Will Attend (Accepted)"
elif not self.request.user.application.rsvp:
context["status"] = "Cannot Attend (Declined)"
else:
context["status"] = "Unknown"

Expand Down
1 change: 1 addition & 0 deletions hackathon_site/hackathon_site/jinja2.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def environment(**options):
"chat_room_name": settings.CHAT_ROOM[0],
"chat_room_link": settings.CHAT_ROOM[1],
"using_teams": settings.TEAMS,
"using_rsvp": settings.RSVP,
}
)
return env
9 changes: 4 additions & 5 deletions hackathon_site/hackathon_site/settings/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@
HARDWARE_SIGN_OUT_START_DATE = datetime(2024, 10, 28, 23, 59, 0, tzinfo=TZ_INFO)
HARDWARE_SIGN_OUT_END_DATE = EVENT_END_DATE

RSVP_DAYS = 10
RSVP_DAYS = 2

# sign in times must be between EVENT_START_DATE and EVENT_END_DATE and in chronological order
# the number of sign in times MUST MATCH the number of columns in UserActivityTable
Expand Down Expand Up @@ -374,16 +374,15 @@
FINAL_REVIEW_RESPONSE_DATE = REGISTRATION_CLOSE_DATE + timedelta(days=7)

# Links
# TODO: NEED TO REPLACE THIS WITH NEW LINK (for acceptance email)
PARTICIPANT_PACKAGE_LINK = "https://docs.google.com/document/d/1AkinPac_KS9_wA9P7H-7wOBfJ5xgIciIGwpU3D1UGu0/edit?usp=sharing"
PARTICIPANT_PACKAGE_LINK = "https://docs.google.com/document/d/1AmgarLDeE8e8oirdG-uY-fdyOwfUomhA4jjU6o-Q2MM/edit?usp=sharing"

# Note this is in the form (chat_room_name, chat_room_link)
# Chat room name is such as the following: Slack, Discord
# TODO: NEED TO REPLACE THIS WITH NEW LINK (for acceptance email)
CHAT_ROOM = ("Discord", "https://discord.gg/cqW93CMu")
CHAT_ROOM = ("Discord", "https://discord.gg/TQZ7aCs24r")

# Enable/Disable certain Features
TEAMS = True
RSVP = True

# HSS Testing
TEST_USER_GROUP = "HSS Test Users"
2 changes: 2 additions & 0 deletions hackathon_site/registration/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class Meta:
"email_agree",
"resume_sharing",
"review__status",
"rsvp",
"created_at",
"updated_at",
)
Expand Down Expand Up @@ -84,6 +85,7 @@ class Meta:
"email_agree",
"resume_sharing",
"review__status",
"rsvp",
"created_at",
"updated_at",
)
Expand Down
47 changes: 47 additions & 0 deletions hackathon_site/registration/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,3 +369,50 @@ def clean_team_code(self):
raise forms.ValidationError(_(f"Team {team_code} is full."))

return team_code


class SignInForm(forms.Form):
email = forms.EmailField()

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.label_suffix = ""
self.error_css_class = "invalid"

def clean(self):
if not is_hackathon_happening():
raise forms.ValidationError(
_("You cannot sign in outside of the hackathon period."),
code="invalid_sign_in_time",
)

return super().clean()

def clean_email(self):
email = self.cleaned_data["email"]

try:
user = User.objects.get(email__exact=email)
application = Application.objects.get(user__exact=user)
review = Review.objects.get(application__exact=application)
if review.status == "Accepted":
if settings.RSVP and application.rsvp is None:
raise forms.ValidationError(
_(f"User {email} has not RSVP'd to the hackathon")
)
else:
raise forms.ValidationError(
_(
f"User {email} has not been Accepted to attend {settings.HACKATHON_NAME}"
)
)
except User.DoesNotExist:
raise forms.ValidationError(_(f"User {email} does not exist."))
except Application.DoesNotExist:
raise forms.ValidationError(
_(f"User {email} has not applied to {settings.HACKATHON_NAME}")
)
except Exception as e:
raise e

return email
1 change: 1 addition & 0 deletions hackathon_site/registration/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@
),
path("application/", views.ApplicationView.as_view(), name="application"),
path("leave_team/", views.LeaveTeamView.as_view(), name="leave-team"),
re_path("rsvp/(?P<rsvp>yes|no)/$", views.RSVPView.as_view(), name="rsvp"),
]
69 changes: 69 additions & 0 deletions hackathon_site/registration/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,72 @@ def get(self, request, *args, **kwargs):
response["Content-Encoding"] = encoding

return response


class RSVPView(LoginRequiredMixin, View):
"""
This page checks if the RSVP deadline has passed and then does one of
the following:
1. If the deadline has passed, redirect to the dashboard
2. Otherwise if their decision was a 'yes', we note that and
create a profile for them
3. Otherwise if their decision was a 'no', we note that and remove
their profile and team if they had one.

Finally we redirect to the dashboard.
"""

def get(self, request, *args, **kwargs):
decision = kwargs["rsvp"]

# Check for nulls
user = self.request.user
if not hasattr(user, "application"):
return HttpResponseBadRequest(
"You have not submitted an application.".encode(encoding="utf-8")
)

application = user.application
if not hasattr(application, "review"):
return HttpResponseBadRequest(
"Your application has not yet been reviewed.".encode(encoding="utf-8")
)

review = application.review
if not review.status == "Accepted":
return HttpResponseBadRequest(
"You cannot RSVP since your application has not yet been accepted.".encode(
encoding="utf-8"
)
)

# Check if RSVP deadline has passed
if _now().date() > review.decision_sent_date + timedelta(
days=settings.RSVP_DAYS
):
return redirect(reverse_lazy("event:dashboard"))

# Check decision
else:
if decision == "yes" and not application.rsvp:
application.rsvp = True
application.save()

# TODO: decide whether to create profile when rsvp
# profile = Profile(user=user, team=EventTeam.objects.create())
# profile.save()

elif decision == "no" and (application.rsvp or application.rsvp is None):
application.rsvp = False
application.save()

# Delete the profile
if hasattr(request.user, "profile"):
team = user.profile.team
user.profile.delete()

# Delete the team if it is empty
if not team.profiles.exists():
team.delete()

return redirect(reverse_lazy("event:dashboard"))
1 change: 1 addition & 0 deletions hackathon_site/review/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class ApplicationInline(admin.TabularInline):
"ethnicity",
"phone_number",
"resume",
"rsvp",
"conduct_agree",
"data_agree",
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
<br><br>
<b>If you have already RSVP'd please ignore the following.</b>
<br><br>
To confirm your attendance, visit your dashboard to RSVP by November 3rd, 2023 otherwise your spot will be given to other applicants. Alternatively, you can press the "Cannot attend" button.
To confirm your attendance, visit your dashboard to RSVP by {{ rsvp_deadline }} otherwise your spot will be given to other applicants. Alternatively, you can press the "Cannot attend" button.
<br><br>
<p>Read our <a href="{{ participant_package_link }}">participant package</a> for all the info regarding the event, and join our <a href="{{ chat_room_link }}">{{ chat_room_name }}</a>. Stay tuned for more updates regarding detailed event logistics, and we hope to see you soon! If you have questions, read the FAQ on your <a href="{{ dashboard_url }}">dashboard</a> or feel free to contact us. </p>
</td>
Expand Down
3 changes: 3 additions & 0 deletions hackathon_site/review/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ def form_valid(self, form, **kwargs):
render_to_string_context = {
"user": review.application.user,
"request": self.request,
"rsvp_deadline": (
current_date + timedelta(days=settings.RSVP_DAYS)
).strftime("%B %-d %Y"),
}

review.application.user.email_user(
Expand Down
Loading