From 7c0423ff03a9e414e9fed6e3be32d92ba2679ce2 Mon Sep 17 00:00:00 2001
From: Matthew Piatetsky <mpiatetsky@edx.org>
Date: Tue, 22 Aug 2017 16:33:05 -0400
Subject: [PATCH] Revert revert of unenrollment survey.

This reverts commit e2ee48c3c9af8a324e18c8347cd9488e473bcb43.
---
 .../courseware/features/registration.feature  | 10 ---
 lms/static/js/dashboard/legacy.js             | 14 ----
 .../learner_dashboard/unenrollment_factory.js | 13 ++++
 .../learner_dashboard/views/unenroll_view.js  | 78 +++++++++++++++++++
 .../learner_dashboard/unenroll_view_spec.js   | 46 +++++++++++
 lms/static/lms/js/build.js                    |  1 +
 lms/static/lms/js/spec/main.js                |  1 +
 lms/static/sass/multicourse/_dashboard.scss   | 52 +++++++++++++
 lms/templates/dashboard.html                  | 13 +++-
 .../dashboard/_dashboard_course_listing.html  |  1 +
 lms/templates/dashboard/_reason_survey.html   | 37 +++++++++
 themes/edx.org/lms/templates/dashboard.html   | 13 +++-
 12 files changed, 253 insertions(+), 26 deletions(-)
 create mode 100644 lms/static/js/learner_dashboard/unenrollment_factory.js
 create mode 100644 lms/static/js/learner_dashboard/views/unenroll_view.js
 create mode 100644 lms/static/js/spec/learner_dashboard/unenroll_view_spec.js
 create mode 100644 lms/templates/dashboard/_reason_survey.html

diff --git a/lms/djangoapps/courseware/features/registration.feature b/lms/djangoapps/courseware/features/registration.feature
index fe270a3f857..60b094de48d 100644
--- a/lms/djangoapps/courseware/features/registration.feature
+++ b/lms/djangoapps/courseware/features/registration.feature
@@ -11,13 +11,3 @@ Feature: LMS.Register for a course
     When I register for the course "6.002x"
     Then I should see the course numbered "6.002x" in my dashboard
     And a "edx.course.enrollment.activated" server event is emitted
-
-  Scenario: I can unenroll from a course
-    Given I am registered for the course "6.002x"
-    And I visit the dashboard
-    Then I should see the course numbered "6.002x" in my dashboard
-    When I unenroll from the course numbered "6.002x"
-    Then I should be on the dashboard page
-    And I should see an empty dashboard message
-    And I should NOT see the course numbered "6.002x" in my dashboard
-    And a "edx.course.enrollment.deactivated" server event is emitted
diff --git a/lms/static/js/dashboard/legacy.js b/lms/static/js/dashboard/legacy.js
index 80402ec5198..a2c3a4a4db1 100644
--- a/lms/static/js/dashboard/legacy.js
+++ b/lms/static/js/dashboard/legacy.js
@@ -191,20 +191,6 @@
              $('#unenroll-modal').css('position', 'fixed');
          });
 
