Commit c6bec6bc by Don Mitchell

Merge pull request #1812 from MITx/feature/christina/gmt

Display UTC on the end of dates (that are in UTC).
parents 6e45db65 c4befa13
...@@ -21,8 +21,7 @@ Feature: Advanced (manual) course policy ...@@ -21,8 +21,7 @@ Feature: Advanced (manual) course policy
Scenario: Test editing key value Scenario: Test editing key value
Given I am on the Advanced Course Settings page in Studio Given I am on the Advanced Course Settings page in Studio
When I edit the value of a policy key When I edit the value of a policy key and save
And I press the "Save" notification button
Then the policy key value is changed Then the policy key value is changed
And I reload the page And I reload the page
Then the policy key value is changed Then the policy key value is changed
......
...@@ -51,6 +51,11 @@ def edit_the_value_of_a_policy_key(step): ...@@ -51,6 +51,11 @@ def edit_the_value_of_a_policy_key(step):
e._element.send_keys(Keys.TAB, Keys.END, Keys.ARROW_LEFT, ' ', 'X') e._element.send_keys(Keys.TAB, Keys.END, Keys.ARROW_LEFT, ' ', 'X')
@step(u'I edit the value of a policy key and save$')
def edit_the_value_of_a_policy_key(step):
change_display_name_value(step, '"foo"')
@step('I create a JSON object as a value$') @step('I create a JSON object as a value$')
def create_JSON_object(step): def create_JSON_object(step):
change_display_name_value(step, '{"key": "value", "key_2": "value_2"}') change_display_name_value(step, '{"key": "value", "key_2": "value_2"}')
...@@ -96,7 +101,7 @@ def the_policy_key_value_is_unchanged(step): ...@@ -96,7 +101,7 @@ def the_policy_key_value_is_unchanged(step):
@step(u'the policy key value is changed$') @step(u'the policy key value is changed$')
def the_policy_key_value_is_changed(step): def the_policy_key_value_is_changed(step):
assert_equal(get_display_name_value(), '"Robot Super Course X"') assert_equal(get_display_name_value(), '"foo"')
############# HELPERS ############### ############# HELPERS ###############
......
...@@ -18,8 +18,8 @@ COURSE_END_TIME_CSS = "#course-end-time" ...@@ -18,8 +18,8 @@ COURSE_END_TIME_CSS = "#course-end-time"
ENROLLMENT_START_TIME_CSS = "#course-enrollment-start-time" ENROLLMENT_START_TIME_CSS = "#course-enrollment-start-time"
ENROLLMENT_END_TIME_CSS = "#course-enrollment-end-time" ENROLLMENT_END_TIME_CSS = "#course-enrollment-end-time"
DUMMY_TIME = "3:30pm" DUMMY_TIME = "15:30"
DEFAULT_TIME = "12:00am" DEFAULT_TIME = "00:00"
############### ACTIONS #################### ############### ACTIONS ####################
......
...@@ -38,7 +38,7 @@ def i_click_the_edit_link_for_the_release_date(step): ...@@ -38,7 +38,7 @@ def i_click_the_edit_link_for_the_release_date(step):
@step('I save a new section release date$') @step('I save a new section release date$')
def i_save_a_new_section_release_date(step): def i_save_a_new_section_release_date(step):
set_date_and_time('input.start-date.date.hasDatepicker', '12/25/2013', set_date_and_time('input.start-date.date.hasDatepicker', '12/25/2013',
'input.start-time.time.ui-timepicker-input', '12:00am') 'input.start-time.time.ui-timepicker-input', '00:00')
world.browser.click_link_by_text('Save') world.browser.click_link_by_text('Save')
...@@ -105,7 +105,7 @@ def the_section_release_date_picker_not_visible(step): ...@@ -105,7 +105,7 @@ def the_section_release_date_picker_not_visible(step):
def the_section_release_date_is_updated(step): def the_section_release_date_is_updated(step):
css = 'span.published-status' css = 'span.published-status'
status_text = world.css_text(css) status_text = world.css_text(css)
assert_equal(status_text, 'Will Release: 12/25/2013 at 12:00am') assert_equal(status_text, 'Will Release: 12/25/2013 at 00:00 UTC')
############ HELPER METHODS ################### ############ HELPER METHODS ###################
......
...@@ -57,18 +57,18 @@ def i_see_complete_subsection_name_with_quote_in_editor(step): ...@@ -57,18 +57,18 @@ def i_see_complete_subsection_name_with_quote_in_editor(step):
@step('I have set a release date and due date in different years$') @step('I have set a release date and due date in different years$')
def test_have_set_dates_in_different_years(step): def test_have_set_dates_in_different_years(step):
set_date_and_time('input#start_date', '12/25/2011', 'input#start_time', '3:00am') set_date_and_time('input#start_date', '12/25/2011', 'input#start_time', '03:00')
world.css_click('.set-date') world.css_click('.set-date')
# Use a year in the past so that current year will always be different. # Use a year in the past so that current year will always be different.
set_date_and_time('input#due_date', '01/02/2012', 'input#due_time', '4:00am') set_date_and_time('input#due_date', '01/02/2012', 'input#due_time', '04:00')
@step('I see the correct dates$') @step('I see the correct dates$')
def i_see_the_correct_dates(step): def i_see_the_correct_dates(step):
assert_equal('12/25/2011', world.css_find('input#start_date').first.value) assert_equal('12/25/2011', world.css_find('input#start_date').first.value)
assert_equal('3:00am', world.css_find('input#start_time').first.value) assert_equal('03:00', world.css_find('input#start_time').first.value)
assert_equal('01/02/2012', world.css_find('input#due_date').first.value) assert_equal('01/02/2012', world.css_find('input#due_date').first.value)
assert_equal('4:00am', world.css_find('input#due_time').first.value) assert_equal('04:00', world.css_find('input#due_time').first.value)
@step('I mark it as Homework$') @step('I mark it as Homework$')
......
...@@ -826,7 +826,7 @@ function saveSetSectionScheduleDate(e) { ...@@ -826,7 +826,7 @@ function saveSetSectionScheduleDate(e) {
data: JSON.stringify({ 'id': id, 'metadata': {'start': start}}) data: JSON.stringify({ 'id': id, 'metadata': {'start': start}})
}).success(function () { }).success(function () {
var $thisSection = $('.courseware-section[data-id="' + id + '"]'); var $thisSection = $('.courseware-section[data-id="' + id + '"]');
$thisSection.find('.section-published-date').html('<span class="published-status"><strong>Will Release:</strong> ' + input_date + ' at ' + input_time + '</span><a href="#" class="edit-button" data-date="' + input_date + '" data-time="' + input_time + '" data-id="' + id + '">Edit</a>'); $thisSection.find('.section-published-date').html('<span class="published-status"><strong>Will Release:</strong> ' + input_date + ' at ' + input_time + ' UTC</span><a href="#" class="edit-button" data-date="' + input_date + '" data-time="' + input_time + '" data-id="' + id + '">Edit</a>');
$thisSection.find('.section-published-date').animate({ $thisSection.find('.section-published-date').animate({
'background-color': 'rgb(182,37,104)' 'background-color': 'rgb(182,37,104)'
}, 300).animate({ }, 300).animate({
......
...@@ -110,7 +110,7 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({ ...@@ -110,7 +110,7 @@ CMS.Views.Settings.Details = CMS.Views.ValidatingView.extend({
}; };
// instrument as date and time pickers // instrument as date and time pickers
timefield.timepicker(); timefield.timepicker({'timeFormat' : 'H:i'});
datefield.datepicker(); datefield.datepicker();
// Using the change event causes savefield to be triggered twice, but it is necessary // Using the change event causes savefield to be triggered twice, but it is necessary
......
...@@ -62,6 +62,12 @@ table { ...@@ -62,6 +62,12 @@ table {
border-spacing: 0; border-spacing: 0;
} }
abbr[title] {
border-bottom: none;
text-decoration: none;
cursor: help;
}
// ==================== // ====================
// grandfathered styles // grandfathered styles
......
...@@ -604,13 +604,39 @@ body.course.outline { ...@@ -604,13 +604,39 @@ body.course.outline {
} }
.picker { .picker {
@include clearfix();
margin: 30px 0 65px; margin: 30px 0 65px;
.field {
float: left;
margin-right: ($baseline/2);
&:first-child {
margin-left: ($baseline*5);
}
&:last-child {
margin-right: 0;
}
label, input {
display: block;
text-align: left;
}
label {
@include font-size(14);
margin-bottom: ($baseline/4);
}
}
} }
.description { .description {
float: left;
margin-top: 30px; margin-top: 30px;
font-size: 14px; font-size: 14px;
line-height: 20px; line-height: 20px;
width: 100%;
} }
strong { strong {
......
...@@ -3,11 +3,41 @@ ...@@ -3,11 +3,41 @@
body.course.subsection { body.course.subsection {
.main-wrapper {
margin-top: ($baseline*2);
}
.unit-settings { .unit-settings {
.window-contents { .window-contents {
padding: 10px 20px; padding: 10px 20px;
} }
.datepair {
.field {
display: inline-block;
margin-right: ($baseline/4);
width: 45%;
&:last-child {
margin-right: 0;
}
label, input {
display: block;
text-align: left;
}
input {
width: 100%;
}
label {
margin-bottom: ($baseline/4);
}
}
}
.unit-actions { .unit-actions {
border-bottom: none; border-bottom: none;
padding-bottom: 0; padding-bottom: 0;
...@@ -74,7 +104,7 @@ body.course.subsection { ...@@ -74,7 +104,7 @@ body.course.subsection {
} }
.window-contents { .window-contents {
display: none; display: none;
} }
} }
...@@ -232,6 +262,7 @@ body.course.subsection { ...@@ -232,6 +262,7 @@ body.course.subsection {
.remove-date { .remove-date {
display: block; display: block;
margin-top: ($baseline/4);
} }
} }
...@@ -259,7 +290,7 @@ body.course.subsection { ...@@ -259,7 +290,7 @@ body.course.subsection {
background-position: 0 -50px; background-position: 0 -50px;
.hidden { .hidden {
background-position: 0 -5px; background-position: 0 -5px;
} }
} }
} }
...@@ -369,4 +400,4 @@ body.course.subsection { ...@@ -369,4 +400,4 @@ body.course.subsection {
} }
} }
} }
} }
\ No newline at end of file
...@@ -3,9 +3,8 @@ ...@@ -3,9 +3,8 @@
body.course.unit { body.course.unit {
.unit .main-wrapper { .main-wrapper {
@include clearfix(); margin-top: ($baseline*2);
margin: 40px;
} }
//Problem Selector tab menu requirements //Problem Selector tab menu requirements
...@@ -31,7 +30,7 @@ body.course.unit { ...@@ -31,7 +30,7 @@ body.course.unit {
} }
.unit-body { .unit-body {
.unit-name-input { .unit-name-input {
padding: 20px 40px; padding: 20px 40px;
...@@ -44,7 +43,7 @@ body.course.unit { ...@@ -44,7 +43,7 @@ body.course.unit {
font-size: 20px; font-size: 20px;
} }
} }
.breadcrumbs { .breadcrumbs {
border-radius: 3px 3px 0 0; border-radius: 3px 3px 0 0;
border-bottom: 1px solid #cbd1db; border-bottom: 1px solid #cbd1db;
...@@ -189,10 +188,10 @@ body.course.unit { ...@@ -189,10 +188,10 @@ body.course.unit {
@include clearfix; @include clearfix;
a { a {
position: relative; position: relative;
border: 1px solid $darkGreen; border: 1px solid $darkGreen;
background: tint($green,20%); background: tint($green,20%);
color: #fff; color: #fff;
&:hover { &:hover {
background: $brightGreen; background: $brightGreen;
...@@ -254,8 +253,8 @@ body.course.unit { ...@@ -254,8 +253,8 @@ body.course.unit {
@include transition (none); @include transition (none);
&:hover { &:hover {
background: tint($green,30%); background: tint($green,30%);
color: #fff; color: #fff;
@include transition(background-color .15s); @include transition(background-color .15s);
} }
} }
...@@ -263,7 +262,7 @@ body.course.unit { ...@@ -263,7 +262,7 @@ body.course.unit {
li { li {
border:none; border:none;
border-bottom: 1px dashed $lightGrey; border-bottom: 1px dashed $lightGrey;
color: #fff; color: #fff;
} }
li:first-child { li:first-child {
...@@ -326,7 +325,7 @@ body.course.unit { ...@@ -326,7 +325,7 @@ body.course.unit {
} }
} }
// specific editor types // specific editor types
.empty { .empty {
a { a {
...@@ -337,20 +336,20 @@ body.course.unit { ...@@ -337,20 +336,20 @@ body.course.unit {
&:hover { &:hover {
background: tint($green,30%); background: tint($green,30%);
color: #fff; color: #fff;
} }
} }
} }
} }
.new-component { .new-component {
text-align: center; text-align: center;
h5 { h5 {
color: $darkGreen; color: $darkGreen;
} }
} }
} }
} }
...@@ -374,7 +373,7 @@ body.course.unit { ...@@ -374,7 +373,7 @@ body.course.unit {
&.editing { &.editing {
border: 1px solid $lightBluishGrey2; border: 1px solid $lightBluishGrey2;
z-index: auto; z-index: auto;
.drag-handle, .drag-handle,
.component-actions { .component-actions {
display: none; display: none;
...@@ -434,7 +433,7 @@ body.course.unit { ...@@ -434,7 +433,7 @@ body.course.unit {
label { label {
display: inline-block; display: inline-block;
margin-right: 10px; margin-right: 10px;
} }
} }
...@@ -528,7 +527,7 @@ body.course.unit { ...@@ -528,7 +527,7 @@ body.course.unit {
} }
.window-contents { .window-contents {
display: none; display: none;
} }
} }
...@@ -678,4 +677,4 @@ body.unit { ...@@ -678,4 +677,4 @@ body.unit {
padding-top: 0; padding-top: 0;
} }
} }
} }
\ No newline at end of file
...@@ -33,17 +33,22 @@ ...@@ -33,17 +33,22 @@
<h4 class="header">Subsection Settings</h4> <h4 class="header">Subsection Settings</h4>
<div class="window-contents"> <div class="window-contents">
<div class="scheduled-date-input row"> <div class="scheduled-date-input row">
<label>Release date:<!-- <span class="description">Determines when this subsection and the units within it will be released publicly.</span>--></label>
<div class="datepair" data-language="javascript"> <div class="datepair" data-language="javascript">
<input type="text" id="start_date" name="start_date" value="${get_time_struct_display(subsection.lms.start, '%m/%d/%Y')}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/> <div class="field field-start-date">
<input type="text" id="start_time" name="start_time" value="${get_time_struct_display(subsection.lms.start, '%H:%M')}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/> <label for="start_date">Release Day</label>
<input type="text" id="start_date" name="start_date" value="${get_time_struct_display(subsection.lms.start, '%m/%d/%Y')}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
</div>
<div class="field field-start-time">
<label for="start_time">Release Time (<abbr title="Coordinated Universal Time">UTC</abbr>)</label>
<input type="text" id="start_time" name="start_time" value="${get_time_struct_display(subsection.lms.start, '%H:%M')}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
</div>
</div> </div>
% if subsection.lms.start != parent_item.lms.start and subsection.lms.start: % if subsection.lms.start != parent_item.lms.start and subsection.lms.start:
% if parent_item.lms.start is None: % if parent_item.lms.start is None:
<p class="notice">The date above differs from the release date of ${parent_item.display_name_with_default}, which is unset. <p class="notice">The date above differs from the release date of ${parent_item.display_name_with_default}, which is unset.
% else: % else:
<p class="notice">The date above differs from the release date of ${parent_item.display_name_with_default} – <p class="notice">The date above differs from the release date of ${parent_item.display_name_with_default} –
${get_time_struct_display(parent_item.lms.start, '%m/%d/%Y at %I:%M %p')}. ${get_time_struct_display(parent_item.lms.start, '%m/%d/%Y at %H:%M UTC')}.
% endif % endif
<a href="#" class="sync-date no-spinner">Sync to ${parent_item.display_name_with_default}.</a></p> <a href="#" class="sync-date no-spinner">Sync to ${parent_item.display_name_with_default}.</a></p>
% endif % endif
...@@ -56,14 +61,17 @@ ...@@ -56,14 +61,17 @@
</div> </div>
<div class="due-date-input row"> <div class="due-date-input row">
<label>Due date:</label>
<a href="#" class="set-date">Set a due date</a> <a href="#" class="set-date">Set a due date</a>
<div class="datepair date-setter"> <div class="datepair date-setter">
<p class="date-description"> <div class="field field-start-date">
<label for="due_date">Due Day</label>
<input type="text" id="due_date" name="due_date" value="${get_time_struct_display(subsection.lms.due, '%m/%d/%Y')}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/> <input type="text" id="due_date" name="due_date" value="${get_time_struct_display(subsection.lms.due, '%m/%d/%Y')}" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
</div>
<div class="field field-start-time">
<label for="due_time">Due Time (<abbr title="Coordinated Universal Time">UTC</abbr>)</label>
<input type="text" id="due_time" name="due_time" value="${get_time_struct_display(subsection.lms.due, '%H:%M')}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/> <input type="text" id="due_time" name="due_time" value="${get_time_struct_display(subsection.lms.due, '%H:%M')}" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
<a href="#" class="remove-date">Remove due date</a> </div>
</p> <a href="#" class="remove-date">Remove due date</a>
</div> </div>
</div> </div>
<div class="row unit-actions"> <div class="row unit-actions">
......
...@@ -148,13 +148,13 @@ ...@@ -148,13 +148,13 @@
<div class="section-published-date"> <div class="section-published-date">
<% <%
start_date_str = get_time_struct_display(section.lms.start, '%m/%d/%Y') start_date_str = get_time_struct_display(section.lms.start, '%m/%d/%Y')
start_time_str = get_time_struct_display(section.lms.start, '%I:%M %p') start_time_str = get_time_struct_display(section.lms.start, '%H:%M')
%> %>
%if section.lms.start is None: %if section.lms.start is None:
<span class="published-status">This section has not been released.</span> <span class="published-status">This section has not been released.</span>
<a href="#" class="schedule-button" data-date="" data-time="" data-id="${section.location}">Schedule</a> <a href="#" class="schedule-button" data-date="" data-time="" data-id="${section.location}">Schedule</a>
%else: %else:
<span class="published-status"><strong>Will Release:</strong> ${start_date_str} at ${start_time_str}</span> <span class="published-status"><strong>Will Release:</strong> ${get_time_struct_display(section.lms.start, '%m/%d/%Y at %H:%M UTC')}</span>
<a href="#" class="edit-button" data-date="${start_date_str}" data-time="${start_time_str}" data-id="${section.location}">Edit</a> <a href="#" class="edit-button" data-date="${start_date_str}" data-time="${start_time_str}" data-id="${section.location}">Edit</a>
%endif %endif
</div> </div>
...@@ -202,13 +202,20 @@ ...@@ -202,13 +202,20 @@
</div> </div>
</div> </div>
<footer></footer> <footer></footer>
<div class="edit-subsection-publish-settings"> <div class="edit-subsection-publish-settings">
<div class="settings"> <div class="settings">
<h3>Section Release Date</h3> <h3>Section Release Date</h3>
<div class="picker datepair"> <div class="picker datepair">
<input class="start-date date" type="text" name="start_date" value="" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/> <div class="field field-start-date">
<input class="start-time time" type="text" name="start_time" value="" placeholder="HH:MM" class="time" size='10' autocomplete="off"/> <label for="">Release Day</label>
<input class="start-date date" type="text" name="start_date" value="" placeholder="MM/DD/YYYY" class="date" size='15' autocomplete="off"/>
</div>
<div class="field field-start-time">
<label for="">Release Time (<abbr title="Coordinated Universal Time">UTC</abbr>)</label>
<input class="start-time time" type="text" name="start_time" value="" placeholder="HH:MM" class="time" size='10' autocomplete="off"/>
</div>
<div class="description"> <div class="description">
<p>On the date set above, this section – <strong class="section-name"></strong> – will be released to students. Any units marked private will only be visible to admins.</p> <p>On the date set above, this section – <strong class="section-name"></strong> – will be released to students. Any units marked private will only be visible to admins.</p>
</div> </div>
......
...@@ -180,6 +180,7 @@ class CourseFields(object): ...@@ -180,6 +180,7 @@ class CourseFields(object):
has_children = True has_children = True
checklists = List(scope=Scope.settings) checklists = List(scope=Scope.settings)
info_sidebar_name = String(scope=Scope.settings, default='Course Handouts') info_sidebar_name = String(scope=Scope.settings, default='Course Handouts')
show_timezone = Boolean(help="True if timezones should be shown on dates in the courseware", scope=Scope.settings, default=True)
# An extra property is used rather than the wiki_slug/number because # An extra property is used rather than the wiki_slug/number because
# there are courses that change the number for different runs. This allows # there are courses that change the number for different runs. This allows
......
...@@ -5,6 +5,7 @@ from xmodule.util import date_utils ...@@ -5,6 +5,7 @@ from xmodule.util import date_utils
import datetime import datetime
import time import time
def test_get_time_struct_display(): def test_get_time_struct_display():
assert_equals("", date_utils.get_time_struct_display(None, "")) assert_equals("", date_utils.get_time_struct_display(None, ""))
test_time = time.struct_time((1992, 3, 12, 15, 3, 30, 1, 71, 0)) test_time = time.struct_time((1992, 3, 12, 15, 3, 30, 1, 71, 0))
...@@ -15,12 +16,20 @@ def test_get_time_struct_display(): ...@@ -15,12 +16,20 @@ def test_get_time_struct_display():
def test_get_default_time_display(): def test_get_default_time_display():
assert_equals("", date_utils.get_default_time_display(None)) assert_equals("", date_utils.get_default_time_display(None))
test_time = time.struct_time((1992, 3, 12, 15, 3, 30, 1, 71, 0)) test_time = time.struct_time((1992, 3, 12, 15, 3, 30, 1, 71, 0))
assert_equals("Mar 12, 1992 at 03:03 PM", assert_equals(
"Mar 12, 1992 at 15:03 UTC",
date_utils.get_default_time_display(test_time)) date_utils.get_default_time_display(test_time))
assert_equals(
"Mar 12, 1992 at 15:03 UTC",
date_utils.get_default_time_display(test_time, True))
assert_equals(
"Mar 12, 1992 at 15:03",
date_utils.get_default_time_display(test_time, False))
def test_time_to_datetime(): def test_time_to_datetime():
assert_equals(None, date_utils.time_to_datetime(None)) assert_equals(None, date_utils.time_to_datetime(None))
test_time = time.struct_time((1992, 3, 12, 15, 3, 30, 1, 71, 0)) test_time = time.struct_time((1992, 3, 12, 15, 3, 30, 1, 71, 0))
assert_equals(datetime.datetime(1992, 3, 12, 15, 3, 30), assert_equals(
datetime.datetime(1992, 3, 12, 15, 3, 30),
date_utils.time_to_datetime(test_time)) date_utils.time_to_datetime(test_time))
...@@ -2,15 +2,18 @@ import time ...@@ -2,15 +2,18 @@ import time
import datetime import datetime
def get_default_time_display(time_struct): def get_default_time_display(time_struct, show_timezone=True):
""" """
Converts a time struct to a string representation. This is the default Converts a time struct to a string representation. This is the default
representation used in Studio and LMS. representation used in Studio and LMS.
It is of the form "Apr 09, 2013 at 04:00 PM". It is of the form "Apr 09, 2013 at 16:00" or "Apr 09, 2013 at 16:00 UTC",
depending on the value of show_timezone.
If None is passed in, an empty string will be returned. If None is passed in for time_struct, an empty string will be returned.
The default value of show_timezone is True.
""" """
return get_time_struct_display(time_struct, "%b %d, %Y at %I:%M %p") timezone = "" if time_struct is None or not show_timezone else " UTC"
return get_time_struct_display(time_struct, "%b %d, %Y at %H:%M") + timezone
def get_time_struct_display(time_struct, format): def get_time_struct_display(time_struct, format):
......
...@@ -24,7 +24,7 @@ $(function() { ...@@ -24,7 +24,7 @@ $(function() {
$('.datepair input.time').each(function() { $('.datepair input.time').each(function() {
var $this = $(this); var $this = $(this);
var opts = { 'showDuration': true, 'timeFormat': 'g:ia', 'scrollDefaultNow': true }; var opts = { 'showDuration': true, 'timeFormat': 'H:i', 'scrollDefaultNow': true };
if ($this.hasClass('start') || $this.hasClass('end')) { if ($this.hasClass('start') || $this.hasClass('end')) {
opts.onSelect = doDatepair; opts.onSelect = doDatepair;
......
...@@ -12,7 +12,6 @@ from django.contrib.auth.decorators import login_required ...@@ -12,7 +12,6 @@ from django.contrib.auth.decorators import login_required
from django.http import Http404, HttpResponse, HttpResponseRedirect from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.shortcuts import redirect from django.shortcuts import redirect
from mitxmako.shortcuts import render_to_response, render_to_string from mitxmako.shortcuts import render_to_response, render_to_string
#from django.views.decorators.csrf import ensure_csrf_cookie
from django_future.csrf import ensure_csrf_cookie from django_future.csrf import ensure_csrf_cookie
from django.views.decorators.cache import cache_control from django.views.decorators.cache import cache_control
...@@ -67,9 +66,9 @@ def user_groups(user): ...@@ -67,9 +66,9 @@ def user_groups(user):
@ensure_csrf_cookie @ensure_csrf_cookie
@cache_if_anonymous @cache_if_anonymous
def courses(request): def courses(request):
''' """
Render "find courses" page. The course selection work is done in courseware.courses. Render "find courses" page. The course selection work is done in courseware.courses.
''' """
courses = get_courses(request.user, request.META.get('HTTP_HOST')) courses = get_courses(request.user, request.META.get('HTTP_HOST'))
courses = sort_by_announcement(courses) courses = sort_by_announcement(courses)
...@@ -77,14 +76,16 @@ def courses(request): ...@@ -77,14 +76,16 @@ def courses(request):
def render_accordion(request, course, chapter, section, model_data_cache): def render_accordion(request, course, chapter, section, model_data_cache):
''' Draws navigation bar. Takes current position in accordion as """
parameter. Draws navigation bar. Takes current position in accordion as
parameter.
If chapter and section are '' or None, renders a default accordion. If chapter and section are '' or None, renders a default accordion.
course, chapter, and section are the url_names. course, chapter, and section are the url_names.
Returns the html string''' Returns the html string
"""
# grab the table of contents # grab the table of contents
user = User.objects.prefetch_related("groups").get(id=request.user.id) user = User.objects.prefetch_related("groups").get(id=request.user.id)
...@@ -92,7 +93,8 @@ def render_accordion(request, course, chapter, section, model_data_cache): ...@@ -92,7 +93,8 @@ def render_accordion(request, course, chapter, section, model_data_cache):
context = dict([('toc', toc), context = dict([('toc', toc),
('course_id', course.id), ('course_id', course.id),
('csrf', csrf(request)['csrf_token'])] + template_imports.items()) ('csrf', csrf(request)['csrf_token']),
('show_timezone', course.show_timezone)] + template_imports.items())
return render_to_string('courseware/accordion.html', context) return render_to_string('courseware/accordion.html', context)
...@@ -166,10 +168,10 @@ def save_child_position(seq_module, child_name): ...@@ -166,10 +168,10 @@ def save_child_position(seq_module, child_name):
def check_for_active_timelimit_module(request, course_id, course): def check_for_active_timelimit_module(request, course_id, course):
''' """
Looks for a timing module for the given user and course that is currently active. Looks for a timing module for the given user and course that is currently active.
If found, returns a context dict with timer-related values to enable display of time remaining. If found, returns a context dict with timer-related values to enable display of time remaining.
''' """
context = {} context = {}
# TODO (cpennington): Once we can query the course structure, replace this with such a query # TODO (cpennington): Once we can query the course structure, replace this with such a query
...@@ -201,11 +203,11 @@ def check_for_active_timelimit_module(request, course_id, course): ...@@ -201,11 +203,11 @@ def check_for_active_timelimit_module(request, course_id, course):
def update_timelimit_module(user, course_id, model_data_cache, timelimit_descriptor, timelimit_module): def update_timelimit_module(user, course_id, model_data_cache, timelimit_descriptor, timelimit_module):
''' """
Updates the state of the provided timing module, starting it if it hasn't begun. Updates the state of the provided timing module, starting it if it hasn't begun.
Returns dict with timer-related values to enable display of time remaining. Returns dict with timer-related values to enable display of time remaining.
Returns 'timer_expiration_duration' in dict if timer is still active, and not if timer has expired. Returns 'timer_expiration_duration' in dict if timer is still active, and not if timer has expired.
''' """
context = {} context = {}
# determine where to go when the exam ends: # determine where to go when the exam ends:
if timelimit_descriptor.time_expired_redirect_url is None: if timelimit_descriptor.time_expired_redirect_url is None:
...@@ -391,14 +393,14 @@ def index(request, course_id, chapter=None, section=None, ...@@ -391,14 +393,14 @@ def index(request, course_id, chapter=None, section=None,
@ensure_csrf_cookie @ensure_csrf_cookie
def jump_to(request, course_id, location): def jump_to(request, course_id, location):
''' """
Show the page that contains a specific location. Show the page that contains a specific location.
If the location is invalid or not in any class, return a 404. If the location is invalid or not in any class, return a 404.
Otherwise, delegates to the index view to figure out whether this user Otherwise, delegates to the index view to figure out whether this user
has access, and what they should see. has access, and what they should see.
''' """
# Complain if the location isn't valid # Complain if the location isn't valid
try: try:
location = Location(location) location = Location(location)
...@@ -486,7 +488,9 @@ def syllabus(request, course_id): ...@@ -486,7 +488,9 @@ def syllabus(request, course_id):
def registered_for_course(course, user): def registered_for_course(course, user):
'''Return CourseEnrollment if user is registered for course, else False''' """
Return CourseEnrollment if user is registered for course, else False
"""
if user is None: if user is None:
return False return False
if user.is_authenticated(): if user.is_authenticated():
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<li class="${'active' if 'active' in section and section['active'] else ''} ${'graded' if 'graded' in section and section['graded'] else ''}"> <li class="${'active' if 'active' in section and section['active'] else ''} ${'graded' if 'graded' in section and section['graded'] else ''}">
<a href="${reverse('courseware_section', args=[course_id, chapter['url_name'], section['url_name']])}"> <a href="${reverse('courseware_section', args=[course_id, chapter['url_name'], section['url_name']])}">
<p>${section['display_name']}</p> <p>${section['display_name']}</p>
<p class="subtitle">${section['format']} ${"due " + get_default_time_display(section['due']) if section.get('due') is not None else ''}</p> <p class="subtitle">${section['format']} ${"due " + get_default_time_display(section['due'], show_timezone) if section.get('due') is not None else ''}</p>
</a> </a>
</li> </li>
% endfor % endfor
......
...@@ -64,7 +64,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph", ...@@ -64,7 +64,7 @@ ${progress_graph.body(grade_summary, course.grade_cutoffs, "grade-detail-graph",
%if section.get('due') is not None: %if section.get('due') is not None:
<em> <em>
due ${get_default_time_display(section['due'])} due ${get_default_time_display(section['due'], course.show_timezone)}
</em> </em>
%endif %endif
</p> </p>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment