Commit 4298c19b by Will Daly

Show a warning when the user disables an assessment.

parent 4027ea3c
......@@ -207,7 +207,7 @@ describe("OpenAssessment.StudioView", function() {
it("validates fields before saving", function() {
// Initially, there should not be a validation alert
expect(view.validationAlert.isVisible()).toBe(false);
expect(view.alert.isVisible()).toBe(false);
// Introduce a validation error (date field does format invalid)
view.settingsView.submissionStart("Not a valid date!", "00:00");
......@@ -218,7 +218,7 @@ describe("OpenAssessment.StudioView", function() {
// Since there was an invalid field, expect that data was NOT sent to the server.
// Also expect that an error is displayed
expect(server.receivedData).toBe(null);
expect(view.validationAlert.isVisible()).toBe(true);
expect(view.alert.isVisible()).toBe(true);
// Expect that individual fields were highlighted
expect(view.validationErrors()).toContain(
......@@ -232,7 +232,7 @@ describe("OpenAssessment.StudioView", function() {
// Expect that the validation errors were cleared
// and that data was successfully sent to the server.
expect(view.validationErrors()).toEqual([]);
expect(view.validationAlert.isVisible()).toBe(false);
expect(view.alert.isVisible()).toBe(false);
expect(server.receivedData).not.toBe(null);
});
});
......@@ -26,6 +26,22 @@ describe("OpenAssessment edit assessment views", function() {
expect(view.validationErrors()).toEqual([]);
};
var testAlertOnDisable = function(view) {
var alert = new OpenAssessment.ValidationAlert();
expect(alert.isVisible()).toBe(false);
// Set the assessment to enabled initially
view.isEnabled(true);
// Disable an assessment, which should display an alert
view.toggleEnabled();
expect(alert.isVisible()).toBe(true);
// Enable an assessment, which dismisses the alert
view.toggleEnabled();
expect(alert.isVisible()).toBe(false);
};
var testLoadXMLExamples = function(view) {
var xml = "XML DEFINITIONS WOULD BE HERE";
view.exampleDefinitions(xml);
......@@ -103,6 +119,8 @@ describe("OpenAssessment edit assessment views", function() {
expect(view.validate()).toBe(true);
expect(view.validationErrors()).toEqual([]);
});
it("shows an alert when disabled", function() { testAlertOnDisable(view); });
});
describe("OpenAssessment.EditSelfAssessmentView", function() {
......@@ -139,6 +157,8 @@ describe("OpenAssessment edit assessment views", function() {
"Self assessment due is invalid"
);
});
it("shows an alert when disabled", function() { testAlertOnDisable(view); });
});
describe("OpenAssessment.EditStudentTrainingView", function() {
......@@ -173,6 +193,8 @@ describe("OpenAssessment edit assessment views", function() {
]
);
});
it("shows an alert when disabled", function() { testAlertOnDisable(view); });
});
describe("OpenAssessment.EditExampleBasedAssessmentView", function() {
......@@ -185,5 +207,6 @@ describe("OpenAssessment edit assessment views", function() {
it("Enables and disables", function() { testEnableAndDisable(view); });
it("Loads a description", function() { testLoadXMLExamples(view); });
it("shows an alert when disabled", function() { testAlertOnDisable(view); });
});
});
......@@ -76,4 +76,80 @@ describe("OpenAssessment.DatetimeControl", function() {
datetimeControl.clearValidationErrors();
expect(datetimeControl.validationErrors()).toEqual([]);
});
});
\ No newline at end of file
});
describe("OpenAssessment.ToggleControl", function() {
var StubNotifier = function() {
this.receivedNotifications = [];
this.notificationFired = function(name, data) {
this.receivedNotifications.push({
name: name,
data: data
});
};
};
var notifier = null;
var toggleControl = null;
beforeEach(function() {
setFixtures(
'<div id="toggle_test">' +
'<div id="shown_section" />' +
'<div id="hidden_section" class="is--hidden"/>' +
'</div>' +
'<input type="checkbox" id="checkbox" checked />'
);
notifier = new StubNotifier();
toggleControl = new OpenAssessment.ToggleControl(
$("#checkbox"),
$("#shown_section"),
$("#hidden_section"),
notifier
).install();
});
it("shows and hides elements", function() {
var assertIsVisible = function(isVisible) {
expect(toggleControl.hiddenSection.hasClass('is--hidden')).toBe(isVisible);
expect(toggleControl.shownSection.hasClass('is--hidden')).toBe(!isVisible);
};
// Initially, the section is visible (default from the fixture)
assertIsVisible(true);
// Simulate clicking the checkbox, hiding the section
toggleControl.checkbox.click();
assertIsVisible(false);
// Click it again to show it
toggleControl.checkbox.click();
assertIsVisible(true);
});
it("fires notifications", function() {
// Toggle off notification
toggleControl.checkbox.click();
expect(notifier.receivedNotifications).toContain({
name: "toggleOff",
data: {}
});
// Toggle back on
toggleControl.checkbox.click();
expect(notifier.receivedNotifications).toContain({
name: "toggleOn",
data: {}
});
// ... and toggle off
toggleControl.checkbox.click();
expect(notifier.receivedNotifications).toContain({
name: "toggleOff",
data: {}
});
});
});
......@@ -274,3 +274,28 @@ describe("OpenAssessment.StudentTrainingListener", function() {
expect(listener.alert.isVisible()).toBe(true);
});
});
describe("OpenAssessment.AssessmentToggleListener", function() {
var alert = null;
var listener = null;
beforeEach(function() {
loadFixtures('oa_edit.html');
alert = new OpenAssessment.ValidationAlert().install();
listener = new OpenAssessment.AssessmentToggleListener();
});
it("displays an alert when the user disables an assessment", function() {
expect(alert.isVisible()).toBe(false);
listener.toggleOff({});
expect(alert.isVisible()).toBe(true);
});
it("hides the alert when the user enables an assessment", function() {
alert.setMessage("test", "test").show();
listener.toggleOn({});
expect(alert.isVisible()).toBe(false);
});
});
......@@ -4,9 +4,7 @@ describe("OpenAssessment.ValidationAlert", function() {
beforeEach(function() {
loadFixtures('oa_edit.html');
alert = new OpenAssessment.ValidationAlert(
$("#openassessment_rubric_validation_alert")
);
alert = new OpenAssessment.ValidationAlert().install();
});
it("shows and hides an alert", function() {
......@@ -23,10 +21,20 @@ describe("OpenAssessment.ValidationAlert", function() {
});
it("sets the alert title and message", function() {
// Set the title and message
alert.setMessage("new title", "new message");
expect(alert.getTitle()).toEqual("new title");
expect(alert.getMessage()).toEqual("new message");
});
it("hides when the user dismisses the alert", function() {
// Show the alert
alert.show();
expect(alert.isVisible()).toBe(true);
// Simulate a user click on the close button
alert.closeButton.click();
// The alert should be hidden
expect(alert.isVisible()).toBe(false);
});
});
\ No newline at end of file
......@@ -23,8 +23,7 @@ OpenAssessment.StudioView = function(runtime, element, server) {
this.initializeTabs();
// Initialize the validation alert
this.validationAlert = new OpenAssessment.ValidationAlert();
this.validationAlert.installEventHandlers();
this.alert = new OpenAssessment.ValidationAlert().install();
// Initialize the prompt tab view
this.promptView = new OpenAssessment.EditPromptView(
......@@ -135,7 +134,7 @@ OpenAssessment.StudioView.prototype = {
// its fields.
this.clearValidationErrors();
if (!this.validate()) {
this.validationAlert.setMessage(
this.alert.setMessage(
gettext("Couldn't Save This Assignment"),
gettext("Please correct the outlined fields.")
).show();
......@@ -143,7 +142,7 @@ OpenAssessment.StudioView.prototype = {
else {
// At this point, we know that all fields are valid,
// so we can dismiss the validation alert.
this.validationAlert.hide();
this.alert.hide();
// Check whether the problem has been released; if not,
// warn the user and allow them to cancel.
......
......@@ -22,10 +22,13 @@ OpenAssessment.EditPeerAssessmentView = function(element) {
// Configure the toggle checkbox to enable/disable this assessment
new OpenAssessment.ToggleControl(
this.element,
"#peer_assessment_description_closed",
"#peer_assessment_settings_editor"
).install("#include_peer_assessment");
$("#include_peer_assessment", this.element),
$("#peer_assessment_settings_editor", this.element),
$("#peer_assessment_description_closed", this.element),
new OpenAssessment.Notifier([
new OpenAssessment.AssessmentToggleListener()
])
).install();
// Configure the date and time fields
this.startDatetimeControl = new OpenAssessment.DatetimeControl(
......@@ -82,6 +85,14 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
},
/**
Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing.
**/
toggleEnabled: function() {
$("#include_peer_assessment", this.element).click();
},
/**
Get or set the required number of submissions a student must peer-assess.
Args:
......@@ -215,10 +226,13 @@ OpenAssessment.EditSelfAssessmentView = function(element) {
// Configure the toggle checkbox to enable/disable this assessment
new OpenAssessment.ToggleControl(
this.element,
"#self_assessment_description_closed",
"#self_assessment_settings_editor"
).install("#include_self_assessment");
$("#include_self_assessment", this.element),
$("#self_assessment_settings_editor", this.element),
$("#self_assessment_description_closed", this.element),
new OpenAssessment.Notifier([
new OpenAssessment.AssessmentToggleListener()
])
).install();
// Configure the date and time fields
this.startDatetimeControl = new OpenAssessment.DatetimeControl(
......@@ -272,6 +286,14 @@ OpenAssessment.EditSelfAssessmentView.prototype = {
},
/**
Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing.
**/
toggleEnabled: function() {
$("#include_self_assessment", this.element).click();
},
/**
Get or set the start date and time of the assessment.
Args:
......@@ -365,10 +387,13 @@ OpenAssessment.EditStudentTrainingView = function(element) {
this.name = "student-training";
new OpenAssessment.ToggleControl(
this.element,
"#student_training_description_closed",
"#student_training_settings_editor"
).install("#include_student_training");
$("#include_student_training", this.element),
$("#student_training_settings_editor", this.element),
$("#student_training_description_closed", this.element),
new OpenAssessment.Notifier([
new OpenAssessment.AssessmentToggleListener()
])
).install();
this.exampleContainer = new OpenAssessment.Container(
OpenAssessment.TrainingExample, {
......@@ -379,7 +404,7 @@ OpenAssessment.EditStudentTrainingView = function(element) {
containerItemClass: "openassessment_training_example"
}
);
this.exampleContainer.addEventListeners();
};
......@@ -433,6 +458,14 @@ OpenAssessment.EditStudentTrainingView.prototype = {
},
/**
Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing.
**/
toggleEnabled: function() {
$("#include_student_training", this.element).click();
},
/**
Gets the ID of the assessment
Returns:
......@@ -462,10 +495,13 @@ OpenAssessment.EditExampleBasedAssessmentView = function(element) {
this.name = "example-based-assessment";
new OpenAssessment.ToggleControl(
this.element,
"#ai_assessment_description_closed",
"#ai_assessment_settings_editor"
).install("#include_ai_assessment");
$("#include_ai_assessment", this.element),
$("#ai_assessment_settings_editor", this.element),
$("#ai_assessment_description_closed", this.element),
new OpenAssessment.Notifier([
new OpenAssessment.AssessmentToggleListener()
])
).install();
};
OpenAssessment.EditExampleBasedAssessmentView.prototype = {
......@@ -504,6 +540,14 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = {
},
/**
Toggle whether the assessment is enabled or disabled.
This triggers the actual click event and is mainly useful for testing.
**/
toggleEnabled: function() {
$("#include_ai_assessment", this.element).click();
},
/**
Get or set the XML defining the training examples.
Args:
......
......@@ -108,16 +108,21 @@ OpenAssessment.IntField.prototype = {
Show and hide elements based on a checkbox.
Args:
element (DOM element): The parent element, used to scope the selectors.
hiddenSelector (string): The CSS selector string for elements
to show when the checkbox is in the "off" state.
shownSelector (string): The CSS selector string for elements
to show when the checkbox is in the "on" state.
checkboxSel (JQuery selector): The checkbox used to toggle whether sections
are shown or hidden.
shownSel (JQuery selector): The section to show when the checkbox is checked.
hiddenSel (JQuery selector): The section to show when the checkbox is unchecked.
notifier (OpenAssessment.Notifier): Receives notifications when the checkbox state changes.
Sends the following notifications:
* toggleOn
* toggleOff
**/
OpenAssessment.ToggleControl = function(element, hiddenSelector, shownSelector) {
this.element = element;
this.hiddenSelector = hiddenSelector;
this.shownSelector = shownSelector;
OpenAssessment.ToggleControl = function(checkboxSel, shownSel, hiddenSel, notifier) {
this.checkbox = checkboxSel;
this.shownSection = shownSel;
this.hiddenSection = hiddenSel;
this.notifier = notifier;
};
OpenAssessment.ToggleControl.prototype = {
......@@ -132,24 +137,30 @@ OpenAssessment.ToggleControl.prototype = {
OpenAssessment.ToggleControl
**/
install: function(checkboxSelector) {
$(checkboxSelector, this.element).change(
this.checkbox.change(
this, function(event) {
var control = event.data;
if (this.checked) { control.show(); }
else { control.hide(); }
if (this.checked) {
control.notifier.notificationFired('toggleOn', {});
control.show();
}
else {
control.notifier.notificationFired('toggleOff', {});
control.hide();
}
}
);
return this;
},
show: function() {
$(this.hiddenSelector, this.element).addClass('is--hidden');
$(this.shownSelector, this.element).removeClass('is--hidden');
this.shownSection.removeClass('is--hidden');
this.hiddenSection.addClass('is--hidden');
},
hide: function() {
$(this.hiddenSelector, this.element).removeClass('is--hidden');
$(this.shownSelector, this.element).addClass('is--hidden');
this.shownSection.addClass('is--hidden');
this.hiddenSection.removeClass('is--hidden');
}
};
......
......@@ -200,8 +200,7 @@ OpenAssessment.StudentTrainingListener.prototype = {
*/
displayAlertMsg: function(title, msg) {
this.alert.setMessage(title, msg);
this.alert.show();
this.alert.setMessage(title, msg).show();
},
/**
......@@ -338,3 +337,26 @@ OpenAssessment.StudentTrainingListener.prototype = {
return examples;
}
};
/**
Show a warning when a user disables an assessment,
since any data in the disabled section won't be persisted
on save.
**/
OpenAssessment.AssessmentToggleListener = function() {
this.alert = new OpenAssessment.ValidationAlert();
};
OpenAssessment.AssessmentToggleListener.prototype = {
toggleOff: function(data) {
this.alert.setMessage(
gettext("Warning"),
gettext("Changes to steps that are not selected as part of the assignment will not be saved.")
).show();
},
toggleOn: function(data) {
this.alert.hide();
}
};
......@@ -10,6 +10,7 @@ OpenAssessment.ValidationAlert = function() {
this.editorElement = $(this.element).parent();
this.title = $(".openassessment_alert_title", this.element);
this.message = $(".openassessment_alert_message", this.element);
this.closeButton = $(".openassessment_alert_close", this.element);
this.ALERT_YELLOW = 'rgb(192, 172, 0)';
this.DARK_GREY = '#323232';
};
......@@ -19,14 +20,15 @@ OpenAssessment.ValidationAlert.prototype = {
/**
Install the event handlers for the alert.
**/
installEventHandlers: function() {
install: function() {
var alert = this;
$(".openassessment_alert_close", this.element).click(
this.closeButton.click(
function(eventObject) {
eventObject.preventDefault();
alert.hide();
}
);
return this;
},
/**
......@@ -49,6 +51,7 @@ OpenAssessment.ValidationAlert.prototype = {
$('.oa_editor_content_wrapper', this.editorElement).each( function () {
$(this).css(styles);
});
return this;
},
......@@ -60,13 +63,15 @@ OpenAssessment.ValidationAlert.prototype = {
*/
show : function() {
var view = this;
if (this.isVisible()){
$(this.element).animate(
{'background-color': view.ALERT_YELLOW}, 300, 'swing', function () {
$(this).animate({'background-color': view.DARK_GREY}, 700, 'swing');
}
);
} else {
}
else {
// Finds the height of all other elements in the editor_and_tabs (the Header and Alert) and sets
// the height of the editing area to be 100% of that element minus those constraints.
this.element.removeClass('covered');
......@@ -82,8 +87,10 @@ OpenAssessment.ValidationAlert.prototype = {
$('.oa_editor_content_wrapper', this.editorElement).each(function () {
$(this).css(styles);
});
return this;
}
return this;
},
/**
......@@ -91,8 +98,8 @@ OpenAssessment.ValidationAlert.prototype = {
How will this work with internationalization?
Args:
newTitle (str): the new title that the message will have
newMessage (str): the new text that the message's body will contain
newTitle (string): the new title that the message will have
newMessage (string): the new text that the message's body will contain
Returns:
OpenAssessment.ValidationAlert
......@@ -133,5 +140,5 @@ OpenAssessment.ValidationAlert.prototype = {
**/
getMessage: function() {
return this.message.text();
}
},
};
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