-         $('#unenroll_form').on('ajax:complete', function(event, xhr) {
-             if (xhr.status === 200) {
-                 location.href = urls.dashboard;
-             } else if (xhr.status === 403) {
-                 location.href = urls.signInUser + '?course_id=' +
-                encodeURIComponent($('#unenroll_course_id').val()) + '&enrollment_action=unenroll';
-             } else {
-                 $('#unenroll_error').text(
-                    xhr.responseText ? xhr.responseText : gettext('An error occurred. Please try again later.')
-                ).stop()
-                     .css('display', 'block');
-             }
-         });
-
          $('#email_settings_form').submit(function() {
              $.ajax({
                  type: 'POST',
diff --git a/lms/static/js/learner_dashboard/unenrollment_factory.js b/lms/static/js/learner_dashboard/unenrollment_factory.js
new file mode 100644
index 00000000000..4afca20bbb4
--- /dev/null
+++ b/lms/static/js/learner_dashboard/unenrollment_factory.js
@@ -0,0 +1,13 @@
+(function(define) {
+    'use strict';
+
+    define([
+        'js/learner_dashboard/views/unenroll_view'
+    ],
+    function(UnenrollView) {
+        return function(options) {
+            var Unenroll = new UnenrollView(options);
+            return Unenroll;
+        };
+    });
+}).call(this, define || RequireJS.define);
diff --git a/lms/static/js/learner_dashboard/views/unenroll_view.js b/lms/static/js/learner_dashboard/views/unenroll_view.js
new file mode 100644
index 00000000000..ab52dfe83eb
--- /dev/null
+++ b/lms/static/js/learner_dashboard/views/unenroll_view.js
@@ -0,0 +1,78 @@
+(function(define) {
+    'use strict';
+    define(['backbone',
+        'jquery',
+        'underscore',
+        'gettext',
+        'edx-ui-toolkit/js/utils/html-utils'
+    ],
+         function(
+             Backbone,
+             $,
+             _,
+             gettext,
+             HtmlUtils
+         ) {
+             return Backbone.View.extend({
+                 el: '.unenroll-modal',
+
+                 switchToSlideOne: function() {
+                     var survey, i,
+                         reasonsSurvey = HtmlUtils.HTML($('.reasons_survey'));
+                     // Randomize survey option order
+                     survey = document.querySelector('.options');
+                     for (i = survey.children.length - 1; i >= 0; i--) {
+                         survey.appendChild(survey.children[Math.random() * i | 0]);
+                     }
+                     $('.inner-wrapper header').hide();
+                     $('#unenroll_form').after(HtmlUtils.ensureHtml(reasonsSurvey).toString()).hide();
+                     $('.reasons_survey .slide1').removeClass('hidden');
+                 },
+
+                 switchToSlideTwo: function() {
+                     var reason = $(".reasons_survey input[name='reason']:checked").attr('val');
+                     if (reason === 'Other') {
+                         reason = $('.other_text').val();
+                     }
+                     if (reason) {
+                         window.analytics.track('unenrollment_reason.selected', {
+                             category: 'user-engagement',
+                             label: reason,
+                             displayName: 'v1'
+                         });
+                     }
+                     HtmlUtils.setHtml($('.reasons_survey'), HtmlUtils.HTML($('.slide2').html()));
+                     $('.reasons_survey .return_to_dashboard').attr('href', this.urls.dashboard);
+                     $('.reasons_survey .browse_courses').attr('href', this.urls.browseCourses);
+                 },
+
+                 unenrollComplete: function(event, xhr) {
+                     if (xhr.status === 200) {
+                         if (!this.isEdx) {
+                             location.href = this.urls.dashboard;
+                         } else {
+                             this.switchToSlideOne();
+                             $('.submit_reasons').click(this.switchToSlideTwo.bind(this));
+                         }
+                     } else if (xhr.status === 403) {
+                         location.href = this.urls.signInUser + '?course_id=' +
+                        encodeURIComponent($('#unenroll_course_id').val()) + '&enrollment_action=unenroll';
+                     } else {
+                         $('#unenroll_error').text(
+                         gettext('Unable to determine whether we should give you a refund because' +
+                                ' of System Error. Please try again later.')
+                         ).stop()
+                          .css('display', 'block');
+                     }
+                 },
+
+                 initialize: function(options) {
+                     this.urls = options.urls;
+                     this.isEdx = options.isEdx;
+
+                     $('#unenroll_form').on('ajax:complete', this.unenrollComplete.bind(this));
+                 }
+             });
+         }
+    );
+}).call(this, define || RequireJS.define);
diff --git a/lms/static/js/spec/learner_dashboard/unenroll_view_spec.js b/lms/static/js/spec/learner_dashboard/unenroll_view_spec.js
new file mode 100644
index 00000000000..1aa0c8efc99
--- /dev/null
+++ b/lms/static/js/spec/learner_dashboard/unenroll_view_spec.js
@@ -0,0 +1,46 @@
+define([
+    'backbone',
+    'js/learner_dashboard/views/unenroll_view'
+], function(Backbone, UnenrollView) {
+    'use strict';
+
+    describe('Unenroll View', function() {
+        var view = null,
+            options = {
+                urls: {
+                    dashboard: '/dashboard',
+                    browseCourses: '/courses'
+                },
+                isEdx: true
+            },
+            initView;
+
+        initView = function() {
+            return new UnenrollView(options);
+        };
+
+        beforeEach(function() {
+            setFixtures('<div class="wrapper-action-more" data-course-key="course-v1:edX+DemoX+Demo_Course"> <button type="button" class="action action-more" id="actions-dropdown-link-0" aria-haspopup="true" aria-expanded="true" aria-controls="actions-dropdown-0" data-course-number="DemoX" data-course-name="edX Demonstration Course" data-dashboard-index="0"> <span class="sr">Course options for</span> <span class="sr">&nbsp;  edX Demonstration Course </span> <span class="fa fa-cog" aria-hidden="true"></span> </button> <div class="actions-dropdown is-visible" id="actions-dropdown-0" tabindex="-1"> <ul class="actions-dropdown-list" id="actions-dropdown-list-0" aria-label="Available Actions" role="menu"> <div class="reasons_survey"> <div class="slide1 hidden">  <h3>We\'re sorry to see you go! Please share your main reason for unenrolling.</h3><br>  <ul class="options">  <li><label class="option"><input type="radio" name="reason" val="I don\'t have enough support">I don\'t have enough support</label></li><li><label class="option"><input type="radio" name="reason" val="I don’t have the academic or language prerequisites">I don\'t have the academic or language prerequisites</label></li><li><label class="option"><input type="radio" name="reason" val="Something was broken">Something was broken</label></li><li><label class="option"><input type="radio" name="reason" val="I just wanted to browse the material">I just wanted to browse the material</label></li><li><label class="option"><input type="radio" name="reason" val="This won’t help me reach my goals">This won\'t help me reach my goals</label></li><li><label class="option"><input type="radio" name="reason" val="I am not happy with the quality of the content">I am not happy with the quality of the content</label></li><li><label class="option"><input type="radio" name="reason" val="The course material was too hard">The course material was too hard</label></li><li><label class="option"><input type="radio" name="reason" val="I don\'t have the time">I don\'t have the time</label></li><li><label class="option"><input type="radio" name="reason" val="The course material was too easy">The course material was too easy</label></li><li><label class="option"><input class="other_radio" type="radio" name="reason" val="Other">Other <input type="text" class="other_text"></label></li></ul>  <button class="submit_reasons">Submit</button> </div> </div> <div class="slide2 hidden"> Thank you for sharing your reasons for unenrolling.<br> You are unenrolled from edX Demonstration Course. <a class="button survey_button return_to_dashboard">  Return To Dashboard </a> <a class="button survey_button browse_courses">  Browse Courses </a> </div>   <li class="actions-item" id="actions-item-unenroll-0">   <a href="#unenroll-modal" class="action action-unenroll" rel="leanModal" data-course-id="course-v1:edX+DemoX+Demo_Course" data-course-number="DemoX" data-course-name="edX Demonstration Course" data-dashboard-index="0" data-track-info="Are you sure you want to unenroll from %(course_name)s (%(course_number)s)?" id="unenroll-0">    Unenroll   </a>  </li>  <li class="actions-item" id="actions-item-email-settings-0">  </li>  </ul> </div> </div>');  // eslint-disable-line max-len
+        });
+
+        afterEach(function() {
+            view.remove();
+        });
+
+        it('should exist', function() {
+            view = initView();
+            expect(view).toBeDefined();
+        });
+
+        it('switch between slides', function() {
+            view = initView();
+            expect($('.slide1').hasClass('hidden')).toEqual(true);
+            view.switchToSlideOne();
+            expect($('.slide1').hasClass('hidden')).toEqual(false);
+            expect($('.slide2').hasClass('hidden')).toEqual(true);
+            view.switchToSlideTwo();
+            expect($('.slide2').hasClass('hidden')).toEqual(true);
+        });
+    });
+}
+);
diff --git a/lms/static/lms/js/build.js b/lms/static/lms/js/build.js
index c2141007e05..b4a74f5a52c 100644
--- a/lms/static/lms/js/build.js
+++ b/lms/static/lms/js/build.js
@@ -32,6 +32,7 @@
             'js/groups/views/cohorts_dashboard_factory',
             'js/discussions_management/views/discussions_dashboard_factory',
             'js/header_factory',
+            'js/learner_dashboard/unenrollment_factory',
             'js/learner_dashboard/program_details_factory',
             'js/learner_dashboard/program_list_factory',
             'js/student_account/logistration_factory',
diff --git a/lms/static/lms/js/spec/main.js b/lms/static/lms/js/spec/main.js
index e377f28e31b..954a9626068 100644
--- a/lms/static/lms/js/spec/main.js
+++ b/lms/static/lms/js/spec/main.js
@@ -759,6 +759,7 @@
         'js/spec/learner_dashboard/program_details_header_spec.js',
         'js/spec/learner_dashboard/program_details_view_spec.js',
         'js/spec/learner_dashboard/program_details_sidebar_view_spec.js',
+        'js/spec/learner_dashboard/unenroll_view_spec.js',
         'js/spec/learner_dashboard/course_card_view_spec.js',
         'js/spec/learner_dashboard/course_enroll_view_spec.js',
         'js/spec/markdown_editor_spec.js',
diff --git a/lms/static/sass/multicourse/_dashboard.scss b/lms/static/sass/multicourse/_dashboard.scss
index 0b3c9e4752b..d27b5be8af8 100644
--- a/lms/static/sass/multicourse/_dashboard.scss
+++ b/lms/static/sass/multicourse/_dashboard.scss
@@ -1498,3 +1498,55 @@ a.fade-cover{
     }
   }
 }
+
+#unenroll-modal {
+  margin-top: -60px;
+}
+
+.reasons_survey {
+  padding: 20px;
+
+  .options {
+    list-style: none;
+    padding: 0;
+  }
+
+  .option {
+    margin-bottom: 10px;
+    display: block;
+  }
+
+  input {
+    margin-right: 10px;
+  }
+
+  .unenroll-header {
+    background-image: none;
+  }
+
+  .other_text {
+    margin-top: 0;
+  }
+
+  .other_radio {
+    margin-top: 10px;
+  }
+
+  .submit_reasons {
+    margin-top: 10px;
+  }
+
+  .survey_button {
+    width: 30%;
+    margin-top: 10px;
+    margin-left: 2.5%;
+    margin-right: 2.5%;
+    color: $white;
+  }
+
+  .survey_button:visited, .survey_button:hover, .survey_button:focus {
+    color: $white;
+    text-decoration: none;
+  }
+
+}
diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html
index 552d815e3b1..13765bdd021 100644
--- a/lms/templates/dashboard.html
+++ b/lms/templates/dashboard.html
@@ -42,6 +42,17 @@ from openedx.core.djangolib.markup import HTML, Text
       });
     });
   </script>
