Commit d0e2b85e by Victor Shnayder

Refactor testing code, hook up frontend.

- now getting requests from js to server and back, with mocked service.
parent ff119265
...@@ -222,24 +222,28 @@ class PageLoader(ActivateLoginTestCase): ...@@ -222,24 +222,28 @@ class PageLoader(ActivateLoginTestCase):
def check_for_get_code(self, code, url): def check_for_get_code(self, code, url):
""" """
Check that we got the expected code when accessing url via GET. Check that we got the expected code when accessing url via GET.
Returns the response.
""" """
resp = self.client.get(url) resp = self.client.get(url)
self.assertEqual(resp.status_code, code, self.assertEqual(resp.status_code, code,
"got code {0} for url '{1}'. Expected code {2}" "got code {0} for url '{1}'. Expected code {2}"
.format(resp.status_code, url, code)) .format(resp.status_code, url, code))
return resp
def check_for_post_code(self, code, url, data={}): def check_for_post_code(self, code, url, data={}):
""" """
Check that we got the expected code when accessing url via POST. Check that we got the expected code when accessing url via POST.
Returns the response.
""" """
resp = self.client.post(url, data) resp = self.client.post(url, data)
self.assertEqual(resp.status_code, code, self.assertEqual(resp.status_code, code,
"got code {0} for url '{1}'. Expected code {2}" "got code {0} for url '{1}'. Expected code {2}"
.format(resp.status_code, url, code)) .format(resp.status_code, url, code))
return resp
def check_pages_load(self, course_name, data_dir, modstore): def check_pages_load(self, course_name, data_dir, modstore):
"""Make all locations in course load""" """Make all locations in course load"""
print "Checking course {0} in {1}".format(course_name, data_dir) print "Checking course {0} in {1}".format(course_name, data_dir)
...@@ -661,46 +665,46 @@ class TestCourseGrader(PageLoader): ...@@ -661,46 +665,46 @@ class TestCourseGrader(PageLoader):
return [c for c in courses if c.id==course_id][0] return [c for c in courses if c.id==course_id][0]
self.graded_course = find_course("edX/graded/2012_Fall") self.graded_course = find_course("edX/graded/2012_Fall")
# create a test student # create a test student
self.student = 'view@test.com' self.student = 'view@test.com'
self.password = 'foo' self.password = 'foo'
self.create_account('u1', self.student, self.password) self.create_account('u1', self.student, self.password)
self.activate_user(self.student) self.activate_user(self.student)
self.enroll(self.graded_course) self.enroll(self.graded_course)
self.student_user = user(self.student) self.student_user = user(self.student)
self.factory = RequestFactory() self.factory = RequestFactory()
def get_grade_summary(self): def get_grade_summary(self):
student_module_cache = StudentModuleCache.cache_for_descriptor_descendents( student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(
self.graded_course.id, self.student_user, self.graded_course) self.graded_course.id, self.student_user, self.graded_course)
fake_request = self.factory.get(reverse('progress', fake_request = self.factory.get(reverse('progress',
kwargs={'course_id': self.graded_course.id})) kwargs={'course_id': self.graded_course.id}))
return grades.grade(self.student_user, fake_request, return grades.grade(self.student_user, fake_request,
self.graded_course, student_module_cache) self.graded_course, student_module_cache)
def get_homework_scores(self): def get_homework_scores(self):
return self.get_grade_summary()['totaled_scores']['Homework'] return self.get_grade_summary()['totaled_scores']['Homework']
def get_progress_summary(self): def get_progress_summary(self):
student_module_cache = StudentModuleCache.cache_for_descriptor_descendents( student_module_cache = StudentModuleCache.cache_for_descriptor_descendents(
self.graded_course.id, self.student_user, self.graded_course) self.graded_course.id, self.student_user, self.graded_course)
fake_request = self.factory.get(reverse('progress', fake_request = self.factory.get(reverse('progress',
kwargs={'course_id': self.graded_course.id})) kwargs={'course_id': self.graded_course.id}))
progress_summary = grades.progress_summary(self.student_user, fake_request, progress_summary = grades.progress_summary(self.student_user, fake_request,
self.graded_course, student_module_cache) self.graded_course, student_module_cache)
return progress_summary return progress_summary
def check_grade_percent(self, percent): def check_grade_percent(self, percent):
grade_summary = self.get_grade_summary() grade_summary = self.get_grade_summary()
self.assertEqual(percent, grade_summary['percent']) self.assertEqual(grade_summary['percent'], percent)
def submit_question_answer(self, problem_url_name, responses): def submit_question_answer(self, problem_url_name, responses):
""" """
The field names of a problem are hard to determine. This method only works The field names of a problem are hard to determine. This method only works
...@@ -710,96 +714,96 @@ class TestCourseGrader(PageLoader): ...@@ -710,96 +714,96 @@ class TestCourseGrader(PageLoader):
input_i4x-edX-graded-problem-H1P3_2_2 input_i4x-edX-graded-problem-H1P3_2_2
""" """
problem_location = "i4x://edX/graded/problem/{0}".format(problem_url_name) problem_location = "i4x://edX/graded/problem/{0}".format(problem_url_name)
modx_url = reverse('modx_dispatch', modx_url = reverse('modx_dispatch',
kwargs={ kwargs={
'course_id' : self.graded_course.id, 'course_id' : self.graded_course.id,
'location' : problem_location, 'location' : problem_location,
'dispatch' : 'problem_check', } 'dispatch' : 'problem_check', }
) )
resp = self.client.post(modx_url, { resp = self.client.post(modx_url, {
'input_i4x-edX-graded-problem-{0}_2_1'.format(problem_url_name): responses[0], 'input_i4x-edX-graded-problem-{0}_2_1'.format(problem_url_name): responses[0],
'input_i4x-edX-graded-problem-{0}_2_2'.format(problem_url_name): responses[1], 'input_i4x-edX-graded-problem-{0}_2_2'.format(problem_url_name): responses[1],
}) })
print "modx_url" , modx_url, "responses" , responses print "modx_url" , modx_url, "responses" , responses
print "resp" , resp print "resp" , resp
return resp return resp
def problem_location(self, problem_url_name): def problem_location(self, problem_url_name):
return "i4x://edX/graded/problem/{0}".format(problem_url_name) return "i4x://edX/graded/problem/{0}".format(problem_url_name)
def reset_question_answer(self, problem_url_name): def reset_question_answer(self, problem_url_name):
problem_location = self.problem_location(problem_url_name) problem_location = self.problem_location(problem_url_name)
modx_url = reverse('modx_dispatch', modx_url = reverse('modx_dispatch',
kwargs={ kwargs={
'course_id' : self.graded_course.id, 'course_id' : self.graded_course.id,
'location' : problem_location, 'location' : problem_location,
'dispatch' : 'problem_reset', } 'dispatch' : 'problem_reset', }
) )
resp = self.client.post(modx_url) resp = self.client.post(modx_url)
return resp return resp
def test_get_graded(self): def test_get_graded(self):
#### Check that the grader shows we have 0% in the course #### Check that the grader shows we have 0% in the course
self.check_grade_percent(0) self.check_grade_percent(0)
#### Submit the answers to a few problems as ajax calls #### Submit the answers to a few problems as ajax calls
def earned_hw_scores(): def earned_hw_scores():
"""Global scores, each Score is a Problem Set""" """Global scores, each Score is a Problem Set"""
return [s.earned for s in self.get_homework_scores()] return [s.earned for s in self.get_homework_scores()]
def score_for_hw(hw_url_name): def score_for_hw(hw_url_name):
hw_section = [section for section hw_section = [section for section
in self.get_progress_summary()[0]['sections'] in self.get_progress_summary()[0]['sections']
if section.get('url_name') == hw_url_name][0] if section.get('url_name') == hw_url_name][0]
return [s.earned for s in hw_section['scores']] return [s.earned for s in hw_section['scores']]
# Only get half of the first problem correct # Only get half of the first problem correct
self.submit_question_answer('H1P1', ['Correct', 'Incorrect']) self.submit_question_answer('H1P1', ['Correct', 'Incorrect'])
self.check_grade_percent(0.06) self.check_grade_percent(0.06)
self.assertEqual(earned_hw_scores(), [1.0, 0, 0]) # Order matters self.assertEqual(earned_hw_scores(), [1.0, 0, 0]) # Order matters
self.assertEqual(score_for_hw('Homework1'), [1.0, 0.0]) self.assertEqual(score_for_hw('Homework1'), [1.0, 0.0])
# Get both parts of the first problem correct # Get both parts of the first problem correct
self.reset_question_answer('H1P1') self.reset_question_answer('H1P1')
self.submit_question_answer('H1P1', ['Correct', 'Correct']) self.submit_question_answer('H1P1', ['Correct', 'Correct'])
self.check_grade_percent(0.13) self.check_grade_percent(0.13)
self.assertEqual(earned_hw_scores(), [2.0, 0, 0]) self.assertEqual(earned_hw_scores(), [2.0, 0, 0])
self.assertEqual(score_for_hw('Homework1'), [2.0, 0.0]) self.assertEqual(score_for_hw('Homework1'), [2.0, 0.0])
# This problem is shown in an ABTest # This problem is shown in an ABTest
self.submit_question_answer('H1P2', ['Correct', 'Correct']) self.submit_question_answer('H1P2', ['Correct', 'Correct'])
self.check_grade_percent(0.25) self.check_grade_percent(0.25)
self.assertEqual(earned_hw_scores(), [4.0, 0.0, 0]) self.assertEqual(earned_hw_scores(), [4.0, 0.0, 0])
self.assertEqual(score_for_hw('Homework1'), [2.0, 2.0]) self.assertEqual(score_for_hw('Homework1'), [2.0, 2.0])
# This problem is hidden in an ABTest. Getting it correct doesn't change total grade # This problem is hidden in an ABTest. Getting it correct doesn't change total grade
self.submit_question_answer('H1P3', ['Correct', 'Correct']) self.submit_question_answer('H1P3', ['Correct', 'Correct'])
self.check_grade_percent(0.25) self.check_grade_percent(0.25)
self.assertEqual(score_for_hw('Homework1'), [2.0, 2.0]) self.assertEqual(score_for_hw('Homework1'), [2.0, 2.0])
# On the second homework, we only answer half of the questions. # On the second homework, we only answer half of the questions.
# Then it will be dropped when homework three becomes the higher percent # Then it will be dropped when homework three becomes the higher percent
# This problem is also weighted to be 4 points (instead of default of 2) # This problem is also weighted to be 4 points (instead of default of 2)
# If the problem was unweighted the percent would have been 0.38 so we # If the problem was unweighted the percent would have been 0.38 so we
# know it works. # know it works.
self.submit_question_answer('H2P1', ['Correct', 'Correct']) self.submit_question_answer('H2P1', ['Correct', 'Correct'])
self.check_grade_percent(0.42) self.check_grade_percent(0.42)
self.assertEqual(earned_hw_scores(), [4.0, 4.0, 0]) self.assertEqual(earned_hw_scores(), [4.0, 4.0, 0])
# Third homework # Third homework
self.submit_question_answer('H3P1', ['Correct', 'Correct']) self.submit_question_answer('H3P1', ['Correct', 'Correct'])
self.check_grade_percent(0.42) # Score didn't change self.check_grade_percent(0.42) # Score didn't change
self.assertEqual(earned_hw_scores(), [4.0, 4.0, 2.0]) self.assertEqual(earned_hw_scores(), [4.0, 4.0, 2.0])
self.submit_question_answer('H3P2', ['Correct', 'Correct']) self.submit_question_answer('H3P2', ['Correct', 'Correct'])
self.check_grade_percent(0.5) # Now homework2 dropped. Score changes self.check_grade_percent(0.5) # Now homework2 dropped. Score changes
self.assertEqual(earned_hw_scores(), [4.0, 4.0, 4.0]) self.assertEqual(earned_hw_scores(), [4.0, 4.0, 4.0])
# Now we answer the final question (worth half of the grade) # Now we answer the final question (worth half of the grade)
self.submit_question_answer('FinalQuestion', ['Correct', 'Correct']) self.submit_question_answer('FinalQuestion', ['Correct', 'Correct'])
self.check_grade_percent(1.0) # Hooray! We got 100% self.check_grade_percent(1.0) # Hooray! We got 100%
......
...@@ -21,6 +21,25 @@ log = logging.getLogger("mitx.courseware") ...@@ -21,6 +21,25 @@ log = logging.getLogger("mitx.courseware")
class GradingServiceError(Exception): class GradingServiceError(Exception):
pass pass
class MockStaffGradingService(object):
"""
A simple mockup of a staff grading service, testing.
"""
def __init__(self):
self.cnt = 0
def get_next(self, course_id):
self.cnt += 1
return json.dumps({'success': True,
'submission_id': self.cnt,
'submission': 'Test submission {cnt}'.format(cnt=self.cnt),
'rubric': 'A rubric'})
def save_grade(self, course_id, submission_id, score, feedback):
return self.get_next(course_id)
class StaffGradingService(object): class StaffGradingService(object):
""" """
Interface to staff grading backend. Interface to staff grading backend.
...@@ -30,20 +49,20 @@ class StaffGradingService(object): ...@@ -30,20 +49,20 @@ class StaffGradingService(object):
# TODO: add auth # TODO: add auth
self.session = requests.session() self.session = requests.session()
def get_next(course_id): def get_next(self, course_id):
""" """
Get the next thing to grade. Returns json, or raises GradingServiceError Get the next thing to grade. Returns json, or raises GradingServiceError
if there's a problem. if there's a problem.
""" """
try: try:
r = self.session.get(url + 'get_next') r = self.session.get(self.url + 'get_next')
except requests.exceptions.ConnectionError as err: except requests.exceptions.ConnectionError as err:
# reraise as promised GradingServiceError, but preserve stacktrace. # reraise as promised GradingServiceError, but preserve stacktrace.
raise GradingServiceError, str(err), sys.exc_info()[2] raise GradingServiceError, str(err), sys.exc_info()[2]
return r.text return r.text
def save_grade(course_id, submission_id, score, feedback): def save_grade(self, course_id, submission_id, score, feedback):
""" """
Save a grade. Save a grade.
...@@ -52,15 +71,15 @@ class StaffGradingService(object): ...@@ -52,15 +71,15 @@ class StaffGradingService(object):
Returns json, or raises GradingServiceError if there's a problem. Returns json, or raises GradingServiceError if there's a problem.
""" """
try: try:
r = self.session.get(url + 'save_grade') r = self.session.get(self.url + 'save_grade')
except requests.exceptions.ConnectionError as err: except requests.exceptions.ConnectionError as err:
# reraise as promised GradingServiceError, but preserve stacktrace. # reraise as promised GradingServiceError, but preserve stacktrace.
raise GradingServiceError, str(err), sys.exc_info()[2] raise GradingServiceError, str(err), sys.exc_info()[2]
return r.text return r.text
_service = StaffGradingService(settings.STAFF_GRADING_BACKEND_URL) #_service = StaffGradingService(settings.STAFF_GRADING_BACKEND_URL)
_service = MockStaffGradingService()
def _err_response(msg): def _err_response(msg):
""" """
......
...@@ -8,15 +8,24 @@ Notes for running by hand: ...@@ -8,15 +8,24 @@ Notes for running by hand:
django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor django-admin.py test --settings=lms.envs.test --pythonpath=. lms/djangoapps/instructor
""" """
import courseware.tests.tests as ct
import json
from nose import SkipTest
from mock import patch, Mock
from override_settings import override_settings from override_settings import override_settings
from django.contrib.auth.models import \ # Need access to internal func to put users in the right group
Group # Need access to internal func to put users in the right group from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, \ from django_comment_client.models import Role, FORUM_ROLE_ADMINISTRATOR, \
FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA, FORUM_ROLE_STUDENT
from django_comment_client.utils import has_forum_access from django_comment_client.utils import has_forum_access
from instructor import staff_grading_service
from courseware.access import _course_staff_group_name from courseware.access import _course_staff_group_name
import courseware.tests.tests as ct import courseware.tests.tests as ct
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
...@@ -79,7 +88,7 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader): ...@@ -79,7 +88,7 @@ class TestInstructorDashboardGradeDownloadCSV(ct.PageLoader):
''' '''
self.assertEqual(body, expected_body, msg) self.assertEqual(body, expected_body, msg)
FORUM_ROLES = [ FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA ] FORUM_ROLES = [ FORUM_ROLE_ADMINISTRATOR, FORUM_ROLE_MODERATOR, FORUM_ROLE_COMMUNITY_TA ]
FORUM_ADMIN_ACTION_SUFFIX = { FORUM_ROLE_ADMINISTRATOR : 'admin', FORUM_ROLE_MODERATOR : 'moderator', FORUM_ROLE_COMMUNITY_TA : 'community TA'} FORUM_ADMIN_ACTION_SUFFIX = { FORUM_ROLE_ADMINISTRATOR : 'admin', FORUM_ROLE_MODERATOR : 'moderator', FORUM_ROLE_COMMUNITY_TA : 'community TA'}
FORUM_ADMIN_USER = { FORUM_ROLE_ADMINISTRATOR : 'forumadmin', FORUM_ROLE_MODERATOR : 'forummoderator', FORUM_ROLE_COMMUNITY_TA : 'forummoderator'} FORUM_ADMIN_USER = { FORUM_ROLE_ADMINISTRATOR : 'forumadmin', FORUM_ROLE_MODERATOR : 'forummoderator', FORUM_ROLE_COMMUNITY_TA : 'forummoderator'}
...@@ -91,6 +100,8 @@ def action_name(operation, rolename): ...@@ -91,6 +100,8 @@ def action_name(operation, rolename):
return '{0} forum {1}'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename]) return '{0} forum {1}'.format(operation, FORUM_ADMIN_ACTION_SUFFIX[rolename])
_mock_service = staff_grading_service.MockStaffGradingService()
@override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE) @override_settings(MODULESTORE=ct.TEST_DATA_XML_MODULESTORE)
class TestInstructorDashboardForumAdmin(ct.PageLoader): class TestInstructorDashboardForumAdmin(ct.PageLoader):
''' '''
...@@ -101,8 +112,15 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): ...@@ -101,8 +112,15 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
xmodule.modulestore.django._MODULESTORES = {} xmodule.modulestore.django._MODULESTORES = {}
courses = modulestore().get_courses() courses = modulestore().get_courses()
<<<<<<< HEAD
self.full = modulestore().get_course("edX/full/6.002_Spring_2012") self.full = modulestore().get_course("edX/full/6.002_Spring_2012")
self.toy = modulestore().get_course("edX/toy/2012_Fall") self.toy = modulestore().get_course("edX/toy/2012_Fall")
=======
self.course_id = "edX/toy/2012_Fall"
self.toy = modulestore().get_course(self.course_id)
>>>>>>> Refactor testing code, hook up frontend.
# Create two accounts # Create two accounts
self.student = 'view@test.com' self.student = 'view@test.com'
...@@ -122,7 +140,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader): ...@@ -122,7 +140,7 @@ class TestInstructorDashboardForumAdmin(ct.PageLoader):
self.enroll(self.toy) self.enroll(self.toy)
def initialize_roles(self, course_id): def initialize_roles(self, course_id):
self.admin_role = Role.objects.get_or_create(name=FORUM_ROLE_ADMINISTRATOR, course_id=course_id)[0] self.admin_role = Role.objects.get_or_create(name=FORUM_ROLE_ADMINISTRATOR, course_id=course_id)[0]
self.moderator_role = Role.objects.get_or_create(name=FORUM_ROLE_MODERATOR, course_id=course_id)[0] self.moderator_role = Role.objects.get_or_create(name=FORUM_ROLE_MODERATOR, course_id=course_id)[0]
...@@ -220,7 +238,7 @@ class TestStaffGradingService(ct.PageLoader): ...@@ -220,7 +238,7 @@ class TestStaffGradingService(ct.PageLoader):
''' '''
def setUp(self): def setUp(self):
xmodule.modulestore.django._MODULESTORES = {} xmodule.modulestore.django._MODULESTORES = {}
...@@ -240,7 +258,6 @@ class TestStaffGradingService(ct.PageLoader): ...@@ -240,7 +258,6 @@ class TestStaffGradingService(ct.PageLoader):
Make sure only staff have access. Make sure only staff have access.
""" """
self.login(self.student, self.password) self.login(self.student, self.password)
self.enroll(self.toy)
# both get and post should return 404 # both get and post should return 404
for view_name in ('staff_grading_get_next', 'staff_grading_save_grade'): for view_name in ('staff_grading_get_next', 'staff_grading_save_grade'):
...@@ -248,3 +265,32 @@ class TestStaffGradingService(ct.PageLoader): ...@@ -248,3 +265,32 @@ class TestStaffGradingService(ct.PageLoader):
self.check_for_get_code(404, url) self.check_for_get_code(404, url)
self.check_for_post_code(404, url) self.check_for_post_code(404, url)
<<<<<<< HEAD
=======
@patch.object(staff_grading_service, '_service', _mock_service)
def test_get_next(self):
self.login(self.instructor, self.password)
url = reverse('staff_grading_get_next', kwargs={'course_id': self.course_id})
r = self.check_for_get_code(200, url)
d = json.loads(r.content)
self.assertTrue(d['success'])
self.assertEquals(d['submission_id'], _mock_service.cnt)
@patch.object(staff_grading_service, '_service', _mock_service)
def test_save_grade(self):
self.login(self.instructor, self.password)
url = reverse('staff_grading_save_grade', kwargs={'course_id': self.course_id})
data = {'score': '12', 'feedback': 'great!', 'submission_id': '123'}
r = self.check_for_post_code(200, url, data)
d = json.loads(r.content)
self.assertTrue(d['success'], str(d))
self.assertEquals(d['submission_id'], _mock_service.cnt)
>>>>>>> Refactor testing code, hook up frontend.
...@@ -422,10 +422,15 @@ def staff_grading(request, course_id): ...@@ -422,10 +422,15 @@ def staff_grading(request, course_id):
grading = StaffGrading(course) grading = StaffGrading(course)
ajax_url = reverse('staff_grading', kwargs={'course_id': course_id})
if not ajax_url.endswith('/'):
ajax_url += '/'
return render_to_response('instructor/staff_grading.html', { return render_to_response('instructor/staff_grading.html', {
'view_html': grading.get_html(), 'view_html': grading.get_html(),
'course': course, 'course': course,
'course_id': course_id, 'course_id': course_id,
'ajax_url': ajax_url,
# Checked above # Checked above
'staff_access': True, }) 'staff_access': True, })
......
...@@ -24,6 +24,7 @@ class StaffGradingBackend ...@@ -24,6 +24,7 @@ class StaffGradingBackend
success: true success: true
submission: 'submission! ' + @mock_cnt submission: 'submission! ' + @mock_cnt
rubric: 'A rubric! ' + @mock_cnt rubric: 'A rubric! ' + @mock_cnt
submission_id: @mock_cnt
else if cmd == 'save_grade' else if cmd == 'save_grade'
console.log("eval: #{data.score} pts, Feedback: #{data.feedback}") console.log("eval: #{data.score} pts, Feedback: #{data.feedback}")
...@@ -31,6 +32,7 @@ class StaffGradingBackend ...@@ -31,6 +32,7 @@ class StaffGradingBackend
success: true success: true
submission: 'another submission! ' + @mock_cnt submission: 'another submission! ' + @mock_cnt
rubric: 'A rubric!' + @mock_cnt rubric: 'A rubric!' + @mock_cnt
submission_id: @mock_cnt
else else
response = response =
success: false success: false
...@@ -74,6 +76,7 @@ class StaffGrading ...@@ -74,6 +76,7 @@ class StaffGrading
# model state # model state
@state = state_no_data @state = state_no_data
@submission_id = null
@submission = '' @submission = ''
@rubric = '' @rubric = ''
@error_msg = '' @error_msg = ''
...@@ -110,7 +113,7 @@ class StaffGrading ...@@ -110,7 +113,7 @@ class StaffGrading
if response.success if response.success
if response.submission if response.submission
@data_loaded(response.submission, response.rubric) @data_loaded(response.submission, response.rubric, response.submission_id)
else else
@no_more(response.message) @no_more(response.message)
else else
...@@ -122,7 +125,10 @@ class StaffGrading ...@@ -122,7 +125,10 @@ class StaffGrading
@backend.post('get_next', {}, @ajax_callback) @backend.post('get_next', {}, @ajax_callback)
submit_and_get_next: () -> submit_and_get_next: () ->
data = {score: @score, feedback: @feedback_area.val()} data =
score: @score
feedback: @feedback_area.val()
submission_id: @submission_id
@backend.post('save_grade', data, @ajax_callback) @backend.post('save_grade', data, @ajax_callback)
...@@ -130,9 +136,10 @@ class StaffGrading ...@@ -130,9 +136,10 @@ class StaffGrading
@error_msg = msg @error_msg = msg
@state = state_error @state = state_error
data_loaded: (submission, rubric) -> data_loaded: (submission, rubric, submission_id) ->
@submission = submission @submission = submission
@rubric = rubric @rubric = rubric
@submission_id = submission_id
@feedback_area.val('') @feedback_area.val('')
@score = null @score = null
@state = state_grading @state = state_grading
...@@ -140,6 +147,7 @@ class StaffGrading ...@@ -140,6 +147,7 @@ class StaffGrading
no_more: (message) -> no_more: (message) ->
@submission = null @submission = null
@rubric = null @rubric = null
@submission_id = null
@message = message @message = message
@state = state_no_data @state = state_no_data
...@@ -196,7 +204,7 @@ class StaffGrading ...@@ -196,7 +204,7 @@ class StaffGrading
# for now, just create an instance and load it... # for now, just create an instance and load it...
mock_backend = true mock_backend = false
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)
......
...@@ -15,7 +15,44 @@ ...@@ -15,7 +15,44 @@
</%block> </%block>
<section class="container"> <section class="container">
<div class="grading-wrapper">
${view_html} <div class="staff-grading" data-ajax_url="${ajax_url}">
</div> <h1>Staff grading</h1>
<div class="error-container">
</div>
<div class="message-container">
</div>
<section class="submission-wrapper">
<h3>Submission</h3>
<div class="submission-container">
</div>
</section>
<section class="rubric-wrapper">
<h3>Rubric</h3>
<div class="rubric-container">
</div>
<div class="evaluation">
<textarea name="feedback" placeholder="Feedback for student..."
class="feedback-area" cols="70" rows="10"></textarea>
<p>
<label for="correct-radio">Correct</label>
<input type="radio" name="score-selection" id="correct-radio" value="1">
<label for="incorrect-radio">Incorrect</label>
<input type="radio" name="score-selection" id="incorrect-radio" value="0">
</p>
</div>
</section>
<div class="submission">
<input type="button" value="Submit" class="submit-button" name="show"/>
</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