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
This commit is contained in:
@@ -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,7 +70,10 @@ class ProgramProgressMeter(object):
|
||||
# enrollment.course_id is really a CourseKey (╯ಠ_ಠ)╯︵ ┻━┻
|
||||
self.course_run_ids = [unicode(e.course_id) for e in self.enrollments]
|
||||
|
||||
self.programs = attach_program_detail_url(get_programs())
|
||||
if uuid:
|
||||
self.programs = [get_programs(uuid=uuid)]
|
||||
else:
|
||||
self.programs = attach_program_detail_url(get_programs())
|
||||
|
||||
def invert_programs(self):
|
||||
"""Intersect programs and enrollments.
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user