+  <%static:require_module module_name="js/learner_dashboard/unenrollment_factory" class_name="UnenrollmentFactory">
+    UnenrollmentFactory({
+      urls: {
+        dashboard: "${reverse('dashboard') | n, js_escaped_string}",
+        signInUser: "${reverse('signin_user') | n, js_escaped_string}",
+        changeEmailSettings: "${reverse('change_email_settings') | n, js_escaped_string}",
+        browseCourses: "${marketing_link('COURSES') | n, js_escaped_string}"
+      },
+      isEdx: false
+    });
+  </%static:require_module>
   % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
     <%static:require_module module_name="course_search/js/dashboard_search_factory" class_name="DashboardSearchFactory">
         DashboardSearchFactory();
@@ -244,7 +255,7 @@ from openedx.core.djangolib.markup import HTML, Text
       </span>
     </button>
 
-    <header>
+    <header class="unenroll-header">
       <h2 id="unenrollment-modal-title">
         <span id='track-info'></span>
         <span id='refund-info'></span>
diff --git a/lms/templates/dashboard/_dashboard_course_listing.html b/lms/templates/dashboard/_dashboard_course_listing.html
index ec2874228d2..943d6fd347c 100644
--- a/lms/templates/dashboard/_dashboard_course_listing.html
+++ b/lms/templates/dashboard/_dashboard_course_listing.html
@@ -220,6 +220,7 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
               <div class="actions-dropdown" id="actions-dropdown-${dashboard_index}" tabindex="-1">
                 <ul class="actions-dropdown-list" id="actions-dropdown-list-${dashboard_index}" aria-label="${_('Available Actions')}" role="menu">
                   % if can_unenroll:
