Merge pull request #36897 from openedx/sundas/INF-1919

feat: implemented self paced email UI
This commit is contained in:
sundasnoreen12
2025-06-16 11:20:56 +05:00
committed by GitHub
8 changed files with 484 additions and 27 deletions

View File

@@ -5411,6 +5411,10 @@ NOTIFICATION_TYPE_ICONS = {}
DEFAULT_NOTIFICATION_ICON_URL = ""
NOTIFICATION_DIGEST_LOGO = DEFAULT_EMAIL_LOGO_URL
############## SELF PACED EMAIL ##############
SELF_PACED_BANNER_URL = ""
SELF_PACED_CLOUD_URL = ""
############## NUDGE EMAILS ###############
# .. setting_name: DISABLED_ORGS_FOR_PROGRAM_NUDGE
# .. setting_default: []

View File

@@ -548,6 +548,8 @@ class CourseNextSectionUpdate(PrefixedDebugLoggerMixin, RecipientResolver):
'course_id': str(course.id),
'course_ids': [str(course.id)],
'unsubscribe_url': unsubscribe_url,
'self_paced_banner_url': settings.SELF_PACED_BANNER_URL,
'self_paced_cloud_url': settings.SELF_PACED_CLOUD_URL,
})
template_context.update(_get_upsell_information_for_schedule(user, schedule))

View File

@@ -0,0 +1,91 @@
{% load django_markup %}
{% load i18n %}
<!-- These tags come from the ace_common djangoapp in edx ace -->
{% load ace %}
<!-- These tags come from the edx_ace app within the edx_ace repository -->
{% load acetags %}
{% get_current_language as LANGUAGE_CODE %}
{% get_current_language_bidi as LANGUAGE_BIDI %}
{# This is preview text that is visible in the inbox view of many email clients but not visible in the actual #}
{# email itself. #}
<div lang="{{ LANGUAGE_CODE|default:"en" }}" style="
display:none;
font-size:1px;
line-height:1px;
max-height:0px;
max-width:0px;
opacity:0;
overflow:hidden;
visibility:hidden;
">
{% block preview_text %}{% endblock %}
</div>
{% for image_src in channel.tracker_image_sources %}
<img src="{image_src}" alt="" role="presentation" aria-hidden="true" />
{% endfor %}
{% google_analytics_tracking_pixel %}
<div bgcolor="#F2F0EF" lang="{{ LANGUAGE_CODE|default:"en" }}" dir="{{ LANGUAGE_BIDI|yesno:"rtl,ltr" }}" style="
margin: 0;
padding: 0;
min-width: 100%;
">
<!-- Hack for outlook 2010, which wants to render everything in Times New Roman -->
<!--[if mso]>
<style type="text/css">
body, table, td {font-family: Arial, sans-serif !important;}
</style>
<![endif]-->
<!--[if (gte mso 9)|(IE)]>
<table role="presentation" width="600" align="center" cellpadding="0" cellspacing="0" border="0">
<tr>
<td>
<![endif]-->
<!-- CONTENT -->
<table class="content" role="presentation" align="center" cellpadding="0" cellspacing="0" border="0" bgcolor="#fbfaf9" width="100%"
{% block table_style %}
style="
font-family: Arial, sans-serif;
font-size: 1em;
line-height: 1.5;
max-width: 600px;
"
{% endblock %}
>
<tr>
<!-- HEADER -->
<td class="header" style="background-color: #F2F0EF;">
{% block header %}{% endblock %}
</td>
</tr>
<tr>
<!-- MAIN -->
<td class="main" bgcolor="#ffffff">
{% block content %}{% endblock %}
</td>
</tr>
<tr>
<!-- FOOTER -->
<td class="footer" style="padding: 30px; background-color: #F2F0EF;">
{% block footer %}{% endblock %}
</td>
</tr>
</table>
<!--[if (gte mso 9)|(IE)]>
</td>
</tr>
</table>
<![endif]-->
</div>

View File

@@ -1,6 +1,8 @@
{% extends 'ace_common/edx_ace/common/base_body.html' %}
{% extends 'schedules/edx_ace/courseupdate/email/base_body.html' %}
{% load i18n %}
{% load django_markup %}
{% load static %}
{% block preview_text %}
{% filter force_escape %}
@@ -11,38 +13,123 @@
{% endblock %}
{% block content %}
<table width="100%" align="left" border="0" cellpadding="0" cellspacing="0" role="presentation">
<table width="100%" style="margin-bottom: 30px;" align="left" border="0" cellpadding="0" cellspacing="0" role="presentation">
<style>
.course-text{
span{
padding-left: 12px;
padding-right: 12px;
padding-top: 10px;
padding-bottom: 10px;
}
}
</style>
{% if route_enabled %}
<tr>
<td>
<p>
{% blocktrans trimmed asvar tmsg %}
We hope you're enjoying {start_strong}{course_name}{end_strong}!
We want to let you know what you can look forward to in week {week_num}:
{% endblocktrans %}
{% interpolate_html tmsg start_strong='<strong>'|safe end_strong='</strong>'|safe course_name=course_name|force_escape|safe week_num=week_num|force_escape|safe %}
<ul>
{% for highlight in week_highlights %}
<li>{{ highlight }}</li>
{% endfor %}
</ul>
</p>
<p>
{% filter force_escape %}
{% blocktrans trimmed %}
With self-paced courses, you learn on your own schedule.
We encourage you to spend time with the course each week.
Your focused attention will pay off in the end!
{% endblocktrans %}
{% blocktrans %}This is a routed Account Activation email for {{ routed_profile_name }} ({{ routed_user_email }}): {{ routed_profile_name }}{% endblocktrans %}
{% endfilter %}
<br />
</p>
{% filter force_escape %}
{% blocktrans asvar course_cta_text %}Resume your course now{% endblocktrans %}
{% endfilter %}
{% include "ace_common/edx_ace/common/return_to_course_cta.html" with course_cta_text=course_cta_text%}
{% include "ace_common/edx_ace/common/upsell_cta.html"%}
</td>
</tr>
{% endif %}
<tr>
<td>
<img
src="{{ self_paced_banner_url }}"
style="margin-bottom: 16px; width: 600px;"
width= "600"
height="265"
alt="{% trans 'Welcome to edX. Its time for your next career move' as tmsg %}{{ tmsg | force_escape }}"
/>
</td>
</tr>
<tr>
<td>
<p style="margin-top: 16px; color: #1F453D; font-family: Arial; font-size: 30px; font-weight: 700; line-height: 36px; margin-left: 30px;">
{% trans "We hope youre enjoying Introduction to Data Science with Python!" as tmsg %}{{ tmsg | force_escape }}
</p>
<p style="margin-top: 16px; color: #000000; font-family: Arial; font-size: 16px; font-weight: 400; line-height: 24px; margin-left: 30px;">
{% trans "We want to let you know what you can look forward to in week two: " as tmsg %}{{ tmsg | force_escape }}
</p>
<ul style="margin-bottom: 16px; list-style: disc;">
<li>
<p>
{% trans "Learn kNN regression" as tmsg %}{{ tmsg | force_escape }}
</p>
</li>
<li>
<p>
{% trans "Learn linear regression" as tmsg %}{{ tmsg | force_escape }}
</p>
</li>
<li>
<p>
{% trans "Find out how to choose which model you want" as tmsg %}{{ tmsg | force_escape }}
</p>
</li>
</ul>
</td>
</tr>
<tr style="height: 32px;">
<td style="padding-top: 1rem;" class="course-text">
{% filter force_escape %}
{% blocktrans asvar course_cta_text %}Resume your course {% endblocktrans %}
{% endfilter %}
{% include "schedules/edx_ace/courseupdate/email/return_to_course_cta.html" with course_cta_text=course_cta_text%}
</td>
</tr>
<tr>
<td style="height: 32px; line-height: 32px; font-size: 1px;">
&nbsp;
</td>
</tr>
<tr style="background-color: #F3F1ED;">
<td>
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="max-width: 540px; border-radius: 8px;" bgcolor="#F3F1ED" class="goals-engage-table" align="left">
<!-- Row 1: Image and title -->
<!--[if mso]>
<tr>
<td style="width: 400px; color: #1F453D; font-size: 16px; font-family: Arial, Helvetica, sans-serif; font-weight: 400; line-height: 24px; width: 100%;">
<p style="padding: 20px 30px; margin-left: 30px">
<strong>
{% trans "Your focused attention will pay off in the end!" as tmsg %}{{ tmsg | force_escape }}
</strong>
{% trans "With self-paced courses, you learn on your own schedule. Its a good idea to spend time with the course each week and check in with your goals often." as tmsg %}{{ tmsg | force_escape }}
</p>
</td>
<td width="120" style="width: 120px; padding: 0; margin: 0; vertical-align: top;">
<img src="{{ self_paced_cloud_url }}"
alt="Message Icon"
width="120"
height="158"
style="display: block; border: 0; margin: 0; padding: 0; width: 120px; height: 158px; max-width: 120px !important; max-height: 158px !important;" />
</td>
</tr>
<![endif]-->
<!--[if !mso]><!-->
<tr>
<td style="width: 400px; color: #1F453D; font-size: 16px; font-family: Arial, sans-serif; font-weight: 400; line-height: 24px;">
<p style="padding: 20px 30px; margin: 0px;">
<strong> {% trans "Your focused attention will pay off in the end! " as tmsg %}{{ tmsg | force_escape }} </strong>
{% trans "With self-paced courses, you learn on your own schedule. Its a good idea to spend time with the course each week and check in with your goals often." as tmsg %}{{ tmsg | force_escape }}
</p>
</td>
<td style="padding: 0; margin: 0;" align="left" valign="top">
<img src="{{ self_paced_cloud_url }}" alt="Message Icon" style="display: block; border: 0; margin: 0; padding: 0; width: 120px; height: 158px; margin-top: -40px;">
</td>
</tr>
<!--<![endif]-->
</table>
</td>
</tr>
</table>
{% endblock %}
{% block footer%}
{%include 'schedules/edx_ace/courseupdate/email/footer.html'%}
{% endblock%}

View File

@@ -0,0 +1,195 @@
{% load django_markup %}
{% load i18n %}
{% load ace %}
{% load acetags %}
{% load static %}
<table role="presentation" width="100%" align="left" border="0" cellpadding="0" cellspacing="0">
<style>
.hyperlink {
color: #00688d;
text-decoration: none;
background-color: transparent;
}
.hyperlink:hover {
color: #004972 !important;
text-decoration: underline !important;
}
</style>
{% if confirm_activation_link %}
{% endif %}
<tr>
<td>
<!-- SOCIAL -->
<table role="presentation" align="{{ LANGUAGE_BIDI|yesno:"right,left" }}" border="0" border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="top">
<table cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="top" style="padding: 0px 15px;">
<table cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="top">
<table cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="top">
<!-- logo -->
<table align="left" cellpadding="0" cellspacing="0" class="width_100percent">
<tbody>
<tr>
<td align="center" valign="top">
<a href="{% with_link_tracking homepage_url %}">
<img src="{{ logo_url }}" width="92" height="65" alt="{% filter force_escape %}{% blocktrans %}Go to {{ platform_name }} Home Page{% endblocktrans %}{% endfilter %}"/></a>
</td>
</tr>
</tbody>
</table>
<table align="right" cellpadding="0" cellspacing="0" class="width_100percent">
<tbody>
<tr>
<td align="center" class="paddingtop_20 height_0" height="66" valign="middle">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr>
{% if social_media_urls.facebook %}
<td height="32" width="35">
<a href="{{ social_media_urls.facebook|safe }}">
<img src="http://email-media.s3.amazonaws.com/edX/2021/social_1_fb.png"
width="25" height="25" alt="{% filter force_escape %}{% blocktrans %}{{ platform_name }} on Facebook{% endblocktrans %}{% endfilter %}"/>
</a>
</td>
{% endif %}
{% if social_media_urls.instagram %}
<td height="32" width="35">
<a href="{{ social_media_urls.instagram|safe }}">
<img src="http://email-media.s3.amazonaws.com/edX/2021/social_4_insta.png"
width="25" height="25" alt="{% filter force_escape %}{% blocktrans %}{{ platform_name }} on Facebook{% endblocktrans %}{% endfilter %}"/>
</a>
</td>
{% endif %}
{% if social_media_urls.linkedin %}
<td height="32" width="35">
<a href="{{ social_media_urls.linkedin|safe }}">
<img src="http://email-media.s3.amazonaws.com/edX/2021/social_3_linkedin.png"
width="25" height="25" alt="{% filter force_escape %}{% blocktrans %}{{ platform_name }} on LinkedIn{% endblocktrans %}{% endfilter %}"/>
</a>
</td>
{% endif %}
{% if social_media_urls.twitter %}
<td height="32" width="35">
<a href="{{ social_media_urls.twitter|safe }}">
<img src="http://email-media.s3.amazonaws.com/edX/2021/social_2_twitter.png"
width="25" height="25" alt="{% filter force_escape %}{% blocktrans %}{{ platform_name }} on Twitter{% endblocktrans %}{% endfilter %}"/>
</a>
</td>
{% endif %}
{% if social_media_urls.reddit %}
<td height="32" width="35">
<a href="{{ social_media_urls.reddit|safe }}">
<img src="http://email-media.s3.amazonaws.com/edX/2021/social_5_reddit.png"
width="25" height="25" alt="{% filter force_escape %}{% blocktrans %}{{ platform_name }} on Reddit{% endblocktrans %}{% endfilter %}"/>
</a>
</td>
{% endif %}
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td height="20" style="line-height:1px;font-size:1px;"></td>
</tr>
<!-- APP BUTTONS -->
<tr>
<td align="left" valign="top" style="padding: 0px 15px;">
<table cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr>
<td align="left" valign="top">
<table align="left" cellpadding="0" cellspacing="0" class="width_100percent">
<tbody>
<tr>
<td align="center" valign="top">
<table cellpadding="0" cellspacing="0">
<tbody>
<tr>
{% if mobile_store_urls.apple %}
<td align="left" valign="top">
<a href="{{ mobile_store_urls.apple|safe }}" style="text-decoration: none">
<img src="http://email-media.s3.amazonaws.com/edX/2021/store_apple_229x78.jpg"
alt="{% trans "Download the iOS app on the Apple Store" as tmsg %}{{ tmsg | force_escape }}"
border="0" height="32" style="display:block;" width="95.135" /></a>
</a>
</td>
{% endif %}
<td width="20"></td>
{% if mobile_store_urls.google %}
<td align="left" valign="top">
<a href="{{ mobile_store_urls.google|safe }}" style="text-decoration: none">
<img src="http://email-media.s3.amazonaws.com/edX/2021/store_google_253x78.jpg"
alt="{% trans "Download the Android app on the Google Play Store" as tmsg %}{{ tmsg | force_escape }}"
border="0" height="32" style="display:block;" width="108.108" /></a>
</a>
</td>
{% endif %}
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td height="24" style="line-height:1px;font-size:1px;"></td>
</tr>
<tr>
<!-- COPYRIGHT -->
<td align="left" class="fallback_font" style="font-family:Arial,sans-serif;font-size:14px;line-height:21px;color:#000000;font-style: normal;font-weight: 400;" valign="top">
{% if disclaimer %}
{{ disclaimer }}<br/>
{% endif %}
{% trans "edX is the trusted platform for education and learning" as tmsg %}{{ tmsg | force_escape }}.<br/>
<br/>
&copy; {% now "Y" %} {{ platform_name }} LLC. {% trans "All rights reserved" as tmsg %}{{ tmsg | force_escape }}.<br/>
<br/>
{% if unsubscribe_link %}
<a href="{% with_link_tracking unsubscribe_link %}" style="color: #000000;">
{%if unsubscribe_text%} {{unsubscribe_text}} {%else%} {% trans "Unsubscribe from these emails." as tmsg %}{{ tmsg | force_escape }} {%endif%}
</a><br/>
<br/>
{% endif %}
{{ contact_mailing_address }}
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</table>

View File

@@ -1 +1,40 @@
{% extends 'ace_common/edx_ace/common/base_head.html' %}
{% load django_markup %}
{% load i18n %}
{% load ace %}
{% load acetags %}
{% load static %}
<table width="600" border="0" cellspacing="0" cellpadding="0" align="center" bgcolor="#F2F0EF">
<tr>
<td valign="top" align="center">
<table width="600" cellpadding="0" cellspacing="0" align="center" class="width_100percent">
<tr>
<td valign="top" align="center" style="max-width:600px;" class="min_width">
<table width="100%" cellpadding="0" cellspacing="0" bgcolor="#F2F0EF">
<tr><td height="20" style="line-height:1px;">&nbsp;</td></tr>
<tr>
<td align="center" valign="top" style="padding:0 60px;" class="padding_none">
<table cellpadding="0" cellspacing="0" align="center" class="width_100percent">
<tr>
<td align="center" valign="top">
<table cellpadding="0" cellspacing="0">
<tr>
<td align="center" valign="top">
<a href="{% with_link_tracking homepage_url %}">
<img src="{{ logo_url }}" width="92" height="65" alt="{% filter force_escape %}{% blocktrans %}Go to {{ platform_name }} Home Page{% endblocktrans %}{% endfilter %}"/></a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
<tr><td height="20" style="line-height:1px;font-size:1px;">&nbsp;</td></tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>

View File

@@ -0,0 +1,35 @@
{% load i18n %}
{% load ace %}
<p>
{# email client support for style sheets is pretty spotty, so we have to inline all of these styles #}
<a
{% if reset_url %}
href={{reset_url}}
{% elif course_cta_url %}
href="{% with_link_tracking course_cta_url %}"
{% else %}
{%if course_ids|length > 1 %}
href="{% with_link_tracking dashboard_url %}"
{% else %}
href="{% with_link_tracking course_url %}"
{% endif %}
{% endif %}
style="
text-decoration: none;
color: white;
background-color: #ED5C13;
text-align: center;
vertical-align: middle;
user-select: none;
font-weight: 500;
font-size: 12px;
text-decoration-style: solid;
display: inline-flex;
flex-direction: row;
border-radius: 30.22px;
">
{# old email clients require the use of the font tag :( #}
<span color="#ffffff"><b>{{ course_cta_text }}</b></span>
</a>
</p>

View File

@@ -271,6 +271,8 @@ class TestCourseNextSectionUpdateResolver(SchedulesResolverTestMixin, ModuleStor
@override_settings(CONTACT_MAILING_ADDRESS='123 Sesame Street')
@override_settings(LOGO_URL_PNG='https://www.logo.png')
@override_settings(SELF_PACED_BANNER_URL='')
@override_settings(SELF_PACED_CLOUD_URL='')
def test_schedule_context(self):
resolver = self.create_resolver()
# using this to make sure the select_related stays intact
@@ -316,6 +318,8 @@ class TestCourseNextSectionUpdateResolver(SchedulesResolverTestMixin, ModuleStor
'twitter': twitter_url},
'template_revision': 'release',
'unsubscribe_url': None,
'self_paced_banner_url': '',
'self_paced_cloud_url': '',
'week_highlights': ['good stuff 2'],
'week_num': 2,
}