Commit 30eba50b by Saleem Latif

Success Message for Account Activation for logged in users

parent 73c41388
<%page expression_filter="h"/> <%page expression_filter="h"/>
<%inherit file="../main.html" /> <%inherit file="../base.html" />
<%namespace name='static' file='../static_content.html'/> <%namespace name='static' file='../static_content.html'/>
<%! <%!
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
...@@ -7,21 +7,23 @@ from django.core.urlresolvers import reverse ...@@ -7,21 +7,23 @@ from django.core.urlresolvers import reverse
from openedx.core.djangolib.markup import HTML, Text from openedx.core.djangolib.markup import HTML, Text
%> %>
<section class="container activation"> <%block name="content">
<section class="container activation">
<section class="message"> <section class="message">
<h1 class="invalid">${_("Activation Invalid")}</h1> <h1 class="invalid" style="padding: 1em;">${_("Activation Invalid")}</h1>
<hr class="horizontal-divider"> <hr class="horizontal-divider">
<p>${Text(_("Something went wrong. Email programs sometimes split URLs " <p style="padding: 0 2em;">${Text(_("Something went wrong. Email programs sometimes split URLs "
"into two lines, so make sure the URL you're using is " "formatted correctly. If you still have issues, send us " "into two lines, so make sure the URL you're using is " "formatted correctly. If you still have issues, send us "
"an email message at " "{email_start}{email}{email_end}.")).format( "an email message at " "{email_start}{email}{email_end}.")).format(
email_start=HTML('<a href="mailto:{}">').format(settings.BUGS_EMAIL), email_start=HTML('<a href="mailto:{}">').format(settings.BUGS_EMAIL),
email=settings.BUGS_EMAIL, email=settings.BUGS_EMAIL,
email_end=HTML('</a>') email_end=HTML('</a>')
)}</p> )}</p>
<p>${Text(_('Return to the {link_start}home page{link_end}.')).format( <p style="padding: 0 2em;">${Text(_('Return to the {link_start}home page{link_end}.')).format(
link_start=HTML('<a href="/">'), link_end=HTML('</a>'))}</p> link_start=HTML('<a href="/">'), link_end=HTML('</a>'))}</p>
</section>
</section> </section>
</section> </%block>
...@@ -90,6 +90,7 @@ from openedx.core.djangoapps.external_auth.login_and_register import ( ...@@ -90,6 +90,7 @@ from openedx.core.djangoapps.external_auth.login_and_register import (
register as external_auth_register register as external_auth_register
) )
from openedx.core.djangoapps import monitoring_utils from openedx.core.djangoapps import monitoring_utils
from openedx.core.djangolib.markup import HTML, Text
import track.views import track.views
...@@ -721,6 +722,11 @@ def dashboard(request): ...@@ -721,6 +722,11 @@ def dashboard(request):
enterprise_message = get_dashboard_consent_notification(request, user, course_enrollments) enterprise_message = get_dashboard_consent_notification(request, user, course_enrollments)
# Account activation message
account_activation_messages = [
message for message in messages.get_messages(request) if 'account-activation' in message.tags
]
# Global staff can see what courses errored on their dashboard # Global staff can see what courses errored on their dashboard
staff_access = False staff_access = False
errored_courses = {} errored_courses = {}
...@@ -844,6 +850,7 @@ def dashboard(request): ...@@ -844,6 +850,7 @@ def dashboard(request):
'enterprise_message': enterprise_message, 'enterprise_message': enterprise_message,
'enrollment_message': enrollment_message, 'enrollment_message': enrollment_message,
'redirect_message': redirect_message, 'redirect_message': redirect_message,
'account_activation_messages': account_activation_messages,
'course_enrollments': course_enrollments, 'course_enrollments': course_enrollments,
'course_optouts': course_optouts, 'course_optouts': course_optouts,
'banner_account_activation_message': banner_account_activation_message, 'banner_account_activation_message': banner_account_activation_message,
...@@ -2285,31 +2292,83 @@ def auto_auth(request): ...@@ -2285,31 +2292,83 @@ def auto_auth(request):
@ensure_csrf_cookie @ensure_csrf_cookie
def activate_account(request, key): def activate_account(request, key):
"""When link in activation e-mail is clicked""" """When link in activation e-mail is clicked"""
regs = Registration.objects.filter(activation_key=key)
if len(regs) == 1: # If request is in Studio call the appropriate view
if theming_helpers.get_project_root_name().lower() == u'cms':
return activate_account_studio(request, key)
try:
registration = Registration.objects.get(activation_key=key)
except (Registration.DoesNotExist, Registration.MultipleObjectsReturned):
messages.error(
request,
Text(_(
'{html_start}Your account could not be activated{html_end}'
'Something went wrong, please <a href="{support_url}">contact support</a> to resolve this issue.'
)).format(
support_url=configuration_helpers.get_value('SUPPORT_SITE_LINK', settings.SUPPORT_SITE_LINK),
html_start=HTML('<p class="message-title">'),
html_end=HTML('</p>'),
),
extra_tags='account-activation icon'
)
else:
if not registration.user.is_active:
registration.activate()
# Add account activation success message for display later
messages.success(
request,
Text(_('{html_start}Success{html_end} You have activated your account.')).format(
html_start=HTML('<p class="message-title">'),
html_end=HTML('</p>'),
),
extra_tags='account-activation icon',
)
else:
messages.info(
request,
Text(_('{html_start}This account has already been activated.{html_end}')).format(
html_start=HTML('<p class="message-title">'),
html_end=HTML('</p>'),
),
extra_tags='account-activation icon',
)
# Enroll student in any pending courses he/she may have if auto_enroll flag is set
_enroll_user_in_pending_courses(registration.user)
return redirect('dashboard')
@ensure_csrf_cookie
def activate_account_studio(request, key):
"""
When link in activation e-mail is clicked and the link belongs to studio.
"""
try:
registration = Registration.objects.get(activation_key=key)
except (Registration.DoesNotExist, Registration.MultipleObjectsReturned):
return render_to_response(
"registration/activation_invalid.html",
{'csrf': csrf(request)['csrf_token']}
)
else:
user_logged_in = request.user.is_authenticated() user_logged_in = request.user.is_authenticated()
already_active = True already_active = True
if not regs[0].user.is_active: if not registration.user.is_active:
regs[0].activate() registration.activate()
already_active = False already_active = False
# Enroll student in any pending courses he/she may have if auto_enroll flag is set # Enroll student in any pending courses he/she may have if auto_enroll flag is set
_enroll_user_in_pending_courses(regs[0].user) _enroll_user_in_pending_courses(registration.user)
resp = render_to_response( return render_to_response(
"registration/activation_complete.html", "registration/activation_complete.html",
{ {
'user_logged_in': user_logged_in, 'user_logged_in': user_logged_in,
'already_active': already_active 'already_active': already_active
} }
) )
return resp
if len(regs) == 0:
return render_to_response(
"registration/activation_invalid.html",
{'csrf': csrf(request)['csrf_token']}
)
return HttpResponseServerError(_("Unknown error. Please e-mail us to let us know how it happened."))
@csrf_exempt @csrf_exempt
......
...@@ -3,6 +3,7 @@ Helpers for courseware tests. ...@@ -3,6 +3,7 @@ Helpers for courseware tests.
""" """
import json import json
from django.contrib import messages
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
...@@ -53,6 +54,14 @@ class LoginEnrollmentTestCase(TestCase): ...@@ -53,6 +54,14 @@ class LoginEnrollmentTestCase(TestCase):
) )
return response return response
def assert_account_activated(self, url, method="GET", **kwargs):
make_request = getattr(self.client, method.lower())
response = make_request(url, **kwargs)
message_list = list(messages.get_messages(response.wsgi_request))
self.assertEqual(len(message_list), 1)
self.assertIn("success", message_list[0].tags)
self.assertTrue("You have activated your account." in message_list[0].message)
# ============ User creation and login ============== # ============ User creation and login ==============
def login(self, email, password): def login(self, email, password):
...@@ -102,7 +111,7 @@ class LoginEnrollmentTestCase(TestCase): ...@@ -102,7 +111,7 @@ class LoginEnrollmentTestCase(TestCase):
activation_key = Registration.objects.get(user__email=email).activation_key activation_key = Registration.objects.get(user__email=email).activation_key
# and now we try to activate # and now we try to activate
url = reverse('activate', kwargs={'key': activation_key}) url = reverse('activate', kwargs={'key': activation_key})
self.assert_request_status_code(200, url) self.assert_account_activated(url)
# Now make sure that the user is now actually activated # Now make sure that the user is now actually activated
user = User.objects.get(email=email) user = User.objects.get(email=email)
self.assertTrue(user.is_active) self.assertTrue(user.is_active)
......
...@@ -367,7 +367,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest ...@@ -367,7 +367,7 @@ class SelfPacedCourseInfoTestCase(LoginEnrollmentTestCase, SharedModuleStoreTest
self.assertEqual(resp.status_code, 200) self.assertEqual(resp.status_code, 200)
def test_num_queries_instructor_paced(self): def test_num_queries_instructor_paced(self):
self.fetch_course_info_with_queries(self.instructor_paced_course, 20, 4) self.fetch_course_info_with_queries(self.instructor_paced_course, 21, 4)
def test_num_queries_self_paced(self): def test_num_queries_self_paced(self):
self.fetch_course_info_with_queries(self.self_paced_course, 20, 4) self.fetch_course_info_with_queries(self.self_paced_course, 21, 4)
...@@ -1420,3 +1420,80 @@ a.fade-cover{ ...@@ -1420,3 +1420,80 @@ a.fade-cover{
} }
} }
// Dashboard alert messages
.activation-message-container {
@include clearfix();
margin: 0 auto 0;
padding-top: ($baseline/2);
max-width: grid-width(12);
min-width: 760px;
width: flex-grid(12);
}
.account-activation {
.message-copy {
position: relative;
left: 2em;
padding: 1em;
}
.message-title {
margin-bottom: 6px;
font-weight: 600;
}
&.info {
color: $palette-info-text;
background-color: $palette-info-back;
border: $palette-info-border 1px solid;
padding: 5px;
.message-title{
margin-bottom: 0;
}
&.icon .message-copy:before {
position: absolute;
left: -1em;
content: "\f05a"; // fa-info-circle
font-size: 1.5em;
padding: 0 2px;
font-family: FontAwesome;
}
}
&.success {
color: $palette-success-text;
background-color: $palette-success-back;
border: $palette-success-border 1px solid;
&.icon .message-copy:before {
position: absolute;
left: -1em;
content: "\f00c"; // fa-check
font-size: 1.5em;
padding: 0 2px;
font-family: FontAwesome;
}
}
&.error {
color: $palette-error-text;
background-color: $palette-error-back;
border: $palette-error-border 1px solid;
&.icon .message-copy:before {
position: absolute;
left: -1em;
content: "\f06a"; // fa-exclamation-circle
font-size: 1.5em;
padding: 0 2px;
font-family: FontAwesome;
}
a {
text-decoration: underline;
}
}
}
...@@ -514,6 +514,17 @@ $dashboard-profile-color: rgb(252,252,252) !default; ...@@ -514,6 +514,17 @@ $dashboard-profile-color: rgb(252,252,252) !default;
$dot-color: rgb(221, 221, 221) !default; $dot-color: rgb(221, 221, 221) !default;
$dashboard-course-cover-border: rgb(221, 221, 221) !default; $dashboard-course-cover-border: rgb(221, 221, 221) !default;
// dashboard notification messages
$palette-info-border: #cce3f0;
$palette-info-back: #f2f8fb;
$palette-info-text: #0075b4;
$palette-error-border: #ebccd1;
$palette-error-back: #feeced;
$palette-error-text: #b20610;
$palette-success-border: #b9edb9;
$palette-success-back: #ecfaec;
$palette-success-text: #008100;
// course elements // course elements
$content-wrapper-bg: $white !default; $content-wrapper-bg: $white !default;
$course-bg-color: $uxpl-grayscale-x-back !default; $course-bg-color: $uxpl-grayscale-x-back !default;
......
...@@ -80,6 +80,19 @@ from openedx.core.djangolib.markup import HTML, Text ...@@ -80,6 +80,19 @@ from openedx.core.djangolib.markup import HTML, Text
${ enterprise_message | n, decode.utf8 } ${ enterprise_message | n, decode.utf8 }
</div> </div>
%endif %endif
%if account_activation_messages:
<div class="activation-message-container">
% for account_activation_message in account_activation_messages:
<div class="account-activation ${account_activation_message.tags}" role="alert" aria-label="Account Activation Message" tabindex="-1">
<div class="message-copy" >
${ account_activation_message | n, decode.utf8 }
</div>
</div>
% endfor
</div>
%endif
</div> </div>
<main id="main" aria-label="Content" tabindex="-1"> <main id="main" aria-label="Content" tabindex="-1">
......
<%page expression_filter="h"/>
<%inherit file="../main.html" />
<%namespace name='static' file='../static_content.html'/>
<%!
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse
from openedx.core.djangolib.markup import HTML, Text
%>
<section class="container activation">
<section class="message">
%if not already_active:
<h1 class="valid">${_("Account Activated")}</h1>
%else:
<h1>${_("Account already active")}</h1>
%endif
<hr class="horizontal-divider">
<p>
%if not already_active:
${_("Thanks for activating your account.")}
%else:
${_("This account has already been activated.")}
%endif
%if user_logged_in:
${Text(_("Visit your {link_start}dashboard{link_end} to see your courses.")).format(
link_start=HTML('<a href="{url}">').format(url=reverse('dashboard')), link_end=HTML('</a>'))}
%else:
${Text(_("You can now {link_start}sign in{link_end}.")).format(
link_start=HTML('<a href="{url}">').format(url=reverse('signin_user')), link_end=HTML('</a>'))}
%endif
</p>
</section>
</section>
...@@ -82,6 +82,19 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers ...@@ -82,6 +82,19 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
${ enterprise_message | n, decode.utf8 } ${ enterprise_message | n, decode.utf8 }
</div> </div>
%endif %endif
%if account_activation_messages:
<div class="activation-message-container">
% for account_activation_message in account_activation_messages:
<div class="account-activation ${account_activation_message.tags}" role="alert" aria-label="Account Activation Message" tabindex="-1">
<div class="message-copy" >
${ account_activation_message | n, decode.utf8 }
</div>
</div>
% endfor
</div>
%endif
</div> </div>
<section class="container dashboard" id="dashboard-main"> <section class="container dashboard" id="dashboard-main">
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment