Skip to content

Commit

Permalink
Fully test 1-in-n contests; make improvements/fixes.
Browse files Browse the repository at this point in the history
  • Loading branch information
davepeck committed Apr 25, 2024
1 parent 24cc086 commit 288fbdf
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 40 deletions.
17 changes: 5 additions & 12 deletions server/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,12 @@
EMAIL_USE_TLS = os.getenv("EMAIL_USE_TLS", "false").lower() == "true"
EMAIL_USE_SSL = os.getenv("EMAIL_USE_SSL", "false").lower() == "true"

# Special debug tool: emails matching this pattern will be sent to the
# debug email address instead of the actual recipient. This is useful for
# testing email functionality without spamming real users.
#
# For instance, if DEBUG_EMAIL_STARTSWITH is set to "frontseat@",
# then any email sent to "[email protected]" will instead be sent to
# DEBUG_EMAIL_TO.
DEBUG_EMAIL_STARTSWITH = os.getenv("DEBUG_EMAIL_STARTSWITH", None)
# Special debug tool: emails matching the pattern
# frontseat-<digits>@ will be sent to DEBUG_EMAIL_TO
# instead of the actual recipient. This is useful for testing email
# functionality without spamming real users.
DEBUG_EMAIL_REGEX = r"^frontseat-[a-zA-Z0-9]+@"
DEBUG_EMAIL_TO = os.getenv("DEBUG_EMAIL_TO", None)
if not DEBUG_EMAIL_STARTSWITH or not DEBUG_EMAIL_TO:
DEBUG_EMAIL_STARTSWITH = None
DEBUG_EMAIL_TO = None


# ----------------------------------------------------------------------------
# Logging settings
Expand Down
7 changes: 4 additions & 3 deletions server/utils/email.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dataclasses
import logging
import re
import typing as t

from django.conf import settings
Expand Down Expand Up @@ -109,12 +110,12 @@ def create_message(
html = render_to_string(f"{template_base}/body.dhtml", context)

final_to = list(to)
if settings.DEBUG_EMAIL_STARTSWITH and settings.DEBUG_EMAIL_TO:
if settings.DEBUG_EMAIL_TO:
for i, email in enumerate(final_to):
if email.startswith(settings.DEBUG_EMAIL_STARTSWITH):
if re.match(settings.DEBUG_EMAIL_REGEX, email):
final_to[i] = settings.DEBUG_EMAIL_TO
logger.info(
f"DEBUG_EMAIL_STARTSWITH rerouting email {email} to {settings.DEBUG_EMAIL_TO} with subject: {subject}" # noqa
f"DEBUG_EMAIL rerouting email {email} to {settings.DEBUG_EMAIL_TO} with subject: {subject}" # noqa
)

message = EmailMultiAlternatives(
Expand Down
7 changes: 4 additions & 3 deletions server/vb/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class StudentAdmin(admin.ModelAdmin):
"show_school",
"email",
"show_is_validated",
"contest_entries",
"gift_card_total",
)
search_fields = ("school__name", "email", "first_name", "last_name")
Expand All @@ -184,16 +185,16 @@ def show_is_validated(self, obj: Student) -> bool:
return obj.is_validated

@admin.display(description="Contest Entries")
def contest_entries(self, obj: Student) -> int | None:
def contest_entries(self, obj: Student) -> int | str:
"""Return the number of contest entries the student has made."""
count = obj.contest_entries.count()
return count if count > 0 else None
return count if count > 0 else ""

@admin.display(description="Gift Card Total")
def gift_card_total(self, obj: Student) -> str | None:
"""Return the total number of gift cards the student has received."""
usd = obj.contest_entries.aggregate(total=models.Sum("amount"))["total"] or 0
return f"${usd}" if usd > 0 else None
return f"${usd}" if usd > 0 else ""


class StatusListFilter(admin.SimpleListFilter):
Expand Down
24 changes: 24 additions & 0 deletions server/vb/migrations/0005_rename_related_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 5.0.3 on 2024-04-25 18:40

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('vb', '0004_index_contest_entry_times'),
]

operations = [
migrations.AlterField(
model_name='contestentry',
name='contest',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contest_entries', to='vb.contest'),
),
migrations.AlterField(
model_name='contestentry',
name='student',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='contest_entries', to='vb.student'),
),
]
17 changes: 17 additions & 0 deletions server/vb/migrations/0006_alter_contestentry_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 5.0.3 on 2024-04-25 18:57

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('vb', '0005_rename_related_fields'),
]

operations = [
migrations.AlterModelOptions(
name='contestentry',
options={'verbose_name_plural': 'Contest entries'},
),
]
6 changes: 4 additions & 2 deletions server/vb/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,10 +425,10 @@ class ContestEntry(models.Model):
created_at = models.DateTimeField(auto_now_add=True, db_index=True)

student = models.ForeignKey(
Student, on_delete=models.CASCADE, related_name="gift_cards"
Student, on_delete=models.CASCADE, related_name="contest_entries"
)
contest = models.ForeignKey(
Contest, on_delete=models.CASCADE, related_name="gift_cards"
Contest, on_delete=models.CASCADE, related_name="contest_entries"
)

# The prize, if any, is a gift card.
Expand All @@ -453,6 +453,8 @@ def is_winner(self) -> bool:
class Meta:
"""Define the contest entry model's meta options."""

verbose_name_plural = "Contest entries"

constraints = [
models.UniqueConstraint(
fields=["student", "contest"],
Expand Down
2 changes: 1 addition & 1 deletion server/vb/ops.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def send_validation_link_email(
if contest.is_giveaway:
button_text = f"Get my ${contest.amount} gift card"
else:
button_text = f"Enter to win a ${contest.amount} gift card"
button_text = f"See if I won a ${contest.amount} gift card"
else:
button_text = "Validate my email"
success = send_template_email(
Expand Down
7 changes: 3 additions & 4 deletions server/vb/templates/email/validate/body.dhtml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@
Thanks for checking your voter registration status! Click this button to
{% if contest %}
{% if contest.is_giveaway %}
get your gift card
get your gift card.
{% else %}
enter to win a gift card
see if you won.
{% endif %}
{% else %}
validate your email address
validate your email address.
{% endif %}
.
{% include "email/base/p_close.html" %}
{% include "email/base/button.html" with url=link.relative_url title=button_text %}
{% endblock message %}
2 changes: 1 addition & 1 deletion server/vb/templates/email/validate/body.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Thanks for checking your voter registration status! You're almost done.

{% if contest %}Click this link to {% if contest.is_giveaway %}get your ${{ contest.amount }} gift card{% else %}enter to win a ${{ contest.amount }} gift card:{% endif %}{% else %}Click this link to validate your email address:{% endif %}
{% if contest %}Click this link to {% if contest.is_giveaway %}get your ${{ contest.amount }} gift card{% else %}see if you won a ${{ contest.amount }} gift card:{% endif %}{% else %}Click this link to validate your email address:{% endif %}

{{ link.absolute_url }}
{% endblock message %}
2 changes: 1 addition & 1 deletion server/vb/templates/finish_check.dhtml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{% if current_contest.is_giveaway %}
claim your ${{ current_contest.amount }}
{% else %}
enter to win a ${{ current_contest.amount }}
see if you won a ${{ current_contest.amount }}
{% endif %}
gift card.
{% else %}
Expand Down
35 changes: 22 additions & 13 deletions server/vb/templates/verify_email.dhtml
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,20 @@
background-color: black;
}
</style>
<div>
<div data-bg-color="{{ school.logo.bg_color }}"
data-color="{{ school.logo.bg_text_color }}">
<style>
me {
--main-color: transparent;
--main-bg-color: transparent;
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
}

me a {
color: white;
color: var(--main-color);
text-decoration: underline;
transition: opacity 0.2s;
}
Expand Down Expand Up @@ -68,12 +71,17 @@
margin: 1.5rem 0;
}
</style>
<main data-bg-color="{{ school.logo.bg_color }}"
data-color="{{ school.logo.bg_text_color }}">
<script>
(function(self) {
onloadAdd(() => {
self.style.setProperty('--main-color', self.dataset.color);
self.style.setProperty('--main-bg-color', self.dataset.bgColor);
});
})(me());
</script>
<main>
<style>
me {
--main-color: transparent;
--main-bg-color: transparent;
color: var(--main-color);
background-color: var(--main-bg-color);
}
Expand Down Expand Up @@ -130,14 +138,14 @@
}
</style>
<script>
(function() {
const self = me();
(function(self) {
onloadAdd(() => {
self.style.setProperty('--main-color', self.dataset.color);
self.style.setProperty('--main-bg-color', self.dataset.bgColor);
const clipboard = self.querySelector(".clipboard");
const copied = self.querySelector(".copied");
const code = self.querySelector(".code");
if (!clipboard || !copied || !code) {
return;
}
clipboard.addEventListener("click", () => {
navigator.clipboard.writeText(code.innerText);
// hide the `clipboard` span; show the `copied` span
Expand All @@ -147,7 +155,7 @@
copied.classList.remove("hidden");
});
});
})();
})(me());
</script>
<div class="container">
<img src="{{ school.logo.url }}"
Expand All @@ -168,9 +176,10 @@
{% elif contest_entry %}
<p>Thanks for entering the Voter Bowl!</p>
<p>
Alas, you didn't win a gift card this time.
Alas, you didn't win a gift card.
{% if most_recent_winner %}
(Your schoolmate {{ most_recent_winner.anonymized_name }} won just {{ most_recent_winner.created_at|timesince }} ago.)
<br />
(Your schoolmate {{ most_recent_winner.student.anonymized_name }} won just {{ most_recent_winner.created_at|timesince }} ago.)
{% endif %}
</p>
<p>
Expand Down

0 comments on commit 288fbdf

Please sign in to comment.