diff --git a/lms/djangoapps/instructor/tests/test_legacy_reset.py b/lms/djangoapps/instructor/tests/test_legacy_reset.py deleted file mode 100644 index de2d51851a..0000000000 --- a/lms/djangoapps/instructor/tests/test_legacy_reset.py +++ /dev/null @@ -1,70 +0,0 @@ -""" -View-level tests for resetting student state in legacy instructor dash. -""" - -import json -from django.core.urlresolvers import reverse -from django.test.utils import override_settings - -from courseware.tests.helpers import LoginEnrollmentTestCase -from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase -from xmodule.modulestore.tests.django_utils import TEST_DATA_MOCK_MODULESTORE -from xmodule.modulestore.tests.factories import CourseFactory -from student.tests.factories import UserFactory, AdminFactory, CourseEnrollmentFactory - -from courseware.models import StudentModule - -from submissions import api as sub_api -from student.models import anonymous_id_for_user - - -@override_settings(MODULESTORE=TEST_DATA_MOCK_MODULESTORE) -class InstructorResetStudentStateTest(ModuleStoreTestCase, LoginEnrollmentTestCase): - """ - Reset student state from the legacy instructor dash. - """ - - def setUp(self): - """ - Log in as an instructor, and create a course/student to reset. - """ - instructor = AdminFactory.create() - self.client.login(username=instructor.username, password='test') - self.student = UserFactory.create(username='test', email='test@example.com') - self.course = CourseFactory.create() - CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) - - def test_delete_student_state_resets_scores(self): - problem_location = self.course.id.make_usage_key('dummy', 'module') - - # Create a student module for the user - StudentModule.objects.create( - student=self.student, - course_id=self.course.id, - module_state_key=problem_location, - state=json.dumps({}) - ) - - # Create a submission and score for the student using the submissions API - student_item = { - 'student_id': anonymous_id_for_user(self.student, self.course.id), - 'course_id': self.course.id.to_deprecated_string(), - 'item_id': problem_location.to_deprecated_string(), - 'item_type': 'openassessment' - } - submission = sub_api.create_submission(student_item, 'test answer') - sub_api.set_score(submission['uuid'], 1, 2) - - # Delete student state using the instructor dash - url = reverse('instructor_dashboard_legacy', kwargs={'course_id': self.course.id.to_deprecated_string()}) - response = self.client.post(url, { - 'action': 'Delete student state for module', - 'unique_student_identifier': self.student.email, - 'problem_for_student': problem_location.to_deprecated_string(), - }) - - self.assertEqual(response.status_code, 200) - - # Verify that the student's scores have been reset in the submissions API - score = sub_api.get_score(student_item) - self.assertIs(score, None) diff --git a/lms/djangoapps/instructor/views/legacy.py b/lms/djangoapps/instructor/views/legacy.py index ea3b6663c1..fac33108e6 100644 --- a/lms/djangoapps/instructor/views/legacy.py +++ b/lms/djangoapps/instructor/views/legacy.py @@ -259,274 +259,6 @@ def instructor_dashboard(request, course_id): track.views.server_track(request, "dump-graded-assignments-config", {}, page="idashboard") msg += dump_grading_context(course) - elif "Rescore ALL students' problem submissions" in action: - problem_location_str = strip_if_string(request.POST.get('problem_for_all_students', '')) - try: - problem_location = course_key.make_usage_key_from_deprecated_string(problem_location_str) - instructor_task = submit_rescore_problem_for_all_students(request, problem_location) - if instructor_task is None: - msg += '{text}'.format( - text=_('Failed to create a background task for rescoring "{problem_url}".').format( - problem_url=problem_location_str - ) - ) - else: - track.views.server_track( - request, - "rescore-all-submissions", - { - "problem": problem_location_str, - "course": course_key.to_deprecated_string() - }, - page="idashboard" - ) - - except (InvalidKeyError, ItemNotFoundError) as err: - msg += '{text}'.format( - text=_('Failed to create a background task for rescoring "{problem_url}": problem not found.').format( - problem_url=problem_location_str - ) - ) - except Exception as err: # pylint: disable=broad-except - log.error("Encountered exception from rescore: {0}".format(err)) - msg += '{text}'.format( - text=_('Failed to create a background task for rescoring "{url}": {message}.').format( - url=problem_location_str, message=err.message - ) - ) - - elif "Reset ALL students' attempts" in action: - problem_location_str = strip_if_string(request.POST.get('problem_for_all_students', '')) - try: - problem_location = course_key.make_usage_key_from_deprecated_string(problem_location_str) - instructor_task = submit_reset_problem_attempts_for_all_students(request, problem_location) - if instructor_task is None: - msg += '{text}'.format( - text=_('Failed to create a background task for resetting "{problem_url}".').format(problem_url=problem_location_str) - ) - else: - track.views.server_track( - request, - "reset-all-attempts", - { - "problem": problem_location_str, - "course": course_key.to_deprecated_string() - }, - page="idashboard" - ) - except (InvalidKeyError, ItemNotFoundError) as err: - log.error('Failure to reset: unknown problem "{0}"'.format(err)) - msg += '{text}'.format( - text=_('Failed to create a background task for resetting "{problem_url}": problem not found.').format( - problem_url=problem_location_str - ) - ) - except Exception as err: # pylint: disable=broad-except - log.error("Encountered exception from reset: {0}".format(err)) - msg += '{text}'.format( - text=_('Failed to create a background task for resetting "{url}": {message}.').format( - url=problem_location_str, message=err.message - ) - ) - - elif "Show Background Task History for Student" in action: - # put this before the non-student case, since the use of "in" will cause this to be missed - unique_student_identifier = request.POST.get('unique_student_identifier', '') - message, student = get_student_from_identifier(unique_student_identifier) - if student is None: - msg += message - else: - problem_location_str = strip_if_string(request.POST.get('problem_for_student', '')) - try: - problem_location = course_key.make_usage_key_from_deprecated_string(problem_location_str) - except InvalidKeyError: - msg += '{text}'.format( - text=_('Could not find problem location "{url}".').format( - url=problem_location_str - ) - ) - else: - message, datatable = get_background_task_table(course_key, problem_location, student) - msg += message - - elif "Show Background Task History" in action: - problem_location_str = strip_if_string(request.POST.get('problem_for_all_students', '')) - try: - problem_location = course_key.make_usage_key_from_deprecated_string(problem_location_str) - except InvalidKeyError: - msg += '{text}'.format( - text=_('Could not find problem location "{url}".').format( - url=problem_location_str - ) - ) - else: - message, datatable = get_background_task_table(course_key, problem_location) - msg += message - - elif ("Reset student's attempts" in action or - "Delete student state for module" in action or - "Rescore student's problem submission" in action): - # get the form data - unique_student_identifier = request.POST.get( - 'unique_student_identifier', '' - ) - problem_location_str = strip_if_string(request.POST.get('problem_for_student', '')) - try: - module_state_key = course_key.make_usage_key_from_deprecated_string(problem_location_str) - except InvalidKeyError: - msg += '{text}'.format( - text=_('Could not find problem location "{url}".').format( - url=problem_location_str - ) - ) - else: - # try to uniquely id student by email address or username - message, student = get_student_from_identifier(unique_student_identifier) - msg += message - student_module = None - if student is not None: - # Reset the student's score in the submissions API - # Currently this is used only by open assessment (ORA 2) - # We need to do this *before* retrieving the `StudentModule` model, - # because it's possible for a score to exist even if no student module exists. - if "Delete student state for module" in action: - try: - sub_api.reset_score( - anonymous_id_for_user(student, course_key), - course_key.to_deprecated_string(), - module_state_key.to_deprecated_string(), - ) - except sub_api.SubmissionError: - # Trust the submissions API to log the error - error_msg = _("An error occurred while deleting the score.") - msg += "{err} ".format(err=error_msg) - - # find the module in question - try: - student_module = StudentModule.objects.get( - student_id=student.id, - course_id=course_key, - module_state_key=module_state_key - ) - msg += _("Found module. ") - - except StudentModule.DoesNotExist as err: - error_msg = _("Couldn't find module with that urlname: {url}. ").format(url=problem_location_str) - msg += "{err_msg} ({err})".format(err_msg=error_msg, err=err) - log.debug(error_msg) - - if student_module is not None: - if "Delete student state for module" in action: - # delete the state - try: - student_module.delete() - - msg += "{text}".format( - text=_("Deleted student module state for {state}!").format(state=module_state_key) - ) - event = { - "problem": problem_location_str, - "student": unique_student_identifier, - "course": course_key.to_deprecated_string() - } - track.views.server_track( - request, - "delete-student-module-state", - event, - page="idashboard" - ) - except Exception as err: # pylint: disable=broad-except - error_msg = _("Failed to delete module state for {id}/{url}. ").format( - id=unique_student_identifier, url=problem_location_str - ) - msg += "{err_msg} ({err})".format(err_msg=error_msg, err=err) - log.exception(error_msg) - elif "Reset student's attempts" in action: - # modify the problem's state - try: - # load the state json - problem_state = json.loads(student_module.state) - old_number_of_attempts = problem_state["attempts"] - problem_state["attempts"] = 0 - # save - student_module.state = json.dumps(problem_state) - student_module.save() - event = { - "old_attempts": old_number_of_attempts, - "student": unicode(student), - "problem": student_module.module_state_key, - "instructor": unicode(request.user), - "course": course_key.to_deprecated_string() - } - track.views.server_track(request, "reset-student-attempts", event, page="idashboard") - msg += "{text}".format( - text=_("Module state successfully reset!") - ) - except Exception as err: # pylint: disable=broad-except - error_msg = _("Couldn't reset module state for {id}/{url}. ").format( - id=unique_student_identifier, url=problem_location_str - ) - msg += "{err_msg} ({err})".format(err_msg=error_msg, err=err) - log.exception(error_msg) - else: - # "Rescore student's problem submission" case - try: - instructor_task = submit_rescore_problem_for_student(request, module_state_key, student) - if instructor_task is None: - msg += '{text}'.format( - text=_('Failed to create a background task for rescoring "{key}" for student {id}.').format( - key=module_state_key, id=unique_student_identifier - ) - ) - else: - track.views.server_track( - request, - "rescore-student-submission", - { - "problem": module_state_key, - "student": unique_student_identifier, - "course": course_key.to_deprecated_string() - }, - page="idashboard" - ) - except Exception as err: # pylint: disable=broad-except - msg += '{text}'.format( - text=_('Failed to create a background task for rescoring "{key}": {id}.').format( - key=module_state_key, id=err.message - ) - ) - log.exception("Encountered exception from rescore: student '{0}' problem '{1}'".format( - unique_student_identifier, module_state_key - ) - ) - - elif "Get link to student's progress page" in action: - unique_student_identifier = request.POST.get('unique_student_identifier', '') - # try to uniquely id student by email address or username - message, student = get_student_from_identifier(unique_student_identifier) - msg += message - if student is not None: - progress_url = reverse('student_progress', kwargs={ - 'course_id': course_key.to_deprecated_string(), - 'student_id': student.id - }) - track.views.server_track( - request, - "get-student-progress-page", - { - "student": unicode(student), - "instructor": unicode(request.user), - "course": course_key.to_deprecated_string() - }, - page="idashboard" - ) - msg += "{text}.".format( - url=progress_url, - text=_("Progress page for username: {username} with email address: {email}").format( - username=student.username, email=student.email - ) - ) - #---------------------------------------- # export grades to remote gradebook diff --git a/lms/templates/courseware/legacy_instructor_dashboard.html b/lms/templates/courseware/legacy_instructor_dashboard.html index c3e5a34b48..00a792a07d 100644 --- a/lms/templates/courseware/legacy_instructor_dashboard.html +++ b/lms/templates/courseware/legacy_instructor_dashboard.html @@ -263,67 +263,13 @@ function goto( mode) %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'):

