Commit 58f45d79 by gradyward

Merge branch 'authoring' of https://github.com/edx/edx-ora2 into grady/ai-authoring

Conflicts:
	openassessment/xblock/defaults.py
	openassessment/xblock/static/css/openassessment.css
	openassessment/xblock/static/js/openassessment-studio.min.js
	openassessment/xblock/studio_mixin.py
	openassessment/xblock/test/data/invalid_update_xblock.json
	openassessment/xblock/test/data/update_xblock.json
	openassessment/xblock/test/test_studio.py
parents 64e90768 eefe1b46
...@@ -100,7 +100,11 @@ ...@@ -100,7 +100,11 @@
</ul> </ul>
<p class="openassessment_description" id="openassessment_step_select_description"> <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. To change the order in which students will complete the steps, drag them into the desired order." %} {% if 'example_based_assessment' in editor_assessments_order %}
{% trans "In this assignment, you can include example based assessment, student training, peer assessment, and self assessment steps. Select the steps that you want below, and then drag them into the order that you want. If you include an example based assessment step, it must be the first step. If you include a student training step, it must precede the peer assessment step." %}
{% else %}
{% trans "In this assignment, you can include student training, peer assessment, and self assessment steps. Select the steps that you want below, and then drag them into the order that you want. If you include a student training step, it must precede the peer assessment step." %}
{% endif %}
</p> </p>
<ol id="openassessment_assessment_module_settings_editors"> <ol id="openassessment_assessment_module_settings_editors">
{% for assessment in editor_assessments_order %} {% for assessment in editor_assessments_order %}
......
...@@ -63,7 +63,7 @@ DEFAULT_RUBRIC_CRITERIA = [ ...@@ -63,7 +63,7 @@ DEFAULT_RUBRIC_CRITERIA = [
# The rubric's feedback prompt is a set of instructions letting the student # The rubric's feedback prompt is a set of instructions letting the student
# know they can provide additional free form feedback in their assessment. # know they can provide additional free form feedback in their assessment.
DEFAULT_RUBRIC_FEEDBACK_PROMPT = """ DEFAULT_RUBRIC_FEEDBACK_PROMPT = """
(Optional) What aspects of this response stood out to you? What did it do well? How could it improve? (Optional) What aspects of this response stood out to you? What did it do well? How could it improve?
""" """
DEFAULT_EXAMPLE_ANSWER = """ DEFAULT_EXAMPLE_ANSWER = """
...@@ -133,8 +133,7 @@ DEFAULT_ASSESSMENT_MODULES = [ ...@@ -133,8 +133,7 @@ DEFAULT_ASSESSMENT_MODULES = [
] ]
DEFAULT_EDITOR_ASSESSMENTS_ORDER = [ DEFAULT_EDITOR_ASSESSMENTS_ORDER = [
"example-based-assessment",
"student-training", "student-training",
"peer-assessment", "peer-assessment",
"self-assessment" "self-assessment",
] ]
...@@ -91,7 +91,6 @@ EDITOR_UPDATE_SCHEMA = Schema({ ...@@ -91,7 +91,6 @@ EDITOR_UPDATE_SCHEMA = Schema({
}) })
], ],
'examples_xml': utf8_validator, 'examples_xml': utf8_validator,
'algorithm_id': All(utf8_validator, In(['ease','fake']))
}) })
], ],
Required('editor_assessments_order'): [ Required('editor_assessments_order'): [
......
This source diff could not be displayed because it is too large. You can view the blob instead.
if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.FileUploader=function(){this.upload=function(url,data,contentType){return $.Deferred(function(defer){$.ajax({url:url,type:"PUT",data:data,async:false,processData:false,contentType:contentType}).done(function(data,textStatus,jqXHR){defer.resolve()}).fail(function(data,textStatus,jqXHR){defer.rejectWith(this,[textStatus])})}).promise()}};if(typeof OpenAssessment.Server=="undefined"||!OpenAssessment.Server){OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX",gettext("This response could not be submitted.")])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},scheduleTraining:function(){var url=this.url("schedule_training");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},rescheduleUnfinishedTasks:function(){var url=this.url("reschedule_unfinished_tasks");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("One or more rescheduling tasks failed.")])})})},updateEditorContext:function(kwargs){var url=this.url("update_editor_context");var payload=JSON.stringify({prompt:kwargs.prompt,feedback_prompt:kwargs.feedbackPrompt,title:kwargs.title,submission_start:kwargs.submissionStart,submission_due:kwargs.submissionDue,criteria:kwargs.criteria,assessments:kwargs.assessments,editor_assessments_order:kwargs.editorAssessmentsOrder,allow_file_upload:kwargs.imageSubmissionEnabled});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This problem could not be saved.")])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("The server could not be contacted.")])})}).promise()},getUploadUrl:function(contentType){var url=this.url("upload_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({contentType:contentType})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve upload url.")])})}).promise()},getDownloadUrl:function(){var url=this.url("download_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve download url.")])})}).promise()}}}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.StudioView=function(runtime,element,server){this.element=element;this.runtime=runtime;this.server=server;this.fixModalHeight();this.initializeTabs();this.promptView=new OpenAssessment.EditPromptView($("#oa_prompt_editor_wrapper",this.element).get(0));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),assessmentLookupDictionary);this.rubricView=new OpenAssessment.EditRubricView($("#oa_rubric_editor_wrapper",this.element).get(0));$(".openassessment_save_button",this.element).click($.proxy(this.save,this));$(".openassessment_cancel_button",this.element).click($.proxy(this.cancel,this))};OpenAssessment.StudioView.prototype={fixModalHeight:function(){$(this.element).addClass("openassessment_full_height").parentsUntil(".modal-window").addClass("openassessment_full_height");$(this.element).closest(".modal-window").addClass("openassessment_modal_window")},initializeTabs:function(){if(typeof OpenAssessment.lastOpenEditingTab==="undefined"){OpenAssessment.lastOpenEditingTab=2}$(".openassessment_editor_content_and_tabs",this.element).tabs({active:OpenAssessment.lastOpenEditingTab})},saveTabState:function(){var tabElement=$(".openassessment_editor_content_and_tabs",this.element);OpenAssessment.lastOpenEditingTab=tabElement.tabs("option","active")},save:function(){var view=this;this.saveTabState();this.server.checkReleased().done(function(isReleased){if(isReleased){view.confirmPostReleaseUpdate($.proxy(view.updateEditorContext,view))}else{view.updateEditorContext()}}).fail(function(errMsg){view.showError(errMsg)})},confirmPostReleaseUpdate:function(onConfirm){var msg=gettext("This problem has already been released. Any changes will apply only to future assessments.");if(confirm(msg)){onConfirm()}},updateEditorContext:function(){this.runtime.notify("save",{state:"start"});var view=this;this.server.updateEditorContext({prompt:view.promptView.promptText(),feedbackPrompt:view.rubricView.feedbackPrompt(),criteria:view.rubricView.criteriaDefinition(),title:view.settingsView.displayName(),submissionStart:view.settingsView.submissionStart(),submissionDue:view.settingsView.submissionDue(),assessments:view.settingsView.assessmentsDescription(),imageSubmissionEnabled:view.settingsView.imageSubmissionEnabled(),editorAssessmentsOrder:view.settingsView.editorAssessmentsOrder()}).done(function(){view.runtime.notify("save",{state:"end"})}).fail(function(msg){view.showError(msg)})},cancel:function(){this.saveTabState();this.runtime.notify("cancel",{})},showError:function(errorMsg){this.runtime.notify("error",{msg:errorMsg})}};function OpenAssessmentEditor(runtime,element){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.StudioView(runtime,element,server)}OpenAssessment.EditPeerAssessmentView=function(element){this.element=element;this.name="peer-assessment";new OpenAssessment.ToggleControl(this.element,"#peer_assessment_description_closed","#peer_assessment_settings_editor").install("#include_peer_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_start_date","#peer_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_due_date","#peer_assessment_due_time").install()};OpenAssessment.EditPeerAssessmentView.prototype={description:function(){return{must_grade:this.mustGradeNum(),must_be_graded_by:this.mustBeGradedByNum(),start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_peer_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},mustGradeNum:function(num){var sel=$("#peer_assessment_must_grade",this.element);return OpenAssessment.Fields.intField(sel,num)},mustBeGradedByNum:function(num){var sel=$("#peer_assessment_graded_by",this.element);return OpenAssessment.Fields.intField(sel,num)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditSelfAssessmentView=function(element){this.element=element;this.name="self-assessment";new OpenAssessment.ToggleControl(this.element,"#self_assessment_description_closed","#self_assessment_settings_editor").install("#include_self_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_start_date","#self_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_due_date","#self_assessment_due_time").install()};OpenAssessment.EditSelfAssessmentView.prototype={description:function(){return{start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_self_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditStudentTrainingView=function(element){this.element=element;this.name="student-training";new OpenAssessment.ToggleControl(this.element,"#student_training_description_closed","#student_training_settings_editor").install("#include_student_training");this.exampleContainer=new OpenAssessment.Container(OpenAssessment.TrainingExample,{containerElement:$("#openassessment_training_example_list",this.element).get(0),templateElement:$("#openassessment_training_example_template",this.element).get(0),addButtonElement:$(".openassessment_add_training_example",this.element).get(0),removeButtonClass:"openassessment_training_example_remove",containerItemClass:"openassessment_training_example"})};OpenAssessment.EditStudentTrainingView.prototype={description:function(){return{examples:this.exampleContainer.getItemValues()}},isEnabled:function(isEnabled){var sel=$("#include_student_training",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#student_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditExampleBasedAssessmentView=function(element){this.element=element;this.name="example-based-assessment";var view=this;new OpenAssessment.ToggleControl(this.element,"#ai_assessment_description_closed","#ai_assessment_settings_editor").install("#include_ai_assessment")};OpenAssessment.EditExampleBasedAssessmentView.prototype={description:function(){return{examples_xml:this.exampleDefinitions(),algorithm_id:"ease"}},isEnabled:function(isEnabled){var sel=$("#include_ai_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#ai_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.Fields={stringField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return sel.val()},intField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return parseInt(sel.val(),10)},booleanField:function(sel,value){if(typeof value!=="undefined"){sel.prop("checked",value)}return sel.prop("checked")}};OpenAssessment.ToggleControl=function(element,hiddenSelector,shownSelector){this.element=element;this.hiddenSelector=hiddenSelector;this.shownSelector=shownSelector};OpenAssessment.ToggleControl.prototype={install:function(checkboxSelector){$(checkboxSelector,this.element).change(this,function(event){var control=event.data;if(this.checked){control.show()}else{control.hide()}});return this},show:function(){$(this.hiddenSelector,this.element).addClass("is--hidden");$(this.shownSelector,this.element).removeClass("is--hidden")},hide:function(){$(this.hiddenSelector,this.element).removeClass("is--hidden");$(this.shownSelector,this.element).addClass("is--hidden")}};OpenAssessment.DatetimeControl=function(element,datePicker,timePicker){this.element=element;this.datePicker=datePicker;this.timePicker=timePicker};OpenAssessment.DatetimeControl.prototype={install:function(){var dateString=$(this.datePicker,this.element).val();$(this.datePicker,this.element).datepicker({showButtonPanel:true}).datepicker("option","dateFormat","yy-mm-dd").datepicker("setDate",dateString);$(this.timePicker,this.element).timepicker({timeFormat:"H:i",step:60});return this},datetime:function(dateString,timeString){var datePickerSel=$(this.datePicker,this.element);var timePickerSel=$(this.timePicker,this.element);if(typeof dateString!=="undefined"){datePickerSel.datepicker("setDate",dateString)}if(typeof timeString!=="undefined"){timePickerSel.val(timeString)}if(datePickerSel.val()===""&&timePickerSel.val()===""){return null}return datePickerSel.val()+"T"+timePickerSel.val()}};OpenAssessment.EditPromptView=function(element){this.element=element};OpenAssessment.EditPromptView.prototype={promptText:function(text){var sel=$("#openassessment_prompt_editor",this.element);return OpenAssessment.Fields.stringField(sel,text)}};OpenAssessment.EditRubricView=function(element){this.element=element;this.criteriaContainer=new OpenAssessment.Container(OpenAssessment.RubricCriterion,{containerElement:$("#openassessment_criterion_list",this.element).get(0),templateElement:$("#openassessment_criterion_template",this.element).get(0),addButtonElement:$("#openassessment_rubric_add_criterion",this.element).get(0),removeButtonClass:"openassessment_criterion_remove_button",containerItemClass:"openassessment_criterion"})};OpenAssessment.EditRubricView.prototype={criteriaDefinition:function(){var criteria=this.criteriaContainer.getItemValues();for(var criterion_idx=0;criterion_idx<criteria.length;criterion_idx++){var criterion=criteria[criterion_idx];criterion.order_num=criterion_idx;for(var option_idx=0;option_idx<criterion.options.length;option_idx++){var option=criterion.options[option_idx];option.order_num=option_idx}}return criteria},feedbackPrompt:function(text){var sel=$("#openassessment_rubric_feedback",this.element);return OpenAssessment.Fields.stringField(sel,text)},removeAllCriteria:function(){var items=this.criteriaContainer.getAllItems();var view=this;$.each(items,function(){view.criteriaContainer.remove(this)})},addCriterion:function(){this.criteriaContainer.add()},getCriterionItem:function(index){return this.criteriaContainer.getItem(index)}};OpenAssessment.EditSettingsView=function(element,assessmentViews){this.settingsElement=element;this.assessmentsElement=$(element).siblings("#openassessment_assessment_module_settings_editors").get(0);this.assessmentViews=assessmentViews;this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_start_date","#openassessment_submission_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_due_date","#openassessment_submission_due_time").install();this.initializeSortableAssessments()};OpenAssessment.EditSettingsView.prototype={initializeSortableAssessments:function(){var view=this;$("#openassessment_assessment_module_settings_editors",view.element).sortable({start:function(event,ui){$(".openassessment_assessment_module_editor",view.element).hide();var targetHeight="auto";ui.placeholder.height(targetHeight);ui.helper.height(targetHeight);$("#openassessment_assessment_module_settings_editors",view.element).sortable("refresh").sortable("refreshPositions")},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 .drag-handle",view.element).disableSelection()},displayName:function(name){var sel=$("#openassessment_title_editor",this.settingsElement);return OpenAssessment.Fields.stringField(sel,name)},submissionStart:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},submissionDue:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},imageSubmissionEnabled:function(isEnabled){var sel=$("#openassessment_submission_image_editor",this.settingsElement);if(typeof isEnabled!=="undefined"){if(isEnabled){sel.val(1)}else{sel.val(0)}}return sel.val()==1},assessmentsDescription:function(){var assessmentDescList=[];var view=this;$(".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},editorAssessmentsOrder:function(){var editorAssessments=[];var view=this;$(".openassessment_assessment_module_settings_editor",this.assessmentsElement).each(function(){var asmntView=view.assessmentViews[$(this).attr("id")];editorAssessments.push(asmntView.name)});return editorAssessments}}; if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.FileUploader=function(){this.upload=function(url,data,contentType){return $.Deferred(function(defer){$.ajax({url:url,type:"PUT",data:data,async:false,processData:false,contentType:contentType}).done(function(data,textStatus,jqXHR){defer.resolve()}).fail(function(data,textStatus,jqXHR){defer.rejectWith(this,[textStatus])})}).promise()}};if(typeof OpenAssessment.Server=="undefined"||!OpenAssessment.Server){OpenAssessment.Server=function(runtime,element){this.runtime=runtime;this.element=element};OpenAssessment.Server.prototype={url:function(handler){return this.runtime.handlerUrl(this.element,handler)},render:function(component){var url=this.url("render_"+component);return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html"}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},renderContinuedPeer:function(){var url=this.url("render_peer_assessment");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{continue_grading:true}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},studentInfo:function(student_id){var url=this.url("render_student_info");return $.Deferred(function(defer){$.ajax({url:url,type:"POST",dataType:"html",data:{student_id:student_id}}).done(function(data){defer.resolveWith(this,[data])}).fail(function(data){defer.rejectWith(this,[gettext("This section could not be loaded.")])})}).promise()},submit:function(submission){var url=this.url("submit");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){var success=data[0];if(success){var studentId=data[1];var attemptNum=data[2];defer.resolveWith(this,[studentId,attemptNum])}else{var errorNum=data[1];var errorMsg=data[2];defer.rejectWith(this,[errorNum,errorMsg])}}).fail(function(data){defer.rejectWith(this,["AJAX",gettext("This response could not be submitted.")])})}).promise()},save:function(submission){var url=this.url("save_submission");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({submission:submission})}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This response could not be saved.")])})}).promise()},submitFeedbackOnAssessment:function(text,options){var url=this.url("submit_feedback");var payload=JSON.stringify({feedback_text:text,feedback_options:options});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This feedback could not be submitted.")])})}).promise()},peerAssess:function(optionsSelected,criterionFeedback,overallFeedback){var url=this.url("peer_assess");var payload=JSON.stringify({options_selected:optionsSelected,criterion_feedback:criterionFeedback,overall_feedback:overallFeedback});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})}).promise()},selfAssess:function(optionsSelected){var url=this.url("self_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},trainingAssess:function(optionsSelected){var url=this.url("training_assess");var payload=JSON.stringify({options_selected:optionsSelected});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.corrections])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},scheduleTraining:function(){var url=this.url("schedule_training");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This assessment could not be submitted.")])})})},rescheduleUnfinishedTasks:function(){var url=this.url("reschedule_unfinished_tasks");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:'""'}).done(function(data){if(data.success){defer.resolveWith(this,[data.msg])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("One or more rescheduling tasks failed.")])})})},updateEditorContext:function(kwargs){var url=this.url("update_editor_context");var payload=JSON.stringify({prompt:kwargs.prompt,feedback_prompt:kwargs.feedbackPrompt,title:kwargs.title,submission_start:kwargs.submissionStart,submission_due:kwargs.submissionDue,criteria:kwargs.criteria,assessments:kwargs.assessments,editor_assessments_order:kwargs.editorAssessmentsOrder,allow_file_upload:kwargs.imageSubmissionEnabled});return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolve()}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("This problem could not be saved.")])})}).promise()},checkReleased:function(){var url=this.url("check_released");var payload='""';return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:payload}).done(function(data){if(data.success){defer.resolveWith(this,[data.is_released])}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("The server could not be contacted.")])})}).promise()},getUploadUrl:function(contentType){var url=this.url("upload_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({contentType:contentType})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve upload url.")])})}).promise()},getDownloadUrl:function(){var url=this.url("download_url");return $.Deferred(function(defer){$.ajax({type:"POST",url:url,data:JSON.stringify({})}).done(function(data){if(data.success){defer.resolve(data.url)}else{defer.rejectWith(this,[data.msg])}}).fail(function(data){defer.rejectWith(this,[gettext("Could not retrieve download url.")])})}).promise()}}}if(typeof OpenAssessment=="undefined"||!OpenAssessment){OpenAssessment={}}if(typeof window.gettext==="undefined"){window.gettext=function(text){return text}}OpenAssessment.StudioView=function(runtime,element,server){this.element=element;this.runtime=runtime;this.server=server;this.fixModalHeight();this.initializeTabs();this.promptView=new OpenAssessment.EditPromptView($("#oa_prompt_editor_wrapper",this.element).get(0));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),assessmentLookupDictionary);this.rubricView=new OpenAssessment.EditRubricView($("#oa_rubric_editor_wrapper",this.element).get(0));$(".openassessment_save_button",this.element).click($.proxy(this.save,this));$(".openassessment_cancel_button",this.element).click($.proxy(this.cancel,this))};OpenAssessment.StudioView.prototype={fixModalHeight:function(){$(this.element).addClass("openassessment_full_height").parentsUntil(".modal-window").addClass("openassessment_full_height");$(this.element).closest(".modal-window").addClass("openassessment_modal_window")},initializeTabs:function(){if(typeof OpenAssessment.lastOpenEditingTab==="undefined"){OpenAssessment.lastOpenEditingTab=2}$(".openassessment_editor_content_and_tabs",this.element).tabs({active:OpenAssessment.lastOpenEditingTab})},saveTabState:function(){var tabElement=$(".openassessment_editor_content_and_tabs",this.element);OpenAssessment.lastOpenEditingTab=tabElement.tabs("option","active")},save:function(){var view=this;this.saveTabState();this.server.checkReleased().done(function(isReleased){if(isReleased){view.confirmPostReleaseUpdate($.proxy(view.updateEditorContext,view))}else{view.updateEditorContext()}}).fail(function(errMsg){view.showError(errMsg)})},confirmPostReleaseUpdate:function(onConfirm){var msg=gettext("This problem has already been released. Any changes will apply only to future assessments.");if(confirm(msg)){onConfirm()}},updateEditorContext:function(){this.runtime.notify("save",{state:"start"});var view=this;this.server.updateEditorContext({prompt:view.promptView.promptText(),feedbackPrompt:view.rubricView.feedbackPrompt(),criteria:view.rubricView.criteriaDefinition(),title:view.settingsView.displayName(),submissionStart:view.settingsView.submissionStart(),submissionDue:view.settingsView.submissionDue(),assessments:view.settingsView.assessmentsDescription(),imageSubmissionEnabled:view.settingsView.imageSubmissionEnabled(),editorAssessmentsOrder:view.settingsView.editorAssessmentsOrder()}).done(function(){view.runtime.notify("save",{state:"end"})}).fail(function(msg){view.showError(msg)})},cancel:function(){this.saveTabState();this.runtime.notify("cancel",{})},showError:function(errorMsg){this.runtime.notify("error",{msg:errorMsg})}};function OpenAssessmentEditor(runtime,element){var server=new OpenAssessment.Server(runtime,element);var view=new OpenAssessment.StudioView(runtime,element,server)}OpenAssessment.EditPeerAssessmentView=function(element){this.element=element;this.name="peer-assessment";new OpenAssessment.ToggleControl(this.element,"#peer_assessment_description_closed","#peer_assessment_settings_editor").install("#include_peer_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_start_date","#peer_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#peer_assessment_due_date","#peer_assessment_due_time").install()};OpenAssessment.EditPeerAssessmentView.prototype={description:function(){return{must_grade:this.mustGradeNum(),must_be_graded_by:this.mustBeGradedByNum(),start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_peer_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},mustGradeNum:function(num){var sel=$("#peer_assessment_must_grade",this.element);return OpenAssessment.Fields.intField(sel,num)},mustBeGradedByNum:function(num){var sel=$("#peer_assessment_graded_by",this.element);return OpenAssessment.Fields.intField(sel,num)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditSelfAssessmentView=function(element){this.element=element;this.name="self-assessment";new OpenAssessment.ToggleControl(this.element,"#self_assessment_description_closed","#self_assessment_settings_editor").install("#include_self_assessment");this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_start_date","#self_assessment_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#self_assessment_due_date","#self_assessment_due_time").install()};OpenAssessment.EditSelfAssessmentView.prototype={description:function(){return{start:this.startDatetime(),due:this.dueDatetime()}},isEnabled:function(isEnabled){var sel=$("#include_self_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},startDatetime:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},dueDatetime:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditStudentTrainingView=function(element){this.element=element;this.name="student-training";new OpenAssessment.ToggleControl(this.element,"#student_training_description_closed","#student_training_settings_editor").install("#include_student_training");this.exampleContainer=new OpenAssessment.Container(OpenAssessment.TrainingExample,{containerElement:$("#openassessment_training_example_list",this.element).get(0),templateElement:$("#openassessment_training_example_template",this.element).get(0),addButtonElement:$(".openassessment_add_training_example",this.element).get(0),removeButtonClass:"openassessment_training_example_remove",containerItemClass:"openassessment_training_example"})};OpenAssessment.EditStudentTrainingView.prototype={description:function(){return{examples:this.exampleContainer.getItemValues()}},isEnabled:function(isEnabled){var sel=$("#include_student_training",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#student_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.EditExampleBasedAssessmentView=function(element){this.element=element;this.name="example-based-assessment";new OpenAssessment.ToggleControl(this.element,"#ai_assessment_description_closed","#ai_assessment_settings_editor").install("#include_ai_assessment")};OpenAssessment.EditExampleBasedAssessmentView.prototype={description:function(){return{examples_xml:this.exampleDefinitions()}},isEnabled:function(isEnabled){var sel=$("#include_ai_assessment",this.element);return OpenAssessment.Fields.booleanField(sel,isEnabled)},exampleDefinitions:function(xml){var sel=$("#ai_training_examples",this.element);return OpenAssessment.Fields.stringField(sel,xml)},getID:function(){return $(this.element).attr("id")}};OpenAssessment.Fields={stringField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return sel.val()},intField:function(sel,value){if(typeof value!=="undefined"){sel.val(value)}return parseInt(sel.val(),10)},booleanField:function(sel,value){if(typeof value!=="undefined"){sel.prop("checked",value)}return sel.prop("checked")}};OpenAssessment.ToggleControl=function(element,hiddenSelector,shownSelector){this.element=element;this.hiddenSelector=hiddenSelector;this.shownSelector=shownSelector};OpenAssessment.ToggleControl.prototype={install:function(checkboxSelector){$(checkboxSelector,this.element).change(this,function(event){var control=event.data;if(this.checked){control.show()}else{control.hide()}});return this},show:function(){$(this.hiddenSelector,this.element).addClass("is--hidden");$(this.shownSelector,this.element).removeClass("is--hidden")},hide:function(){$(this.hiddenSelector,this.element).removeClass("is--hidden");$(this.shownSelector,this.element).addClass("is--hidden")}};OpenAssessment.DatetimeControl=function(element,datePicker,timePicker){this.element=element;this.datePicker=datePicker;this.timePicker=timePicker};OpenAssessment.DatetimeControl.prototype={install:function(){var dateString=$(this.datePicker,this.element).val();$(this.datePicker,this.element).datepicker({showButtonPanel:true}).datepicker("option","dateFormat","yy-mm-dd").datepicker("setDate",dateString);$(this.timePicker,this.element).timepicker({timeFormat:"H:i",step:60});return this},datetime:function(dateString,timeString){var datePickerSel=$(this.datePicker,this.element);var timePickerSel=$(this.timePicker,this.element);if(typeof dateString!=="undefined"){datePickerSel.datepicker("setDate",dateString)}if(typeof timeString!=="undefined"){timePickerSel.val(timeString)}if(datePickerSel.val()===""&&timePickerSel.val()===""){return null}return datePickerSel.val()+"T"+timePickerSel.val()}};OpenAssessment.EditPromptView=function(element){this.element=element};OpenAssessment.EditPromptView.prototype={promptText:function(text){var sel=$("#openassessment_prompt_editor",this.element);return OpenAssessment.Fields.stringField(sel,text)}};OpenAssessment.EditRubricView=function(element){this.element=element;this.criteriaContainer=new OpenAssessment.Container(OpenAssessment.RubricCriterion,{containerElement:$("#openassessment_criterion_list",this.element).get(0),templateElement:$("#openassessment_criterion_template",this.element).get(0),addButtonElement:$("#openassessment_rubric_add_criterion",this.element).get(0),removeButtonClass:"openassessment_criterion_remove_button",containerItemClass:"openassessment_criterion"})};OpenAssessment.EditRubricView.prototype={criteriaDefinition:function(){var criteria=this.criteriaContainer.getItemValues();for(var criterion_idx=0;criterion_idx<criteria.length;criterion_idx++){var criterion=criteria[criterion_idx];criterion.order_num=criterion_idx;for(var option_idx=0;option_idx<criterion.options.length;option_idx++){var option=criterion.options[option_idx];option.order_num=option_idx}}return criteria},feedbackPrompt:function(text){var sel=$("#openassessment_rubric_feedback",this.element);return OpenAssessment.Fields.stringField(sel,text)},removeAllCriteria:function(){var items=this.criteriaContainer.getAllItems();var view=this;$.each(items,function(){view.criteriaContainer.remove(this)})},addCriterion:function(){this.criteriaContainer.add()},getCriterionItem:function(index){return this.criteriaContainer.getItem(index)}};OpenAssessment.EditSettingsView=function(element,assessmentViews){this.settingsElement=element;this.assessmentsElement=$(element).siblings("#openassessment_assessment_module_settings_editors").get(0);this.assessmentViews=assessmentViews;this.startDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_start_date","#openassessment_submission_start_time").install();this.dueDatetimeControl=new OpenAssessment.DatetimeControl(this.element,"#openassessment_submission_due_date","#openassessment_submission_due_time").install();this.initializeSortableAssessments()};OpenAssessment.EditSettingsView.prototype={initializeSortableAssessments:function(){var view=this;$("#openassessment_assessment_module_settings_editors",view.element).sortable({start:function(event,ui){$(".openassessment_assessment_module_editor",view.element).hide();var targetHeight="auto";ui.placeholder.height(targetHeight);ui.helper.height(targetHeight);$("#openassessment_assessment_module_settings_editors",view.element).sortable("refresh").sortable("refreshPositions")},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 .drag-handle",view.element).disableSelection()},displayName:function(name){var sel=$("#openassessment_title_editor",this.settingsElement);return OpenAssessment.Fields.stringField(sel,name)},submissionStart:function(dateString,timeString){return this.startDatetimeControl.datetime(dateString,timeString)},submissionDue:function(dateString,timeString){return this.dueDatetimeControl.datetime(dateString,timeString)},imageSubmissionEnabled:function(isEnabled){var sel=$("#openassessment_submission_image_editor",this.settingsElement);if(typeof isEnabled!=="undefined"){if(isEnabled){sel.val(1)}else{sel.val(0)}}return sel.val()==1},assessmentsDescription:function(){var assessmentDescList=[];var view=this;$(".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},editorAssessmentsOrder:function(){var editorAssessments=[];var view=this;$(".openassessment_assessment_module_settings_editor",this.assessmentsElement).each(function(){var asmntView=view.assessmentViews[$(this).attr("id")];editorAssessments.push(asmntView.name)});return editorAssessments}};
\ No newline at end of file \ No newline at end of file
...@@ -14,7 +14,7 @@ describe("OpenAssessment edit assessment views", function() { ...@@ -14,7 +14,7 @@ describe("OpenAssessment edit assessment views", function() {
var testLoadXMLExamples = function(view) { var testLoadXMLExamples = function(view) {
var xml = "XML DEFINITIONS WOULD BE HERE"; var xml = "XML DEFINITIONS WOULD BE HERE";
view.exampleDefinitions(xml); view.exampleDefinitions(xml);
expect(view.description()).toEqual({ examples: xml }); expect(view.description()).toEqual({ examples_xml: xml });
}; };
beforeEach(function() { beforeEach(function() {
......
...@@ -372,8 +372,6 @@ OpenAssessment.EditExampleBasedAssessmentView = function(element) { ...@@ -372,8 +372,6 @@ OpenAssessment.EditExampleBasedAssessmentView = function(element) {
this.element = element; this.element = element;
this.name = "example-based-assessment"; this.name = "example-based-assessment";
var view = this;
new OpenAssessment.ToggleControl( new OpenAssessment.ToggleControl(
this.element, this.element,
"#ai_assessment_description_closed", "#ai_assessment_description_closed",
...@@ -393,14 +391,12 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = { ...@@ -393,14 +391,12 @@ OpenAssessment.EditExampleBasedAssessmentView.prototype = {
>>> editTrainingView.description(); >>> editTrainingView.description();
{ {
examples_xml: "XML DEFINITION HERE", examples_xml: "XML DEFINITION HERE",
algorithm: 'ease'
} }
**/ **/
description: function() { description: function() {
return { return {
examples_xml: this.exampleDefinitions(), examples_xml: this.exampleDefinitions()
algorithm_id: 'ease'
}; };
}, },
......
...@@ -187,12 +187,6 @@ ...@@ -187,12 +187,6 @@
height: Calc(100% - 97px); height: Calc(100% - 97px);
} }
#openassessment_editor_header{
background-color: #e5e5e5;
width: 100%;
top: 0;
}
#oa_editor_window_title{ #oa_editor_window_title{
float: left; float: left;
} }
...@@ -203,17 +197,40 @@ ...@@ -203,17 +197,40 @@
background-image: linear-gradient(#F2F2F2,#FFF); background-image: linear-gradient(#F2F2F2,#FFF);
} }
.oa_editor_tab{ #openassessment_editor_header {
float: right; background-color: #e5e5e5;
padding: ($baseline-v/8) ($baseline-h/8); width: 100%;
margin: ($baseline-v/8) ($baseline-h/8); top: 0;
border-radius: ($baseline-v/4); height: 42px;
box-shadow: none;
border: 0; .editor_tabs {
width: 35%;
min-width: 190px;
max-width: 360px;
float: right;
.oa_editor_tab {
float: right;
padding: 0;
width: 29%;
margin: 0px 2%;
height: 35px;
border-radius: 5px;
box-shadow: none;
border: 0;
text-align: center;
a {
padding: 8px 0 0 0;
width: 100%;
}
}
}
} }
.oa_editor_content_wrapper { .oa_editor_content_wrapper {
height: Calc(100% - 1px); height: 100%;
width: 100%; width: 100%;
border-radius: 3px; border-radius: 3px;
border: 1px solid $edx-gray-d1; border: 1px solid $edx-gray-d1;
...@@ -419,7 +436,6 @@ ...@@ -419,7 +436,6 @@
} }
.openassessment_criterion { .openassessment_criterion {
padding-bottom: 10px;
.openassessment_criterion_remove_button{ .openassessment_criterion_remove_button{
@extend .openassessment_rubric_remove_button; @extend .openassessment_rubric_remove_button;
...@@ -469,8 +485,8 @@ ...@@ -469,8 +485,8 @@
border: 1px solid; border: 1px solid;
color: #009fe6; color: #009fe6;
background-color: white; background-color: white;
padding: 5px; padding: 7.5px;
margin: 10px; margin: 10px 10px 10px 20px;
border-radius: 3px; border-radius: 3px;
cursor: pointer; cursor: pointer;
} }
...@@ -551,7 +567,7 @@ ...@@ -551,7 +567,7 @@
} }
.openassessment_criterion_option{ .openassessment_criterion_option{
padding: 7.5px; padding: 5px 5px 5px 15px;
.openassessment_criterion_option_remove_button{ .openassessment_criterion_option_remove_button{
@extend .openassessment_rubric_remove_button; @extend .openassessment_rubric_remove_button;
...@@ -583,13 +599,14 @@ ...@@ -583,13 +599,14 @@
margin: 0; margin: 0;
.wrapper-comp-setting{ .wrapper-comp-setting{
min-width: 200px; min-width: 150px;
} }
label{ label{
width: auto; width: auto;
padding-left: 15%; padding-left: Calc((100% - 150px)/2);
margin: 0; margin: 0;
float: right;
input{ input{
min-width: 50px; min-width: 50px;
...@@ -599,8 +616,6 @@ ...@@ -599,8 +616,6 @@
font-size: 11px; font-size: 11px;
} }
} }
} }
.openassessment_criterion_option_name_wrapper{ .openassessment_criterion_option_name_wrapper{
...@@ -728,13 +743,13 @@ ...@@ -728,13 +743,13 @@
} }
background-color: white; background-color: white;
border-top: 1px solid; border: 1px solid;
border-bottom: 1px solid; border-radius: 4px;
text-align: center; text-align: center;
color: #009fe6; color: #009fe6;
padding: 10px; padding: 10px;
margin: 10px, 0; margin: 15px 10px;
} }
#openassessment_rubric_add_criterion:hover{ #openassessment_rubric_add_criterion:hover{
...@@ -760,6 +775,7 @@ ...@@ -760,6 +775,7 @@
.modal-lg.modal-window.confirm.openassessment_modal_window{ .modal-lg.modal-window.confirm.openassessment_modal_window{
height: 80%; height: 80%;
top: 10%; top: 10%;
min-width: 600px;
} }
.openassessment_full_height.edit-xblock-modal, .openassessment_full_height.edit-xblock-modal,
......
...@@ -18,6 +18,7 @@ from openassessment.xblock.data_conversion import create_rubric_dict, make_djang ...@@ -18,6 +18,7 @@ from openassessment.xblock.data_conversion import create_rubric_dict, make_djang
from openassessment.xblock.schema import EDITOR_UPDATE_SCHEMA from openassessment.xblock.schema import EDITOR_UPDATE_SCHEMA
from openassessment.xblock.resolve_dates import resolve_dates from openassessment.xblock.resolve_dates import resolve_dates
from openassessment.xblock.xml import serialize_examples_to_xml_str, parse_examples_from_xml_str from openassessment.xblock.xml import serialize_examples_to_xml_str, parse_examples_from_xml_str
from xml import UpdateFromXmlError
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
...@@ -119,14 +120,8 @@ class StudioMixin(object): ...@@ -119,14 +120,8 @@ class StudioMixin(object):
Update the XBlock's configuration. Update the XBlock's configuration.
Args: Args:
data (dict): Data from the request; should have a value for the keys: 'rubric', 'prompt', data (dict): Data from the request; should have the format described
'title', 'submission_start', 'submission_due', and 'assessments'. in the editor schema.
-- The 'rubric' should be an XML representation of the new rubric.
-- The 'prompt' and 'title' should be plain text.
-- The dates 'submission_start' and 'submission_due' are both ISO strings
-- The 'assessments' is a list of assessment dictionaries (much like self.rubric_assessments)
with the notable exception that all examples (for Student Training and eventually AI)
are in XML string format and need to be parsed into dictionaries.
Kwargs: Kwargs:
suffix (str): Not used suffix (str): Not used
...@@ -145,8 +140,7 @@ class StudioMixin(object): ...@@ -145,8 +140,7 @@ class StudioMixin(object):
return {'success': False, 'msg': _('Error updating XBlock configuration')} return {'success': False, 'msg': _('Error updating XBlock configuration')}
# Check that the editor assessment order contains all the assessments. We are more flexible on example-based. # Check that the editor assessment order contains all the assessments. We are more flexible on example-based.
if (set(DEFAULT_EDITOR_ASSESSMENTS_ORDER) - {'example-based-assessment'}) \ if set(DEFAULT_EDITOR_ASSESSMENTS_ORDER) != (set(data['editor_assessments_order']) - {'example-based-assessment'}):
!= (set(data['editor_assessments_order']) - {'example-based-assessment'}):
logger.exception('editor_assessments_order does not contain all expected assessment types') logger.exception('editor_assessments_order does not contain all expected assessment types')
return {'success': False, 'msg': _('Error updating XBlock configuration')} return {'success': False, 'msg': _('Error updating XBlock configuration')}
...@@ -167,7 +161,19 @@ class StudioMixin(object): ...@@ -167,7 +161,19 @@ class StudioMixin(object):
# definition we expect for validation and storing. # definition we expect for validation and storing.
for assessment in data['assessments']: for assessment in data['assessments']:
if assessment['name'] == 'example-based-assessment': if assessment['name'] == 'example-based-assessment':
assessment['examples'] = parse_examples_from_xml_str(assessment['examples_xml']) try:
assessment['examples'] = parse_examples_from_xml_str(assessment['examples_xml'])
except UpdateFromXmlError:
return {'success': False, 'msg': _(
u'Validation error: There was an error in the XML definition of the '
u'examples provided by the user. Please correct the XML definition before saving.')
}
except KeyError:
return {'success': False, 'msg': _(
u'Validation error: No examples were provided for example based assessment.'
)}
# This is where we default to EASE for problems which are edited in the GUI
assessment['algorithm_id'] = 'ease'
xblock_validator = validator(self) xblock_validator = validator(self)
success, msg = xblock_validator( success, msg = xblock_validator(
...@@ -299,7 +305,7 @@ class StudioMixin(object): ...@@ -299,7 +305,7 @@ class StudioMixin(object):
if asmnt_name in order if asmnt_name in order
] ]
if problem_order_indices != sorted(problem_order_indices): if problem_order_indices != sorted(problem_order_indices):
unused_assessments = list(set(DEFAULT_EDITOR_ASSESSMENTS_ORDER) - {'example-based-assessment'} - set(used_assessments)) unused_assessments = list(set(DEFAULT_EDITOR_ASSESSMENTS_ORDER) - set(used_assessments))
return sorted(unused_assessments) + used_assessments return sorted(unused_assessments) + used_assessments
# Forwards compatibility: # Forwards compatibility:
......
...@@ -605,7 +605,7 @@ ...@@ -605,7 +605,7 @@
}, },
"student_training_example_missing_answer": { "student_training_example_missing_answer": {
"criteria": [ "criteria": [
{ {
"order_num": 0, "order_num": 0,
"label": "тєѕт ¢яιтєяιση", "label": "тєѕт ¢яιтєяιση",
...@@ -1041,6 +1041,10 @@ ...@@ -1041,6 +1041,10 @@
"due": null "due": null
} }
], ],
"editor_assessments_order": ["student-training", "peer-assessment", "self-assessment", "NOT A VALID ASSESSMENT"] "editor_assessments_order": [
"student-training", "peer-assessment",
"self-assessment", "example-based-assessment",
"NOT A VALID ASSESSMENT"
]
} }
} }
...@@ -87,6 +87,13 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -87,6 +87,13 @@ class StudioViewTest(XBlockHandlerTestCase):
} }
] ]
EXAMPLE_BASED_ASSESSMENT_EXAMPLES = '<examples>' + \
'<example>' + \
'<answer> TEST ANSWER </answer>' + \
'<select criterion="Test criterion" option="Test option" />' + \
'</example>' + \
'</examples>'
ASSESSMENT_CSS_IDS = { ASSESSMENT_CSS_IDS = {
"example-based-assessment": "oa_ai_assessment_editor", "example-based-assessment": "oa_ai_assessment_editor",
"peer-assessment": "oa_peer_assessment_editor", "peer-assessment": "oa_peer_assessment_editor",
...@@ -104,6 +111,11 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -104,6 +111,11 @@ class StudioViewTest(XBlockHandlerTestCase):
frag = self.runtime.render(xblock, 'studio_view') frag = self.runtime.render(xblock, 'studio_view')
self.assertTrue(frag.body_html().find('openassessment-edit')) self.assertTrue(frag.body_html().find('openassessment-edit'))
@scenario('data/example_based_only.xml')
def test_render_studio_with_ai(self, xblock):
frag = self.runtime.render(xblock, 'studio_view')
self.assertTrue(frag.body_html().find('openassessment-edit'))
@file_data('data/update_xblock.json') @file_data('data/update_xblock.json')
@scenario('data/basic_scenario.xml') @scenario('data/basic_scenario.xml')
def test_update_editor_context(self, xblock, data): def test_update_editor_context(self, xblock, data):
...@@ -126,6 +138,25 @@ class StudioViewTest(XBlockHandlerTestCase): ...@@ -126,6 +138,25 @@ class StudioViewTest(XBlockHandlerTestCase):
self.assertEqual(xblock.editor_assessments_order, data['editor_assessments_order']) self.assertEqual(xblock.editor_assessments_order, data['editor_assessments_order'])
@scenario('data/basic_scenario.xml') @scenario('data/basic_scenario.xml')
def test_update_editor_context_saves_assessment_order_with_ai(self, xblock):
# Update the XBlock with a different editor assessment order
data = copy.deepcopy(self.UPDATE_EDITOR_DATA)
data['assessments'] = [{
'name': 'example-based-assessment',
'examples_xml': self.EXAMPLE_BASED_ASSESSMENT_EXAMPLES
}]
data['editor_assessments_order'] = [
"example-based-assessment",
"student-training",
"peer-assessment",
"self-assessment",
]
xblock.published_date = None
resp = self.request(xblock, 'update_editor_context', json.dumps(data), response_format='json')
self.assertTrue(resp['success'], msg=resp.get('msg'))
self.assertEqual(xblock.editor_assessments_order, data['editor_assessments_order'])
@scenario('data/basic_scenario.xml')
def test_update_editor_context_assign_unique_names(self, xblock): def test_update_editor_context_assign_unique_names(self, xblock):
# Update the XBlock with a rubric that is missing # Update the XBlock with a rubric that is missing
# some of the (unique) names for rubric criteria/options. # some of the (unique) names for rubric criteria/options.
......
...@@ -66,6 +66,7 @@ def _is_valid_assessment_sequence(assessments): ...@@ -66,6 +66,7 @@ def _is_valid_assessment_sequence(assessments):
['student-training', 'peer-assessment'], ['student-training', 'peer-assessment'],
['student-training', 'peer-assessment', 'self-assessment'], ['student-training', 'peer-assessment', 'self-assessment'],
['student-training', 'self-assessment', 'peer-assessment'], ['student-training', 'self-assessment', 'peer-assessment'],
['self-assessment', 'student-training', 'peer-assessment'],
['example-based-assessment'], ['example-based-assessment'],
['example-based-assessment', 'self-assessment'], ['example-based-assessment', 'self-assessment'],
['example-based-assessment', 'peer-assessment'], ['example-based-assessment', 'peer-assessment'],
...@@ -74,6 +75,7 @@ def _is_valid_assessment_sequence(assessments): ...@@ -74,6 +75,7 @@ def _is_valid_assessment_sequence(assessments):
['example-based-assessment', 'student-training', 'peer-assessment'], ['example-based-assessment', 'student-training', 'peer-assessment'],
['example-based-assessment', 'student-training', 'peer-assessment', 'self-assessment'], ['example-based-assessment', 'student-training', 'peer-assessment', 'self-assessment'],
['example-based-assessment', 'student-training', 'self-assessment', 'peer-assessment'], ['example-based-assessment', 'student-training', 'self-assessment', 'peer-assessment'],
['example-based-assessment', 'self-assessment', 'student-training', 'peer-assessment'],
] ]
sequence = [asmnt.get('name') for asmnt in assessments] sequence = [asmnt.get('name') for asmnt in assessments]
...@@ -108,13 +110,8 @@ def validate_assessments(assessments, current_assessments, is_released): ...@@ -108,13 +110,8 @@ def validate_assessments(assessments, current_assessments, is_released):
# Ensure that we support this sequence of assessments. # Ensure that we support this sequence of assessments.
if not _is_valid_assessment_sequence(assessments): if not _is_valid_assessment_sequence(assessments):
msg = _( msg = _("The assessment order you selected is invalid.")
"For this assignment, you can set a peer assessment only, a self " return False, msg
"assessment only, or a peer assessment followed by a self "
"assessment. Student training is allowed only immediately before "
"peer assessment."
)
return (False, msg)
for assessment_dict in assessments: for assessment_dict in assessments:
# Number you need to grade is >= the number of people that need to grade you # Number you need to grade is >= the number of people that need to grade you
......
...@@ -806,9 +806,16 @@ def _unicode_to_xml(xml): ...@@ -806,9 +806,16 @@ def _unicode_to_xml(xml):
def parse_examples_from_xml_str(xml): def parse_examples_from_xml_str(xml):
"""
Converts an XML string of examples (Student Training or AI) into a dictionary
representing the same information.
examples_root = _unicode_to_xml(xml) Args:
xml (unicode): The XML definition of the examples
Returns
(list of dict): The example definition
"""
examples_root = _unicode_to_xml(xml)
examples = examples_root.findall('example') examples = examples_root.findall('example')
return parse_examples_xml(examples) return parse_examples_xml(examples)
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