From 4a2dabd30a38c717ea73a9aadd30cfdf1729934e Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Mon, 10 Dec 2012 16:31:43 -0500 Subject: [PATCH 1/2] new test for problem lists --- .../instructor/staff_grading_service.py | 30 ++++++++++++++++++- lms/djangoapps/instructor/tests.py | 19 ++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lms/djangoapps/instructor/staff_grading_service.py b/lms/djangoapps/instructor/staff_grading_service.py index 33c1d875af..60449bd093 100644 --- a/lms/djangoapps/instructor/staff_grading_service.py +++ b/lms/djangoapps/instructor/staff_grading_service.py @@ -42,6 +42,17 @@ class MockStaffGradingService(object): 'max_score': 2 + self.cnt % 3, 'rubric': 'A rubric'}) + def get_problem_list(self, course_id, grader_id): + self.cnt += 1 + return json.dumps({'success': True, + 'problem_list': [ + json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo1', \ + 'problem_name': "Problem 1", 'num_graded': 3, 'num_pending': 5, 'min_for_ml': 10}), + json.dumps({'location': 'i4x://MITx/3.091x/problem/open_ended_demo2', \ + 'problem_name': "Problem 2", 'num_graded': 1, 'num_pending': 5, 'min_for_ml': 10}) + ]}) + + def save_grade(self, course_id, grader_id, submission_id, score, feedback): return self.get_next(course_id, 'fake location', grader_id) @@ -274,7 +285,24 @@ def get_next(request, course_id): def get_problem_list(request, course_id): """ Get all the problems for the given course id - TODO: fill in all of this stuff + + Returns a json dict with the following keys: + success: bool + + problem_list: a list containing json dicts with the following keys: + each dict represents a different problem in the course + + location: the location of the problem + + problem_name: the name of the problem + + num_graded: the number of responses that have been graded + + num_pending: the number of responses that are sitting in the queue + + min_for_ml: the number of responses that need to be graded before + the ml can be run + """ _check_access(request.user, course_id) try: diff --git a/lms/djangoapps/instructor/tests.py b/lms/djangoapps/instructor/tests.py index 4b5ab7e309..865a97951e 100644 --- a/lms/djangoapps/instructor/tests.py +++ b/lms/djangoapps/instructor/tests.py @@ -278,6 +278,14 @@ class TestStaffGradingService(ct.PageLoader): d = json.loads(r.content) self.assertTrue(d['success']) self.assertEquals(d['submission_id'], self.mock_service.cnt) + self.assertIsNotNone(d['submission']) + self.assertIsNotNone(d['num_graded']) + self.assertIsNotNone(d['min_for_ml']) + self.assertIsNotNone(d['num_pending']) + self.assertIsNotNone(d['prompt']) + self.assertIsNotNone(d['ml_error_info']) + self.assertIsNotNone(d['max_score']) + self.assertIsNotNone(d['rubric']) def test_save_grade(self): @@ -294,4 +302,15 @@ class TestStaffGradingService(ct.PageLoader): self.assertTrue(d['success'], str(d)) self.assertEquals(d['submission_id'], self.mock_service.cnt) + def test_get_problem_list(self): + self.login(self.instructor, self.password) + + url = reverse('staff_grading_get_problem_list', kwargs={'course_id': self.course_id}) + data = {} + + r = self.check_for_post_code(200, url, data) + d = json.loads(r.content) + self.assertTrue(d['success'], str(d)) + self.assertIsNotNone(d['problem_list']) + From 43d76b98130aace1ec2873a3148e31b19a47bdef Mon Sep 17 00:00:00 2001 From: Diana Huang Date: Tue, 11 Dec 2012 14:06:07 -0500 Subject: [PATCH 2/2] Add skip button logic to the LMS --- .../instructor/staff_grading_service.py | 18 +++++++++++------- .../src/staff_grading/staff_grading.coffee | 14 +++++++++++++- lms/templates/instructor/staff_grading.html | 1 + 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/lms/djangoapps/instructor/staff_grading_service.py b/lms/djangoapps/instructor/staff_grading_service.py index 60449bd093..ea8f0de074 100644 --- a/lms/djangoapps/instructor/staff_grading_service.py +++ b/lms/djangoapps/instructor/staff_grading_service.py @@ -53,7 +53,7 @@ class MockStaffGradingService(object): ]}) - def save_grade(self, course_id, grader_id, submission_id, score, feedback): + def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped): return self.get_next(course_id, 'fake location', grader_id) @@ -109,7 +109,8 @@ class StaffGradingService(object): log.warning("Couldn't log into staff_grading backend. Response: %s", r) # try again - return operation() + response = operation() + response.raise_for_status() return response @@ -173,7 +174,7 @@ class StaffGradingService(object): return r.text - def save_grade(self, course_id, grader_id, submission_id, score, feedback): + def save_grade(self, course_id, grader_id, submission_id, score, feedback, skipped): """ Save a score and feedback for a submission. @@ -190,7 +191,8 @@ class StaffGradingService(object): 'submission_id': submission_id, 'score': score, 'feedback': feedback, - 'grader_id': grader_id} + 'grader_id': grader_id, + 'skipped': skipped} op = lambda: self.session.post(self.save_grade_url, data=data, allow_redirects=False) @@ -350,7 +352,6 @@ def save_grade(request, course_id): required = set(['score', 'feedback', 'submission_id', 'location']) actual = set(request.POST.keys()) - log.debug(actual) missing = required - actual if len(missing) > 0: return _err_response('Missing required keys {0}'.format( @@ -358,14 +359,17 @@ def save_grade(request, course_id): grader_id = request.user.id p = request.POST - location = p['location'] + + location = p['location'] + skipped = 'skipped' in p try: result_json = grading_service().save_grade(course_id, grader_id, p['submission_id'], p['score'], - p['feedback']) + p['feedback'], + skipped) except GradingServiceError: log.exception("Error saving grade") return _err_response('Could not connect to grading service') diff --git a/lms/static/coffee/src/staff_grading/staff_grading.coffee b/lms/static/coffee/src/staff_grading/staff_grading.coffee index abcf99e40b..cbecea4694 100644 --- a/lms/static/coffee/src/staff_grading/staff_grading.coffee +++ b/lms/static/coffee/src/staff_grading/staff_grading.coffee @@ -139,8 +139,10 @@ class StaffGrading @feedback_area = $('.feedback-area') @score_selection_container = $('.score-selection-container') + @submit_button = $('.submit-button') @action_button = $('.action-button') + @skip_button = $('.skip-button') @problem_meta_info = $('.problem-meta-info-container') @meta_info_wrapper = $('.meta-info-wrapper') @@ -171,6 +173,7 @@ class StaffGrading @submit_button.click @submit # TODO: fix this to do something more intelligent @action_button.click @submit + @skip_button.click @skip_and_get_next # send initial request automatically @get_problem_list() @@ -225,6 +228,15 @@ class StaffGrading @list_view = false @backend.post('get_next', {location: location}, @ajax_callback) + skip_and_get_next: () => + data = + score: @score + feedback: @feedback_area.val() + submission_id: @submission_id + location: @location + skipped: true + @backend.post('save_grade', data, @ajax_callback) + get_problem_list: () -> @list_view = true @backend.post('get_problem_list', {}, @ajax_callback) @@ -342,7 +354,7 @@ class StaffGrading meta_list = $("