Commit 9c0c1566 by gradyward

Merge pull request #490 from edx/grady/assessment-reorder

Grady/assessment reorder
parents 78078148 218d7513
......@@ -55,19 +55,18 @@
</ul>
<p class="openassessment_description" id="openassessment_step_select_description">
{% trans "Select the steps that students must complete. All steps are optional, but every assignment must include at least one step." %}
{% trans "Select the steps that students must complete. All steps are optional, but every assignment must include at least one step. To change the order in which students will complete the steps, drag them into the desired order." %}
</p>
<ol id="openassessment_assessment_module_settings_editors">
{% include "openassessmentblock/edit/oa_edit_training.html" %}
{% include "openassessmentblock/edit/oa_edit_training.html" %}
{% include "openassessmentblock/edit/oa_edit_peer.html" %}
{% include "openassessmentblock/edit/oa_edit_peer.html" %}
{% include "openassessmentblock/edit/oa_edit_self.html" %}
{% include "openassessmentblock/edit/oa_edit_ai.html" %}
{% include "openassessmentblock/edit/oa_edit_self.html" %}
{% include "openassessmentblock/edit/oa_edit_ai.html" %}
</ol>
</div>
</div>
<div class="openassessment_editor_buttons xblock-actions">
......
{% load i18n %}
{% spaceless %}
<div class="openassessment_assessment_module_settings_editor" id="oa_ai_assessment_editor">
<li class="openassessment_assessment_module_settings_editor" id="oa_ai_assessment_editor">
<div class = "drag-handle action"></div>
<div class = "openassessment_inclusion_wrapper">
<input id="include_ai_assessment" type="checkbox"
{% if assessments.example_based_assessment %} checked="true" {% endif %}>
......@@ -19,5 +20,5 @@
<textarea id="ai_training_examples">{{ assessments.example_based_assessment.examples }}</textarea>
</div>
</div>
</div>
</li>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div class="openassessment_assessment_module_settings_editor" id="oa_peer_assessment_editor">
<li class="openassessment_assessment_module_settings_editor" id="oa_peer_assessment_editor">
<div class = "drag-handle action"></div>
<div class="openassessment_inclusion_wrapper">
<input type="checkbox" id="include_peer_assessment"
{% if assessments.peer_assessment %} checked="true" {% endif %}>
......@@ -48,5 +49,5 @@
</ul>
</div>
</div>
</div>
</li>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div class="openassessment_assessment_module_settings_editor" id="oa_self_assessment_editor">
<li class="openassessment_assessment_module_settings_editor" id="oa_self_assessment_editor">
<div class = "drag-handle action"></div>
<div class = "openassessment_inclusion_wrapper">
<input id="include_self_assessment" type="checkbox"
{% if assessments.self_assessment %} checked="true" {% endif %}>
......@@ -34,5 +35,5 @@
</ul>
</div>
</div>
</div>
</li>
{% endspaceless %}
\ No newline at end of file
{% load i18n %}
{% spaceless %}
<div class="openassessment_assessment_module_settings_editor" id="oa_student_training_editor">
<li class="openassessment_assessment_module_settings_editor" id="oa_student_training_editor">
<div class = "drag-handle action"></div>
<div class = "openassessment_inclusion_wrapper">
<input type="checkbox" id="include_student_training"
{% if assessments.student_training %} checked="true" {% endif %}>
......@@ -19,5 +20,5 @@
<textarea id="student_training_examples">{{ assessments.student_training.examples }}</textarea>
</div>
</div>
</div>
</li>
{% endspaceless %}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -26,10 +26,12 @@ describe("OpenAssessment.EditSettingsView", function() {
loadFixtures('oa_edit.html');
// Create the stub assessment views
assessmentViews = [
new StubView("self-assessment", "Self assessment description"),
new StubView("peer-assessment", "Peer assessment description")
];
assessmentViews = {
"oa_self_assessment_editor": new StubView("self-assessment", "Self assessment description"),
"oa_peer_assessment_editor": new StubView("peer-assessment", "Peer assessment description"),
"oa_ai_assessment_editor": new StubView("ai-assessment", "Example Based assessment description"),
"oa_student_training_editor": new StubView("student-training", "Student Training description")
};
// Create the view
var element = $("#oa_basic_settings_editor").get(0);
......@@ -66,14 +68,29 @@ describe("OpenAssessment.EditSettingsView", function() {
});
it("builds a description of enabled assessments", function() {
// In this test we also verify that the mechansim that reads off of the DOM is correct, in that it gets
// the right order of assessments, in addition to performing the correct calls. Note that this test's
// success depends on our Template having the original order (as it does in an unconfigured ORA problem)
// of TRAINING -> PEER -> SELF -> AI
// The Peer and Self Editor ID's
var peerID = "oa_peer_assessment_editor";
var selfID = "oa_self_assessment_editor";
var aiID = "oa_ai_assessment_editor";
var studentID = "oa_student_training_editor";
// Disable all assessments, and expect an empty description
assessmentViews[0].isEnabled(false);
assessmentViews[1].isEnabled(false);
assessmentViews[peerID].isEnabled(false);
assessmentViews[selfID].isEnabled(false);
assessmentViews[aiID].isEnabled(false);
assessmentViews[studentID].isEnabled(false);
expect(view.assessmentsDescription()).toEqual([]);
// Enable the first assessment only
assessmentViews[0].isEnabled(true);
assessmentViews[1].isEnabled(false);
assessmentViews[peerID].isEnabled(false);
assessmentViews[selfID].isEnabled(true);
assessmentViews[aiID].isEnabled(false);
assessmentViews[studentID].isEnabled(false);
expect(view.assessmentsDescription()).toEqual([
{
name: "self-assessment",
......@@ -82,8 +99,10 @@ describe("OpenAssessment.EditSettingsView", function() {
]);
// Enable the second assessment only
assessmentViews[0].isEnabled(false);
assessmentViews[1].isEnabled(true);
assessmentViews[peerID].isEnabled(true);
assessmentViews[selfID].isEnabled(false);
assessmentViews[aiID].isEnabled(false);
assessmentViews[studentID].isEnabled(false);
expect(view.assessmentsDescription()).toEqual([
{
name: "peer-assessment",
......@@ -92,12 +111,30 @@ describe("OpenAssessment.EditSettingsView", function() {
]);
// Enable both assessments
assessmentViews[0].isEnabled(true);
assessmentViews[1].isEnabled(true);
assessmentViews[peerID].isEnabled(true);
assessmentViews[selfID].isEnabled(true);
assessmentViews[aiID].isEnabled(false);
assessmentViews[studentID].isEnabled(false);
expect(view.assessmentsDescription()).toEqual([
{
name: "peer-assessment",
dummy: "Peer assessment description"
},
{
name: "self-assessment",
dummy: "Self assessment description"
}
]);
// Enable Training and Peer assessments
assessmentViews[peerID].isEnabled(true);
assessmentViews[selfID].isEnabled(false);
assessmentViews[aiID].isEnabled(false);
assessmentViews[studentID].isEnabled(true);
expect(view.assessmentsDescription()).toEqual([
{
name: "student-training",
dummy: "Student Training description"
},
{
name: "peer-assessment",
......
......@@ -28,21 +28,26 @@ OpenAssessment.StudioView = function(runtime, element, server) {
);
// Initialize the settings tab view
var studentTrainingView = new OpenAssessment.EditStudentTrainingView(
$("#oa_student_training_editor", this.element).get(0)
);
var peerAssessmentView = new OpenAssessment.EditPeerAssessmentView(
$("#oa_peer_assessment_editor", this.element).get(0)
);
var selfAssessmentView = new OpenAssessment.EditSelfAssessmentView(
$("#oa_self_assessment_editor", this.element).get(0)
);
var exampleBasedAssessmentView = new OpenAssessment.EditExampleBasedAssessmentView(
$("#oa_ai_assessment_editor", this.element).get(0)
);
var assessmentLookupDictionary = {};
assessmentLookupDictionary[studentTrainingView.getID()] = studentTrainingView;
assessmentLookupDictionary[peerAssessmentView.getID()] = peerAssessmentView;
assessmentLookupDictionary[selfAssessmentView.getID()] = selfAssessmentView;
assessmentLookupDictionary[exampleBasedAssessmentView.getID()] = exampleBasedAssessmentView;
this.settingsView = new OpenAssessment.EditSettingsView(
$("#oa_basic_settings_editor", this.element).get(0), [
new OpenAssessment.EditPeerAssessmentView(
$("#oa_peer_assessment_editor", this.element).get(0)
),
new OpenAssessment.EditSelfAssessmentView(
$("#oa_self_assessment_editor", this.element).get(0)
),
new OpenAssessment.EditStudentTrainingView(
$("#oa_student_training_editor", this.element).get(0)
),
new OpenAssessment.EditExampleBasedAssessmentView(
$("#oa_ai_assessment_editor", this.element).get(0)
)
]
$("#oa_basic_settings_editor", this.element).get(0), assessmentLookupDictionary
);
// Initialize the rubric tab view
......@@ -53,6 +58,8 @@ OpenAssessment.StudioView = function(runtime, element, server) {
// Install the save and cancel buttons
$(".openassessment_save_button", this.element).click($.proxy(this.save, this));
$(".openassessment_cancel_button", this.element).click($.proxy(this.cancel, this));
this.initializeSortableAssessments()
};
OpenAssessment.StudioView.prototype = {
......@@ -64,14 +71,52 @@ OpenAssessment.StudioView.prototype = {
// Add the full height class to every element from the XBlock
// to the modal window in Studio.
$(this.element)
.toggleClass('openassessment_full_height', true)
.addClass('openassessment_full_height')
.parentsUntil('.modal-window')
.toggleClass('openassessment_full_height', true);
.addClass('openassessment_full_height');
// Add the modal window class to the modal window
$(this.element)
.closest('.modal-window')
.toggleClass('openassessment_modal_window', true);
.addClass('openassessment_modal_window');
},
/**
Installs click listeners which initialize drag and drop functionality for assessment modules.
**/
initializeSortableAssessments: function () {
var view = this;
// Initialize Drag and Drop of Assessment Modules
$('#openassessment_assessment_module_settings_editors', view.element).sortable({
// On Start, we want to collapse all draggable items so that dragging is visually simple (no scrolling)
start: function(event, ui) {
// Hide all of the contents (not the headers) of the divs, to collapse during dragging.
$('.openassessment_assessment_module_editor', view.element).hide();
// Because of the way that JQuery actively resizes elements during dragging (directly setting
// the style property), the only way to over come it is to use an important tag ( :( ), or
// to tell JQuery to set the height to be Automatic (i.e. resize to the minimum nescesary size.)
// Because all of the information we don't want displayed is now hidden, an auto height will
// perform the apparent "collapse" that we are looking for in the Placeholder and Helper.
var targetHeight = 'auto';
// Shrink the blank area behind the dragged item.
ui.placeholder.height(targetHeight);
// Shrink the dragged item itself.
ui.helper.height(targetHeight);
// Update the sortable to reflect these changes.
$('#openassessment_assessment_module_settings_editors', view.element)
.sortable('refresh').sortable('refreshPositions');
},
// On stop, we redisplay the divs to their original state
stop: function(event, ui){
$('.openassessment_assessment_module_editor', view.element).show();
},
snap: true,
axis: "y",
handle: ".drag-handle",
cursorAt: {top: 20}
});
$('#openassessment_assessment_module_settings_editors', view.element).disableSelection();
},
/**
......
......@@ -121,7 +121,7 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
mustGradeNum: function(num) {
var sel = $("#peer_assessment_must_grade", this.element);
return OpenAssessment.Fields.intField(sel, num);
},
},
/**
Get or set the required number of peer-assessments a student must receive.
......@@ -149,7 +149,7 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
startDatetime: function(datetime) {
var sel = $("#peer_assessment_start_date", this.element);
return OpenAssessment.Fields.datetimeField(sel, datetime);
},
},
/**
Get or set the due date and time of the assessment.
......@@ -164,6 +164,16 @@ OpenAssessment.EditPeerAssessmentView.prototype = {
var sel = $("#peer_assessment_due_date", this.element);
return OpenAssessment.Fields.datetimeField(sel, datetime);
},
/**
Gets the ID of the assessment
Returns:
string (CSS ID of the Element object)
**/
getID: function() {
return $(this.element).attr('id');
}
};
......@@ -237,7 +247,7 @@ OpenAssessment.EditSelfAssessmentView.prototype = {
startDatetime: function(datetime) {
var sel = $("#self_assessment_start_date", this.element);
return OpenAssessment.Fields.datetimeField(sel, datetime);
},
},
/**
Get or set the due date and time of the assessment.
......@@ -251,7 +261,17 @@ OpenAssessment.EditSelfAssessmentView.prototype = {
dueDatetime: function(datetime) {
var sel = $("#self_assessment_due_date", this.element);
return OpenAssessment.Fields.datetimeField(sel, datetime);
},
},
/**
Gets the ID of the assessment
Returns:
string (CSS ID of the Element object)
**/
getID: function() {
return $(this.element).attr('id');
}
};
/**
......@@ -308,7 +328,7 @@ OpenAssessment.EditStudentTrainingView.prototype = {
isEnabled: function(isEnabled) {
var sel = $("#include_student_training", this.element);
return OpenAssessment.Fields.booleanField(sel, isEnabled);
},
},
/**
Get or set the XML defining the training examples.
......@@ -324,6 +344,16 @@ OpenAssessment.EditStudentTrainingView.prototype = {
var sel = $("#student_training_examples", this.element);
return OpenAssessment.Fields.stringField(sel, xml);
},
/**
Gets the ID of the assessment
Returns:
string (CSS ID of the Element object)
**/
getID: function() {
return $(this.element).attr('id');
}
};
/**
......@@ -396,4 +426,14 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = {
var sel = $("#ai_training_examples", this.element);
return OpenAssessment.Fields.stringField(sel, xml);
},
/**
Gets the ID of the assessment
Returns:
string (CSS ID of the Element object)
**/
getID: function() {
return $(this.element).attr('id');
}
};
\ No newline at end of file
......@@ -10,7 +10,8 @@ Returns:
**/
OpenAssessment.EditSettingsView = function(element, assessmentViews) {
this.element = element;
this.settingsElement = element;
this.assessmentsElement = $(element).siblings('#openassessment_assessment_module_settings_editors').get(0);
this.assessmentViews = assessmentViews;
};
......@@ -28,7 +29,7 @@ OpenAssessment.EditSettingsView.prototype = {
**/
displayName: function(name) {
var sel = $("#openassessment_title_editor", this.element);
var sel = $("#openassessment_title_editor", this.settingsElement);
return OpenAssessment.Fields.stringField(sel, name);
},
......@@ -43,7 +44,7 @@ OpenAssessment.EditSettingsView.prototype = {
**/
submissionStart: function(datetime) {
var sel = $("#openassessment_submission_start_editor", this.element);
var sel = $("#openassessment_submission_start_editor", this.settingsElement);
return OpenAssessment.Fields.datetimeField(sel, datetime);
},
......@@ -58,7 +59,7 @@ OpenAssessment.EditSettingsView.prototype = {
**/
submissionDue: function(datetime) {
var sel = $("#openassessment_submission_start_editor", this.element);
var sel = $("#openassessment_submission_start_editor", this.settingsElement);
return OpenAssessment.Fields.datetimeField(sel, datetime);
},
......@@ -73,7 +74,7 @@ OpenAssessment.EditSettingsView.prototype = {
**/
imageSubmissionEnabled: function(isEnabled) {
var sel = $("#openassessment_submission_image_editor", this.element);
var sel = $("#openassessment_submission_image_editor", this.settingsElement);
if (typeof(isEnabled) !== "undefined") {
if (isEnabled) { sel.val(1); }
else { sel.val(0); }
......@@ -105,15 +106,17 @@ OpenAssessment.EditSettingsView.prototype = {
]
**/
assessmentsDescription: function() {
assessmentDescList = [];
for (var idx in this.assessmentViews) {
var asmntView = this.assessmentViews[idx];
var assessmentDescList = [];
var view = this;
// Finds all assessment modules within our element in the DOM, and appends their definitions to the DescList
$('.openassessment_assessment_module_settings_editor', this.assessmentsElement).each( function () {
var asmntView = view.assessmentViews[$(this).attr('id')];
if (asmntView.isEnabled()) {
var description = asmntView.description();
description["name"] = asmntView.name;
assessmentDescList.push(description);
}
}
});
return assessmentDescList;
},
}
};
\ No newline at end of file
......@@ -259,12 +259,45 @@
font-size: 80%;
}
.openassessment_assessment_module_settings_editor.openassessment_shrink_for_drag{
height: 40px;
}
.openassessment_assessment_module_settings_editor{
overflow-y: scroll;
padding: 5px;
margin: 10px;
border: 1px solid lightgray;
border: 1px solid $edx-gray-l3;
border-radius: 3px;
position: relative;
.drag-handle{
position: absolute;
background-color: $edx-gray-l4;
background-position: center;
display: block;
top: 0px;
right: 0px;
z-index: 10;
width: 15px;
height: 100%;
border-left: 1px solid $edx-gray-l3;
cursor: move;
@include transition(none);
}
.openassessment_description{
padding: 0 20px 0 10px;
}
}
.openassessment_assessment_module_settings_editor:hover {
border-color: $blue;
.drag-handle {
background-color: #009fe6;
border-color: #009fe6;
@include transition(none);
}
}
.openassessment_description{
......@@ -335,6 +368,12 @@
}
}
.ui-widget-header .ui-state-active:hover,
.ui-widget-header .ui-state-default:hover{
background: $edx-gray-l2;
}
#oa_rubric_editor_wrapper{
.wrapper-comp-settings{
......@@ -646,3 +685,4 @@
{
height: 100%;
}
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