Allow grace periods of > 24 hours.

This commit is contained in:
Peter Fogg
2013-08-20 09:48:25 -04:00
parent 9065023132
commit eb5b6cc6ea
7 changed files with 105 additions and 19 deletions

View File

@@ -0,0 +1,24 @@
describe "CMS.Models.Settings.CourseGradingPolicy", ->
beforeEach ->
@model = new CMS.Models.Settings.CourseGradingPolicy()
describe "parse", ->
it "sets a null grace period to 00:00", ->
attrs = @model.parse(grace_period: null)
expect(attrs.grace_period).toEqual(
hours: 0,
minutes: 0
)
describe "parseGracePeriod", ->
it "parses a time in HH:MM format", ->
time = @model.parseGracePeriod("07:19")
expect(time).toEqual(
hours: 7,
minutes: 19
)
it "returns null on an incorrectly formatted string", ->
expect(@model.parseGracePeriod("asdf")).toBe(null)
expect(@model.parseGracePeriod("7:19")).toBe(null)
expect(@model.parseGracePeriod("1000:00")).toBe(null)

View File

@@ -24,6 +24,14 @@ CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({
}
attributes.graders = graderCollection;
}
// If grace period is unset or equal to 00:00 on the server,
// it's received as null
if (attributes['grace_period'] === null) {
attributes.grace_period = {
hours: 0,
minutes: 0
}
}
return attributes;
},
url : function() {
@@ -44,8 +52,25 @@ CMS.Models.Settings.CourseGradingPolicy = Backbone.Model.extend({
return newDate;
},
dateToGracePeriod : function(date) {
return {hours : date.getHours(), minutes : date.getMinutes(), seconds : date.getSeconds() };
parseGracePeriod : function(grace_period) {
// Enforce hours:minutes format
if(!/^\d{2,3}:\d{2}$/.test(grace_period)) {
return null;
}
var pieces = grace_period.split(/:/);
return {
hours: parseInt(pieces[0], 10),
minutes: parseInt(pieces[1], 10)
}
},
validate : function(attrs) {
if(_.has(attrs, 'grace_period')) {
if(attrs['grace_period'] === null) {
return {
'grace_period': gettext('Grace period must be specified in HH:MM format.')
}
}
}
}
});

View File

@@ -28,9 +28,6 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({
this.setupCutoffs();
// Instrument grace period
this.$el.find('#course-grading-graceperiod').timepicker();
// instantiates an editor template for each update in the collection
// Because this calls render, put it after everything which render may depend upon to prevent race condition.
window.templateLoader.loadRemoteTemplate("course_grade_policy",
@@ -51,6 +48,10 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({
// prevent bootstrap race condition by event dispatch
if (!this.template) return;
this.clearValidationErrors();
this.renderGracePeriod();
// Create and render the grading type subs
var self = this;
var gradelist = this.$el.find('.course-grading-assignment-list');
@@ -87,13 +88,6 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({
// render the grade cutoffs
this.renderCutoffBar();
var graceEle = this.$el.find('#course-grading-graceperiod');
graceEle.timepicker({'timeFormat' : 'H:i'}); // init doesn't take setTime
if (this.model.has('grace_period')) graceEle.timepicker('setTime', this.model.gracePeriodToDate());
// remove any existing listeners to keep them from piling on b/c render gets called frequently
graceEle.off('change', this.setGracePeriod);
graceEle.on('change', this, this.setGracePeriod);
return this;
},
addAssignmentType : function(e) {
@@ -103,17 +97,26 @@ CMS.Views.Settings.Grading = CMS.Views.ValidatingView.extend({
fieldToSelectorMap : {
'grace_period' : 'course-grading-graceperiod'
},
renderGracePeriod: function() {
var format = function(time) {
return time >= 10 ? time.toString() : '0' + time;
};
var grace_period = this.model.get('grace_period');
this.$el.find('#course-grading-graceperiod').val(
format(grace_period.hours) + ':' + format(grace_period.minutes)
);
},
setGracePeriod : function(event) {
var self = event.data;
self.clearValidationErrors();
var newVal = self.model.dateToGracePeriod($(event.currentTarget).timepicker('getTime'));
self.model.set('grace_period', newVal, {validate: true});
this.clearValidationErrors();
var newVal = this.model.parseGracePeriod($(event.currentTarget).val());
this.model.set('grace_period', newVal, {validate: true});
},
updateModel : function(event) {
if (!this.selectorToField[event.currentTarget.id]) return;
switch (this.selectorToField[event.currentTarget.id]) {
case 'grace_period': // handled above
case 'grace_period':
this.setGracePeriod(event);
break;
default: