Create custom Text Me the App landing page.
Rebrand the branch.io text me the app landing page to reflect edX's style. LEARNER-2730
This commit is contained in:
@@ -11,6 +11,7 @@ import pytz
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.test import RequestFactory, TestCase
|
from django.test import RequestFactory, TestCase
|
||||||
|
from django.test.utils import override_settings
|
||||||
from edx_oauth2_provider.constants import AUTHORIZED_CLIENTS_SESSION_KEY
|
from edx_oauth2_provider.constants import AUTHORIZED_CLIENTS_SESSION_KEY
|
||||||
from edx_oauth2_provider.tests.factories import ClientFactory, TrustedClientFactory
|
from edx_oauth2_provider.tests.factories import ClientFactory, TrustedClientFactory
|
||||||
from milestones.tests.utils import MilestonesTestCaseMixin
|
from milestones.tests.utils import MilestonesTestCaseMixin
|
||||||
@@ -28,6 +29,7 @@ from student.models import CourseEnrollment, UserProfile
|
|||||||
from student.signals import REFUND_ORDER
|
from student.signals import REFUND_ORDER
|
||||||
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
||||||
from util.milestones_helpers import get_course_milestones, remove_prerequisite_course, set_prerequisite_courses
|
from util.milestones_helpers import get_course_milestones, remove_prerequisite_course, set_prerequisite_courses
|
||||||
|
from util.testing import UrlResetMixin
|
||||||
from xmodule.modulestore import ModuleStoreEnum
|
from xmodule.modulestore import ModuleStoreEnum
|
||||||
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
|
||||||
from xmodule.modulestore.tests.factories import CourseFactory
|
from xmodule.modulestore.tests.factories import CourseFactory
|
||||||
@@ -398,3 +400,13 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
|
|||||||
response = self.client.get(self.path)
|
response = self.client.get(self.path)
|
||||||
self.assertEqual(response.content.count('<li class="course-item">'), 1)
|
self.assertEqual(response.content.count('<li class="course-item">'), 1)
|
||||||
self.assertIn('<button class="change-session btn-link "', response.content)
|
self.assertIn('<button class="change-session btn-link "', response.content)
|
||||||
|
|
||||||
|
|
||||||
|
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
|
||||||
|
@override_settings(BRANCH_IO_KEY='test_key')
|
||||||
|
class TextMeTheAppViewTests(UrlResetMixin, TestCase):
|
||||||
|
""" Tests for the TextMeTheAppView. """
|
||||||
|
|
||||||
|
def test_text_me_the_app(self):
|
||||||
|
response = self.client.get(reverse('text_me_the_app'))
|
||||||
|
self.assertContains(response, 'Send me a text with the link')
|
||||||
|
|||||||
21
common/djangoapps/student/text_me_the_app.py
Normal file
21
common/djangoapps/student/text_me_the_app.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
"""
|
||||||
|
Fragment for rendering text me the app.
|
||||||
|
"""
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
from web_fragments.fragment import Fragment
|
||||||
|
|
||||||
|
from openedx.core.djangoapps.plugin_api.views import EdxFragmentView
|
||||||
|
|
||||||
|
|
||||||
|
class TextMeTheAppFragmentView(EdxFragmentView):
|
||||||
|
"""
|
||||||
|
A fragment to text me the app.
|
||||||
|
|
||||||
|
In future we can add this to learner dashboard.
|
||||||
|
"""
|
||||||
|
def render_to_fragment(self, request, **kwargs):
|
||||||
|
"""
|
||||||
|
Render text me the app fragment.
|
||||||
|
"""
|
||||||
|
html = render_to_string('learner_dashboard/text-me-fragment.html', {})
|
||||||
|
return Fragment(html)
|
||||||
@@ -125,6 +125,7 @@ from student.models import (
|
|||||||
)
|
)
|
||||||
from student.signals import REFUND_ORDER
|
from student.signals import REFUND_ORDER
|
||||||
from student.tasks import send_activation_email
|
from student.tasks import send_activation_email
|
||||||
|
from student.text_me_the_app import TextMeTheAppFragmentView
|
||||||
from third_party_auth import pipeline, provider
|
from third_party_auth import pipeline, provider
|
||||||
from util.bad_request_rate_limiter import BadRequestRateLimiter
|
from util.bad_request_rate_limiter import BadRequestRateLimiter
|
||||||
from util.db import outer_atomic
|
from util.db import outer_atomic
|
||||||
@@ -3062,3 +3063,19 @@ class LogoutView(TemplateView):
|
|||||||
})
|
})
|
||||||
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ensure_csrf_cookie
|
||||||
|
def text_me_the_app(request):
|
||||||
|
"""
|
||||||
|
Text me the app view.
|
||||||
|
"""
|
||||||
|
text_me_fragment = TextMeTheAppFragmentView().render_to_fragment(request)
|
||||||
|
context = {
|
||||||
|
'nav_hidden': True,
|
||||||
|
'show_dashboard_tabs': True,
|
||||||
|
'show_program_listing': ProgramsApiConfig.is_enabled(),
|
||||||
|
'fragment': text_me_fragment
|
||||||
|
}
|
||||||
|
|
||||||
|
return render_to_response('text-me-the-app.html', context)
|
||||||
|
|||||||
@@ -62,6 +62,7 @@
|
|||||||
@import "views/financial-assistance";
|
@import "views/financial-assistance";
|
||||||
@import 'course/auto-cert';
|
@import 'course/auto-cert';
|
||||||
@import 'views/api-access';
|
@import 'views/api-access';
|
||||||
|
@import 'views/text-me-the-app';
|
||||||
|
|
||||||
// features
|
// features
|
||||||
@import 'features/bookmarks-v1';
|
@import 'features/bookmarks-v1';
|
||||||
|
|||||||
86
lms/static/sass/views/_text-me-the-app.scss
Normal file
86
lms/static/sass/views/_text-me-the-app.scss
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
.text-me-content {
|
||||||
|
@include box-sizing(border-box);
|
||||||
|
@include outer-container;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
background: $white;
|
||||||
|
display: block;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
-webkit-flex-wrap: wrap;
|
||||||
|
-moz-flex-wrap: wrap;
|
||||||
|
|
||||||
|
.text-me-container {
|
||||||
|
$grid-columns: 12;
|
||||||
|
|
||||||
|
background: $white;
|
||||||
|
min-height: 100%;
|
||||||
|
padding-left: ($baseline/2);
|
||||||
|
padding-right: ($baseline/2);
|
||||||
|
padding-top: ($baseline*6);
|
||||||
|
padding-bottom: ($baseline*6);
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
max-width: 350px;
|
||||||
|
min-width: 250px;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-me-fragment {
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
@extend %t-title4;
|
||||||
|
|
||||||
|
letter-spacing: normal;
|
||||||
|
font-family: $font-family-sans-serif;
|
||||||
|
color: $uxpl-blue-hover-active;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
@extend %t-title6;
|
||||||
|
@extend %t-light;
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
letter-spacing: normal;
|
||||||
|
font-family: $font-family-sans-serif;
|
||||||
|
color: $uxpl-gray-dark;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
@include clearfix();
|
||||||
|
|
||||||
|
clear: both;
|
||||||
|
|
||||||
|
.form-field {
|
||||||
|
@include clearfix();
|
||||||
|
|
||||||
|
clear: both;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
margin: ($baseline/2) 0 0 0;
|
||||||
|
|
||||||
|
label, input {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
line-height: 1.5em;
|
||||||
|
border-radius: 0;
|
||||||
|
font-family: $font-family-sans-serif;
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: font-weight(normal);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-primary {
|
||||||
|
@extend %btn-primary-blue;
|
||||||
|
|
||||||
|
padding: 1ex 1em;
|
||||||
|
text-transform: none;
|
||||||
|
font-weight: font-weight(semi-bold);
|
||||||
|
letter-spacing: normal;
|
||||||
|
margin-top: $baseline;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
lms/templates/learner_dashboard/text-me-fragment.html
Normal file
54
lms/templates/learner_dashboard/text-me-fragment.html
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
## mako
|
||||||
|
|
||||||
|
<%page expression_filter="h"/>
|
||||||
|
|
||||||
|
<%namespace name='static' file='/static_content.html'/>
|
||||||
|
|
||||||
|
<%!
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from openedx.core.djangolib.js_utils import js_escaped_string
|
||||||
|
%>
|
||||||
|
|
||||||
|
<%block name="headextra">
|
||||||
|
<script type="text/javascript">
|
||||||
|
(function(b,r,a,n,c,h,_,s,d,k){if(!b[n]||!b[n]._q){for(;s<_.length;)c(h,_[s++]);d=r.createElement(a);d.async=1;d.src="https://cdn.branch.io/branch-latest.min.js";k=r.getElementsByTagName(a)[0];k.parentNode.insertBefore(d,k);b[n]=h}})(window,document,"script","branch",function(b,r){b[r]=function(){b._q.push([r,arguments])}},{_q:[],_v:1},"addListener applyCode banner closeBanner creditHistory credits data deepview deepviewCta first getCode init link logout redeem referrals removeListener sendSMS setBranchViewData setIdentity track validateCode".split(" "), 0);
|
||||||
|
branch.init('${static.get_value("BRANCH_IO_KEY", settings.BRANCH_IO_KEY) | n, js_escaped_string}');
|
||||||
|
function sendSMS(form) {
|
||||||
|
var phone = form.phone.value;
|
||||||
|
var linkData = {
|
||||||
|
tags: [],
|
||||||
|
channel: 'Website',
|
||||||
|
feature: 'TextMeTheApp',
|
||||||
|
data: {}
|
||||||
|
};
|
||||||
|
var options = {};
|
||||||
|
var callback = function(err, result) {
|
||||||
|
if (err) {
|
||||||
|
alert(gettext("Sorry, something went wrong."));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
alert(gettext("SMS sent!"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
branch.sendSMS(phone, linkData, options, callback);
|
||||||
|
form.phone.value = "";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</%block>
|
||||||
|
|
||||||
|
<section class="text-me-fragment">
|
||||||
|
<h2>${_("Get the {platform_name} Mobile App!").format(platform_name=static.get_platform_name())}</h2>
|
||||||
|
<h3>${_("We'll send you a one time SMS with a link to download the app.")}</h3>
|
||||||
|
<form onsubmit="sendSMS(this); return false;">
|
||||||
|
<div class="form-field">
|
||||||
|
<label class="label">${_("Mobile phone number")}</label>
|
||||||
|
<input id="phone" name="phone" type="tel" placeholder="+1 (123) 123-1234" />
|
||||||
|
</div>
|
||||||
|
<div class="form-field">
|
||||||
|
<button class="action action-primary" type="submit">
|
||||||
|
<span class="fa fa-send"></span>
|
||||||
|
<span class="action-text">${_("Send me a text with the link")}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
20
lms/templates/text-me-the-app.html
Normal file
20
lms/templates/text-me-the-app.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
## mako
|
||||||
|
|
||||||
|
<%page expression_filter="h"/>
|
||||||
|
<%inherit file="main.html" />
|
||||||
|
<%namespace name='static' file='static_content.html'/>
|
||||||
|
|
||||||
|
<%!
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
from openedx.core.djangolib.markup import HTML
|
||||||
|
%>
|
||||||
|
|
||||||
|
<%block name="title">
|
||||||
|
<title>${_("Text Me The App")}</title>
|
||||||
|
</%block>
|
||||||
|
|
||||||
|
<div class="text-me-content">
|
||||||
|
<div class="container text-me-container">
|
||||||
|
${HTML(fragment.body_html())}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -1075,3 +1075,9 @@ if settings.FEATURES.get('ENABLE_FINANCIAL_ASSISTANCE_FORM'):
|
|||||||
name='submit_financial_assistance_request'
|
name='submit_financial_assistance_request'
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Branch.io Text Me The App
|
||||||
|
if settings.BRANCH_IO_KEY:
|
||||||
|
urlpatterns += [
|
||||||
|
url(r'^text-me-the-app', 'student.views.text_me_the_app', name='text_me_the_app'),
|
||||||
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user