Merge pull request #11725 from edx/schen/ECOM-3415
ECOM-3415 - Dashboard should show all XSeries association messages
This commit is contained in:
@@ -933,7 +933,7 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
_id = 0
|
||||
|
||||
for course, program_status in data:
|
||||
programs[unicode(course)] = {
|
||||
programs[unicode(course)] = [{
|
||||
'id': _id,
|
||||
'category': self.category,
|
||||
'organization': {'display_name': 'Test Organization 1', 'key': 'edX'},
|
||||
@@ -958,7 +958,7 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
],
|
||||
'subtitle': 'sub',
|
||||
'name': self.program_name
|
||||
}
|
||||
}]
|
||||
|
||||
_id += 1
|
||||
|
||||
@@ -975,7 +975,7 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
"""Verify that program data is parsed correctly for a given course"""
|
||||
with patch('student.views.get_programs_for_dashboard') as mock_data:
|
||||
mock_data.return_value = {
|
||||
u'edx/demox/Run_1': {
|
||||
u'edx/demox/Run_1': [{
|
||||
'id': 0,
|
||||
'category': self.category,
|
||||
'organization': {'display_name': 'Test Organization 1', 'key': 'edX'},
|
||||
@@ -984,7 +984,7 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
'course_codes': course_codes,
|
||||
'subtitle': 'sub',
|
||||
'name': self.program_name
|
||||
}
|
||||
}]
|
||||
}
|
||||
parse_data = _get_course_programs(
|
||||
self.user, [
|
||||
@@ -998,14 +998,16 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
self.assertEqual(
|
||||
{
|
||||
u'edx/demox/Run_1': {
|
||||
'program_id': 0,
|
||||
'category': 'xseries',
|
||||
'course_count': len(course_codes),
|
||||
'display_name': self.program_name,
|
||||
'program_marketing_url': urljoin(
|
||||
settings.MKTG_URLS.get('ROOT'), 'xseries' + '/{}'
|
||||
).format(marketing_slug),
|
||||
'display_category': 'XSeries'
|
||||
'display_category': 'XSeries',
|
||||
'course_program_list': [{
|
||||
'program_id': 0,
|
||||
'course_count': len(course_codes),
|
||||
'display_name': self.program_name,
|
||||
'program_marketing_url': urljoin(
|
||||
settings.MKTG_URLS.get('ROOT'), 'xseries' + '/{}'
|
||||
).format(marketing_slug)
|
||||
}]
|
||||
}
|
||||
},
|
||||
parse_data
|
||||
@@ -1122,8 +1124,9 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
self.create_programs_config()
|
||||
|
||||
program_data = self._create_program_data([(self.course_1.id, 'active')])
|
||||
if key_remove and key_remove in program_data[unicode(self.course_1.id)]:
|
||||
del program_data[unicode(self.course_1.id)][key_remove]
|
||||
for program in program_data[unicode(self.course_1.id)]:
|
||||
if key_remove and key_remove in program:
|
||||
del program[key_remove]
|
||||
|
||||
with patch('student.views.get_programs_for_dashboard') as mock_data:
|
||||
mock_data.return_value = program_data
|
||||
@@ -1135,7 +1138,7 @@ class DashboardTestXSeriesPrograms(ModuleStoreTestCase, ProgramsApiConfigMixin):
|
||||
log_warn.assert_called_with(
|
||||
'Program structure is invalid, skipping display: %r', program_data[
|
||||
unicode(self.course_1.id)
|
||||
]
|
||||
][0]
|
||||
)
|
||||
# verify that no programs related upsell messages appear on the
|
||||
# student dashboard.
|
||||
|
||||
@@ -2421,26 +2421,29 @@ def _get_course_programs(user, user_enrolled_courses): # pylint: disable=invali
|
||||
the given user has active enrollments.
|
||||
|
||||
Returns:
|
||||
dict, containing programs keyed by course. Empty if programs cannot be retrieved.
|
||||
dict, containing programs keyed by course.
|
||||
"""
|
||||
course_programs = get_programs_for_dashboard(user, user_enrolled_courses)
|
||||
programs_data = {}
|
||||
|
||||
for course_key, program in course_programs.viewitems():
|
||||
if program.get('status') == 'active' and program.get('category') == 'xseries':
|
||||
try:
|
||||
programs_data[course_key] = {
|
||||
'course_count': len(program['course_codes']),
|
||||
'display_name': program['name'],
|
||||
'category': program.get('category'),
|
||||
'program_id': program['id'],
|
||||
'program_marketing_url': urljoin(
|
||||
settings.MKTG_URLS.get('ROOT'), 'xseries' + '/{}'
|
||||
).format(program['marketing_slug']),
|
||||
'display_category': 'XSeries'
|
||||
}
|
||||
except KeyError:
|
||||
log.warning('Program structure is invalid, skipping display: %r', program)
|
||||
for course_key, programs in course_programs.viewitems():
|
||||
for program in programs:
|
||||
if program.get('status') == 'active' and program.get('category') == 'xseries':
|
||||
try:
|
||||
programs_for_course = programs_data.setdefault(course_key, {})
|
||||
programs_for_course.setdefault('course_program_list', []).append({
|
||||
'course_count': len(program['course_codes']),
|
||||
'display_name': program['name'],
|
||||
'program_id': program['id'],
|
||||
'program_marketing_url': urljoin(
|
||||
settings.MKTG_URLS.get('ROOT'),
|
||||
'xseries' + '/{}'
|
||||
).format(program['marketing_slug'])
|
||||
})
|
||||
programs_for_course['display_category'] = 'XSeries'
|
||||
programs_for_course['category'] = program.get('category')
|
||||
except KeyError:
|
||||
log.warning('Program structure is invalid, skipping display: %r', program)
|
||||
|
||||
return programs_data
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ from student.helpers import (
|
||||
<% mode_class = '' %>
|
||||
% endif
|
||||
<div class="course-container">
|
||||
% if course_program_info and course_program_info['category']=='xseries':
|
||||
% if course_program_info and course_program_info.get('category')=='xseries':
|
||||
<div class="label-xseries-association">
|
||||
<i class="xseries-icon"></i>
|
||||
<p class="message-copy">${_("{category} Program Course").format(category=course_program_info['display_category'])}</p>
|
||||
@@ -345,8 +345,10 @@ from student.helpers import (
|
||||
</div>
|
||||
%endif
|
||||
|
||||
% if course_program_info and course_program_info['category']=='xseries':
|
||||
<%include file = "_dashboard_xseries_info.html" args="course_program_info=course_program_info, enrollment_mode=enrollment.mode" />
|
||||
% if course_program_info and course_program_info.get('category')=='xseries':
|
||||
%for program_data in course_program_info.get('course_program_list', []):
|
||||
<%include file = "_dashboard_xseries_info.html" args="program_data=program_data, enrollment_mode=enrollment.mode, display_category=course_program_info['display_category']" />
|
||||
%endfor
|
||||
% endif
|
||||
|
||||
% if is_course_blocked:
|
||||
|
||||
@@ -1,36 +1,34 @@
|
||||
<%page args="course_program_info, enrollment_mode" />
|
||||
<%page args="program_data, enrollment_mode, display_category" />
|
||||
<%!
|
||||
from django.utils.translation import ugettext as _
|
||||
%>
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
<div class="message message-status is-shown credit-message">
|
||||
<div class="xseries-action">
|
||||
<div class="message-copy xseries-msg">
|
||||
<p>
|
||||
<b class="message-copy-bold">${_("{category} Program: Interested in more courses in this subject?").format(category=course_program_info['display_category'])}</b>
|
||||
</p>
|
||||
<p class="message-copy">
|
||||
${_("This course is 1 of {course_count} courses in the {link_start}{program_display_name}{link_end} {program_category}.").format(
|
||||
course_count=course_program_info['course_count'],
|
||||
link_start='<a href="{}">'.format(course_program_info['program_marketing_url']),
|
||||
link_end='</a>',
|
||||
program_display_name=course_program_info['display_name'],
|
||||
program_category=course_program_info['display_category'],
|
||||
)}
|
||||
</p>
|
||||
<div class="message message-status is-shown credit-message">
|
||||
<div class="xseries-action">
|
||||
<div class="message-copy xseries-msg">
|
||||
<p class="message-copy-bold">
|
||||
${_("{category} Program: Interested in more courses in this subject?").format(category=display_category)}
|
||||
</p>
|
||||
<p class="message-copy">
|
||||
${_("This course is 1 of {course_count} courses in the {link_start}{program_display_name}{link_end} {program_category}.").format(
|
||||
course_count=program_data['course_count'],
|
||||
link_start='<a href="{}">'.format(program_data['program_marketing_url']),
|
||||
link_end='</a>',
|
||||
program_display_name=program_data['display_name'],
|
||||
program_category=display_category,
|
||||
)}
|
||||
</p>
|
||||
|
||||
</div>
|
||||
<%
|
||||
xseries_btn_class = "xseries-border-btn"
|
||||
if enrollment_mode == "verified":
|
||||
xseries_btn_class = "xseries-base-btn";
|
||||
%>
|
||||
<a class="btn ${xseries_btn_class}" href="${program_data['program_marketing_url']}" target="_blank"
|
||||
data-program-id="${program_data['program_id']}" >
|
||||
<i class="action-xseries-icon" aria-hidden="true"></i>
|
||||
${_("View {category} Details").format(category=display_category)}
|
||||
</a>
|
||||
</div>
|
||||
<%
|
||||
xseries_btn_class = "xseries-border-btn"
|
||||
if enrollment_mode == "verified":
|
||||
xseries_btn_class = "xseries-base-btn";
|
||||
%>
|
||||
<a class="btn ${xseries_btn_class}" href="${course_program_info['program_marketing_url']}" target="_blank"
|
||||
data-program-id="${course_program_info['program_id']}" >
|
||||
<i class="action-xseries-icon"></i>
|
||||
<span>
|
||||
${_("View {category} Details").format(category=course_program_info['display_category'])}
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -107,7 +107,7 @@ class TestProgramRetrieval(ProgramsApiConfigMixin, ProgramsDataMixin,
|
||||
for course_code in program['course_codes']:
|
||||
for run in course_code['run_modes']:
|
||||
course_key = run['course_key']
|
||||
expected[course_key] = program
|
||||
expected.setdefault(course_key, []).append(program)
|
||||
|
||||
self.assertEqual(actual, expected)
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ def get_programs_for_dashboard(user, course_keys):
|
||||
# Reindex the result returned by the Programs API from:
|
||||
# program -> course code -> course run
|
||||
# to:
|
||||
# course run -> program
|
||||
# course run -> program_array
|
||||
# Ignore course runs not present in the user's active enrollments.
|
||||
for program in programs:
|
||||
try:
|
||||
@@ -69,7 +69,7 @@ def get_programs_for_dashboard(user, course_keys):
|
||||
for run in course_code['run_modes']:
|
||||
course_key = run['course_key']
|
||||
if course_key in course_keys:
|
||||
course_programs[course_key] = program
|
||||
course_programs.setdefault(course_key, []).append(program)
|
||||
except KeyError:
|
||||
log.exception('Unable to parse Programs API response: %r', program)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user