From 0361b50286d92fa62b3a323d5a98a9864c9ca951 Mon Sep 17 00:00:00 2001
From: Saleem Latif <saleem_ee@hotmail.com>
Date: Wed, 12 Apr 2017 15:09:19 +0500
Subject: [PATCH] Change Account Activation UI on Dashboard

---
 .../student/tests/test_activate_account.py    | 87 ++++++++++++++++++-
 common/djangoapps/student/views.py            | 22 ++++-
 lms/envs/common.py                            |  3 +
 lms/static/sass/multicourse/_dashboard.scss   | 29 +++++++
 lms/templates/dashboard.html                  | 11 ++-
 .../account_activation_sidebar_notice.html    | 34 ++++++++
 .../registration/activate_account_notice.html | 41 +++++----
 themes/edx.org/lms/templates/dashboard.html   | 15 +++-
 8 files changed, 209 insertions(+), 33 deletions(-)
 create mode 100644 lms/templates/registration/account_activation_sidebar_notice.html

diff --git a/common/djangoapps/student/tests/test_activate_account.py b/common/djangoapps/student/tests/test_activate_account.py
index 56f9b052b5c..8d4bcffa150 100644
--- a/common/djangoapps/student/tests/test_activate_account.py
+++ b/common/djangoapps/student/tests/test_activate_account.py
@@ -3,10 +3,12 @@ from mock import patch
 import unittest
 
 from django.conf import settings
-from django.contrib.auth.models import User
 from django.test import TestCase, override_settings
+from django.core.urlresolvers import reverse
 
+from edxmako.shortcuts import render_to_string
 from student.models import Registration
+from student.tests.factories import UserFactory
 
 
 @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@@ -17,13 +19,38 @@ class TestActivateAccount(TestCase):
         super(TestActivateAccount, self).setUp()
         self.username = "jack"
         self.email = "jack@fake.edx.org"
-        self.user = User.objects.create(username=self.username, email=self.email, is_active=False)
+        self.password = "test-password"
+        self.user = UserFactory.create(
+            username=self.username, email=self.email, password=self.password, is_active=False,
+        )
 
         # Set Up Registration
         self.registration = Registration()
         self.registration.register(self.user)
         self.registration.save()
 
+    def login(self):
+        """
+        Login with test user.
+
+        Since, only active users can login, so we must activate the user before login.
+        This method does the following tasks in order,
+            1. Stores user's active/in-active status in a variable.
+            2. Makes sure user account is active.
+            3. Authenticated user with the client.
+            4. Reverts user's original active/in-active status.
+        """
+        is_active = self.user.is_active
+
+        # Make sure user is active before login
+        self.user.is_active = True
+        self.user.save()
+        self.client.login(username=self.username, password=self.password)
+
+        # Revert user activation status
+        self.user.is_active = is_active
+        self.user.save()
+
     def assert_no_tracking(self, mock_segment_identify):
         """ Assert that activate sets the flag but does not call segment. """
         # Ensure that the user starts inactive
@@ -76,3 +103,59 @@ class TestActivateAccount(TestCase):
     @patch('student.models.analytics.identify')
     def test_activation_without_keys(self, mock_segment_identify):
         self.assert_no_tracking(mock_segment_identify)
+
+    @override_settings(FEATURES=dict(settings.FEATURES, DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR=True))
+    def test_account_activation_message(self):
+        """
+        Verify that account correct activation message is displayed.
+
+        If logged in user has not activated his/her account, make sure that an
+        account activation message is displayed on dashboard sidebar.
+        """
+        # Log in with test user.
+        self.login()
+        expected_message = render_to_string(
+            'registration/account_activation_sidebar_notice.html',
+            {'email': self.user.email}
+        )
+
+        response = self.client.get(reverse('dashboard'))
+        self.assertContains(response, expected_message, html=True)
+
+        # Now make sure account activation message goes away when user activated the account
+        self.user.is_active = True
+        self.user.save()
+        self.login()
+        expected_message = render_to_string(
+            'registration/account_activation_sidebar_notice.html',
+            {'email': self.user.email}
+        )
+        response = self.client.get(reverse('dashboard'))
+        self.assertNotContains(response, expected_message, html=True)
+
+    @override_settings(FEATURES=dict(settings.FEATURES, DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR=False))
+    def test_account_activation_message_disabled(self):
+        """
+        Verify that old account activation message is displayed when
+        DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR is disabled.
+        """
+        # Log in with test user.
+        self.login()
+        expected_message = render_to_string(
+            'registration/activate_account_notice.html',
+            {'email': self.user.email}
+        )
+
+        response = self.client.get(reverse('dashboard'))
+        self.assertContains(response, expected_message, html=True)
+
+        # Now make sure account activation message goes away when user activated the account
+        self.user.is_active = True
+        self.user.save()
+        self.login()
+        expected_message = render_to_string(
+            'registration/activate_account_notice.html',
+            {'email': self.user.email}
+        )
+        response = self.client.get(reverse('dashboard'))
+        self.assertNotContains(response, expected_message, html=True)
diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py
index 2cdf3ffe095..381c51a9a38 100644
--- a/common/djangoapps/student/views.py
+++ b/common/djangoapps/student/views.py
@@ -685,9 +685,22 @@ def dashboard(request):
 
     course_optouts = Optout.objects.filter(user=user).values_list('course_id', flat=True)
 
-    message = ""
-    if not user.is_active:
-        message = render_to_string(
+    sidebar_account_activation_message = ''
+    banner_account_activation_message = ''
+    display_account_activation_message_on_sidebar = configuration_helpers.get_value(
+        'DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR',
+        settings.FEATURES.get('DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR', False)
+    )
+
+    # Display activation message in sidebar if DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR
+    # flag is active. Otherwise display existing message at the top.
+    if display_account_activation_message_on_sidebar and not user.is_active:
+        sidebar_account_activation_message = render_to_string(
+            'registration/account_activation_sidebar_notice.html',
+            {'email': user.email}
+        )
+    elif not user.is_active:
+        banner_account_activation_message = render_to_string(
             'registration/activate_account_notice.html',
             {'email': user.email, 'platform_name': platform_name}
         )
@@ -819,7 +832,8 @@ def dashboard(request):
         'redirect_message': redirect_message,
         'course_enrollments': course_enrollments,
         'course_optouts': course_optouts,
-        'message': message,
+        'banner_account_activation_message': banner_account_activation_message,
+        'sidebar_account_activation_message': sidebar_account_activation_message,
         'staff_access': staff_access,
         'errored_courses': errored_courses,
         'show_courseware_links_for': show_courseware_links_for,
diff --git a/lms/envs/common.py b/lms/envs/common.py
index a8b6d94d50f..fbba924d80b 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -377,6 +377,9 @@ FEATURES = {
     # Enable one click program purchase
     # See LEARNER-493
     'ENABLE_ONE_CLICK_PROGRAM_PURCHASE': False,
+
+    # Whether to display account activation notification on dashboard.
+    'DISPLAY_ACCOUNT_ACTIVATION_MESSAGE_ON_SIDEBAR': False,
 }
 
 # Ignore static asset files on import which match this pattern
diff --git a/lms/static/sass/multicourse/_dashboard.scss b/lms/static/sass/multicourse/_dashboard.scss
index 5718bc4d722..1fae8f0982d 100644
--- a/lms/static/sass/multicourse/_dashboard.scss
+++ b/lms/static/sass/multicourse/_dashboard.scss
@@ -1227,6 +1227,35 @@
       border-bottom-color: $m-gray-l4;
     }
   }
+
+  // Warning for status verification
+  &.warning {
+     border-top: 3px solid #ffc01f !important;
+
+    .status-title {
+      font-weight: 400 !important;
+
+      .fa {
+        color: #ffc01f;
+      }
+    }
+
+    .btn {
+      font-size: 16px;
+      line-height: 25.16px;
+      padding: 10px 10px;
+      border: 1px solid #0079bc;
+      color: #0079bc;
+      text-decoration: none;
+      display: block;
+    }
+    .btn:hover {
+      cursor: pointer;
+      color: #fff;
+      background-color: #0079bc;
+    }
+
+  }
 }
 
 // status - verification
diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html
index faf9ed0fae5..0e57bc39734 100644
--- a/lms/templates/dashboard.html
+++ b/lms/templates/dashboard.html
@@ -62,9 +62,10 @@ from openedx.core.djangolib.markup import HTML, Text
 </%block>
 
 <div class="dashboard-notifications" tabindex="-1">
-    %if message:
+
+    %if banner_account_activation_message:
         <div class="dashboard-banner">
-            ${message | n, decode.utf8}
+            ${banner_account_activation_message | n, decode.utf8}
         </div>
     %endif
 
@@ -137,6 +138,12 @@ from openedx.core.djangolib.markup import HTML, Text
         % endif
     </div>
 
+      %if sidebar_account_activation_message:
+        <div class="sidebar-notification">
+          ${sidebar_account_activation_message | n, decode.utf8}
+        </div>
+      %endif
+
       % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
         <div id="dashboard-search-bar" class="search-bar dashboard-search-bar" role="search" aria-label="Dashboard">
           <form>
