Commit f9f4876b by Bill Filler

Add 'View Consent' button to dashboard when required

Enterprise customers can require user to agree to Data Sharing Consent
form before they can access a course. We now add it conditionally to
Course Dashboard when it's required so it's apparent to user and they
have a way to revist the consent form if they've previously declined or
the course has not yet started.

WL-1281
parent dbad9fbc
......@@ -7,6 +7,7 @@ import json
import unittest
import ddt
import mock
import pytz
from django.conf import settings
from django.core.urlresolvers import reverse
......@@ -335,3 +336,43 @@ class StudentDashboardTests(SharedModuleStoreTestCase, MilestonesTestCaseMixin):
remove_prerequisite_course(self.course.id, get_course_milestones(self.course.id)[0])
response = self.client.get(reverse('dashboard'))
self.assertNotIn('<div class="prerequisites">', response.content)
@mock.patch('student.views.consent_needed_for_course')
@mock.patch('student.views.enterprise_customer_for_request')
@ddt.data(
(True, True, True),
(True, True, False),
(True, False, False),
(False, True, False),
(False, False, False),
)
@ddt.unpack
def test_enterprise_view_consent_for_course(
self,
enterprise_enabled,
consent_needed,
future_course,
mock_enterprise_customer,
mock_consent_necessary
):
"""
Verify that the 'View Consent' icon show up if data sharing consent turned on
for enterprise customer
"""
if future_course:
self.course = CourseFactory.create(start=self.TOMORROW, emit_signals=True)
else:
self.course = CourseFactory.create(emit_signals=True)
self.course_enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user)
if enterprise_enabled:
mock_enterprise_customer.return_value = {'name': 'TestEnterprise', 'uuid': 'abc123xxx'}
else:
mock_enterprise_customer.return_value = None
mock_consent_necessary.return_value = consent_needed
# Assert 'View Consent' button shows up appropriately
response = self.client.get(reverse('dashboard'))
self.assertEquals('View Consent' in response.content, enterprise_enabled and consent_needed)
self.assertEquals('TestEnterprise' in response.content, enterprise_enabled and consent_needed)
......@@ -87,7 +87,11 @@ from openedx.core.djangoapps.theming import helpers as theming_helpers
from openedx.core.djangoapps.user_api.preferences import api as preferences_api
from openedx.core.djangolib.markup import HTML
from openedx.features.course_experience import course_home_url_name
from openedx.features.enterprise_support.api import get_dashboard_consent_notification
from openedx.features.enterprise_support.api import (
consent_needed_for_course,
enterprise_customer_for_request,
get_dashboard_consent_notification
)
from shoppingcart.api import order_history
from shoppingcart.models import CourseRegistrationCode, DonationConfiguration
from student.cookies import delete_logged_in_cookies, set_logged_in_cookies, set_user_info_cookie
......@@ -729,6 +733,16 @@ def dashboard(request):
enterprise_message = get_dashboard_consent_notification(request, user, course_enrollments)
enterprise_customer = enterprise_customer_for_request(request)
consent_required_courses = set()
enterprise_customer_name = None
if enterprise_customer:
consent_required_courses = {
enrollment.course_id for enrollment in course_enrollments
if consent_needed_for_course(request, request.user, str(enrollment.course_id), True)
}
enterprise_customer_name = enterprise_customer['name']
# Account activation message
account_activation_messages = [
message for message in messages.get_messages(request) if 'account-activation' in message.tags
......@@ -847,6 +861,8 @@ def dashboard(request):
context = {
'enterprise_message': enterprise_message,
'consent_required_courses': consent_required_courses,
'enterprise_customer_name': enterprise_customer_name,
'enrollment_message': enrollment_message,
'redirect_message': redirect_message,
'account_activation_messages': account_activation_messages,
......
......@@ -721,7 +721,7 @@
@include clearfix();
position: relative;
position: inherit;
@include left($baseline/2);
@include padding(($baseline * 0.4), 0, ($baseline * 0.4), ($baseline * 0.75));
......@@ -772,6 +772,15 @@
opacity: 0.875;
}
}
.action-view-consent {
@extend %btn-pl-white-base;
@include float(right);
&.archived {
@extend %btn-pl-default-base;
}
}
}
// TYPE: status
......
......@@ -128,7 +128,8 @@ from openedx.core.djangolib.markup import HTML, Text
<% course_verification_status = verification_status_by_course.get(enrollment.course_id, {}) %>
<% course_requirements = courses_requirements_not_met.get(enrollment.course_id) %>
<% related_programs = inverted_programs.get(unicode(enrollment.course_id)) %>
<%include file='dashboard/_dashboard_course_listing.html' args='course_overview=enrollment.course_overview, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, is_course_blocked=is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard' />
<% show_consent_link = (enrollment.course_id in consent_required_courses) %>
<%include file='dashboard/_dashboard_course_listing.html' args='course_overview=enrollment.course_overview, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, can_unenroll=can_unenroll, credit_status=credit_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, is_paid_course=is_paid_course, is_course_blocked=is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements, dashboard_index=dashboard_index, share_settings=share_settings, user=user, related_programs=related_programs, display_course_modes_on_dashboard=display_course_modes_on_dashboard, show_consent_link=show_consent_link, enterprise_customer_name=enterprise_customer_name' />
% endfor
</ul>
......
<%page args="course_overview, enrollment, show_courseware_link, cert_status, can_unenroll, credit_status, show_email_settings, course_mode_info, is_paid_course, is_course_blocked, verification_status, course_requirements, dashboard_index, share_settings, related_programs, display_course_modes_on_dashboard" expression_filter="h"/>
<%page args="course_overview, enrollment, show_courseware_link, cert_status, can_unenroll, credit_status, show_email_settings, course_mode_info, is_paid_course, is_course_blocked, verification_status, course_requirements, dashboard_index, share_settings, related_programs, display_course_modes_on_dashboard, show_consent_link, enterprise_customer_name" expression_filter="h"/>
<%!
import urllib
......@@ -289,7 +289,33 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
<%include file="_dashboard_credit_info.html" args="credit_status=credit_status"/>
% endif
% if verification_status.get('status') in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED, VERIFY_STATUS_RESUBMITTED, VERIFY_STATUS_APPROVED, VERIFY_STATUS_NEED_TO_REVERIFY] and not is_course_blocked:
% if is_course_blocked:
<p id="block-course-msg" class="course-block">
${Text(_("You can no longer access this course because payment has not yet been received. "
"You can {contact_link_start}contact the account holder{contact_link_end} "
"to request payment, or you can "
"{unenroll_link_start}unenroll{unenroll_link_end} "
"from this course")).format(
contact_link_start=HTML('<button type="button">'),
contact_link_end=HTML('</button>'),
unenroll_link_start=HTML(
'<a id="unregister_block_course" rel="leanModal" '
'data-course-id="{course_id}" data-course-number="{course_number}" data-course-name="{course_name}" '
'href="#unenroll-modal">'
).format(
course_id=course_overview.id,
course_number=course_overview.number,
course_name=course_overview.display_name_with_default,
),
unenroll_link_end=HTML('</a>'),
)}
</p>
% else:
% if show_consent_link:
<%include file="_dashboard_show_consent.html" args="course_overview=course_overview, course_target=course_target, enrollment=enrollment, enterprise_customer_name=enterprise_customer_name"/>
%endif
% if verification_status.get('status') in [VERIFY_STATUS_NEED_TO_VERIFY, VERIFY_STATUS_SUBMITTED, VERIFY_STATUS_RESUBMITTED, VERIFY_STATUS_APPROVED, VERIFY_STATUS_NEED_TO_REVERIFY]:
<div class="message message-status wrapper-message-primary is-shown">
% if verification_status['status'] == VERIFY_STATUS_NEED_TO_VERIFY:
<div class="verification-reminder">
......@@ -333,9 +359,8 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
</div>
% endif
% if course_mode_info['show_upsell'] and not is_course_blocked:
% if course_mode_info['show_upsell']:
<div class="message message-upsell has-actions is-shown">
<div class="wrapper-extended">
<p class="message-copy" align="justify">
<b class="message-copy-bold">
......@@ -368,31 +393,8 @@ from util.course import get_link_for_about_page, get_encoded_course_sharing_utm_
</div>
</div>
</div>
%endif
% if is_course_blocked:
<p id="block-course-msg" class="course-block">
${Text(_("You can no longer access this course because payment has not yet been received. "
"You can {contact_link_start}contact the account holder{contact_link_end} "
"to request payment, or you can "
"{unenroll_link_start}unenroll{unenroll_link_end} "
"from this course")).format(
contact_link_start=HTML('<button type="button">'),
contact_link_end=HTML('</button>'),
unenroll_link_start=HTML(
'<a id="unregister_block_course" rel="leanModal" '
'data-course-id="{course_id}" data-course-number="{course_number}" data-course-name="{course_name}" '
'href="#unenroll-modal">'
).format(
course_id=course_overview.id,
course_number=course_overview.number,
course_name=course_overview.display_name_with_default,
),
unenroll_link_end=HTML('</a>'),
)}
</p>
%endif
% endif
% endif
% if course_requirements:
## Multiple pre-requisite courses are not supported on frontend that's why we are pulling first element
......
<%page expression_filter="h" args="course_overview, course_target, enrollment, enterprise_customer_name" />
<%!
from django.utils.translation import ugettext as _
%>
<%namespace name='static' file='../static_content.html'/>
<div class="message message-upsell has-actions is-shown">
<div class="wrapper-extended">
<p class="message-copy" align="justify">
<b class="message-copy-bold">
${_("Consent to share your data")}
</b>
<br>
${_("To access this course, you must first consent to share your learning achievements with {enterprise_customer_name}.").format(enterprise_customer_name=enterprise_customer_name)}
</p>
<div class="action-upgrade-container">
<a class="action action-view-consent" href="${course_target}" data-course-key="${enrollment.course_id}">
<span class="wrapper-copy">
<span class="copy" id="view-consent">${_("View Consent")}</span>
<span class="sr">&nbsp;${_(course_overview.display_name_with_default)}</span>
</span>
</a>
</div>
</div>
</div>
\ No newline at end of file
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