diff --git a/lms/djangoapps/courseware/courses.py b/lms/djangoapps/courseware/courses.py index f87c0004e3..72b69b456f 100644 --- a/lms/djangoapps/courseware/courses.py +++ b/lms/djangoapps/courseware/courses.py @@ -72,7 +72,8 @@ log = logging.getLogger(__name__) # Used by get_course_assignments below. You shouldn't need to use this type directly. _Assignment = namedtuple( - 'Assignment', ['block_key', 'title', 'url', 'date', 'contains_gated_content', 'complete', 'past_due'] + 'Assignment', ['block_key', 'title', 'url', 'date', 'contains_gated_content', 'complete', 'past_due', + 'assignment_type'] ) @@ -505,6 +506,7 @@ def get_course_assignment_date_blocks(course, user, request, num_return=None, date_block.date = assignment.date date_block.contains_gated_content = assignment.contains_gated_content date_block.complete = assignment.complete + date_block.assignment_type = assignment.assignment_type date_block.past_due = assignment.past_due date_block.link = assignment.url date_block.set_title(assignment.title, link=assignment.url) @@ -520,7 +522,8 @@ def get_course_assignments(course_key, user, request, include_access=False): """ Returns a list of assignment (at the subsection/sequential level) due dates for the given course. - Each returned object is a namedtuple with fields: title, url, date, contains_gated_content, complete, past_due + Each returned object is a namedtuple with fields: title, url, date, contains_gated_content, complete, past_due, + assignment_type """ store = modulestore() course_usage_key = store.make_course_usage_key(course_key) @@ -539,6 +542,8 @@ def get_course_assignments(course_key, user, request, include_access=False): subsection_key, 'contains_gated_content', False) title = block_data.get_xblock_field(subsection_key, 'display_name', _('Assignment')) + assignment_type = block_data.get_xblock_field(subsection_key, 'format', None) + url = '' start = block_data.get_xblock_field(subsection_key, 'start') assignment_released = not start or start < now @@ -549,7 +554,7 @@ def get_course_assignments(course_key, user, request, include_access=False): complete = block_data.get_xblock_field(subsection_key, 'complete', False) past_due = not complete and due < now assignments.append(_Assignment( - subsection_key, title, url, due, contains_gated_content, complete, past_due + subsection_key, title, url, due, contains_gated_content, complete, past_due, assignment_type )) return assignments diff --git a/lms/djangoapps/courseware/tests/test_date_summary.py b/lms/djangoapps/courseware/tests/test_date_summary.py index d52a2aaca5..f2b31be836 100644 --- a/lms/djangoapps/courseware/tests/test_date_summary.py +++ b/lms/djangoapps/courseware/tests/test_date_summary.py @@ -165,6 +165,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=now - timedelta(days=1), due=now + timedelta(days=6), graded=True, + format='Homework', ) ItemFactory.create( category='sequential', @@ -173,6 +174,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=now + timedelta(days=1), due=now + timedelta(days=7), graded=True, + format='Homework', ) ItemFactory.create( category='sequential', @@ -181,6 +183,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=now + timedelta(days=1), due=now + timedelta(days=8), graded=True, + format='Exam', ) ItemFactory.create( category='sequential', @@ -189,6 +192,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=now - timedelta(days=14), due=now - timedelta(days=7), graded=True, + format='Exam', ) ItemFactory.create( category='sequential', @@ -205,6 +209,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=None, due=now + timedelta(days=9), graded=True, + format='Speech', ) ItemFactory.create( category='sequential', @@ -214,6 +219,7 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): start=now - timedelta(days=14), due=now + timedelta(days=10), graded=True, + format=None, ) dummy_subsection = ItemFactory.create(category='sequential', graded=True, due=now + timedelta(days=11)) @@ -257,28 +263,37 @@ class CourseDateSummaryTest(SharedModuleStoreTestCase): for assignment in assignment_blocks: assignment_title = str(assignment.title_html) or str(assignment.title) self.assertNotEqual(assignment_title, 'Not returned since we do not get non-graded subsections') + + assignment_type = str(assignment.assignment_type) # checking if it is _in_ the title instead of being the title since released assignments # are actually links. Unreleased assignments are just the string of the title. + # also checking that the assignment type is returned for graded subsections if 'Released' in assignment_title: + self.assertEqual(assignment_type, 'Homework') for html_tag in assignment_title_html: self.assertIn(html_tag, assignment_title) elif assignment_title == 'Not released': + self.assertEqual(assignment_type, 'Homework') for html_tag in assignment_title_html: self.assertNotIn(html_tag, assignment_title) elif assignment_title == 'Third nearest assignment': + self.assertEqual(assignment_type, 'Exam') # It's still not released for html_tag in assignment_title_html: self.assertNotIn(html_tag, assignment_title) elif 'Past due date' in assignment_title: self.assertGreater(now, assignment.date) + self.assertEqual(assignment_type, 'Exam') for html_tag in assignment_title_html: self.assertIn(html_tag, assignment_title) elif 'No start date' == assignment_title: + self.assertEqual(assignment_type, 'Speech') # Can't determine if it is released so it does not get a link for html_tag in assignment_title_html: self.assertNotIn(html_tag, assignment_title) # This is the item with no display name where we set one ourselves. elif 'Assignment' in assignment_title: + self.assertEqual(assignment_type, None) # Can't determine if it is released so it does not get a link for html_tag in assignment_title_html: self.assertIn(html_tag, assignment_title) diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py index 5d89cfbe2d..5adcbf55f7 100644 --- a/lms/djangoapps/courseware/tests/test_views.py +++ b/lms/djangoapps/courseware/tests/test_views.py @@ -3117,6 +3117,7 @@ class DatesTabTestCase(ModuleStoreTestCase): start=now - timedelta(days=1), due=now + timedelta(days=1), # Setting this to tomorrow so it'll show the 'Due Next' pill graded=True, + format='Homework', ) vertical = ItemFactory.create(category='vertical', parent_location=subsection.location) ItemFactory.create(category='problem', parent_location=vertical.location) @@ -3135,6 +3136,8 @@ class DatesTabTestCase(ModuleStoreTestCase): self.assertContains(response, '
') # No pills for verified enrollments self.assertNotContains(response, '
') + # Make sure the assignment type is rendered + self.assertContains(response, 'Homework:') enrollment.delete() enrollment = CourseEnrollmentFactory(course_id=self.course.id, user=self.user, mode=CourseMode.AUDIT) @@ -3158,6 +3161,8 @@ class DatesTabTestCase(ModuleStoreTestCase): self.assertNotContains(response, '
') # Should have verified pills for audit enrollments self.assertContains(response, '
') + # Make sure the assignment type is rendered + self.assertContains(response, 'Homework:') @RELATIVE_DATES_FLAG.override(active=True) def test_reset_deadlines_banner_displays(self): diff --git a/lms/templates/courseware/dates.html b/lms/templates/courseware/dates.html index 926eb43e12..f140089522 100644 --- a/lms/templates/courseware/dates.html +++ b/lms/templates/courseware/dates.html @@ -33,6 +33,7 @@ from openedx.core.djangolib.markup import HTML, Text <% learner_has_access = not block_is_verified or learner_is_full_access %> <% access_class = '' if learner_has_access else 'no-access' %> <% is_assignment = isinstance(block, CourseAssignmentDate) %> + <% assignment_type = is_assignment and block.assignment_type %> <% todays_date = 'todays-date' if isinstance(block, TodaysDate) else '' %> <% past_date = 'past-date' if block.date and block.date < block.current_time else '' %> <% past_due = 'past-due' if learner_is_full_access and is_assignment and block.past_due else '' %> @@ -69,6 +70,9 @@ from openedx.core.djangolib.markup import HTML, Text
% if not todays_date:
+ % if assignment_type: + ${assignment_type}:  + % endif % if block.title_html and is_assignment and learner_has_access: ${block.title_html} % else: diff --git a/openedx/features/calendar_sync/tests/test_ics.py b/openedx/features/calendar_sync/tests/test_ics.py index a0bfe91dcd..bd0892ce36 100644 --- a/openedx/features/calendar_sync/tests/test_ics.py +++ b/openedx/features/calendar_sync/tests/test_ics.py @@ -33,10 +33,10 @@ class TestIcsGeneration(TestCase): def make_assigment( self, block_key=None, title=None, url=None, date=None, contains_gated_content=False, complete=False, - past_due=False + past_due=False, assignment_type=None ): """ Bundles given info into a namedtupled like get_course_assignments returns """ - return _Assignment(block_key, title, url, date, contains_gated_content, complete, past_due) + return _Assignment(block_key, title, url, date, contains_gated_content, complete, past_due, assignment_type) def expected_ics(self, *assignments): """ Returns hardcoded expected ics strings for given assignments """