Commit 98cf69ba by Matthew Piatetsky

Revert "Revert "LEARNER-1510 Add unenrollment reason survey""

This reverts commit 441bccf4.
parent 2cd20d28
......@@ -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
......@@ -62,7 +62,6 @@
}
);
// Generate the properties object to be passed along with business intelligence events.
function generateProperties(element) {
var $el = $(element),
......@@ -79,35 +78,6 @@
return properties;
}
function setDialogAttributes(isPaidCourse, certNameLong,
courseNumber, courseName, enrollmentMode, showRefundOption) {
var diagAttr = {};
if (isPaidCourse) {
if (showRefundOption) {
diagAttr['data-refund-info'] = gettext('You will be refunded the amount you paid.');
} else {
diagAttr['data-refund-info'] = gettext('You will not be refunded the amount you paid.');
}
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from the purchased course ' +
'%(courseName)s (%(courseNumber)s)?');
} else if (enrollmentMode !== 'verified') {
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from %(courseName)s ' +
'(%(courseNumber)s)?');
} else if (showRefundOption) {
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from the verified ' +
'%(certNameLong)s track of %(courseName)s (%(courseNumber)s)?');
diagAttr['data-refund-info'] = gettext('You will be refunded the amount you paid.');
} else {
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from the verified ' +
'%(certNameLong)s track of %(courseName)s (%(courseNumber)s)?');
diagAttr['data-refund-info'] = gettext('The refund deadline for this course has passed,' +
'so you will not receive a refund.');
}
return diagAttr;
}
$('#failed-verification-button-dismiss').click(function() {
$.ajax({
url: urls.verifyToggleBannerFailedOff,
......@@ -131,79 +101,6 @@
}
edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
$('.action-unenroll').click(function(event) {
var isPaidCourse = $(event.target).data('course-is-paid-course') === 'True';
var certNameLong = $(event.target).data('course-cert-name-long');
var enrollmentMode = $(event.target).data('course-enrollment-mode');
var courseNumber = $(event.target).data('course-number');
var courseName = $(event.target).data('course-name');
var courseRefundUrl = $(event.target).data('course-refund-url');
var dialogMessageAttr;
var request = $.ajax({
url: courseRefundUrl,
method: 'GET',
dataType: 'json'
});
request.success(function(data, textStatus, xhr) {
if (xhr.status === 200) {
dialogMessageAttr = setDialogAttributes(isPaidCourse, certNameLong,
courseNumber, courseName, enrollmentMode, data.course_refundable_status);
$('#track-info').empty();
$('#refund-info').empty();
$('#track-info').html(interpolate(dialogMessageAttr['data-track-info'], {
courseNumber: ['<span id="unenroll_course_number">', courseNumber, '</span>'].join(''),
courseName: ['<span id="unenroll_course_name">', courseName, '</span>'].join(''),
certNameLong: ['<span id="unenroll_cert_name">', certNameLong, '</span>'].join('')
}, true));
if ('data-refund-info' in dialogMessageAttr) {
$('#refund-info').text(dialogMessageAttr['data-refund-info']);
}
$('#unenroll_course_id').val($(event.target).data('course-id'));
} 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');
$('#unenroll_form input[type="submit"]').prop('disabled', true);
}
edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
request.fail(function() {
$('#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');
$('#unenroll_form input[type="submit"]').prop('disabled', true);
edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
$('#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({
......@@ -236,22 +133,5 @@
$(this).attr('id', 'email-settings-' + index);
});
$('.action-unenroll').each(function(index) {
// a bit of a hack, but gets the unique selector for the modal trigger
var trigger = '#' + $(this).attr('id');
accessibleModal(
trigger,
'#unenroll-modal .close-modal',
'#unenroll-modal',
'#dashboard-main'
);
$(this).attr('id', 'unenroll-' + index);
});
$('#unregister_block_course').click(function(event) {
$('#unenroll_course_id').val($(event.target).data('course-id'));
$('#unenroll_course_number').text($(event.target).data('course-number'));
$('#unenroll_course_name').text($(event.target).data('course-name'));
});
};
})(jQuery, gettext, Logger, accessible_modal, interpolate);
(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);
(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',
unenrollClick: function(event) {
var isPaidCourse = $(event.target).data('course-is-paid-course') === 'True',
certNameLong = $(event.target).data('course-cert-name-long'),
enrollmentMode = $(event.target).data('course-enrollment-mode'),
courseNumber = $(event.target).data('course-number'),
courseName = $(event.target).data('course-name'),
courseRefundUrl = $(event.target).data('course-refund-url'),
dialogMessageAttr,
request = $.ajax({
url: courseRefundUrl,
method: 'GET',
dataType: 'json'
});
request.success(function(data, textStatus, xhr) {
if (xhr.status === 200) {
dialogMessageAttr = setDialogAttributes(isPaidCourse, certNameLong,
courseNumber, courseName, enrollmentMode, data.course_refundable_status);
$('#track-info').empty();
$('#refund-info').empty();
$('#track-info').html(interpolate(dialogMessageAttr['data-track-info'], {
courseNumber: ['<span id="unenroll_course_number">', courseNumber, '</span>'].join(''),
courseName: ['<span id="unenroll_course_name">', courseName, '</span>'].join(''),
certNameLong: ['<span id="unenroll_cert_name">', certNameLong, '</span>'].join('')
}, true));
if ('data-refund-info' in dialogMessageAttr) {
$('#refund-info').text(dialogMessageAttr['data-refund-info']);
}
$('#unenroll_course_id').val($(event.target).data('course-id'));
} 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');
$('#unenroll_form input[type="submit"]').prop('disabled', true);
}
edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
request.fail(function() {
$('#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');
$('#unenroll_form input[type="submit"]').prop('disabled', true);
edx.dashboard.dropdown.toggleCourseActionsDropdownMenu(event);
});
// 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]);
}
},
function setDialogAttributes(isPaidCourse, certNameLong,
courseNumber, courseName, enrollmentMode, showRefundOption) {
var diagAttr = {};
if (isPaidCourse) {
if (showRefundOption) {
diagAttr['data-refund-info'] = gettext('You will be refunded the amount you paid.');
} else {
diagAttr['data-refund-info'] = gettext('You will not be refunded the amount you paid.');
}
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from the purchased course ' +
'%(courseName)s (%(courseNumber)s)?');
} else if (enrollmentMode !== 'verified') {
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from %(courseName)s ' +
'(%(courseNumber)s)?');
} else if (showRefundOption) {
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from the verified ' +
'%(certNameLong)s track of %(courseName)s (%(courseNumber)s)?');
diagAttr['data-refund-info'] = gettext('You will be refunded the amount you paid.');
} else {
diagAttr['data-track-info'] = gettext('Are you sure you want to unenroll from the verified ' +
'%(certNameLong)s track of %(courseName)s (%(courseNumber)s)?');
diagAttr['data-refund-info'] = gettext('The refund deadline for this course has passed,' +
'so you will not receive a refund.');
}
return diagAttr;
},
switchToSlideOne: function() {
var reasonsSurvey = HtmlUtils.HTML($('.reasons_survey'));
$('.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) {
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;
$('.action-unenroll').click(this.unenrollClick);
$('#unenroll_form').on('ajax:complete', this.unenrollComplete.bind(this));
$('#unregister_block_course').click(function(event) {
$('#unenroll_course_id').val($(event.target).data('course-id'));
$('#unenroll_course_number').text($(event.target).data('course-number'));
$('#unenroll_course_name').text($(event.target).data('course-name'));
});
}
});
}
);
}).call(this, define || RequireJS.define);
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'
}
},
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);
});
});
}
);
......@@ -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',
......
......@@ -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',
......
......@@ -1498,3 +1498,42 @@ a.fade-cover{
}
}
}
.reasons_survey {
padding: 20px;
.option {
margin-bottom: 10px;
display: block;
}
input {
margin-right: 10px;
}
.unenroll-header {
background-image: none;
}
.other_text {
margin-top: 10px;
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;
}
}
......@@ -42,6 +42,16 @@ 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}"
}
});
</%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 +254,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>
......
......@@ -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:
......
<%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}.
<a class="button survey_button return_to_dashboard">
${_('Return To Dashboard')}
</a>
<a class="button survey_button browse_courses">
${_('Browse Courses')}
</a>
</div>
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