+                    <%include file='_reason_survey.html' args='course_overview=course_overview' />
                     <li class="actions-item" id="actions-item-unenroll-${dashboard_index}">
                       <% course_refund_url = reverse('course_run_refund_status', args=[unicode(course_overview.id)]) %>
                           % if not is_course_blocked:
diff --git a/lms/templates/dashboard/_reason_survey.html b/lms/templates/dashboard/_reason_survey.html
new file mode 100644
index 00000000000..b0fffb0b54f
--- /dev/null
+++ b/lms/templates/dashboard/_reason_survey.html
@@ -0,0 +1,37 @@
+<%page args="course_overview" expression_filter="h"/>
+<%!
+import urllib
+
+from django.utils.translation import ugettext as _
+%>
+<div class="reasons_survey">
+  <div class="slide1 hidden">
+    <h3>${_("We're sorry to see you go! Please share your main reason for unenrolling.")}</h3><br>
+    <ul class="options">
+      <li><label class="option"><input type="radio" name="reason" val="I just wanted to browse the material">${_('I just wanted to browse the material')}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="This won’t help me reach my goals">${_("This won't help me reach my goals")}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="I don't have the time">${_("I don't have the time")}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="I don’t have the academic or language prerequisites">${_("I don't have the academic or language prerequisites")}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="I don't have enough support">${_("I don't have enough support")}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="I am not happy with the quality of the content">${_('I am not happy with the quality of the content')}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="The course material was too hard">${_('The course material was too hard')}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="The course material was too easy">${_('The course material was too easy')}</label></li>
+      <li><label class="option"><input type="radio" name="reason" val="Something was broken">${_('Something was broken')}</label></li>
+      <li><label class="option"><input class="other_radio" type="radio" name="reason" val="Other">${_('Other')}   <input type="text" class="other_text"/></label></li>
+    </ul>
+    <button class="submit_reasons">${_('Submit')}</button>
+  </div>
+</div>
+<div class="slide2 hidden">
+  ${_('Thank you for sharing your reasons for unenrolling.')}<br>
+  ${_('You are unenrolled from')} ${course_overview.display_name_with_default}.
+
+  <div>
+    <a class="button survey_button return_to_dashboard">
+      ${_('Return To Dashboard')}
+    </a>
+    <a class="button survey_button browse_courses">
+      ${_('Browse Courses')}
+    </a>
+  </div>
+</div>
diff --git a/themes/edx.org/lms/templates/dashboard.html b/themes/edx.org/lms/templates/dashboard.html
index e6d9ee4bd62..deaf0cb4844 100644
--- a/themes/edx.org/lms/templates/dashboard.html
+++ b/themes/edx.org/lms/templates/dashboard.html
@@ -43,6 +43,17 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
       });
     });
   </script>
+  <%static:require_module module_name="js/learner_dashboard/unenrollment_factory" class_name="UnenrollmentFactory">
+    UnenrollmentFactory({
+      urls: {
+        dashboard: "${reverse('dashboard') | n, js_escaped_string}",
+        signInUser: "${reverse('signin_user') | n, js_escaped_string}",
+        changeEmailSettings: "${reverse('change_email_settings') | n, js_escaped_string}",
+        browseCourses: "${marketing_link('COURSES') | n, js_escaped_string}"
+      },
+      isEdx: true
+    });
+  </%static:require_module>
   % if settings.FEATURES.get('ENABLE_DASHBOARD_SEARCH'):
     <%static:require_module module_name="course_search/js/dashboard_search_factory" class_name="DashboardSearchFactory">
         DashboardSearchFactory();
@@ -258,7 +269,7 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
       </span>
     </button>
 
-    <header>
+    <header class="unenroll-header">
       <h2 id="unenrollment-modal-title">
         <span id='track-info'></span>
         <span id='refund-info'></span>
-- 
GitLab