Commit b47a6d59 by Simon Chen

ECOM-3415 make sure all the xseries programs associated with a course is displayed

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