diff --git a/lms/templates/registration/account_activation_sidebar_notice.html b/lms/templates/registration/account_activation_sidebar_notice.html
new file mode 100644
index 00000000000..487a878e56b
--- /dev/null
+++ b/lms/templates/registration/account_activation_sidebar_notice.html
@@ -0,0 +1,34 @@
+<%page expression_filter="h"/>
+<%!
+from django.utils.translation import ugettext as _
+from openedx.core.djangolib.markup import HTML, Text
+%>
+<div class="profile-sidebar" role="region" aria-label="Account Activation Info">
+  <header class="profile">
+    <h2 class="account-activation-title sr">${_("Account Activation Info")}: </h2>
+  </header>
+  <div class="user-info">
+    <ul>
+      <li class="status status-verification warning" role="alert" aria-labelledby="title status-title" tabindex="1">
+        <span class="title status-title">
+          <i class="fa fa-exclamation-circle" aria-hidden="true"></i>
+          ${_("Activate your account!")}
+        </span>
+        <p class="status-note">${Text(_(
+          "Check your {email_start}{email}{email_end} inbox for an account activation link from edX. "
+          "If you need help, contact {link_start}edX Support{link_end}."
+        )).format(
+          email_start=HTML("<strong>"),
+          email_end=HTML("</strong>"),
+          email=email,
+          link_start=HTML("<a target='_blank' href='https://support.edx.org/hc/en-us/articles/227340127-Why-haven-t-I-received-my-activation-email-'>"),
+          link_end=HTML("</a>"),
+        )}
+        </p>
+        ## TODO: Add resend activation email functionality.
+        ## TODO: Implementation of this is part of ENT-353.
+        ## <a class="btn btn-neutral"><i class="fa fa-envelope-o"></i> Resend Activation Email </a>
+      </li>
+    </ul>
+  </div>
+</div>
diff --git a/lms/templates/registration/activate_account_notice.html b/lms/templates/registration/activate_account_notice.html
index b09e40791d4..42811c03056 100644
--- a/lms/templates/registration/activate_account_notice.html
+++ b/lms/templates/registration/activate_account_notice.html
@@ -4,25 +4,24 @@ from django.utils.translation import ugettext as _
 from openedx.core.djangolib.markup import HTML, Text
 %>
 <div class="wrapper-msg urgency-high">
-    <div class="msg">
-        <div class="msg-content">
-            <h2 class="title">${_("You're almost there!")}</h2>
-            <div class="copy">
-                <p class='activation-message'>${Text(_(
-                        "There's just one more step: Before you "
-                        "enroll in a course, you need to activate "
-                        "your account. We've sent an email message to "
-                        "{email_start}{email}{email_end} with "
-                        "instructions for activating your account. If "
-                        "you don't receive this message, check your "
-                        "spam folder."
-                        )).format(email_start=HTML("<strong>"),
-                                  email_end=HTML("</strong>"),
-                                  email=email,
-                                  platform_name=platform_name
-                    )}
-                </p>
-            </div>
-        </div>
+  <div class="msg">
+    <div class="msg-content">
+      <h2 class="title">${_("You're almost there!")}</h2>
+      <div class="copy">
+        <p class='activation-message'>${Text(_(
+          "There's just one more step: Before you "
+          "enroll in a course, you need to activate "
+          "your account. We've sent an email message to "
+          "{email_start}{email}{email_end} with "
+          "instructions for activating your account. If "
+          "you don't receive this message, check your "
+          "spam folder."
+          )).format(email_start=HTML("<strong>"),
+            email_end=HTML("</strong>"),
+            email=email,
+        )}
+        </p>
+      </div>
     </div>
-</div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/themes/edx.org/lms/templates/dashboard.html b/themes/edx.org/lms/templates/dashboard.html
index 13494aac144..75cda00e143 100644
--- a/themes/edx.org/lms/templates/dashboard.html
+++ b/themes/edx.org/lms/templates/dashboard.html
@@ -64,10 +64,11 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
 </%block>
 
 <div class="dashboard-notifications" tabindex="-1">
-    %if message:
-        <section class="dashboard-banner">
-            ${message | n, decode.utf8}
-        </section>
+
+    %if banner_account_activation_message:
+        <div class="dashboard-banner">
+            ${banner_account_activation_message | n, decode.utf8}
+        </div>
     %endif
 
     %if enrollment_message:
@@ -142,6 +143,12 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
   </section>
 </main>
 
+  %if sidebar_account_activation_message:
+    <div class="sidebar-notification">
+      ${sidebar_account_activation_message | n, decode.utf8}
+    </div>
+  %endif
+
   % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
     <div id="dashboard-search-bar" class="search-bar dashboard-search-bar" role="search" aria-label="Dashboard">
       <form>
-- 
GitLab