email-templates: Add zulip_onboarding_topics email templates.

The "followup_day2" email template name is not clear or descriptive
about the purpose of the email. Creates a duplicate of those email
template files with the template name "zulip_onboarding_topics".

Because any existing scheduled emails that use the "followup_day2"
templates will need to be updated before the current templates can
be removed, we don't do a simple file rename here.
This commit is contained in:
Lauryn Menard 2023-07-18 11:50:12 +02:00 committed by Tim Abbott
parent c491bef07b
commit 5e29e025c5
9 changed files with 96 additions and 40 deletions

View File

@ -38,7 +38,7 @@ is figuring out how to schedule it. There are 3 ways to schedule email.
email.
- Add it to a queue. An example is the `invitation` email.
- Send it (approximately) at a specified time in the future, using
`send_future_email`. An example is the `followup_day2` email.
`send_future_email`. An example is the `onboarding_zulip_topics` email.
Email takes about a quarter second per email to process and send. Generally
speaking, if you're sending just one email, doing it in the current process

View File

@ -0,0 +1,36 @@
{% extends "zerver/emails/email_base_default.html" %}
{% block illustration %}
<img src="{{ email_images_base_url }}/day2_1.png" alt=""/>
{% endblock %}
{% block content %}
<p>
{{ _("Here are some tips for keeping your Zulip conversations organized with topics.") }}
</p>
<p>
{{ _("In Zulip, <b>streams</b> determine who gets a message. <b>Topics</b> tell you what the message is about.")}} {{ _("Using topics, you can read Zulip one conversation at a time. You'll see each message in context, no matter how many different discussions are going on.") }}
</p>
<img class="responsive-width" src="{{ email_images_base_url }}/streams-and-topics.png" alt="{{ _('Streams and topics in the Zulip app') }}"/>
<p>
{{ _("To kick off a new conversation, just pick a stream and start a new topic. This way, the new conversation thread won't interrupt ongoing discussions. For a good topic name, think about finishing the sentence: “Hey, can we chat about…?”") }}
</p>
<img class="responsive-width" src="{{ email_images_base_url }}/day2_2.png" alt="{{ _('Examples of short topics') }}"/>
<p>
{% trans %}Don't stress about picking the perfect name for your topic. If anything is out of place, it's easy to <a href="{{ move_messages_link }}">move messages</a>, <a href="{{ rename_topics_link }}">rename topics</a>, or even <a href="{{ move_topic_to_different_stream_link }}">move a topic to a different stream</a>.{% endtrans %}
</p>
<a class="button" href="{{ realm_uri }}">{{ _("Go to Zulip") }}</a>
{% endblock %}
{% block manage_preferences %}
<p><a href="{{ unsubscribe_link }}">{% trans %}Unsubscribe from welcome emails for {{ realm_name }}{% endtrans %}</a></p>
{% endblock %}

View File

@ -0,0 +1 @@
{{ _("Keep your conversations organized with topics") }}

View File

@ -0,0 +1,15 @@
{{ _("Here are some tips for keeping your Zulip conversations organized with topics.") }}
{{ _("In Zulip, streams determine who gets a message. Topics tell you what the message is about.") }} {{ _("Using topics, you can read Zulip one conversation at a time. You'll see each message in context, no matter how many different discussions are going on.") }}
{{ _("To kick off a new conversation, just pick a stream and start a new topic. This way, the new conversation thread won't interrupt ongoing discussions. For a good topic name, think about finishing the sentence: “Hey, can we chat about…?”") }}
{% trans %}Don't stress about picking the perfect name for your topic. If anything is out of place, it's easy to move messages ({{ move_messages_link }}), rename topics ({{ rename_topics_link }}), or even move a topic to a different stream ({{ move_topic_to_different_stream_link }}).{% endtrans %}
{{ _("Go to Zulip") }}:
<{{ realm_uri }}>
----
{% trans %}Unsubscribe from welcome emails for {{ realm_name }}{% endtrans %}:
{{ unsubscribe_link }}

View File

@ -693,7 +693,7 @@ def get_onboarding_email_schedule(user: UserProfile) -> Dict[str, timedelta]:
# as our goal is to maximize the chance that this email is near the top
# of the user's inbox when the user sits down to deal with their inbox,
# or comes in while they are dealing with their inbox.
"followup_day2": timedelta(days=2, hours=-1),
"onboarding_zulip_topics": timedelta(days=2, hours=-1),
"onboarding_zulip_guide": timedelta(days=4, hours=-1),
}
@ -708,27 +708,27 @@ def get_onboarding_email_schedule(user: UserProfile) -> Dict[str, timedelta]:
# User signed up on Tuesday
if signup_day == 2:
# Send followup_day2 on Thursday
# Send onboarding_zulip_topics on Thursday
# Send onboarding_zulip_guide on Monday
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
# User signed up on Wednesday
if signup_day == 3:
# Send followup_day2 on Friday
# Send onboarding_zulip_topics on Friday
# Send onboarding_zulip_guide on Tuesday
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
# User signed up on Thursday
if signup_day == 4:
# Send followup_day2 on Monday
onboarding_emails["followup_day2"] = timedelta(days=4, hours=-1)
# Send onboarding_zulip_topics on Monday
onboarding_emails["onboarding_zulip_topics"] = timedelta(days=4, hours=-1)
# Send onboarding_zulip_guide on Wednesday
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
# User signed up on Friday
if signup_day == 5:
# Send followup_day2 on Tuesday
onboarding_emails["followup_day2"] = timedelta(days=4, hours=-1)
# Send onboarding_zulip_topics on Tuesday
onboarding_emails["onboarding_zulip_topics"] = timedelta(days=4, hours=-1)
# Send onboarding_zulip_guide on Thursday
onboarding_emails["onboarding_zulip_guide"] = timedelta(days=6, hours=-1)
@ -829,9 +829,9 @@ def enqueue_welcome_emails(user: UserProfile) -> None:
onboarding_email_schedule = get_onboarding_email_schedule(user)
if other_account_count == 0:
followup_day2_context = common_context(user)
onboarding_zulip_topics_context = common_context(user)
followup_day2_context.update(
onboarding_zulip_topics_context.update(
unsubscribe_link=unsubscribe_link,
move_messages_link=realm_url + "/help/move-content-to-another-topic",
rename_topics_link=realm_url + "/help/rename-a-topic",
@ -839,13 +839,13 @@ def enqueue_welcome_emails(user: UserProfile) -> None:
)
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
user.realm,
to_user_ids=[user.id],
from_name=from_name,
from_address=from_address,
context=followup_day2_context,
delay=onboarding_email_schedule["followup_day2"],
context=onboarding_zulip_topics_context,
delay=onboarding_email_schedule["onboarding_zulip_topics"],
)
# We only send the onboarding_zulip_guide email for a subset of Realm.ORG_TYPES
@ -863,7 +863,7 @@ def enqueue_welcome_emails(user: UserProfile) -> None:
if onboarding_zulip_guide_url is not None:
onboarding_zulip_guide_context = common_context(user)
onboarding_zulip_guide_context.update(
# We use the same unsubscribe link in both followup_day2
# We use the same unsubscribe link in both onboarding_zulip_topics
# and onboarding_zulip_guide as these links do not expire.
unsubscribe_link=unsubscribe_link,
organization_type=organization_type_reference,

View File

@ -4423,6 +4423,7 @@ class ScheduledMessage(models.Model):
EMAIL_TYPES = {
"account_registered": ScheduledEmail.WELCOME,
"onboarding_zulip_topics": ScheduledEmail.WELCOME,
"followup_day1": ScheduledEmail.WELCOME,
"followup_day2": ScheduledEmail.WELCOME,
"onboarding_zulip_guide": ScheduledEmail.WELCOME,

View File

@ -386,7 +386,8 @@ class TestFollowupEmails(ZulipTestCase):
"zerver/emails/account_registered",
)
self.assertEqual(
orjson.loads(scheduled_emails[1].data)["template_prefix"], "zerver/emails/followup_day2"
orjson.loads(scheduled_emails[1].data)["template_prefix"],
"zerver/emails/onboarding_zulip_topics",
)
self.assertEqual(
orjson.loads(scheduled_emails[2].data)["template_prefix"],
@ -412,7 +413,8 @@ class TestFollowupEmails(ZulipTestCase):
"zerver/emails/account_registered",
)
self.assertEqual(
orjson.loads(scheduled_emails[1].data)["template_prefix"], "zerver/emails/followup_day2"
orjson.loads(scheduled_emails[1].data)["template_prefix"],
"zerver/emails/onboarding_zulip_topics",
)
ScheduledEmail.objects.all().delete()
@ -427,7 +429,8 @@ class TestFollowupEmails(ZulipTestCase):
"zerver/emails/account_registered",
)
self.assertEqual(
orjson.loads(scheduled_emails[1].data)["template_prefix"], "zerver/emails/followup_day2"
orjson.loads(scheduled_emails[1].data)["template_prefix"],
"zerver/emails/onboarding_zulip_topics",
)
self.assertEqual(
orjson.loads(scheduled_emails[2].data)["template_prefix"],
@ -574,9 +577,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Monday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Wednesday
# onboarding_zulip_topics email sent on Wednesday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["2"],
)
self.assertEqual((dates_joined["Monday"] + days_delayed["2"]).isoweekday(), 3)
@ -592,9 +595,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Tuesday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Thursday
# onboarding_zulip_topics email sent on Thursday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["2"],
)
self.assertEqual((dates_joined["Tuesday"] + days_delayed["2"]).isoweekday(), 4)
@ -610,9 +613,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Wednesday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Friday
# onboarding_zulip_topics email sent on Friday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["2"],
)
self.assertEqual((dates_joined["Wednesday"] + days_delayed["2"]).isoweekday(), 5)
@ -628,9 +631,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Thursday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Monday
# onboarding_zulip_topics email sent on Monday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["4"],
)
self.assertEqual((dates_joined["Thursday"] + days_delayed["4"]).isoweekday(), 1)
@ -646,9 +649,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Friday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Tuesday
# onboarding_zulip_topics email sent on Tuesday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["4"],
)
self.assertEqual((dates_joined["Friday"] + days_delayed["4"]).isoweekday(), 2)
@ -664,9 +667,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Saturday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Monday
# onboarding_zulip_topics email sent on Monday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["2"],
)
self.assertEqual((dates_joined["Saturday"] + days_delayed["2"]).isoweekday(), 1)
@ -682,9 +685,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = dates_joined["Sunday"]
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Tuesday
# onboarding_zulip_topics email sent on Tuesday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["2"],
)
self.assertEqual((dates_joined["Sunday"] + days_delayed["2"]).isoweekday(), 2)
@ -703,9 +706,9 @@ class TestFollowupEmailDelay(ZulipTestCase):
user_profile.date_joined = datetime(2018, 1, 5, 1, 0, 0, 0, tzinfo=timezone.utc)
onboarding_email_schedule = get_onboarding_email_schedule(user_profile)
# followup_day2 email sent on Monday
# onboarding_zulip_topics email sent on Monday
self.assertEqual(
onboarding_email_schedule["followup_day2"],
onboarding_email_schedule["onboarding_zulip_topics"],
days_delayed["4"],
)

View File

@ -323,7 +323,7 @@ class RealmTest(ZulipTestCase):
def test_do_deactivate_realm_clears_scheduled_jobs(self) -> None:
user = self.example_user("hamlet")
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
user.realm,
to_user_ids=[user.id],
delay=datetime.timedelta(hours=1),

View File

@ -1699,7 +1699,7 @@ class ActivateTest(ZulipTestCase):
def test_clear_scheduled_jobs(self) -> None:
user = self.example_user("hamlet")
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
user.realm,
to_user_ids=[user.id],
delay=datetime.timedelta(hours=1),
@ -1712,7 +1712,7 @@ class ActivateTest(ZulipTestCase):
hamlet = self.example_user("hamlet")
iago = self.example_user("iago")
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
iago.realm,
to_user_ids=[hamlet.id, iago.id],
delay=datetime.timedelta(hours=1),
@ -1728,7 +1728,7 @@ class ActivateTest(ZulipTestCase):
hamlet = self.example_user("hamlet")
iago = self.example_user("iago")
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
iago.realm,
to_user_ids=[hamlet.id, iago.id],
delay=datetime.timedelta(hours=1),
@ -1743,7 +1743,7 @@ class ActivateTest(ZulipTestCase):
iago = self.example_user("iago")
hamlet = self.example_user("hamlet")
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
iago.realm,
to_user_ids=[hamlet.id, iago.id],
delay=datetime.timedelta(hours=1),
@ -1769,7 +1769,7 @@ class ActivateTest(ZulipTestCase):
hamlet = self.example_user("hamlet")
to_user_ids = [hamlet.id, iago.id]
send_future_email(
"zerver/emails/followup_day2",
"zerver/emails/onboarding_zulip_topics",
iago.realm,
to_user_ids=to_user_ids,
delay=datetime.timedelta(hours=1),
@ -1792,7 +1792,7 @@ class ActivateTest(ZulipTestCase):
[
f"WARNING:zulip.send_email:ScheduledEmail {email_id} at {scheduled_at} "
"had empty users and address attributes: "
"{'template_prefix': 'zerver/emails/followup_day2', 'from_name': None, "
"{'template_prefix': 'zerver/emails/onboarding_zulip_topics', 'from_name': None, "
"'from_address': None, 'language': None, 'context': {}}"
],
)