% else:
-
+
% endif
% endfor
From 52f3e9daafa96ee5a589e79e09aaa5611d58c229 Mon Sep 17 00:00:00 2001
From: Vik Paruchuri
Date: Thu, 31 Jan 2013 18:05:57 -0500
Subject: [PATCH 030/169] Start moving peer grading to xmodule
---
.../js/src/peergrading/peer_grading.coffee | 27 +
.../peergrading/peer_grading_problem.coffee | 478 ++++++++++++++++++
.../xmodule/xmodule/peer_grading_module.py | 439 ++++++++++++++++
.../xmodule/xmodule/peer_grading_service.py | 256 ++++++++++
4 files changed, 1200 insertions(+)
create mode 100644 common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee
create mode 100644 common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee
create mode 100644 common/lib/xmodule/xmodule/peer_grading_module.py
create mode 100644 common/lib/xmodule/xmodule/peer_grading_service.py
diff --git a/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee
new file mode 100644
index 0000000000..ed79ba9c71
--- /dev/null
+++ b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee
@@ -0,0 +1,27 @@
+# This is a simple class that just hides the error container
+# and message container when they are empty
+# Can (and should be) expanded upon when our problem list
+# becomes more sophisticated
+class PeerGrading
+ constructor: () ->
+ @error_container = $('.error-container')
+ @error_container.toggle(not @error_container.is(':empty'))
+
+ @message_container = $('.message-container')
+ @message_container.toggle(not @message_container.is(':empty'))
+
+ @problem_list = $('.problem-list')
+ @construct_progress_bar()
+
+ construct_progress_bar: () =>
+ problems = @problem_list.find('tr').next()
+ problems.each( (index, element) =>
+ problem = $(element)
+ progress_bar = problem.find('.progress-bar')
+ bar_value = parseInt(problem.data('graded'))
+ bar_max = parseInt(problem.data('required')) + bar_value
+ progress_bar.progressbar({value: bar_value, max: bar_max})
+ )
+
+
+$(document).ready(() -> new PeerGrading())
diff --git a/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee
new file mode 100644
index 0000000000..ab16b34d12
--- /dev/null
+++ b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee
@@ -0,0 +1,478 @@
+##################################
+#
+# This is the JS that renders the peer grading problem page.
+# Fetches the correct problem and/or calibration essay
+# and sends back the grades
+#
+# Should not be run when we don't have a location to send back
+# to the server
+#
+# PeerGradingProblemBackend -
+# makes all the ajax requests and provides a mock interface
+# for testing purposes
+#
+# PeerGradingProblem -
+# handles the rendering and user interactions with the interface
+#
+##################################
+class PeerGradingProblemBackend
+ constructor: (ajax_url, mock_backend) ->
+ @mock_backend = mock_backend
+ @ajax_url = ajax_url
+ @mock_cnt = 0
+
+ post: (cmd, data, callback) ->
+ if @mock_backend
+ callback(@mock(cmd, data))
+ else
+ # if this post request fails, the error callback will catch it
+ $.post(@ajax_url + cmd, data, callback)
+ .error => callback({success: false, error: "Error occured while performing this operation"})
+
+ mock: (cmd, data) ->
+ if cmd == 'is_student_calibrated'
+ # change to test each version
+ response =
+ success: true
+ calibrated: @mock_cnt >= 2
+ else if cmd == 'show_calibration_essay'
+ #response =
+ # success: false
+ # error: "There was an error"
+ @mock_cnt++
+ response =
+ success: true
+ submission_id: 1
+ submission_key: 'abcd'
+ student_response: '''
+ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
+
+The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ '''
+ prompt: '''
+
S11E3: Metal Bands
+
Shown below are schematic band diagrams for two different metals. Both diagrams appear different, yet both of the elements are undisputably metallic in nature.
+
* Why is it that both sodium and magnesium behave as metals, even though the s-band of magnesium is filled?
+
This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.
+ '''
+ rubric: '''
+
Purpose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Organization
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '''
+ max_score: 4
+ else if cmd == 'get_next_submission'
+ response =
+ success: true
+ submission_id: 1
+ submission_key: 'abcd'
+ student_response: '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec tristique ante. Proin at mauris sapien, quis varius leo. Morbi laoreet leo nisi. Morbi aliquam lacus ante. Cras iaculis velit sed diam mattis a fermentum urna luctus. Duis consectetur nunc vitae felis facilisis eget vulputate risus viverra. Cras consectetur ullamcorper lobortis. Nam eu gravida lorem. Nulla facilisi. Nullam quis felis enim. Mauris orci lectus, dictum id cursus in, vulputate in massa.
+
+Phasellus non varius sem. Nullam commodo lacinia odio sit amet egestas. Donec ullamcorper sapien sagittis arcu volutpat placerat. Phasellus ut pretium ante. Nam dictum pulvinar nibh dapibus tristique. Sed at tellus mi, fringilla convallis justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tristique rutrum nulla sed eleifend. Praesent at nunc arcu. Mauris condimentum faucibus nibh, eget commodo quam viverra sed. Morbi in tincidunt dolor. Morbi sed augue et augue interdum fermentum.
+
+Curabitur tristique purus ac arcu consequat cursus. Cras diam felis, dignissim quis placerat at, aliquet ac metus. Mauris vulputate est eu nibh imperdiet varius. Cras aliquet rhoncus elit a laoreet. Mauris consectetur erat et erat scelerisque eu faucibus dolor consequat. Nam adipiscing sagittis nisl, eu mollis massa tempor ac. Nulla scelerisque tempus blandit. Phasellus ac ipsum eros, id posuere arcu. Nullam non sapien arcu. Vivamus sit amet lorem justo, ac tempus turpis. Suspendisse pharetra gravida imperdiet. Pellentesque lacinia mi eu elit luctus pellentesque. Sed accumsan libero a magna elementum varius. Nunc eget pellentesque metus. '''
+ prompt: '''
+
S11E3: Metal Bands
+
Shown below are schematic band diagrams for two different metals. Both diagrams appear different, yet both of the elements are undisputably metallic in nature.
+
* Why is it that both sodium and magnesium behave as metals, even though the s-band of magnesium is filled?
+
This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.
+ '''
+ rubric: '''
+
Purpose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Organization
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '''
+ max_score: 4
+ else if cmd == 'save_calibration_essay'
+ response =
+ success: true
+ actual_score: 2
+ else if cmd == 'save_grade'
+ response =
+ success: true
+
+ return response
+
+
+class PeerGradingProblem
+ constructor: (backend) ->
+ @prompt_wrapper = $('.prompt-wrapper')
+ @backend = backend
+
+
+ # get the location of the problem
+ @location = $('.peer-grading').data('location')
+ # prevent this code from trying to run
+ # when we don't have a location
+ if(!@location)
+ return
+
+ # get the other elements we want to fill in
+ @submission_container = $('.submission-container')
+ @prompt_container = $('.prompt-container')
+ @rubric_container = $('.rubric-container')
+ @flag_student_container = $('.flag-student-container')
+ @calibration_panel = $('.calibration-panel')
+ @grading_panel = $('.grading-panel')
+ @content_panel = $('.content-panel')
+ @grading_message = $('.grading-message')
+ @grading_message.hide()
+
+ @grading_wrapper =$('.grading-wrapper')
+ @calibration_feedback_panel = $('.calibration-feedback')
+ @interstitial_page = $('.interstitial-page')
+ @interstitial_page.hide()
+
+ @error_container = $('.error-container')
+
+ @submission_key_input = $("input[name='submission-key']")
+ @essay_id_input = $("input[name='essay-id']")
+ @feedback_area = $('.feedback-area')
+
+ @score_selection_container = $('.score-selection-container')
+ @rubric_selection_container = $('.rubric-selection-container')
+ @grade = null
+ @calibration = null
+
+ @submit_button = $('.submit-button')
+ @action_button = $('.action-button')
+ @calibration_feedback_button = $('.calibration-feedback-button')
+ @interstitial_page_button = $('.interstitial-page-button')
+ @flag_student_checkbox = $('.flag-checkbox')
+
+ Collapsible.setCollapsibles(@content_panel)
+
+ # Set up the click event handlers
+ @action_button.click -> history.back()
+ @calibration_feedback_button.click =>
+ @calibration_feedback_panel.hide()
+ @grading_wrapper.show()
+ @is_calibrated_check()
+
+ @interstitial_page_button.click =>
+ @interstitial_page.hide()
+ @is_calibrated_check()
+
+ @is_calibrated_check()
+
+
+ ##########
+ #
+ # Ajax calls to the backend
+ #
+ ##########
+ is_calibrated_check: () =>
+ @backend.post('is_student_calibrated', {location: @location}, @calibration_check_callback)
+
+ fetch_calibration_essay: () =>
+ @backend.post('show_calibration_essay', {location: @location}, @render_calibration)
+
+ fetch_submission_essay: () =>
+ @backend.post('get_next_submission', {location: @location}, @render_submission)
+
+ # finds the scores for each rubric category
+ get_score_list: () =>
+ # find the number of categories:
+ num_categories = $('table.rubric tr').length
+
+ score_lst = []
+ # get the score for each one
+ for i in [0..(num_categories-1)]
+ score = $("input[name='score-selection-#{i}']:checked").val()
+ score_lst.push(score)
+
+ return score_lst
+
+ construct_data: () ->
+ data =
+ rubric_scores: @get_score_list()
+ score: @grade
+ location: @location
+ submission_id: @essay_id_input.val()
+ submission_key: @submission_key_input.val()
+ feedback: @feedback_area.val()
+ submission_flagged: @flag_student_checkbox.is(':checked')
+ return data
+
+
+ submit_calibration_essay: ()=>
+ data = @construct_data()
+ @backend.post('save_calibration_essay', data, @calibration_callback)
+
+ submit_grade: () =>
+ data = @construct_data()
+ @backend.post('save_grade', data, @submission_callback)
+
+
+ ##########
+ #
+ # Callbacks for various events
+ #
+ ##########
+
+ # called after we perform an is_student_calibrated check
+ calibration_check_callback: (response) =>
+ if response.success
+ # if we haven't been calibrating before
+ if response.calibrated and (@calibration == null or @calibration == false)
+ @calibration = false
+ @fetch_submission_essay()
+ # If we were calibrating before and no longer need to,
+ # show the interstitial page
+ else if response.calibrated and @calibration == true
+ @calibration = false
+ @render_interstitial_page()
+ else
+ @calibration = true
+ @fetch_calibration_essay()
+ else if response.error
+ @render_error(response.error)
+ else
+ @render_error("Error contacting the grading service")
+
+
+ # called after we submit a calibration score
+ calibration_callback: (response) =>
+ if response.success
+ @render_calibration_feedback(response)
+ else if response.error
+ @render_error(response.error)
+ else
+ @render_error("Error saving calibration score")
+
+ # called after we submit a submission score
+ submission_callback: (response) =>
+ if response.success
+ @is_calibrated_check()
+ @grading_message.fadeIn()
+ @grading_message.html("
Grade sent successfully.
")
+ else
+ if response.error
+ @render_error(response.error)
+ else
+ @render_error("Error occurred while submitting grade")
+
+ # called after a grade is selected on the interface
+ graded_callback: (event) =>
+ @grade = $("input[name='grade-selection']:checked").val()
+ if @grade == undefined
+ return
+ # check to see whether or not any categories have not been scored
+ num_categories = $('table.rubric tr').length
+ for i in [0..(num_categories-1)]
+ score = $("input[name='score-selection-#{i}']:checked").val()
+ if score == undefined
+ return
+ # show button if we have scores for all categories
+ @show_submit_button()
+
+
+
+ ##########
+ #
+ # Rendering methods and helpers
+ #
+ ##########
+ # renders a calibration essay
+ render_calibration: (response) =>
+ if response.success
+
+ # load in all the data
+ @submission_container.html("
Training Essay
")
+ @render_submission_data(response)
+ # TODO: indicate that we're in calibration mode
+ @calibration_panel.addClass('current-state')
+ @grading_panel.removeClass('current-state')
+
+ # Display the right text
+ # both versions of the text are written into the template itself
+ # we only need to show/hide the correct ones at the correct time
+ @calibration_panel.find('.calibration-text').show()
+ @grading_panel.find('.calibration-text').show()
+ @calibration_panel.find('.grading-text').hide()
+ @grading_panel.find('.grading-text').hide()
+ @flag_student_container.hide()
+
+ @submit_button.unbind('click')
+ @submit_button.click @submit_calibration_essay
+
+ else if response.error
+ @render_error(response.error)
+ else
+ @render_error("An error occurred while retrieving the next calibration essay")
+
+ # Renders a student submission to be graded
+ render_submission: (response) =>
+ if response.success
+ @submit_button.hide()
+ @submission_container.html("
Submitted Essay
")
+ @render_submission_data(response)
+
+ @calibration_panel.removeClass('current-state')
+ @grading_panel.addClass('current-state')
+
+ # Display the correct text
+ # both versions of the text are written into the template itself
+ # we only need to show/hide the correct ones at the correct time
+ @calibration_panel.find('.calibration-text').hide()
+ @grading_panel.find('.calibration-text').hide()
+ @calibration_panel.find('.grading-text').show()
+ @grading_panel.find('.grading-text').show()
+ @flag_student_container.show()
+
+ @submit_button.unbind('click')
+ @submit_button.click @submit_grade
+ else if response.error
+ @render_error(response.error)
+ else
+ @render_error("An error occured when retrieving the next submission.")
+
+
+ make_paragraphs: (text) ->
+ paragraph_split = text.split(/\n\s*\n/)
+ new_text = ''
+ for paragraph in paragraph_split
+ new_text += "
From c1583dbba2861434fb37635d031f7b2b7a61c50b Mon Sep 17 00:00:00 2001
From: Vik Paruchuri
Date: Thu, 31 Jan 2013 19:57:35 -0500
Subject: [PATCH 038/169] Properly load javascript, fix templates to work with
xmodule, modify AJAX handlers
---
.../js/src/peergrading/peer_grading.coffee | 14 +-
.../peergrading/peer_grading_problem.coffee | 229 +++++++++---------
.../xmodule/xmodule/peer_grading_module.py | 73 +++---
.../xmodule/xmodule/peer_grading_service.py | 2 +
lms/templates/peer_grading/peer_grading.html | 2 +-
.../peer_grading/peer_grading_problem.html | 2 +-
6 files changed, 159 insertions(+), 163 deletions(-)
diff --git a/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee
index 113f5e02a6..b8196838f3 100644
--- a/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee
+++ b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading.coffee
@@ -2,11 +2,11 @@
# and message container when they are empty
# Can (and should be) expanded upon when our problem list
# becomes more sophisticated
-class PeerGrading
- constructor: () ->
+class @PeerGrading
+ constructor: (element) ->
@peer_grading_container = $('.peer-grading')
@peer_grading_outer_container = $('.peer-grading-container')
- @ajax_url = peer_grading_container.data('ajax-url')
+ @ajax_url = @peer_grading_container.data('ajax-url')
@error_container = $('.error-container')
@error_container.toggle(not @error_container.is(':empty'))
@@ -14,7 +14,7 @@ class PeerGrading
@message_container.toggle(not @message_container.is(':empty'))
@problem_button = $('.problem-button')
- @problem_button.click show_results
+ @problem_button.click @show_results
@problem_list = $('.problem-list')
@construct_progress_bar()
@@ -35,7 +35,7 @@ class PeerGrading
$.postWithPrefix "#{@ajax_url}problem", data, (response) =>
if response.success
@peer_grading_outer_container.after(response.html).remove()
+ backend = new PeerGradingProblemBackend(@ajax_url, false)
+ new PeerGradingProblem(backend)
else
- @gentle_alert response.error
-
-$(document).ready(() -> new PeerGrading())
+ @gentle_alert response.error
\ No newline at end of file
diff --git a/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee
index ab16b34d12..ee98905cda 100644
--- a/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee
+++ b/common/lib/xmodule/xmodule/js/src/peergrading/peer_grading_problem.coffee
@@ -7,7 +7,7 @@
# Should not be run when we don't have a location to send back
# to the server
#
-# PeerGradingProblemBackend -
+# PeerGradingProblemBackend -
# makes all the ajax requests and provides a mock interface
# for testing purposes
#
@@ -15,7 +15,7 @@
# handles the rendering and user interactions with the interface
#
##################################
-class PeerGradingProblemBackend
+class @PeerGradingProblemBackend
constructor: (ajax_url, mock_backend) ->
@mock_backend = mock_backend
@ajax_url = ajax_url
@@ -32,141 +32,140 @@ class PeerGradingProblemBackend
mock: (cmd, data) ->
if cmd == 'is_student_calibrated'
# change to test each version
- response =
- success: true
+ response =
+ success: true
calibrated: @mock_cnt >= 2
else if cmd == 'show_calibration_essay'
- #response =
+ #response =
# success: false
# error: "There was an error"
@mock_cnt++
- response =
+ response =
success: true
submission_id: 1
submission_key: 'abcd'
student_response: '''
- Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
+ Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.
-The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
- '''
+ The standard chunk of Lorem Ipsum used since the 1500s is reproduced below for those interested. Sections 1.10.32 and 1.10.33 from "de Finibus Bonorum et Malorum" by Cicero are also reproduced in their exact original form, accompanied by English versions from the 1914 translation by H. Rackham.
+ '''
prompt: '''
-
S11E3: Metal Bands
-
Shown below are schematic band diagrams for two different metals. Both diagrams appear different, yet both of the elements are undisputably metallic in nature.
-
* Why is it that both sodium and magnesium behave as metals, even though the s-band of magnesium is filled?
-
This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.
- '''
+
S11E3: Metal Bands
+
Shown below are schematic band diagrams for two different metals. Both diagrams appear different, yet both of the elements are undisputably metallic in nature.
+
* Why is it that both sodium and magnesium behave as metals, even though the s-band of magnesium is filled?
+
This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.
+ '''
rubric: '''
-
Purpose
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Organization
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- '''
+
Purpose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Organization
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '''
max_score: 4
else if cmd == 'get_next_submission'
- response =
+ response =
success: true
submission_id: 1
submission_key: 'abcd'
student_response: '''Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec tristique ante. Proin at mauris sapien, quis varius leo. Morbi laoreet leo nisi. Morbi aliquam lacus ante. Cras iaculis velit sed diam mattis a fermentum urna luctus. Duis consectetur nunc vitae felis facilisis eget vulputate risus viverra. Cras consectetur ullamcorper lobortis. Nam eu gravida lorem. Nulla facilisi. Nullam quis felis enim. Mauris orci lectus, dictum id cursus in, vulputate in massa.
-Phasellus non varius sem. Nullam commodo lacinia odio sit amet egestas. Donec ullamcorper sapien sagittis arcu volutpat placerat. Phasellus ut pretium ante. Nam dictum pulvinar nibh dapibus tristique. Sed at tellus mi, fringilla convallis justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tristique rutrum nulla sed eleifend. Praesent at nunc arcu. Mauris condimentum faucibus nibh, eget commodo quam viverra sed. Morbi in tincidunt dolor. Morbi sed augue et augue interdum fermentum.
+ Phasellus non varius sem. Nullam commodo lacinia odio sit amet egestas. Donec ullamcorper sapien sagittis arcu volutpat placerat. Phasellus ut pretium ante. Nam dictum pulvinar nibh dapibus tristique. Sed at tellus mi, fringilla convallis justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus tristique rutrum nulla sed eleifend. Praesent at nunc arcu. Mauris condimentum faucibus nibh, eget commodo quam viverra sed. Morbi in tincidunt dolor. Morbi sed augue et augue interdum fermentum.
-Curabitur tristique purus ac arcu consequat cursus. Cras diam felis, dignissim quis placerat at, aliquet ac metus. Mauris vulputate est eu nibh imperdiet varius. Cras aliquet rhoncus elit a laoreet. Mauris consectetur erat et erat scelerisque eu faucibus dolor consequat. Nam adipiscing sagittis nisl, eu mollis massa tempor ac. Nulla scelerisque tempus blandit. Phasellus ac ipsum eros, id posuere arcu. Nullam non sapien arcu. Vivamus sit amet lorem justo, ac tempus turpis. Suspendisse pharetra gravida imperdiet. Pellentesque lacinia mi eu elit luctus pellentesque. Sed accumsan libero a magna elementum varius. Nunc eget pellentesque metus. '''
+ Curabitur tristique purus ac arcu consequat cursus. Cras diam felis, dignissim quis placerat at, aliquet ac metus. Mauris vulputate est eu nibh imperdiet varius. Cras aliquet rhoncus elit a laoreet. Mauris consectetur erat et erat scelerisque eu faucibus dolor consequat. Nam adipiscing sagittis nisl, eu mollis massa tempor ac. Nulla scelerisque tempus blandit. Phasellus ac ipsum eros, id posuere arcu. Nullam non sapien arcu. Vivamus sit amet lorem justo, ac tempus turpis. Suspendisse pharetra gravida imperdiet. Pellentesque lacinia mi eu elit luctus pellentesque. Sed accumsan libero a magna elementum varius. Nunc eget pellentesque metus. '''
prompt: '''
-
S11E3: Metal Bands
-
Shown below are schematic band diagrams for two different metals. Both diagrams appear different, yet both of the elements are undisputably metallic in nature.
-
* Why is it that both sodium and magnesium behave as metals, even though the s-band of magnesium is filled?
-
This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.
- '''
+
S11E3: Metal Bands
+
Shown below are schematic band diagrams for two different metals. Both diagrams appear different, yet both of the elements are undisputably metallic in nature.
+
* Why is it that both sodium and magnesium behave as metals, even though the s-band of magnesium is filled?
+
This is a self-assessed open response question. Please use as much space as you need in the box below to answer the question.
+ '''
rubric: '''
-
Purpose
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Organization
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- '''
+
Purpose
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Organization
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ '''
max_score: 4
else if cmd == 'save_calibration_essay'
- response =
+ response =
success: true
actual_score: 2
else if cmd == 'save_grade'
- response =
+ response =
success: true
return response
-
-class PeerGradingProblem
+class @PeerGradingProblem
constructor: (backend) ->
@prompt_wrapper = $('.prompt-wrapper')
@backend = backend
-
+
# get the location of the problem
@location = $('.peer-grading').data('location')
- # prevent this code from trying to run
+ # prevent this code from trying to run
# when we don't have a location
if(!@location)
return
@@ -208,7 +207,7 @@ class PeerGradingProblem
# Set up the click event handlers
@action_button.click -> history.back()
- @calibration_feedback_button.click =>
+ @calibration_feedback_button.click =>
@calibration_feedback_panel.hide()
@grading_wrapper.show()
@is_calibrated_check()
@@ -266,7 +265,7 @@ class PeerGradingProblem
submit_grade: () =>
data = @construct_data()
@backend.post('save_grade', data, @submission_callback)
-
+
##########
#
@@ -301,7 +300,7 @@ class PeerGradingProblem
@render_calibration_feedback(response)
else if response.error
@render_error(response.error)
- else
+ else
@render_error("Error saving calibration score")
# called after we submit a submission score
@@ -330,8 +329,8 @@ class PeerGradingProblem
# show button if we have scores for all categories
@show_submit_button()
-
-
+
+
##########
#
# Rendering methods and helpers
@@ -344,7 +343,7 @@ class PeerGradingProblem
# load in all the data
@submission_container.html("
Training Essay
")
@render_submission_data(response)
- # TODO: indicate that we're in calibration mode
+ # TODO: indicate that we're in calibration mode
@calibration_panel.addClass('current-state')
@grading_panel.removeClass('current-state')
@@ -428,12 +427,12 @@ class PeerGradingProblem
if score == actual_score
calibration_wrapper.append("
Congratulations! Your score matches the actual score!
")
else
- calibration_wrapper.append("
Please try to understand the grading critera better to be more accurate next time.
")
+ calibration_wrapper.append("
Please try to understand the grading critera better to be more accurate next time.
")
# disable score selection and submission from the grading interface
$("input[name='score-selection']").attr('disabled', true)
@submit_button.hide()
-
+
render_interstitial_page: () =>
@content_panel.hide()
@interstitial_page.show()
@@ -449,7 +448,7 @@ class PeerGradingProblem
@submit_button.show()
setup_score_selection: (max_score) =>
-
+
# first, get rid of all the old inputs, if any.
@score_selection_container.html("""
Overall Score
@@ -460,7 +459,7 @@ class PeerGradingProblem
for score in [0..max_score]
id = 'score-' + score
label = """"""
-
+
input = """
""" # " fix broken parsing in emacs
@@ -470,9 +469,7 @@ class PeerGradingProblem
$("input[name='score-selection']").change @graded_callback
$("input[name='grade-selection']").change @graded_callback
-
-
-mock_backend = false
-ajax_url = $('.peer-grading').data('ajax_url')
-backend = new PeerGradingProblemBackend(ajax_url, mock_backend)
-$(document).ready(() -> new PeerGradingProblem(backend))
+#mock_backend = false
+#ajax_url = $('.peer-grading').data('ajax_url')
+#backend = new PeerGradingProblemBackend(ajax_url, mock_backend)
+#$(document).ready(() -> new PeerGradingProblem(backend))
diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py
index c5a08e0812..be09751e29 100644
--- a/common/lib/xmodule/xmodule/peer_grading_module.py
+++ b/common/lib/xmodule/xmodule/peer_grading_module.py
@@ -68,7 +68,6 @@ class PeerGradingModule(XModule):
system.set('location', location)
self.system = system
self.peer_gs = peer_grading_service()
- log.debug(self.system)
self.use_for_single_location = self.metadata.get('use_for_single_location', USE_FOR_SINGLE_LOCATION)
if isinstance(self.use_for_single_location, basestring):
@@ -108,7 +107,7 @@ class PeerGradingModule(XModule):
Needs to be implemented by child modules. Handles AJAX events.
@return:
"""
-
+ log.debug(get)
handlers = {
'get_next_submission': self.get_next_submission,
'show_calibration_essay': self.show_calibration_essay,
@@ -123,6 +122,8 @@ class PeerGradingModule(XModule):
d = handlers[dispatch](get)
+ log.debug(d)
+
return json.dumps(d, cls=ComplexEncoder)
def get_progress(self):
@@ -149,14 +150,12 @@ class PeerGradingModule(XModule):
'error': if success is False, will have an error message with more info.
"""
- _check_post(request)
required = set(['location'])
- success, message = _check_required(request, required)
+ success, message = self._check_required(get, required)
if not success:
return _err_response(message)
- grader_id = unique_id_for_user(request.user)
- p = request.POST
- location = p['location']
+ grader_id = self.system.anonymous_student_id
+ location = get['location']
try:
response = self.peer_gs.get_next_submission(location, grader_id)
@@ -183,20 +182,20 @@ class PeerGradingModule(XModule):
success: bool indicating whether the save was a success
error: if there was an error in the submission, this is the error message
"""
- _check_post(request)
+
required = set(['location', 'submission_id', 'submission_key', 'score', 'feedback', 'rubric_scores[]', 'submission_flagged'])
- success, message = _check_required(request, required)
+ success, message = self._check_required(get, required)
if not success:
return _err_response(message)
- grader_id = unique_id_for_user(request.user)
- p = request.POST
- location = p['location']
- submission_id = p['submission_id']
- score = p['score']
- feedback = p['feedback']
- submission_key = p['submission_key']
- rubric_scores = p.getlist('rubric_scores[]')
- submission_flagged = p['submission_flagged']
+ grader_id = self.system.anonymous_student_id
+
+ location = get['location']
+ submission_id = get['submission_id']
+ score = get['score']
+ feedback = get['feedback']
+ submission_key = get['submission_key']
+ rubric_scores = get['rubric_scores']
+ submission_flagged = get['submission_flagged']
try:
response = self.peer_gs.save_grade(location, grader_id, submission_id,
score, feedback, submission_key, rubric_scores, submission_flagged)
@@ -227,14 +226,14 @@ class PeerGradingModule(XModule):
total_calibrated_on_so_far - the number of calibration essays for this problem
that this grader has graded
"""
- _check_post(request)
+
required = set(['location'])
- success, message = _check_required(request, required)
+ success, message = self._check_required(get, required)
if not success:
return _err_response(message)
- grader_id = unique_id_for_user(request.user)
- p = request.POST
- location = p['location']
+ grader_id = self.system.anonymous_student_id
+
+ location = get['location']
try:
response = self.peer_gs.is_student_calibrated(location, grader_id)
@@ -268,16 +267,15 @@ class PeerGradingModule(XModule):
'error': if success is False, will have an error message with more info.
"""
- _check_post(request)
required = set(['location'])
- success, message = _check_required(request, required)
+ success, message = self._check_required(get, required)
if not success:
return _err_response(message)
- grader_id = unique_id_for_user(request.user)
- p = request.POST
- location = p['location']
+ grader_id = self.system.anonymous_student_id
+
+ location = get['location']
try:
response = self.peer_gs.show_calibration_essay(location, grader_id)
return HttpResponse(response, mimetype="application/json")
@@ -311,20 +309,19 @@ class PeerGradingModule(XModule):
actual_score: the score that the instructor gave to this calibration essay
"""
- _check_post(request)
required = set(['location', 'submission_id', 'submission_key', 'score', 'feedback', 'rubric_scores[]'])
- success, message = _check_required(request, required)
+ success, message = self._check_required(get, required)
if not success:
return _err_response(message)
- grader_id = unique_id_for_user(request.user)
- p = request.POST
- location = p['location']
- calibration_essay_id = p['submission_id']
- submission_key = p['submission_key']
- score = p['score']
- feedback = p['feedback']
- rubric_scores = p.getlist('rubric_scores[]')
+ grader_id = self.system.anonymous_student_id
+
+ location = get['location']
+ calibration_essay_id = get['submission_id']
+ submission_key = get['submission_key']
+ score = get['score']
+ feedback = get['feedback']
+ rubric_scores = get['rubric_scores']
try:
response = self.peer_gs.save_calibration_essay(location, grader_id, calibration_essay_id,
diff --git a/common/lib/xmodule/xmodule/peer_grading_service.py b/common/lib/xmodule/xmodule/peer_grading_service.py
index 172a981a96..a8e74dd3cc 100644
--- a/common/lib/xmodule/xmodule/peer_grading_service.py
+++ b/common/lib/xmodule/xmodule/peer_grading_service.py
@@ -48,6 +48,7 @@ class PeerGradingService():
'rubric_scores': rubric_scores,
'rubric_scores_complete': True,
'submission_flagged' : submission_flagged}
+ log.debug(data)
return self.post(self.save_grade_url, data)
def is_student_calibrated(self, problem_location, grader_id):
@@ -69,6 +70,7 @@ class PeerGradingService():
'feedback': feedback,
'rubric_scores[]': rubric_scores,
'rubric_scores_complete': True}
+ log.debug(data)
return self.post(self.save_calibration_essay_url, data)
def get_problem_list(self, course_id, grader_id):
diff --git a/lms/templates/peer_grading/peer_grading.html b/lms/templates/peer_grading/peer_grading.html
index 99ef288e5f..1dd74d74e4 100644
--- a/lms/templates/peer_grading/peer_grading.html
+++ b/lms/templates/peer_grading/peer_grading.html
@@ -1,5 +1,5 @@
-
From d1c55208c1fdfc636e9be8ae900540bd3347a163 Mon Sep 17 00:00:00 2001
From: Vik Paruchuri
Date: Thu, 31 Jan 2013 20:08:55 -0500
Subject: [PATCH 039/169] Clean up response code
---
.../xmodule/xmodule/peer_grading_module.py | 43 ++++++++++---------
.../xmodule/xmodule/peer_grading_service.py | 24 +++++++++--
2 files changed, 42 insertions(+), 25 deletions(-)
diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py
index be09751e29..cd60e2572c 100644
--- a/common/lib/xmodule/xmodule/peer_grading_module.py
+++ b/common/lib/xmodule/xmodule/peer_grading_module.py
@@ -12,7 +12,6 @@ import requests
import sys
from django.conf import settings
-from django.http import HttpResponse, Http404
from combined_open_ended_rubric import CombinedOpenEndedRubric
from lxml import etree
@@ -81,8 +80,7 @@ class PeerGradingModule(XModule):
"""
Return a HttpResponse with a json dump with success=False, and the given error message.
"""
- return HttpResponse(json.dumps({'success': False, 'error': msg}),
- mimetype="application/json")
+ return {'success': False, 'error': msg}
def _check_required(self, get, required):
actual = set(get.keys())
@@ -107,7 +105,7 @@ class PeerGradingModule(XModule):
Needs to be implemented by child modules. Handles AJAX events.
@return:
"""
- log.debug(get)
+
handlers = {
'get_next_submission': self.get_next_submission,
'show_calibration_essay': self.show_calibration_essay,
@@ -123,7 +121,7 @@ class PeerGradingModule(XModule):
d = handlers[dispatch](get)
log.debug(d)
-
+
return json.dumps(d, cls=ComplexEncoder)
def get_progress(self):
@@ -159,13 +157,12 @@ class PeerGradingModule(XModule):
try:
response = self.peer_gs.get_next_submission(location, grader_id)
- return HttpResponse(response,
- mimetype="application/json")
+ return response
except GradingServiceError:
log.exception("Error getting next submission. server url: {0} location: {1}, grader_id: {2}"
.format(self.peer_gs.url, location, grader_id))
- return json.dumps({'success': False,
- 'error': 'Could not connect to grading service'})
+ return {'success': False,
+ 'error': 'Could not connect to grading service'}
def save_grade(self, get):
"""
@@ -199,15 +196,17 @@ class PeerGradingModule(XModule):
try:
response = self.peer_gs.save_grade(location, grader_id, submission_id,
score, feedback, submission_key, rubric_scores, submission_flagged)
- return HttpResponse(response, mimetype="application/json")
+ return response
except GradingServiceError:
log.exception("""Error saving grade. server url: {0}, location: {1}, submission_id:{2},
submission_key: {3}, score: {4}"""
.format(self.peer_gs.url,
location, submission_id, submission_key, score)
)
- return json.dumps({'success': False,
- 'error': 'Could not connect to grading service'})
+ return {
+ 'success': False,
+ 'error': 'Could not connect to grading service'
+ }
def is_student_calibrated(self, get):
"""
@@ -237,12 +236,14 @@ class PeerGradingModule(XModule):
try:
response = self.peer_gs.is_student_calibrated(location, grader_id)
- return HttpResponse(response, mimetype="application/json")
+ return response
except GradingServiceError:
log.exception("Error from grading service. server url: {0}, grader_id: {0}, location: {1}"
.format(self.peer_gs.url, grader_id, location))
- return json.dumps({'success': False,
- 'error': 'Could not connect to grading service'})
+ return {
+ 'success': False,
+ 'error': 'Could not connect to grading service'
+ }
def show_calibration_essay(self, get):
"""
@@ -278,18 +279,18 @@ class PeerGradingModule(XModule):
location = get['location']
try:
response = self.peer_gs.show_calibration_essay(location, grader_id)
- return HttpResponse(response, mimetype="application/json")
+ return response
except GradingServiceError:
log.exception("Error from grading service. server url: {0}, location: {0}"
.format(self.peer_gs.url, location))
- return json.dumps({'success': False,
- 'error': 'Could not connect to grading service'})
+ return {'success': False,
+ 'error': 'Could not connect to grading service'}
# if we can't parse the rubric into HTML,
except etree.XMLSyntaxError:
log.exception("Cannot parse rubric string. Raw string: {0}"
.format(rubric))
- return json.dumps({'success': False,
- 'error': 'Error displaying submission'})
+ return {'success': False,
+ 'error': 'Error displaying submission'}
def save_calibration_essay(self, get):
@@ -326,7 +327,7 @@ class PeerGradingModule(XModule):
try:
response = self.peer_gs.save_calibration_essay(location, grader_id, calibration_essay_id,
submission_key, score, feedback, rubric_scores)
- return HttpResponse(response, mimetype="application/json")
+ return response
except GradingServiceError:
log.exception("Error saving calibration grade, location: {0}, submission_id: {1}, submission_key: {2}, grader_id: {3}".format(location, submission_id, submission_key, grader_id))
return _err_response('Could not connect to grading service')
diff --git a/common/lib/xmodule/xmodule/peer_grading_service.py b/common/lib/xmodule/xmodule/peer_grading_service.py
index a8e74dd3cc..3328a2c3cc 100644
--- a/common/lib/xmodule/xmodule/peer_grading_service.py
+++ b/common/lib/xmodule/xmodule/peer_grading_service.py
@@ -36,7 +36,7 @@ class PeerGradingService():
def get_next_submission(self, problem_location, grader_id):
response = self.get(self.get_next_submission_url,
{'location': problem_location, 'grader_id': grader_id})
- return json.dumps(self._render_rubric(response))
+ return self._render_rubric(response)
def save_grade(self, location, grader_id, submission_id, score, feedback, submission_key, rubric_scores, submission_flagged):
data = {'grader_id' : grader_id,
@@ -58,7 +58,7 @@ class PeerGradingService():
def show_calibration_essay(self, problem_location, grader_id):
params = {'problem_id' : problem_location, 'student_id': grader_id}
response = self.get(self.show_calibration_essay_url, params)
- return json.dumps(self._render_rubric(response))
+ return self._render_rubric(response)
def save_calibration_essay(self, problem_location, grader_id, calibration_essay_id, submission_key,
score, feedback, rubric_scores):
@@ -111,7 +111,13 @@ class PeerGradingService():
# reraise as promised GradingServiceError, but preserve stacktrace.
raise GradingServiceError, str(err), sys.exc_info()[2]
- return r.text
+ text = r.text
+ try:
+ text= json.loads(text)
+ except:
+ pass
+
+ return text
def get(self, url, params, allow_redirects=False):
"""
@@ -127,7 +133,13 @@ class PeerGradingService():
# reraise as promised GradingServiceError, but preserve stacktrace.
raise GradingServiceError, str(err), sys.exc_info()[2]
- return r.text
+ text = r.text
+ try:
+ text= json.loads(text)
+ except:
+ pass
+
+ return text
def _try_with_login(self, operation):
@@ -163,6 +175,10 @@ class PeerGradingService():
"""
try:
response_json = json.loads(response)
+ except:
+ response_json = response
+
+ try:
if 'rubric' in response_json:
rubric = response_json['rubric']
rubric_renderer = CombinedOpenEndedRubric(self.system, False)
From 5ac6439cc015b826c6c968cc123f40e503984d5d Mon Sep 17 00:00:00 2001
From: Vik Paruchuri
Date: Thu, 31 Jan 2013 20:22:35 -0500
Subject: [PATCH 040/169] Xmodule working...need to work on some issues (rubric
scores not passing properly), and also fix notifications
---
common/lib/xmodule/xmodule/peer_grading_module.py | 13 +++++++------
common/lib/xmodule/xmodule/peer_grading_service.py | 10 ++++------
2 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/common/lib/xmodule/xmodule/peer_grading_module.py b/common/lib/xmodule/xmodule/peer_grading_module.py
index cd60e2572c..c2df24dfff 100644
--- a/common/lib/xmodule/xmodule/peer_grading_module.py
+++ b/common/lib/xmodule/xmodule/peer_grading_module.py
@@ -66,7 +66,7 @@ class PeerGradingModule(XModule):
#We need to set the location here so the child modules can use it
system.set('location', location)
self.system = system
- self.peer_gs = peer_grading_service()
+ self.peer_gs = peer_grading_service(self.system)
self.use_for_single_location = self.metadata.get('use_for_single_location', USE_FOR_SINGLE_LOCATION)
if isinstance(self.use_for_single_location, basestring):
@@ -106,6 +106,7 @@ class PeerGradingModule(XModule):
@return:
"""
+ log.debug(get)
handlers = {
'get_next_submission': self.get_next_submission,
'show_calibration_essay': self.show_calibration_essay,
@@ -120,8 +121,6 @@ class PeerGradingModule(XModule):
d = handlers[dispatch](get)
- log.debug(d)
-
return json.dumps(d, cls=ComplexEncoder)
def get_progress(self):
@@ -191,8 +190,10 @@ class PeerGradingModule(XModule):
score = get['score']
feedback = get['feedback']
submission_key = get['submission_key']
- rubric_scores = get['rubric_scores']
+ rubric_scores = get['rubric_scores[]']
submission_flagged = get['submission_flagged']
+ log.debug(get)
+ log.debug(rubric_scores)
try:
response = self.peer_gs.save_grade(location, grader_id, submission_id,
score, feedback, submission_key, rubric_scores, submission_flagged)
@@ -322,7 +323,7 @@ class PeerGradingModule(XModule):
submission_key = get['submission_key']
score = get['score']
feedback = get['feedback']
- rubric_scores = get['rubric_scores']
+ rubric_scores = get['rubric_scores[]']
try:
response = self.peer_gs.save_calibration_essay(location, grader_id, calibration_essay_id,
@@ -343,7 +344,7 @@ class PeerGradingModule(XModule):
problem_list = []
try:
problem_list_json = self.peer_gs.get_problem_list(self.system.course_id, self.system.anonymous_student_id)
- problem_list_dict = json.loads(problem_list_json)
+ problem_list_dict = problem_list_json
success = problem_list_dict['success']
if 'error' in problem_list_dict:
error_text = problem_list_dict['error']
diff --git a/common/lib/xmodule/xmodule/peer_grading_service.py b/common/lib/xmodule/xmodule/peer_grading_service.py
index 3328a2c3cc..06fa7351cd 100644
--- a/common/lib/xmodule/xmodule/peer_grading_service.py
+++ b/common/lib/xmodule/xmodule/peer_grading_service.py
@@ -19,7 +19,7 @@ class PeerGradingService():
"""
Interface with the grading controller for peer grading
"""
- def __init__(self, config):
+ def __init__(self, config, system):
self.username = config['username']
self.password = config['password']
self.url = config['url']
@@ -32,6 +32,7 @@ class PeerGradingService():
self.save_calibration_essay_url = self.url + '/save_calibration_essay/'
self.get_problem_list_url = self.url + '/get_problem_list/'
self.get_notifications_url = self.url + '/get_notifications/'
+ self.system = system
def get_next_submission(self, problem_location, grader_id):
response = self.get(self.get_next_submission_url,
@@ -48,7 +49,6 @@ class PeerGradingService():
'rubric_scores': rubric_scores,
'rubric_scores_complete': True,
'submission_flagged' : submission_flagged}
- log.debug(data)
return self.post(self.save_grade_url, data)
def is_student_calibrated(self, problem_location, grader_id):
@@ -70,7 +70,6 @@ class PeerGradingService():
'feedback': feedback,
'rubric_scores[]': rubric_scores,
'rubric_scores_complete': True}
- log.debug(data)
return self.post(self.save_calibration_essay_url, data)
def get_problem_list(self, course_id, grader_id):
@@ -123,7 +122,6 @@ class PeerGradingService():
"""
Make a get request to the grading controller
"""
- log.debug(params)
op = lambda: self.session.get(url,
allow_redirects=allow_redirects,
params=params)
@@ -240,7 +238,7 @@ class MockPeerGradingService(object):
]})
_service = None
-def peer_grading_service():
+def peer_grading_service(system):
"""
Return a peer grading service instance--if settings.MOCK_PEER_GRADING is True,
returns a mock one, otherwise a real one.
@@ -255,6 +253,6 @@ def peer_grading_service():
if settings.MOCK_PEER_GRADING:
_service = MockPeerGradingService()
else:
- _service = PeerGradingService(settings.PEER_GRADING_INTERFACE)
+ _service = PeerGradingService(settings.PEER_GRADING_INTERFACE, system)
return _service
From 6575386d6992bea4e68332370d0e9de13180c861 Mon Sep 17 00:00:00 2001
From: Diana Huang
Date: Fri, 1 Feb 2013 08:43:55 -0500
Subject: [PATCH 041/169] Refactor rubric JS so that we don't have to keep
duplicating this code.
---
.../js/src/combinedopenended/display.coffee | 29 +++++++++++++++
.../peer_grading/peer_grading_problem.coffee | 15 ++------
.../src/staff_grading/staff_grading.coffee | 37 ++++---------------
3 files changed, 41 insertions(+), 40 deletions(-)
diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
index 594efe2f9b..c4560559c8 100644
--- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
+++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
@@ -1,3 +1,32 @@
+class @Rubric
+ constructor: () ->
+
+ # finds the scores for each rubric category
+ @get_score_list: () =>
+ # find the number of categories:
+ num_categories = $('table.rubric tr').length
+
+ score_lst = []
+ # get the score for each one
+ for i in [0..(num_categories-2)]
+ score = $("input[name='score-selection-#{i}']:checked").val()
+ score_lst.push(score)
+
+ return score_lst
+
+ @get_total_score: () ->
+ score_lst = @get_score_list()
+
+ @check_complete: () ->
+ # check to see whether or not any categories have not been scored
+ num_categories = $('table.rubric tr').length
+ # -2 because we want to skip the header
+ for i in [0..(num_categories-2)]
+ score = $("input[name='score-selection-#{i}']:checked").val()
+ if score == undefined
+ return false
+ return true
+
class @CombinedOpenEnded
constructor: (element) ->
@element=element
diff --git a/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee b/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee
index c4b87eb30e..525891bb03 100644
--- a/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee
+++ b/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee
@@ -239,7 +239,7 @@ class PeerGradingProblem
score_lst = []
# get the score for each one
- for i in [0..(num_categories-1)]
+ for i in [0..(num_categories-2)]
score = $("input[name='score-selection-#{i}']:checked").val()
score_lst.push(score)
@@ -315,17 +315,10 @@ class PeerGradingProblem
# called after a grade is selected on the interface
graded_callback: (event) =>
- @grade = $("input[name='grade-selection']:checked").val()
- if @grade == undefined
- return
# check to see whether or not any categories have not been scored
- num_categories = $('table.rubric tr').length
- for i in [0..(num_categories-1)]
- score = $("input[name='score-selection-#{i}']:checked").val()
- if score == undefined
- return
- # show button if we have scores for all categories
- @show_submit_button()
+ if Rubric.check_complete():
+ # show button if we have scores for all categories
+ @show_submit_button()
diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee
index 005a8e682e..2d3cafd3e7 100644
--- a/lms/static/coffee/src/staff_grading/staff_grading.coffee
+++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee
@@ -232,35 +232,14 @@ class @StaffGrading
graded_callback: () =>
- @grade = $("input[name='grade-selection']:checked").val()
- if @grade == undefined
- return
- # check to see whether or not any categories have not been scored
- num_categories = $('table.rubric tr').length
- for i in [0..(num_categories-1)]
- score = $("input[name='score-selection-#{i}']:checked").val()
- if score == undefined
- return
- # show button if we have scores for all categories
- @state = state_graded
- @submit_button.show()
+ # show button if we have scores for all categories
+ if Rubric.check_complete()
+ @state = state_graded
+ @submit_button.show()
set_button_text: (text) =>
@action_button.attr('value', text)
- # finds the scores for each rubric category
- get_score_list: () =>
- # find the number of categories:
- num_categories = $('table.rubric tr').length
-
- score_lst = []
- # get the score for each one
- for i in [0..(num_categories-1)]
- score = $("input[name='score-selection-#{i}']:checked").val()
- score_lst.push(score)
-
- return score_lst
-
ajax_callback: (response) =>
# always clear out errors and messages on transition.
@error_msg = ''
@@ -285,8 +264,8 @@ class @StaffGrading
skip_and_get_next: () =>
data =
- score: @grade
- rubric_scores: @get_score_list()
+ score: Rubric.get_total_score()
+ rubric_scores: Rubric.get_score_list()
feedback: @feedback_area.val()
submission_id: @submission_id
location: @location
@@ -299,8 +278,8 @@ class @StaffGrading
submit_and_get_next: () ->
data =
- score: @grade
- rubric_scores: @get_score_list()
+ score: Rubric.get_total_score()
+ rubric_scores: Rubric.get_score_list()
feedback: @feedback_area.val()
submission_id: @submission_id
location: @location
From f05bda764470b80873937cb8573cf3db27228137 Mon Sep 17 00:00:00 2001
From: Diana Huang
Date: Fri, 1 Feb 2013 08:44:08 -0500
Subject: [PATCH 042/169] Visual updates to rubric
---
lms/static/sass/course/_rubric.scss | 3 ++-
lms/templates/open_ended_rubric.html | 8 ++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/lms/static/sass/course/_rubric.scss b/lms/static/sass/course/_rubric.scss
index 9aa0ca2f2a..722a790e6d 100644
--- a/lms/static/sass/course/_rubric.scss
+++ b/lms/static/sass/course/_rubric.scss
@@ -35,7 +35,8 @@
right:0px;
margin:10px;
}
- .selected-grade {
+ .selected-grade,
+ .selected-grade .rubric-label {
background: #666;
color: white;
}
diff --git a/lms/templates/open_ended_rubric.html b/lms/templates/open_ended_rubric.html
index a2d8d6945c..eb3fc564b4 100644
--- a/lms/templates/open_ended_rubric.html
+++ b/lms/templates/open_ended_rubric.html
@@ -22,14 +22,14 @@
${category['description']}
% for j in range(len(category['options'])):
<% option = category['options'][j] %>
+ %if option['selected']:
+
+ %else:
+ % endif
% if view_only:
## if this is the selected rubric block, show it highlighted
- % if option['selected']:
-
- % else:
- % endif
${option['text']}
% else:
From 0ec3be18155d5136aeade3139686f04c07b6d8a4 Mon Sep 17 00:00:00 2001
From: Diana Huang
Date: Fri, 1 Feb 2013 10:17:16 -0500
Subject: [PATCH 043/169] Calculate the total score from the rubric.
---
.../xmodule/xmodule/js/src/combinedopenended/display.coffee | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
index c4560559c8..576fb7290d 100644
--- a/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
+++ b/common/lib/xmodule/xmodule/js/src/combinedopenended/display.coffee
@@ -16,6 +16,10 @@ class @Rubric
@get_total_score: () ->
score_lst = @get_score_list()
+ tot = 0
+ for score in score_lst
+ tot += parseInt(score)
+ return tot
@check_complete: () ->
# check to see whether or not any categories have not been scored
From cb44918f4958ebef6cd70bb8d1e760c534f046ea Mon Sep 17 00:00:00 2001
From: Diana Huang
Date: Fri, 1 Feb 2013 10:31:46 -0500
Subject: [PATCH 044/169] Remove duplicate Javascript and remove total grade
selection.
---
.../peer_grading/peer_grading_problem.coffee | 35 ++-----------------
.../src/staff_grading/staff_grading.coffee | 15 --------
2 files changed, 3 insertions(+), 47 deletions(-)
diff --git a/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee b/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee
index 525891bb03..f4b9bdbe78 100644
--- a/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee
+++ b/lms/static/coffee/src/peer_grading/peer_grading_problem.coffee
@@ -232,23 +232,11 @@ class PeerGradingProblem
fetch_submission_essay: () =>
@backend.post('get_next_submission', {location: @location}, @render_submission)
- # finds the scores for each rubric category
- get_score_list: () =>
- # find the number of categories:
- num_categories = $('table.rubric tr').length
-
- score_lst = []
- # get the score for each one
- for i in [0..(num_categories-2)]
- score = $("input[name='score-selection-#{i}']:checked").val()
- score_lst.push(score)
-
- return score_lst
construct_data: () ->
data =
- rubric_scores: @get_score_list()
- score: @grade
+ rubric_scores: Rubric.get_score_list()
+ score: Rubric.get_total_score()
location: @location
submission_id: @essay_id_input.val()
submission_key: @submission_key_input.val()
@@ -316,7 +304,7 @@ class PeerGradingProblem
# called after a grade is selected on the interface
graded_callback: (event) =>
# check to see whether or not any categories have not been scored
- if Rubric.check_complete():
+ if Rubric.check_complete()
# show button if we have scores for all categories
@show_submit_button()
@@ -439,25 +427,8 @@ class PeerGradingProblem
setup_score_selection: (max_score) =>
- # first, get rid of all the old inputs, if any.
- @score_selection_container.html("""
-
Overall Score
-
Choose an overall score for this submission.
- """)
-
- # Now create new labels and inputs for each possible score.
- for score in [0..max_score]
- id = 'score-' + score
- label = """"""
-
- input = """
-
- """ # " fix broken parsing in emacs
- @score_selection_container.append(input + label)
-
# And now hook up an event handler again
$("input[name='score-selection']").change @graded_callback
- $("input[name='grade-selection']").change @graded_callback
diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee
index 2d3cafd3e7..117388bab0 100644
--- a/lms/static/coffee/src/staff_grading/staff_grading.coffee
+++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee
@@ -212,21 +212,6 @@ class @StaffGrading
setup_score_selection: =>
- # first, get rid of all the old inputs, if any.
- @grade_selection_container.html("""
-
Overall Score
-
Choose an overall score for this submission.
- """)
- # Now create new labels and inputs for each possible score.
- for score in [0..@max_score]
- id = 'score-' + score
- label = """"""
- input = """
-
- """ # " fix broken parsing in emacs
- @grade_selection_container.append(input + label)
- $('.grade-selection').click => @graded_callback()
-
@score_selection_container.html(@rubric)
$('.score-selection').click => @graded_callback()
From 1fef6b161b767fddc88aac4194cfac7792b82cd0 Mon Sep 17 00:00:00 2001
From: Diana Huang
Date: Fri, 1 Feb 2013 11:21:56 -0500
Subject: [PATCH 045/169] Add in some better encouragement to write feedback
---
lms/templates/instructor/staff_grading.html | 1 +
lms/templates/peer_grading/peer_grading_problem.html | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/lms/templates/instructor/staff_grading.html b/lms/templates/instructor/staff_grading.html
index 56aed5a54a..dcfece34b8 100644
--- a/lms/templates/instructor/staff_grading.html
+++ b/lms/templates/instructor/staff_grading.html
@@ -75,6 +75,7 @@