Commit f3e8d01e by Diana Huang

Pull out old rubric and score selection logic

and set up the new rubric
parent 5a211f56
<form class="rubric-template" id="inputtype_${id}"> <form class="rubric-template" id="inputtype_${id}">
<h3>Rubric</h3>
% if view_only:
<p>Select the criteria you feel best represents this submission in each category.</p>
% else
<p>The highlighted selection best matches how the student feels you performed in each category.</p>
% endif
<table class="rubric"> <table class="rubric">
% for i in range(len(categories)): % for i in range(len(categories)):
<% category = categories[i] %> <% category = categories[i] %>
...@@ -7,7 +13,6 @@ ...@@ -7,7 +13,6 @@
% for j in range(len(category['options'])): % for j in range(len(category['options'])):
<% option = category['options'][j] %> <% option = category['options'][j] %>
<td> <td>
<!--TODO: figure out the state variables/selected info -->
% if view_only: % if view_only:
<div class="view-only"> <div class="view-only">
${option['text']} ${option['text']}
......
...@@ -17,6 +17,10 @@ from courseware.access import has_access ...@@ -17,6 +17,10 @@ from courseware.access import has_access
from util.json_request import expect_json from util.json_request import expect_json
from xmodule.course_module import CourseDescriptor from xmodule.course_module import CourseDescriptor
from student.models import unique_id_for_user from student.models import unique_id_for_user
from xmodule.x_module import ModuleSystem
from mitxmako.shortcuts import render_to_string
from capa import inputtypes
from lxml import etree
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
...@@ -136,6 +140,8 @@ class StaffGradingService(GradingService): ...@@ -136,6 +140,8 @@ class StaffGradingService(GradingService):
# importing this file doesn't create objects that may not have the right config # importing this file doesn't create objects that may not have the right config
_service = None _service = None
module_system = ModuleSystem("", None, None, render_to_string, None)
def staff_grading_service(): def staff_grading_service():
""" """
Return a staff grading service instance--if settings.MOCK_STAFF_GRADING is True, Return a staff grading service instance--if settings.MOCK_STAFF_GRADING is True,
...@@ -252,12 +258,24 @@ def _get_next(course_id, grader_id, location): ...@@ -252,12 +258,24 @@ def _get_next(course_id, grader_id, location):
Implementation of get_next (also called from save_grade) -- returns a json string Implementation of get_next (also called from save_grade) -- returns a json string
""" """
try: try:
return staff_grading_service().get_next(course_id, location, grader_id) response = staff_grading_service().get_next(course_id, location, grader_id)
response_json = json.loads(response)
rubric = response_json['rubric']
rubric_input = inputtypes.RubricInput(module_system, etree.XML(rubric), {'id': location})
rubric_html = etree.tostring(rubric_input.get_html())
response_json['rubric'] = rubric_html
return json.dumps(response_json)
except GradingServiceError: except GradingServiceError:
log.exception("Error from grading service. server url: {0}" log.exception("Error from grading service. server url: {0}"
.format(staff_grading_service().url)) .format(staff_grading_service().url))
return json.dumps({'success': False, return json.dumps({'success': False,
'error': 'Could not connect to grading service'}) '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'})
@expect_json @expect_json
......
...@@ -42,14 +42,49 @@ class StaffGradingBackend ...@@ -42,14 +42,49 @@ class StaffGradingBackend
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.
''' '''
rubric: ''' rubric: '''
<ul> <table class="rubric"><tbody><tr><th>Purpose</th>
<li>Metals tend to be good electronic conductors, meaning that they have a large number of electrons which are able to access empty (mobile) energy states within the material.</li>
<li>Sodium has a half-filled s-band, so there are a number of empty states immediately above the highest occupied energy levels within the band.</li> <td>
<li>Magnesium has a full s-band, but the the s-band and p-band overlap in magnesium. Thus are still a large number of available energy states immediately above the s-band highest occupied energy level.</li> <!--TODO: figure out the state variables/selected info -->
</ul> <input type="radio" class="score-selection" name="score-selection-0" id="score-0-0" value="0"><label for="score-0-0">No product</label>
</td>
<p>Please score your response according to how many of the above components you identified:</p>
''' <td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-1" value="1"><label for="score-0-1">Unclear purpose or main idea</label>
</td>
<td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-2" value="2"><label for="score-0-2">Communicates an identifiable purpose and/or main idea for an audience</label>
</td>
<td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-0" id="score-0-3" value="3"><label for="score-0-3">Achieves a clear and distinct purpose for a targeted audience and communicates main ideas with effectively used techniques to introduce and represent ideas and insights</label>
</td>
</tr><tr><th>Organization</th>
<td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-0" value="0"><label for="score-1-0">No product</label>
</td>
<td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-1" value="1"><label for="score-1-1">Organization is unclear; introduction, body, and/or conclusion are underdeveloped, missing or confusing.</label>
</td>
<td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-2" value="2"><label for="score-1-2">Organization is occasionally unclear; introduction, body or conclusion may be underdeveloped.</label>
</td>
<td>
<!--TODO: figure out the state variables/selected info -->
<input type="radio" class="score-selection" name="score-selection-1" id="score-1-3" value="3"><label for="score-1-3">Organization is clear and easy to follow; introduction, body and conclusion are defined and aligned with purpose.</label>
</td>
</tr></tbody></table>'''
submission_id: @mock_cnt submission_id: @mock_cnt
max_score: 2 + @mock_cnt % 3 max_score: 2 + @mock_cnt % 3
ml_error_info : 'ML accuracy info: ' + @mock_cnt ml_error_info : 'ML accuracy info: ' + @mock_cnt
...@@ -166,8 +201,8 @@ class StaffGrading ...@@ -166,8 +201,8 @@ class StaffGrading
@min_for_ml = 0 @min_for_ml = 0
@num_graded = 0 @num_graded = 0
@num_pending = 0 @num_pending = 0
@score_lst = []
@score = null
@problems = null @problems = null
# action handlers # action handlers
...@@ -181,31 +216,36 @@ class StaffGrading ...@@ -181,31 +216,36 @@ class StaffGrading
setup_score_selection: => setup_score_selection: =>
# first, get rid of all the old inputs, if any. @score_selection_container.html(@rubric)
@score_selection_container.html('Choose score: ') $('.score-selection').click => @graded_callback()
# Now create new labels and inputs for each possible score. graded_callback: () =>
for score in [0..@max_score] # check to see whether or not any categories have not been scored
id = 'score-' + score num_categories = $('table.rubric tr').length
label = """<label for="#{id}">#{score}</label>""" 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
@submit_button.show()
input = """
<input type="radio" name="score-selection" id="#{id}" value="#{score}"/>
""" # " 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
set_button_text: (text) => set_button_text: (text) =>
@action_button.attr('value', text) @action_button.attr('value', text)
graded_callback: (event) => # finds the scores for each rubric category
@score = event.target.value get_score_list: () =>
@state = state_graded # find the number of categories:
@message = '' num_categories = $('table.rubric tr').length
@render_view()
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.append(score)
return score_lst
ajax_callback: (response) => ajax_callback: (response) =>
# always clear out errors and messages on transition. # always clear out errors and messages on transition.
...@@ -231,7 +271,7 @@ class StaffGrading ...@@ -231,7 +271,7 @@ class StaffGrading
skip_and_get_next: () => skip_and_get_next: () =>
data = data =
score: @score rubric_scores: @get_score_list()
feedback: @feedback_area.val() feedback: @feedback_area.val()
submission_id: @submission_id submission_id: @submission_id
location: @location location: @location
...@@ -244,7 +284,7 @@ class StaffGrading ...@@ -244,7 +284,7 @@ class StaffGrading
submit_and_get_next: () -> submit_and_get_next: () ->
data = data =
score: @score rubric_scores: @get_score_list()
feedback: @feedback_area.val() feedback: @feedback_area.val()
submission_id: @submission_id submission_id: @submission_id
location: @location location: @location
...@@ -261,8 +301,6 @@ class StaffGrading ...@@ -261,8 +301,6 @@ class StaffGrading
@rubric = response.rubric @rubric = response.rubric
@submission_id = response.submission_id @submission_id = response.submission_id
@feedback_area.val('') @feedback_area.val('')
@max_score = response.max_score
@score = null
@ml_error_info=response.ml_error_info @ml_error_info=response.ml_error_info
@prompt_name = response.problem_name @prompt_name = response.problem_name
@num_graded = response.num_graded @num_graded = response.num_graded
...@@ -282,8 +320,6 @@ class StaffGrading ...@@ -282,8 +320,6 @@ class StaffGrading
@ml_error_info = null @ml_error_info = null
@submission_id = null @submission_id = null
@message = message @message = message
@score = null
@max_score = 0
@state = state_no_data @state = state_no_data
...@@ -361,8 +397,6 @@ class StaffGrading ...@@ -361,8 +397,6 @@ class StaffGrading
@prompt_container.html(@prompt) @prompt_container.html(@prompt)
@prompt_name_container.html("#{@prompt_name}") @prompt_name_container.html("#{@prompt_name}")
@submission_container.html(@make_paragraphs(@submission)) @submission_container.html(@make_paragraphs(@submission))
@rubric_container.html(@rubric)
# no submit button until user picks grade. # no submit button until user picks grade.
show_submit_button = false show_submit_button = false
show_action_button = false show_action_button = false
...@@ -397,7 +431,7 @@ class StaffGrading ...@@ -397,7 +431,7 @@ class StaffGrading
# for now, just create an instance and load it... # for now, just create an instance and load it...
mock_backend = false mock_backend = true
ajax_url = $('.staff-grading').data('ajax_url') ajax_url = $('.staff-grading').data('ajax_url')
backend = new StaffGradingBackend(ajax_url, mock_backend) backend = new StaffGradingBackend(ajax_url, mock_backend)
......
...@@ -159,5 +159,50 @@ div.peer-grading{ ...@@ -159,5 +159,50 @@ div.peer-grading{
} }
} }
padding: 40px; padding: 40px;
.rubric {
tr {
margin:10px 0px;
height: 100%;
}
td {
padding: 20px 0px;
margin: 10px 0px;
height: 100%;
}
th {
padding: 5px;
margin: 5px;
}
label,
.view-only {
margin:3px;
position: relative;
padding: 15px;
width: 150px;
height:100%;
display: inline-block;
min-height: 50px;
min-width: 50px;
background-color: #CCC;
font-size: .9em;
}
.grade {
position: absolute;
bottom:0px;
right:0px;
margin:10px;
}
.selected-grade {
background: #666;
color: white;
}
input[type=radio]:checked + label {
background: #666;
color: white; }
input[class='score-selection'] {
display: none;
}
}
} }
...@@ -54,11 +54,6 @@ ...@@ -54,11 +54,6 @@
<div class="prompt-container"> <div class="prompt-container">
</div> </div>
</div> </div>
<div class="rubric-wrapper">
<h3>Grading Rubric</h3>
<div class="rubric-container">
</div>
</div>
</section> </section>
......
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