Commit 69f75296 by Stephen Sanchez

Merge pull request #63 from edx/sanchez/TIM-191-Grade-UI

Sanchez/tim 191 grade ui
parents 16c6fcf7 6ee9936a
<!-- CASE: is incomplete and problem closed -->
<div id="openassessment__grade" class="openassessment__grade is--incomplete has--grade">
<h2 class="openassessment__grade__title">Your Grade:</h2>
<div class="openassessment__grade__content">
<span class="grade__value">Incomplete</span>
<p>You did not complete the <span class="step">Peer Assessment</span>, and <span class="step">Self Assessment</span> portions of this problem.</p>
</div>
</div>
\ No newline at end of file
<!-- CASE: is complete -->
<div id="openassessment__grade" class="openassessment__grade is--complete has--grade">
<h2 class="openassessment__grade__title">Your Grade:</h2>
<div class="openassessment__grade__content">
<span class="grade__value">{{ score.points_earned }}</span> out of <span class="grade__potential">{{ score.points_possible }}</span>
</div>
<div class="grade__actions">
<ul class="list list--actions">
<li class="list--actions__item">
<a class="action action--view">View in Courseware</a>
</li>
</ul>
</div>
</div>
\ No newline at end of file
<!-- CASE: is in-progress and incomplete (peer responses to assess) -->
<div id="openassessment__grade" class="openassessment__grade is--incomplete awaiting--peer-responses">
<h2 class="openassessment__grade__title">Your Grade:</h2>
<div class="openassessment__grade__content">
<span class="grade__value">Incomplete</span>
<p>You have not completed the <span class="step">Peer Assessment</span>, and <span class="step">Self Assessment</span> portions of this problem.</p>
</div>
</div>
\ No newline at end of file
<!-- CASE: is in-progress and incomplete (peer evaluations of user's response) -->
<div id="openassessment__grade" class="openassessment__grade is--incomplete awaiting--peer-evaluations">
<h2 class="openassessment__grade__title">Your Grade:</h2>
<div class="openassessment__grade__content">
<span class="grade__value">Waiting for Peers to Assess Your Response</span>
<p>Your response is still being evaluated by your peers. Once complete, you will receive a final grade and detailed feedback from their evaluations.</p>
</div>
</div>
\ No newline at end of file
...@@ -67,9 +67,6 @@ ...@@ -67,9 +67,6 @@
{% endfor %} {% endfor %}
</ol> </ol>
<!-- STATUS: problem grade -->
{% include "openassessmentblock/oa_grade.html" %}
</div> </div>
</div> </div>
</div> </div>
<!-- TEMPLATE: grade status -->
<!-- NOTES:
* class of is--incomplete is added when the problem is in an incomplete state
* class of is--complete is added when problem is successfully completed by user
* class of has--grade is added when a grade (failing or passing) is calculated for user
* classes of needs--* are added when user action is needed
* classes of awaiting--* are added when a user's flow is dependent upon system readiness
-->
<!-- CASE: default/unstarted -->
<div id="openassessment__grade" class="openassessment__grade {{ grade_state.style_class }}">
<h2 class="openassessment__grade__title">{{ grade_state.title }}</h2>
<div class="openassessment__grade__content">
<span class="grade__value">{{ grade_state.value }}</span>
<p class="grade__description">{{ grade_state.message }}</p>
</div>
</div>
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<!-- CASE: default/not started --> <!-- CASE: default/not started -->
{% block list_item %} {% block list_item %}
<li id="openassessment__peer-assessment" class="openassessment__steps__step step--peer-assessment ui-toggle-visibility"> <li id="openassessment__peer-assessment" class="openassessment__steps__step step--peer-assessment ui-toggle-visibility is--expanded">
{% endblock %} {% endblock %}
<span class="system__element" id="peer_submission_uuid"> <span class="system__element" id="peer_submission_uuid">
{{ peer_submission.uuid }} {{ peer_submission.uuid }}
......
{% extends "openassessmentblock/response/oa_response.html" %} {% extends "openassessmentblock/response/oa_response.html" %}
{% block list_item %} {% block list_item %}
<li id="openassessment__response" class="openassessment__steps__step step--response ui-toggle-visibility"> <li id="openassessment__response" class="openassessment__steps__step step--response ui-toggle-visibility">
{% endblock %} {% endblock %}
{% block title %} {% block title %}
......
{% extends "openassessmentblock/response/oa_response.html" %} {% extends "openassessmentblock/response/oa_response.html" %}
{% block list_item %} {% block list_item %}
<li id="openassessment__response" class="openassessment__steps__step step--response is--graded ui-toggle-visibility"> <li id="openassessment__response" class="openassessment__steps__step step--response is--graded ui-toggle-visibility">
{% endblock %} {% endblock %}
{% block title %} {% block title %}
...@@ -15,28 +15,28 @@ ...@@ -15,28 +15,28 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<div class="step__content"> <div class="step__content">
<!-- user's response --> <!-- user's response -->
<article class="submission__answer__display"> <article class="submission__answer__display">
<h3 class="submission__answer__display__title">Your Submitted Response</h3> <h3 class="submission__answer__display__title">Your Submitted Response</h3>
<div class="submission__answer__display__content"> <div class="submission__answer__display__content">
{{ student_submission.answer }} {{ student_submission.answer }}
</div> </div>
</article> </article>
<!-- peer evaluations --> <!-- peer evaluations -->
<article class="submission__peer-evaluations"> <article class="submission__peer-evaluations">
<h3 class="submission__peer-evaluations__title">Peer Evaluations Of Your Response</h3> <h3 class="submission__peer-evaluations__title">Peer Evaluations Of Your Response</h3>
<ol class="list submission__peer-evaluations__questions"> <ol class="list submission__peer-evaluations__questions">
{% for criterion in rubric_criteria %} {% for criterion in rubric_criteria %}
{% with criterion_num=forloop.counter %} {% with criterion_num=forloop.counter %}
<!-- individual question from rubric --> <!-- individual question from rubric -->
<li class="question question--{{ criterion_num }} ui-toggle-visibility"> <li class="question question--{{ criterion_num }} ui-toggle-visibility">
<h4 class="question__title ui-toggle-visibility__control"> <h4 class="question__title ui-toggle-visibility__control">
<span class="question__title__copy">{{ criterion.name }}</span> <span class="question__title__copy">{{ criterion.name }}</span>
<span class="question__score"> <span class="question__score">
<span class="label sr">Overall Question Score</span> <span class="label sr">Overall Question Score</span>
...@@ -47,16 +47,16 @@ ...@@ -47,16 +47,16 @@
<span class="unit">Points</span> <span class="unit">Points</span>
</span> </span>
</span> </span>
</h4> </h4>
<ul class="question__answers ui-toggle-visibility__content"> <ul class="question__answers ui-toggle-visibility__content">
{% for assessment in peer_assessments %} {% for assessment in peer_assessments %}
{% with peer_num=forloop.counter %} {% with peer_num=forloop.counter %}
{% for part in assessment.parts %} {% for part in assessment.parts %}
{% if part.option.criterion.name == criterion.name %} {% if part.option.criterion.name == criterion.name %}
<li class="answer peer-assessment--{{ peer_num}}" <li class="answer peer-assessment--{{ peer_num}}"
id="question--{{ criterion_num }}__answer-{{ peer_num }}"> id="question--{{ criterion_num }}__answer-{{ peer_num }}">
<h5 class="answer__title"> <h5 class="answer__title">
<span class="answer__source"> <span class="answer__source">
<span class="label sr">Assessor: </span> <span class="label sr">Assessor: </span>
<span class="value">Peer {{ peer_num }}</span> <span class="value">Peer {{ peer_num }}</span>
...@@ -65,39 +65,39 @@ ...@@ -65,39 +65,39 @@
<span class="label sr">Peer's Assessment: </span> <span class="label sr">Peer's Assessment: </span>
<span class="value">{{ part.option.name }}</span> <span class="value">{{ part.option.name }}</span>
</span> </span>
</h5> </h5>
<span class="answer__content"> <span class="answer__content">
{{ part.option.explanation }} {{ part.option.explanation }}
</span> </span>
</li> </li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% endwith %} {% endwith %}
{% endfor %}
</ul>
</li>
{% endwith %}
{% endfor %} {% endfor %}
</ul> </ol>
</li> </article>
{% endwith %}
{% endfor %}
</ol>
</article>
<!-- peer assessment feedback --> <!-- peer assessment feedback -->
<form id="submission__feeedback" class="submission__feeedback ui-toggle-visibility" method="post"> <form id="submission__feeedback" class="submission__feeedback ui-toggle-visibility" method="post">
<h3 class="submission__feeedback__title ui-toggle-visibility__control">Give Feedback On Peer Evaluations</h3> <h3 class="submission__feeedback__title ui-toggle-visibility__control">Give Feedback On Peer Evaluations</h3>
<ol class="list list--fields submission__feeedback__content ui-toggle-visibility__content"> <ol class="list list--fields submission__feeedback__content ui-toggle-visibility__content">
<li class="field field--textarea feedback__remarks" id="feedback__remarks"> <li class="field field--textarea feedback__remarks" id="feedback__remarks">
<label for="feedback__remarks__value">Please provide any thoughts or comments on the feedback you received from your peers here.</label> <label for="feedback__remarks__value">Please provide any thoughts or comments on the feedback you received from your peers here.</label>
<textarea id="feedback__remarks__value" placeholder="I feel the feedback I received was..."></textarea> <textarea id="feedback__remarks__value" placeholder="I feel the feedback I received was..."></textarea>
</li> </li>
</ol> </ol>
<ul class="list list--actions submission__feeedback__actions"> <ul class="list list--actions submission__feeedback__actions">
<li class="list--actions__item"> <li class="list--actions__item">
<button type="submit" id="feedback__submit" class="action action--submit feedback__submit">Submit Feedback On Peer Evaluations</button> <button type="submit" id="feedback__submit" class="action action--submit feedback__submit">Submit Feedback On Peer Evaluations</button>
</li> </li>
</ul> </ul>
</form> </form>
</div> </div>
{% endblock %} {% endblock %}
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
<!-- CASE: default/not started --> <!-- CASE: default/not started -->
{% block list_item %} {% block list_item %}
<li id="openassessment__self-assessment" class="openassessment__steps__step step--self-assessment"> <li id="openassessment__self-assessment" class="openassessment__steps__step step--self-assessment is--expanded">
{% endblock %} {% endblock %}
<header class="step__header ui-toggle-visibility__control"> <header class="step__header ui-toggle-visibility__control">
<h2 class="step__title"> <h2 class="step__title">
......
from xblock.core import XBlock
from submissions.api import get_score
class GradeMixin(object):
"""Grade Mixin introduces all handlers for displaying grades
Abstracts all functionality and handlers associated with Grades.
GradeMixin is a Mixin for the OpenAssessmentBlock. Functions in the
GradeMixin call into the OpenAssessmentBlock functions and will not work
outside of OpenAssessmentBlock.
"""
@XBlock.handler
def render_grade(self, data, suffix=''):
problem_open, date = self.is_open()
workflowstate = "complete" # TODO hook in workflow.
context = {}
if workflowstate == "complete":
path = 'openassessmentblock/grade/oa_grade_complete.html'
student_item = self.get_student_item_dict()
scores = get_score(student_item)
if scores:
context = {"score": scores[0]}
else:
path = 'openassessmentblock/grade/oa_grade_waiting.html'
elif not problem_open and date == "due":
path = 'openassessmentblock/grade/oa_grade_closed.html'
else:
path = 'openassessmentblock/grade/oa_grade_incomplete.html'
# TODO: How do we determine which modules are incomplete?
return self.render_assessment(path, context)
...@@ -12,6 +12,7 @@ from webob import Response ...@@ -12,6 +12,7 @@ from webob import Response
from xblock.core import XBlock from xblock.core import XBlock
from xblock.fields import List, Scope, String from xblock.fields import List, Scope, String
from xblock.fragment import Fragment from xblock.fragment import Fragment
from openassessment.xblock.grade_mixin import GradeMixin
from openassessment.xblock.peer_assessment_mixin import PeerAssessmentMixin from openassessment.xblock.peer_assessment_mixin import PeerAssessmentMixin
from openassessment.xblock.self_assessment_mixin import SelfAssessmentMixin from openassessment.xblock.self_assessment_mixin import SelfAssessmentMixin
...@@ -139,7 +140,7 @@ def load(path): ...@@ -139,7 +140,7 @@ def load(path):
return data.decode("utf8") return data.decode("utf8")
class OpenAssessmentBlock(XBlock, SubmissionMixin, PeerAssessmentMixin, SelfAssessmentMixin, StudioMixin): class OpenAssessmentBlock(XBlock, SubmissionMixin, PeerAssessmentMixin, SelfAssessmentMixin, StudioMixin, GradeMixin):
"""Displays a question and gives an area where students can compose a response.""" """Displays a question and gives an area where students can compose a response."""
start_datetime = String( start_datetime = String(
......
...@@ -5,6 +5,13 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -5,6 +5,13 @@ function OpenAssessmentBlock(runtime, element) {
var renderSubmissionUrl = runtime.handlerUrl(element, 'render_submission'); var renderSubmissionUrl = runtime.handlerUrl(element, 'render_submission');
var renderPeerUrl = runtime.handlerUrl(element, 'render_peer_assessment'); var renderPeerUrl = runtime.handlerUrl(element, 'render_peer_assessment');
var renderSelfUrl = runtime.handlerUrl(element, 'render_self_assessment'); var renderSelfUrl = runtime.handlerUrl(element, 'render_self_assessment');
var renderGradeUrl = runtime.handlerUrl(element, 'render_grade');
var submissionListItem = '#openassessment__response';
var peerListItem = '#openassessment__peer-assessment';
var selfListItem = '#openassessment__self-assessment';
var gradeListItem = '#openassessment__grade';
/* Sample Debug Console: http://localhost:8000/submissions/Joe_Bloggs/TestCourse/u_3 */ /* Sample Debug Console: http://localhost:8000/submissions/Joe_Bloggs/TestCourse/u_3 */
/* /*
...@@ -23,7 +30,7 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -23,7 +30,7 @@ function OpenAssessmentBlock(runtime, element) {
* Submission Functions * Submission Functions
*/ */
function render_submissions(data) { function render_submissions(data) {
$('#openassessment__response', element).replaceWith(data); $(submissionListItem, element).replaceWith(data);
$('#step--response__submit', element).click(function(eventObject) { $('#step--response__submit', element).click(function(eventObject) {
$.ajax({ $.ajax({
type: "POST", type: "POST",
...@@ -38,12 +45,13 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -38,12 +45,13 @@ function OpenAssessmentBlock(runtime, element) {
render_peer_assessment(data); render_peer_assessment(data);
} }
}); });
collapse($(submissionListItem, element));
$.ajax({ $.ajax({
type: "POST", type: "POST",
url: renderSubmissionUrl, url: renderSubmissionUrl,
success: function(data) { success: function(data) {
render_submissions(data); render_submissions(data);
collapse($('#openassessment__response', element)); collapse($(submissionListItem, element));
} }
}); });
} }
...@@ -55,7 +63,7 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -55,7 +63,7 @@ function OpenAssessmentBlock(runtime, element) {
* Peer Assessment Functions * Peer Assessment Functions
*/ */
function render_peer_assessment(data) { function render_peer_assessment(data) {
$('#openassessment__peer-assessment', element).replaceWith(data); $(peerListItem, element).replaceWith(data);
function prepare_assessment_post(element) { function prepare_assessment_post(element) {
var selector = $("input[type=radio]:checked", element); var selector = $("input[type=radio]:checked", element);
...@@ -85,7 +93,7 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -85,7 +93,7 @@ function OpenAssessmentBlock(runtime, element) {
url: renderSelfUrl, url: renderSelfUrl,
dataType: "html", dataType: "html",
success: function(data) { success: function(data) {
$('#openassessment__self-assessment', element).replaceWith(data); $(selfListItem, element).replaceWith(data);
} }
}); });
$.ajax({ $.ajax({
...@@ -116,8 +124,8 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -116,8 +124,8 @@ function OpenAssessmentBlock(runtime, element) {
type: "POST", type: "POST",
url: renderPeerUrl, url: renderPeerUrl,
success: function(data) { success: function(data) {
$('#openassessment__peer-assessment', element).replaceWith(data); $(peerListItem, element).replaceWith(data);
collapse($('#openassessment__peer-assessment', element)); collapse($(peerListItem, element));
} }
}); });
...@@ -125,8 +133,17 @@ function OpenAssessmentBlock(runtime, element) { ...@@ -125,8 +133,17 @@ function OpenAssessmentBlock(runtime, element) {
type: "POST", type: "POST",
url: renderSelfUrl, url: renderSelfUrl,
success: function(data) { success: function(data) {
$('#openassessment__self-assessment', element).replaceWith(data); $(selfListItem, element).replaceWith(data);
collapse($('#openassessment__self-assessment', element)); collapse($(selfListItem, element));
}
});
$.ajax({
type: "POST",
url: renderGradeUrl,
success: function(data) {
$(gradeListItem, element).replaceWith(data);
collapse($(gradeListItem, element));
} }
}); });
}); });
......
...@@ -156,6 +156,11 @@ class TestOpenAssessment(TestCase): ...@@ -156,6 +156,11 @@ class TestOpenAssessment(TestCase):
self.assertIsNotNone(self_response) self.assertIsNotNone(self_response)
self.assertTrue(self_response.body.find("openassessment__peer-assessment")) self.assertTrue(self_response.body.find("openassessment__peer-assessment"))
# Validate Grading.
grade_response = self.assessment.render_grade({})
self.assertIsNotNone(grade_response)
self.assertTrue(grade_response.body.find("openassessment__grade"))
def test_start_end_date_checks(self): def test_start_end_date_checks(self):
""" """
Check if the start and end date checks work appropriately. Check if the start and end date checks work appropriately.
......
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