Commit 72dd85ce by Renzo Lucioni

Modify program progress meter for use on detail pages

The meter now supports use with a single program, and can return serialized courses instead of counts when measuring progress.

ECOM-6602
parent 4baf18fe
......@@ -34,7 +34,7 @@ def program_listing(request):
'marketing_url': get_program_marketing_url(programs_config),
'nav_hidden': True,
'programs': meter.engaged_programs,
'progress': meter.progress,
'progress': meter.progress(),
'show_program_listing': programs_config.enabled,
'uses_pattern_library': True,
}
......@@ -50,7 +50,9 @@ def program_details(request, program_uuid):
if not programs_config.enabled:
raise Http404
program_data = get_programs(uuid=program_uuid)
meter = ProgramProgressMeter(request.user, uuid=program_uuid)
program_data = meter.programs[0]
if not program_data:
raise Http404
......@@ -65,7 +67,6 @@ def program_details(request, program_uuid):
}
context = {
'program_data': program_data,
'urls': urls,
'show_program_listing': programs_config.enabled,
'nav_hidden': True,
......@@ -75,6 +76,16 @@ def program_details(request, program_uuid):
}
if waffle.switch_is_active('new_program_progress'):
course_progress = meter.progress(programs=[program_data], count_only=False)[0]
program_data.pop('courses')
context.update({
'program_data': program_data,
'course_progress': course_progress,
})
return render_to_response('learner_dashboard/program_details_2017.html', context)
else:
context.update({'program_data': program_data})
return render_to_response('learner_dashboard/program_details.html', context)
......@@ -53,7 +53,7 @@ class TestProgramProgressMeter(TestCase):
def _assert_progress(self, meter, *progresses):
"""Variadic helper used to verify progress calculations."""
self.assertEqual(meter.progress, list(progresses))
self.assertEqual(meter.progress(), list(progresses))
def _attach_detail_url(self, programs):
"""Add expected detail URLs to a list of program dicts."""
......@@ -113,6 +113,39 @@ class TestProgramProgressMeter(TestCase):
)
self.assertEqual(meter.completed_programs, [])
def test_course_progress(self, mock_get_programs):
"""
Verify that the progress meter can represent progress in terms of
serialized courses.
"""
course_run_key = generate_course_run_key()
data = [
ProgramFactory(
courses=[
CourseFactory(course_runs=[
CourseRunFactory(key=course_run_key),
]),
]
)
]
mock_get_programs.return_value = data
self._create_enrollments(course_run_key)
meter = ProgramProgressMeter(self.user)
program = data[0]
expected = [
ProgressFactory(
uuid=program['uuid'],
completed=[],
in_progress=[program['courses'][0]],
not_started=[]
)
]
self.assertEqual(meter.progress(count_only=False), expected)
def test_mutiple_program_engagement(self, mock_get_programs):
"""
Verify that correct programs are returned in the correct order when the
......
......@@ -57,8 +57,11 @@ class ProgramProgressMeter(object):
Keyword Arguments:
enrollments (list): List of the user's enrollments.
uuid (str): UUID identifying a specific program. If provided, the meter
will only inspect this one program, not all programs the user may be
engaged with.
"""
def __init__(self, user, enrollments=None):
def __init__(self, user, enrollments=None, uuid=None):
self.user = user
self.enrollments = enrollments or list(CourseEnrollment.enrollments_for_user(self.user))
......@@ -67,6 +70,9 @@ class ProgramProgressMeter(object):
# enrollment.course_id is really a CourseKey (╯ಠ_ಠ)╯︵ ┻━┻
self.course_run_ids = [unicode(e.course_id) for e in self.enrollments]
if uuid:
self.programs = [get_programs(uuid=uuid)]
else:
self.programs = attach_program_detail_url(get_programs())
def invert_programs(self):
......@@ -119,31 +125,39 @@ class ProgramProgressMeter(object):
return programs
@property
def progress(self):
def progress(self, programs=None, count_only=True):
"""Gauge a user's progress towards program completion.
Keyword Arguments:
programs (list): Specific list of programs to check the user's progress
against. If left unspecified, self.engaged_programs will be used.
count_only (bool): Whether or not to return counts of completed, in
progress, and unstarted courses instead of serialized representations
of the courses.
Returns:
list of dict, each containing information about a user's progress
towards completing a program.
"""
progress = []
for program in self.engaged_programs:
completed, in_progress, not_started = 0, 0, 0
programs = programs or self.engaged_programs
for program in programs:
completed, in_progress, not_started = [], [], []
for course in program['courses']:
if self._is_course_complete(course):
completed += 1
completed.append(course)
elif self._is_course_in_progress(course):
in_progress += 1
in_progress.append(course)
else:
not_started += 1
not_started.append(course)
progress.append({
'uuid': program['uuid'],
'completed': completed,
'in_progress': in_progress,
'not_started': not_started,
'completed': len(completed) if count_only else completed,
'in_progress': len(in_progress) if count_only else in_progress,
'not_started': len(not_started) if count_only else not_started,
})
return progress
......
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