Merge pull request #10353 from mitocw/enhancement/aq/disbale_due_dates_section_unit
Made CCX schedule configuration sync with studio (Date time management).
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:
|
||||
|
||||
@@ -49,6 +49,9 @@ var edx = edx || {};
|
||||
self.render();
|
||||
});
|
||||
|
||||
// By default input date and time fileds are disable.
|
||||
self.disableFields($('.ccx_due_date_time_fields'));
|
||||
self.disableFields($('.ccx_start_date_time_fields'));
|
||||
// Add unit handlers
|
||||
this.chapter_select.on('change', function() {
|
||||
var chapter_location = self.chapter_select.val();
|
||||
@@ -60,10 +63,15 @@ var edx = edx || {};
|
||||
.append(self.schedule_options(chapter.children));
|
||||
self.sequential_select.prop('disabled', false);
|
||||
$('#add-unit-button').prop('disabled', false);
|
||||
self.set_datetime('start', chapter.start);
|
||||
self.set_datetime('due', chapter.due);
|
||||
// When a chapter is selected, start date fields are enabled and due date
|
||||
// fields are disabled because due dates are not applicable on a chapter.
|
||||
self.disableFields($('.ccx_due_date_time_fields'));
|
||||
self.enableFields($('.ccx_start_date_time_fields'));
|
||||
} else {
|
||||
self.sequential_select.html('').prop('disabled', true);
|
||||
// When no chapter is selected, all date fields are disabled.
|
||||
self.disableFields($('.ccx_due_date_time_fields'));
|
||||
self.disableFields($('.ccx_start_date_time_fields'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -78,8 +86,15 @@ var edx = edx || {};
|
||||
self.vertical_select.prop('disabled', false);
|
||||
self.set_datetime('start', sequential.start);
|
||||
self.set_datetime('due', sequential.due);
|
||||
// When a subsection (aka sequential) is selected,
|
||||
// both start and due date fields are enabled.
|
||||
self.enableFields($('.ccx_due_date_time_fields'));
|
||||
self.enableFields($('.ccx_start_date_time_fields'));
|
||||
} else {
|
||||
// When "All subsections" is selected, all date fields are disabled.
|
||||
self.vertical_select.html('').prop('disabled', true);
|
||||
self.disableFields($('.ccx_due_date_time_fields'));
|
||||
self.enableFields($('.ccx_start_date_time_fields'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -90,8 +105,16 @@ var edx = edx || {};
|
||||
sequential = self.sequential_select.val();
|
||||
var vertical = self.find_unit(
|
||||
self.hidden, chapter, sequential, vertical_location);
|
||||
self.set_datetime('start', vertical.start);
|
||||
self.set_datetime('due', vertical.due);
|
||||
// When a unit (aka vertical) is selected, all date fields are disabled because units
|
||||
// inherit dates from subsection
|
||||
self.disableFields($('.ccx_due_date_time_fields'));
|
||||
self.disableFields($('.ccx_start_date_time_fields'));
|
||||
} else {
|
||||
// When "All units" is selected, all date fields are enabled,
|
||||
// because units inherit dates from subsections and we
|
||||
// are showing dates from the selected subsection.
|
||||
self.enableFields($('.ccx_due_date_time_fields'));
|
||||
self.enableFields($('.ccx_start_date_time_fields'));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -330,6 +353,14 @@ var edx = edx || {};
|
||||
});
|
||||
},
|
||||
|
||||
disableFields: function($selector) {
|
||||
$selector.find('select,input,button').prop('disabled', true);
|
||||
},
|
||||
|
||||
enableFields: function($selector) {
|
||||
$selector.find('select,input,button').prop('disabled', false);
|
||||
},
|
||||
|
||||
toggle_collapse: function(event) {
|
||||
event.preventDefault();
|
||||
var row = $(this).closest('tr');
|
||||
@@ -344,10 +375,19 @@ var edx = edx || {};
|
||||
$(this).attr('aria-expanded', 'true');
|
||||
$(this).find(".fa-caret-right").removeClass('fa-caret-right').addClass('fa-caret-down');
|
||||
row.removeClass('collapsed').addClass('expanded');
|
||||
children.filter('.collapsed').each(function() {
|
||||
children = children.not(self.get_children(this));
|
||||
});
|
||||
children.show();
|
||||
var depth = $(row).data('depth');
|
||||
var $childNodes = children.filter('.collapsed');
|
||||
if ($childNodes.length <= 0) {
|
||||
children.show();
|
||||
} else {
|
||||
// this will expand units.
|
||||
$childNodes.each(function() {
|
||||
var depthChild = $(this).data('depth');
|
||||
if (depth === (depthChild - 1)) {
|
||||
$(this).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -374,9 +414,9 @@ var edx = edx || {};
|
||||
$(row).find('.ccx_sr_alert').attr('aria-expanded', 'false');
|
||||
$(row).find('.fa-caret-down').removeClass('fa-caret-down').addClass('fa-caret-right');
|
||||
row.removeClass('expanded').addClass('collapsed');
|
||||
$('table.ccx-schedule .sequential,.vertical').hide();
|
||||
}
|
||||
});
|
||||
$('table.ccx-schedule .sequential,.vertical').hide();
|
||||
},
|
||||
|
||||
enterNewDate: function(what) {
|
||||
@@ -429,8 +469,14 @@ var edx = edx || {};
|
||||
}
|
||||
if (what === 'start') {
|
||||
unit.start = date + ' ' + time;
|
||||
if (unit.category === "sequential") {
|
||||
self.updateChildrenDates(unit, what, unit.start);
|
||||
}
|
||||
} else {
|
||||
unit.due = date + ' ' + time;
|
||||
if (unit.category === "sequential") {
|
||||
self.updateChildrenDates(unit, what, unit.due);
|
||||
}
|
||||
}
|
||||
modal.find('.close-modal').click();
|
||||
self.dirty = true;
|
||||
@@ -440,6 +486,19 @@ var edx = edx || {};
|
||||
};
|
||||
},
|
||||
|
||||
updateChildrenDates: function(sequential, date_type, date) {
|
||||
// This code iterates the children (aka verticals) of a sequential.
|
||||
// It updates start and due dates to corresponding dates
|
||||
// of sequential (parent).
|
||||
_.forEach(sequential.children, function (unit) {
|
||||
if (date_type === 'start') {
|
||||
unit.start = date;
|
||||
} else {
|
||||
unit.due = date;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
find_unit: function(tree, chapter, sequential, vertical) {
|
||||
var units = self.find_lineage(tree, chapter, sequential, vertical);
|
||||
return units[units.length -1];
|
||||
|
||||
@@ -18,6 +18,11 @@ table.ccx-schedule {
|
||||
th, td {
|
||||
padding: 10px;
|
||||
}
|
||||
td.no-link {
|
||||
font-size: 13px;
|
||||
text-shadow: 0 1px 0 #fcfbfb;
|
||||
text-decoration: none;
|
||||
}
|
||||
.sequential .unit {
|
||||
padding-left: 25px;
|
||||
}
|
||||
@@ -40,6 +45,7 @@ table.ccx-schedule {
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
|
||||
.ccx-sidebar-panel {
|
||||
border: 1px solid #cbcbcb;
|
||||
padding: 15px;
|
||||
@@ -48,8 +54,46 @@ table.ccx-schedule {
|
||||
|
||||
form.ccx-form {
|
||||
line-height: 1.5;
|
||||
// inspiration was taken from https://github.com/edx/ux-pattern-library
|
||||
select {
|
||||
@include font-size(16);
|
||||
background: #fcfcfc;
|
||||
border: 1px solid #e9e8e8;
|
||||
box-sizing: padding-box;
|
||||
color: #282c2e;
|
||||
display: inline-block;
|
||||
font-size: ($baseline*.9.5);
|
||||
height: 40px;
|
||||
line-height: 20px;
|
||||
padding: 10px;
|
||||
transition: all 125ms ease-in-out 0s;
|
||||
width: 100%;
|
||||
&:disabled {
|
||||
border-color: #cfd8dc;
|
||||
background: #e7ecee;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
input {
|
||||
@include font-size(15);
|
||||
background: #FCFCFC none repeat scroll 0% 0%;
|
||||
border: 1px solid #E7E6E6;
|
||||
box-sizing: border-box;
|
||||
color: #34383A;
|
||||
display: inline-block;
|
||||
line-height: normal;
|
||||
transition: all 0.125s ease-in-out 0s;
|
||||
padding: 5px 10px 5px 10px;
|
||||
&:focus {
|
||||
border-color: #0ea6ec;
|
||||
color: #282c2e;
|
||||
outline: 0;
|
||||
}
|
||||
&:disabled {
|
||||
border-color: #cfd8dc;
|
||||
background: #e7ecee;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
.field {
|
||||
margin: 5px 0 5px 0;
|
||||
@@ -72,6 +116,10 @@ button.ccx-button-link {
|
||||
}
|
||||
&:hover {
|
||||
color: brown;
|
||||
background: none;
|
||||
}
|
||||
&:focus {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,14 +39,14 @@
|
||||
<header>
|
||||
<h2 id="ccx_schedule_set_date_heading"></h2>
|
||||
</header>
|
||||
<form>
|
||||
<form class="ccx-form">
|
||||
<div class="field datepair">
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of YYYY-MM-DD
|
||||
<label class="sr form-label" for="ccx_dialog_date">${_('Date format four digit year dash two digit month dash two digit day')}</label>
|
||||
<input placeholder="Date" class="date" type="text" name="date" id="ccx_dialog_date" size="11" />
|
||||
<input placeholder="${_('Date')}" class="date" type="text" name="date" id="ccx_dialog_date" size="11" />
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of HH:MM
|
||||
<label class="sr form-label" for="ccx_dialog_time">${_('Time format two digit hours colon two digit minutes')}</label>
|
||||
<input placeholder="Time" class="time" type="text" name="time" id="ccx_dialog_time" size="6" />
|
||||
<input placeholder="${_('Time')}" class="time" type="text" name="time" id="ccx_dialog_time" size="6" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<button type="submit" class="btn btn-primary">${_('Set date')}</button>
|
||||
@@ -63,7 +63,7 @@
|
||||
<p id="message_save" class="text-helper">${_("You have unsaved changes.")}</p>
|
||||
<div class="field">
|
||||
<br/>
|
||||
<button id="save-changes" aria-describedby="message_save">${_("Save changes")}</button>
|
||||
<button id="save-changes" aria-describedby="message_save" class="ccx-schedule-save-changes">${_("Save changes")}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
@@ -87,31 +87,35 @@
|
||||
<label for="ccx_vertical" class="form-label"><b>${_('Unit')}</b></label>
|
||||
<select name="vertical" id="ccx_vertical"></select>
|
||||
</div>
|
||||
<div class="field datepair">
|
||||
<label for="ccx_start_date" class="form-label">
|
||||
<b>${_('Start Date')}</b>
|
||||
<span class="sr">
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of YYYY-MM-DD
|
||||
${_('format four digit year dash two digit month dash two digit day')}
|
||||
</span>
|
||||
</label>
|
||||
<input placeholder="yyyy-mm-dd" type="text" class="date" name="start_date" id="ccx_start_date" />
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of HH:MM
|
||||
<label for="ccx_start_time" class="sr form-label">${_('Start time format two digit hours colon two digit minutes')}</label>
|
||||
<input placeholder="time" type="text" class="time" name="start_time" id="ccx_start_time"/>
|
||||
</div>
|
||||
<div class="field datepair">
|
||||
<label for="ccx_due_date" class="form-label">
|
||||
<b>${_('Due Date')}</b> ${_('(Optional)')}
|
||||
<span class="sr">
|
||||
<div class="ccx_start_date_time_fields">
|
||||
<div class="field datepair">
|
||||
<label for="ccx_start_date" class="form-label">
|
||||
<b>${_('Start Date')}</b>
|
||||
<span class="sr">
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of YYYY-MM-DD
|
||||
${_('format four digit year dash two digit month dash two digit day')}
|
||||
</span>
|
||||
</label>
|
||||
<input placeholder="yyyy-mm-dd" type="text" class="date" name="due_date" id="ccx_due_date"/>
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of HH:MM
|
||||
<label for="ccx_due_time" class="sr form-label">${_('Due Time format two digit hours colon two digit minutes')}</label>
|
||||
<input placeholder="time" type="text" class="time" name="due_time" id="ccx_due_time"/>
|
||||
</span>
|
||||
</label>
|
||||
<input placeholder="${_('yyyy-mm-dd')}" type="text" class="date" name="start_date" id="ccx_start_date" />
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of HH:MM
|
||||
<label for="ccx_start_time" class="sr form-label">${_('Start time format two digit hours colon two digit minutes')}</label>
|
||||
<input placeholder="${_('time')}" type="text" class="time" name="start_time" id="ccx_start_time"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ccx_due_date_time_fields">
|
||||
<div class="field datepair">
|
||||
<label for="ccx_due_date" class="form-label">
|
||||
<b>${_('Due Date')}</b> ${_('(Optional)')}
|
||||
<span class="sr">
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of YYYY-MM-DD
|
||||
${_('format four digit year dash two digit month dash two digit day')}
|
||||
</span>
|
||||
</label>
|
||||
<input placeholder="${_('yyyy-mm-dd')}" type="text" class="date" name="due_date" id="ccx_due_date"/>
|
||||
## Translators: This explains to people using a screen reader how to interpret the format of HH:MM
|
||||
<label for="ccx_due_time" class="sr form-label">${_('Due Time format two digit hours colon two digit minutes')}</label>
|
||||
<input placeholder="${_('time')}" type="text" class="time" name="due_time" id="ccx_due_time"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<br/>
|
||||
|
||||
@@ -24,9 +24,13 @@
|
||||
<td class="unit">
|
||||
<button class="toggle-collapse ccx-button-link" aria-expanded="false">
|
||||
<i class="fa fa-caret-right"></i>
|
||||
<span class="sr"><%- gettext('toggle chapter') %> <%= chapter.display_name %></span>
|
||||
<span class="sr">
|
||||
<%- interpolate(gettext('toggle chapter %(displayName)s'),
|
||||
{displayName: chapter.display_name}, true) %>
|
||||
</span>
|
||||
</button>
|
||||
<span class="sr"><%- gettext('Section') %> </span><%= chapter.display_name %>
|
||||
<span class="sr">
|
||||
<%- gettext('Section') %> </span><%= chapter.display_name %>
|
||||
</td>
|
||||
<td class="date start-date">
|
||||
<button class="ccx-button-link">
|
||||
@@ -34,13 +38,11 @@
|
||||
<span class="sr"><%- gettext('Click to change') %></span>
|
||||
</button>
|
||||
</td>
|
||||
<td class="date due-date">
|
||||
<button class="ccx-button-link">
|
||||
<%= chapter.due %>
|
||||
<span class="sr"><%- gettext('Click to change') %></span>
|
||||
</button>
|
||||
<td class="date due-date no-link">
|
||||
<%- gettext('N/A') %>
|
||||
</td>
|
||||
<td><button class="remove-unit ccx-button-link" aria-label="Remove chapter <%= chapter.display_name %>">
|
||||
<td><button class="remove-unit ccx-button-link" aria-label="<%- interpolate(
|
||||
gettext('Remove chapter %(chapterDisplayName)s'), {chapterDisplayName: chapter.display_name}, true) %>">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i> <%- gettext('remove') %>
|
||||
</button></td>
|
||||
</tr>
|
||||
@@ -50,7 +52,10 @@
|
||||
<td class="unit">
|
||||
<button class="toggle-collapse ccx-button-link" aria-expanded="false">
|
||||
<i class="fa fa-caret-right"></i>
|
||||
<span class="sr"><%- gettext('toggle subsection') %> <%= child.display_name %></span>
|
||||
<span class="sr">
|
||||
<%- interpolate(gettext('toggle subsection %(displayName)s'),
|
||||
{displayName: child.display_name}, true) %>
|
||||
</span>
|
||||
</button>
|
||||
<span class="sr"><%- gettext('Subsection') %> </span><%= child.display_name %>
|
||||
</td>
|
||||
@@ -66,32 +71,45 @@
|
||||
<span class="sr"><%- gettext('Click to change') %></span>
|
||||
</button>
|
||||
</td>
|
||||
<td><button class="remove-unit ccx-button-link" aria-label="Remove subsection <%= child.display_name %>">
|
||||
<td><button class="remove-unit ccx-button-link" aria-label="<%- interpolate(
|
||||
gettext('Remove subsection %(subsectionDisplayName)s'), {subsectionDisplayName: child.display_name}, true) %>">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i> <%- gettext('remove') %>
|
||||
</button></td>
|
||||
</tr>
|
||||
<% _.each(child.children, function(subchild) { %>
|
||||
<tr class="vertical" data-dapth="3"
|
||||
<tr class="vertical" data-depth="3"
|
||||
data-location="<%= chapter.location %> <%= child.location %> <%= subchild.location %>">
|
||||
<td class="unit">
|
||||
<span class="sr"><%- gettext('Unit') %> </span>
|
||||
<%= subchild.display_name %>
|
||||
</td>
|
||||
<td class="date start-date">
|
||||
<button class="ccx-button-link">
|
||||
<td class="date start-date no-link">
|
||||
<% if (subchild.start) { %>
|
||||
<%= subchild.start %>
|
||||
<span class="sr"><%- gettext('Click to change') %></span>
|
||||
</button>
|
||||
<% } else { %>
|
||||
<%
|
||||
// Translators: Unit's aka vertical start date is set to Unscheduled when user has not set start date on corresponding subsection aka sequential.
|
||||
%>
|
||||
<%- gettext('Unscheduled') %>
|
||||
<% } %>
|
||||
</td>
|
||||
<td class="date due-date">
|
||||
<button class="ccx-button-link">
|
||||
<td class="date due-date no-link">
|
||||
<% if (subchild.due) { %>
|
||||
<%= subchild.due %>
|
||||
<span class="sr"><%- gettext('Click to change') %></span>
|
||||
<% } else { %>
|
||||
<%
|
||||
// Translators: Unit's aka vertical due date is set to Unscheduled when user has not set due date on corresponding subsection aka sequential.
|
||||
%>
|
||||
<%- gettext('Unscheduled') %>
|
||||
<% } %>
|
||||
</td>
|
||||
<td>
|
||||
<button class="remove-unit ccx-button-link" aria-label="<%- interpolate(
|
||||
gettext('Remove unit %(unitName)s'), {unitName: subchild.display_name}, true) %>">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i> <%- gettext('remove') %>
|
||||
</button>
|
||||
</td>
|
||||
<td><button class="remove-unit ccx-button-link" aria-label="Remove unit <%= subchild.display_name %>">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i> <%- gettext('remove') %>
|
||||
</button></td>
|
||||
</tr>
|
||||
<% }); %>
|
||||
<% }); %>
|
||||
<% }); %>
|
||||
|
||||
Reference in New Issue
Block a user