Made dates configuration for CCX schedule same as in studio (Course)
This commit is contained in:
@@ -52,6 +52,7 @@ from ccx_keys.locator import CCXLocator
|
||||
from lms.djangoapps.ccx.models import CustomCourseForEdX
|
||||
from lms.djangoapps.ccx.overrides import get_override_for_ccx, override_field_for_ccx
|
||||
from lms.djangoapps.ccx.tests.factories import CcxFactory
|
||||
from lms.djangoapps.ccx.views import get_date
|
||||
|
||||
|
||||
def intercept_renderer(path, context):
|
||||
@@ -290,6 +291,21 @@ class TestCoachDashboard(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
role = CourseCcxCoachRole(course_key)
|
||||
self.assertTrue(role.has_user(self.coach))
|
||||
|
||||
def test_get_date(self):
|
||||
"""
|
||||
Assert that get_date returns valid date.
|
||||
"""
|
||||
ccx = self.make_ccx()
|
||||
for section in self.course.get_children():
|
||||
self.assertEqual(get_date(ccx, section, 'start'), self.mooc_start)
|
||||
self.assertEqual(get_date(ccx, section, 'due'), None)
|
||||
for subsection in section.get_children():
|
||||
self.assertEqual(get_date(ccx, subsection, 'start'), self.mooc_start)
|
||||
self.assertEqual(get_date(ccx, subsection, 'due'), self.mooc_due)
|
||||
for unit in subsection.get_children():
|
||||
self.assertEqual(get_date(ccx, unit, 'start', parent_node=subsection), self.mooc_start)
|
||||
self.assertEqual(get_date(ccx, unit, 'due', parent_node=subsection), self.mooc_due)
|
||||
|
||||
@SharedModuleStoreTestCase.modifies_courseware
|
||||
@patch('ccx.views.render_to_response', intercept_renderer)
|
||||
@patch('ccx.views.TODAY')
|
||||
@@ -341,15 +357,24 @@ class TestCoachDashboard(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
kwargs={'course_id': CCXLocator.from_course_locator(self.course.id, ccx.id)})
|
||||
response = self.client.get(url)
|
||||
schedule = json.loads(response.mako_context['schedule']) # pylint: disable=no-member
|
||||
|
||||
self.assertEqual(len(schedule), 2)
|
||||
self.assertEqual(schedule[0]['hidden'], False)
|
||||
self.assertEqual(schedule[0]['start'], None)
|
||||
self.assertEqual(schedule[0]['children'][0]['start'], None)
|
||||
self.assertEqual(schedule[0]['due'], None)
|
||||
self.assertEqual(schedule[0]['children'][0]['due'], None)
|
||||
# If a coach does not override dates, then dates will be imported from master course.
|
||||
self.assertEqual(
|
||||
schedule[0]['children'][0]['children'][0]['due'], None
|
||||
schedule[0]['start'],
|
||||
self.chapters[0].start.strftime('%Y-%m-%d %H:%M')
|
||||
)
|
||||
self.assertEqual(
|
||||
schedule[0]['children'][0]['start'],
|
||||
self.sequentials[0].start.strftime('%Y-%m-%d %H:%M')
|
||||
)
|
||||
|
||||
if self.sequentials[0].due:
|
||||
expected_due = self.sequentials[0].due.strftime('%Y-%m-%d %H:%M')
|
||||
else:
|
||||
expected_due = None
|
||||
self.assertEqual(schedule[0]['children'][0]['due'], expected_due)
|
||||
|
||||
url = reverse(
|
||||
'save_ccx',
|
||||
@@ -392,7 +417,7 @@ class TestCoachDashboard(SharedModuleStoreTestCase, LoginEnrollmentTestCase):
|
||||
# scheduled chapter
|
||||
ccx = CustomCourseForEdX.objects.get()
|
||||
course_start = get_override_for_ccx(ccx, self.course, 'start')
|
||||
self.assertEqual(str(course_start)[:-9], u'2014-11-20 00:00')
|
||||
self.assertEqual(str(course_start)[:-9], self.chapters[0].start.strftime('%Y-%m-%d %H:%M'))
|
||||
|
||||
# Make sure grading policy adjusted
|
||||
policy = get_override_for_ccx(ccx, self.course, 'grading_policy',
|
||||
|
||||
@@ -274,10 +274,16 @@ def save_ccx(request, course, ccx=None):
|
||||
ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'start_id'))
|
||||
clear_ccx_field_info_from_ccx_map(ccx, block, 'start')
|
||||
|
||||
due = parse_date(unit['due'])
|
||||
if due:
|
||||
override_field_for_ccx(ccx, block, 'due', due)
|
||||
# Only subsection (aka sequential) and unit (aka vertical) have due dates.
|
||||
if 'due' in unit: # checking that the key (due) exist in dict (unit).
|
||||
due = parse_date(unit['due'])
|
||||
if due:
|
||||
override_field_for_ccx(ccx, block, 'due', due)
|
||||
else:
|
||||
ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'due_id'))
|
||||
clear_ccx_field_info_from_ccx_map(ccx, block, 'due')
|
||||
else:
|
||||
# In case of section aka chapter we do not have due date.
|
||||
ccx_ids_to_delete.append(get_override_for_ccx(ccx, block, 'due_id'))
|
||||
clear_ccx_field_info_from_ccx_map(ccx, block, 'due')
|
||||
|
||||
@@ -398,6 +404,35 @@ def get_ccx_for_coach(course, coach):
|
||||
return None
|
||||
|
||||
|
||||
def get_date(ccx, node, date_type=None, parent_node=None):
|
||||
"""
|
||||
This returns override or master date for section, subsection or a unit.
|
||||
|
||||
:param ccx: ccx instance
|
||||
:param node: chapter, subsection or unit
|
||||
:param date_type: start or due
|
||||
:param parent_node: parent of node
|
||||
:return: start or due date
|
||||
"""
|
||||
date = get_override_for_ccx(ccx, node, date_type, None)
|
||||
if date_type == "start":
|
||||
master_date = node.start
|
||||
else:
|
||||
master_date = node.due
|
||||
|
||||
if date is not None:
|
||||
# Setting override date [start or due]
|
||||
date = date.strftime('%Y-%m-%d %H:%M')
|
||||
elif not parent_node and master_date is not None:
|
||||
# Setting date from master course
|
||||
date = master_date.strftime('%Y-%m-%d %H:%M')
|
||||
elif parent_node is not None:
|
||||
# Set parent date (vertical has same dates as subsections)
|
||||
date = get_date(ccx, node=parent_node, date_type=date_type)
|
||||
|
||||
return date
|
||||
|
||||
|
||||
def get_ccx_schedule(course, ccx):
|
||||
"""
|
||||
Generate a JSON serializable CCX schedule.
|
||||
@@ -409,28 +444,50 @@ def get_ccx_schedule(course, ccx):
|
||||
widgets, which use text inputs.
|
||||
Visits students visible nodes only; nodes children of hidden ones
|
||||
are skipped as well.
|
||||
|
||||
Dates:
|
||||
Only start date is applicable to a section. If ccx coach did not override start date then
|
||||
getting it from the master course.
|
||||
Both start and due dates are applicable to a subsection (aka sequential). If ccx coach did not override
|
||||
these dates then getting these dates from corresponding subsection in master course.
|
||||
Unit inherits start date and due date from its subsection. If ccx coach did not override these dates
|
||||
then getting them from corresponding subsection in master course.
|
||||
"""
|
||||
for child in node.get_children():
|
||||
# in case the children are visible to staff only, skip them
|
||||
if child.visible_to_staff_only:
|
||||
continue
|
||||
start = get_override_for_ccx(ccx, child, 'start', None)
|
||||
if start:
|
||||
start = str(start)[:-9]
|
||||
due = get_override_for_ccx(ccx, child, 'due', None)
|
||||
if due:
|
||||
due = str(due)[:-9]
|
||||
|
||||
hidden = get_override_for_ccx(
|
||||
ccx, child, 'visible_to_staff_only',
|
||||
child.visible_to_staff_only)
|
||||
visited = {
|
||||
'location': str(child.location),
|
||||
'display_name': child.display_name,
|
||||
'category': child.category,
|
||||
'start': start,
|
||||
'due': due,
|
||||
'hidden': hidden,
|
||||
}
|
||||
|
||||
start = get_date(ccx, child, 'start')
|
||||
if depth > 1:
|
||||
# Subsection has both start and due dates and unit inherit dates from their subsections
|
||||
if depth == 2:
|
||||
due = get_date(ccx, child, 'due')
|
||||
elif depth == 3:
|
||||
# Get start and due date of subsection in case unit has not override dates.
|
||||
due = get_date(ccx, child, 'due', node)
|
||||
start = get_date(ccx, child, 'start', node)
|
||||
|
||||
visited = {
|
||||
'location': str(child.location),
|
||||
'display_name': child.display_name,
|
||||
'category': child.category,
|
||||
'start': start,
|
||||
'due': due,
|
||||
'hidden': hidden,
|
||||
}
|
||||
else:
|
||||
visited = {
|
||||
'location': str(child.location),
|
||||
'display_name': child.display_name,
|
||||
'category': child.category,
|
||||
'start': start,
|
||||
'hidden': hidden,
|
||||
}
|
||||
if depth < 3:
|
||||
children = tuple(visit(child, depth + 1))
|
||||
if children:
|
||||
|
||||
Reference in New Issue
Block a user