Show number of problems in outline
Specifically, the number of 'problem' blocks that are graded, in a given subsection. Also shows an icon next to the subsection if so. AA-45
This commit is contained in:
@@ -10,7 +10,8 @@ import pytz
|
||||
from datetime import date, datetime, timedelta
|
||||
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import gettext as _
|
||||
from django.utils.translation import ngettext
|
||||
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
%>
|
||||
@@ -58,6 +59,7 @@ reset_deadlines_banner_displayed = False
|
||||
needs_prereqs = not gated_content[subsection['id']]['completed_prereqs'] if gated_subsection else False
|
||||
scored = 'scored' if subsection.get('scored', False) else ''
|
||||
graded = 'graded' if subsection.get('graded') else ''
|
||||
num_graded_problems = subsection.get('num_graded_problems', 0)
|
||||
due_date = subsection.get('due')
|
||||
overdue = due_date is not None and due_date < timezone.now() and not subsection.get('complete', True)
|
||||
%>
|
||||
@@ -77,8 +79,16 @@ reset_deadlines_banner_displayed = False
|
||||
class="subsection-text outline-button"
|
||||
id="${ subsection['id'] }"
|
||||
>
|
||||
% if num_graded_problems:
|
||||
<span class="icon fa fa-pencil-square-o" aria-hidden="true"></span>
|
||||
% endif
|
||||
<h4 class="subsection-title">
|
||||
${ subsection['display_name'] }
|
||||
% if num_graded_problems:
|
||||
${ngettext("({number} Question)",
|
||||
"({number} Questions)",
|
||||
num_graded_problems).format(number=num_graded_problems)}
|
||||
% endif
|
||||
</h4>
|
||||
% if subsection.get('complete'):
|
||||
<span class="complete-checkmark fa fa-check" aria-hidden="true"></span>
|
||||
|
||||
@@ -135,6 +135,34 @@ class TestCourseOutlinePage(SharedModuleStoreTestCase):
|
||||
self.assertContains(response, sequential.format)
|
||||
self.assertTrue(sequential.children)
|
||||
|
||||
def test_num_graded_problems(self):
|
||||
course = CourseFactory.create()
|
||||
with self.store.bulk_operations(course.id):
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
|
||||
sequential = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
problem = ItemFactory.create(category='problem', parent_location=sequential.location)
|
||||
sequential2 = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
problem2 = ItemFactory.create(category='problem', graded=True, has_score=True,
|
||||
parent_location=sequential2.location)
|
||||
sequential3 = ItemFactory.create(category='sequential', parent_location=chapter.location)
|
||||
problem3_1 = ItemFactory.create(category='problem', graded=True, has_score=True,
|
||||
parent_location=sequential3.location)
|
||||
problem3_2 = ItemFactory.create(category='problem', graded=True, has_score=True,
|
||||
parent_location=sequential3.location)
|
||||
course.children = [chapter]
|
||||
chapter.children = [sequential, sequential2, sequential3]
|
||||
sequential.children = [problem]
|
||||
sequential2.children = [problem2]
|
||||
sequential3.children = [problem3_1, problem3_2]
|
||||
CourseEnrollment.enroll(self.user, course.id)
|
||||
|
||||
url = course_home_url(course)
|
||||
response = self.client.get(url)
|
||||
content = response.content.decode('utf8')
|
||||
self.assertRegex(content, sequential.display_name + r'\s*</h4>')
|
||||
self.assertRegex(content, sequential2.display_name + r'\s*\(1 Question\)\s*</h4>')
|
||||
self.assertRegex(content, sequential3.display_name + r'\s*\(2 Questions\)\s*</h4>')
|
||||
|
||||
def test_reset_course_deadlines(self):
|
||||
course = self.courses[0]
|
||||
enrollment = CourseEnrollment.objects.get(course_id=course.id)
|
||||
|
||||
@@ -136,6 +136,21 @@ def get_course_outline_block_tree(request, course_id, user=None):
|
||||
block['scored'] = False
|
||||
return False
|
||||
|
||||
def recurse_num_graded_problems(block):
|
||||
"""
|
||||
Marks each block with the number of graded and scored leaf blocks below it as 'num_graded_problems'
|
||||
|
||||
Must be run after recurse_mark_scored.
|
||||
"""
|
||||
children = block.get('children', [])
|
||||
if children:
|
||||
num_graded_problems = sum(recurse_num_graded_problems(child) for child in children)
|
||||
else:
|
||||
num_graded_problems = 1 if block.get('scored') and block.get('graded') else 0
|
||||
|
||||
block['num_graded_problems'] = num_graded_problems
|
||||
return num_graded_problems
|
||||
|
||||
def recurse_mark_auth_denial(block):
|
||||
"""
|
||||
Mark this block as 'scored' if any of its descendents are 'scored' (that is, 'has_score' and 'weight' > 0).
|
||||
@@ -192,6 +207,7 @@ def get_course_outline_block_tree(request, course_id, user=None):
|
||||
if course_outline_root_block:
|
||||
populate_children(course_outline_root_block, all_blocks['blocks'])
|
||||
recurse_mark_scored(course_outline_root_block)
|
||||
recurse_num_graded_problems(course_outline_root_block)
|
||||
recurse_mark_auth_denial(course_outline_root_block)
|
||||
if user:
|
||||
set_last_accessed_default(course_outline_root_block)
|
||||
|
||||
Reference in New Issue
Block a user