${_("Course-specific grade adjustment")}

-

- ${_("Specify a problem in the course here with its complete location:")} - -

- ## Translators: A location (string of text) follows this sentence. -

${_("You must provide the complete location of the problem. In the Staff Debug viewer, the location looks like this:")}
- i4x://edX/Open_DemoX/problem/78c98390884243b89f6023745231c525

-

- ${_("Then select an action:")} - - -

-

-

${_("These actions run in the background, and status for active tasks will appear in a table below. To see status for all tasks submitted for this problem, click on this button:")} -

-

- -

+

${_("To perform these actions, please visit the 'Student Admin' section of the instructor dashboard.")}

-
%endif

${_("Student-specific grade inspection and adjustment")}

-

- ${_("Specify the {platform_name} email address or username of a student here:").format(platform_name=settings.PLATFORM_NAME)} - -

-

- ${_("Click this, and a link to student's progress page will appear below:")} - -

-

- ${_("Specify a problem in the course here with its complete location:")} - -

- ## Translators: A location (string of text) follows this sentence. -

${_("You must provide the complete location of the problem. In the Staff Debug viewer, the location looks like this:")}
- i4x://edX/Open_DemoX/problem/78c98390884243b89f6023745231c525

-

- ${_("Then select an action:")} - - %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'): - - %endif -

- - %if instructor_access: -

- ${_("You may also delete the entire state of a student for the specified module:")} - -

- %endif - %if settings.FEATURES.get('ENABLE_INSTRUCTOR_BACKGROUND_TASKS'): -

${_("Rescoring runs in the background, and status for active tasks will appear in a table below. " - "To see status for all tasks submitted for this problem and student, click on this button:")} -

-

- -

- %endif +

${_("To perform these actions, please visit the 'Student Admin' section of the instructor dashboard.")}

%endif