Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
d1da0445
Commit
d1da0445
authored
Jul 12, 2017
by
noraiz-anwar
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Throw error if messaging queue is not available
parent
3e7243ea
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
302 additions
and
229 deletions
+302
-229
lms/djangoapps/instructor/tests/test_api.py
+61
-35
lms/djangoapps/instructor/views/api.py
+91
-150
lms/djangoapps/instructor_task/api_helper.py
+79
-3
lms/djangoapps/instructor_task/tests/test_api.py
+19
-2
lms/static/js/instructor_dashboard/data_download.js
+49
-36
lms/static/js/spec/staff_debug_actions_spec.js
+1
-1
lms/static/js/staff_debug_actions.js
+2
-2
No files found.
lms/djangoapps/instructor/tests/test_api.py
View file @
d1da0445
...
@@ -52,7 +52,11 @@ from lms.djangoapps.instructor.views.api import (
...
@@ -52,7 +52,11 @@ from lms.djangoapps.instructor.views.api import (
generate_unique_password
,
generate_unique_password
,
require_finance_admin
require_finance_admin
)
)
from
lms.djangoapps.instructor_task.api_helper
import
AlreadyRunningError
from
lms.djangoapps.instructor_task.api_helper
import
(
AlreadyRunningError
,
QueueConnectionError
,
generate_already_running_error_message
)
from
openedx.core.djangoapps.course_groups.cohorts
import
set_course_cohorted
from
openedx.core.djangoapps.course_groups.cohorts
import
set_course_cohorted
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.site_configuration
import
helpers
as
configuration_helpers
from
openedx.core.djangoapps.site_configuration.tests.mixins
import
SiteMixin
from
openedx.core.djangoapps.site_configuration.tests.mixins
import
SiteMixin
...
@@ -143,6 +147,7 @@ REPORTS_DATA = (
...
@@ -143,6 +147,7 @@ REPORTS_DATA = (
EXECUTIVE_SUMMARY_DATA
=
(
EXECUTIVE_SUMMARY_DATA
=
(
{
{
'report_type'
:
'executive summary'
,
'report_type'
:
'executive summary'
,
'task_type'
:
'exec_summary_report'
,
'instructor_api_endpoint'
:
'get_exec_summary_report'
,
'instructor_api_endpoint'
:
'get_exec_summary_report'
,
'task_api_endpoint'
:
'lms.djangoapps.instructor_task.api.submit_executive_summary_report'
,
'task_api_endpoint'
:
'lms.djangoapps.instructor_task.api.submit_executive_summary_report'
,
'extra_instructor_api_kwargs'
:
{}
'extra_instructor_api_kwargs'
:
{}
...
@@ -244,7 +249,16 @@ def view_alreadyrunningerror(request): # pylint: disable=unused-argument
...
@@ -244,7 +249,16 @@ def view_alreadyrunningerror(request): # pylint: disable=unused-argument
raise
AlreadyRunningError
()
raise
AlreadyRunningError
()
@common_exceptions_400
def
view_queue_connection_error
(
request
):
# pylint: disable=unused-argument
"""
A dummy view that raises a QueueConnectionError exception.
"""
raise
QueueConnectionError
()
@attr
(
shard
=
1
)
@attr
(
shard
=
1
)
@ddt.ddt
class
TestCommonExceptions400
(
TestCase
):
class
TestCommonExceptions400
(
TestCase
):
"""
"""
Testing the common_exceptions_400 decorator.
Testing the common_exceptions_400 decorator.
...
@@ -269,21 +283,29 @@ class TestCommonExceptions400(TestCase):
...
@@ -269,21 +283,29 @@ class TestCommonExceptions400(TestCase):
self
.
request
.
is_ajax
.
return_value
=
True
self
.
request
.
is_ajax
.
return_value
=
True
resp
=
view_user_doesnotexist
(
self
.
request
)
# pylint: disable=assignment-from-no-return
resp
=
view_user_doesnotexist
(
self
.
request
)
# pylint: disable=assignment-from-no-return
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
result
=
json
.
loads
(
resp
.
content
)
self
.
assertIn
(
"User does not exist"
,
resp
.
content
)
self
.
assertIn
(
"User does not exist"
,
result
[
"error"
])
def
test_alreadyrunningerror
(
self
):
def
test_alreadyrunningerror
(
self
):
self
.
request
.
is_ajax
.
return_value
=
False
self
.
request
.
is_ajax
.
return_value
=
False
resp
=
view_alreadyrunningerror
(
self
.
request
)
# pylint: disable=assignment-from-no-return
resp
=
view_alreadyrunningerror
(
self
.
request
)
# pylint: disable=assignment-from-no-return
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertIn
(
"
T
ask is already running"
,
resp
.
content
)
self
.
assertIn
(
"
Requested t
ask is already running"
,
resp
.
content
)
def
test_alreadyrunningerror_ajax
(
self
):
def
test_alreadyrunningerror_ajax
(
self
):
self
.
request
.
is_ajax
.
return_value
=
True
self
.
request
.
is_ajax
.
return_value
=
True
resp
=
view_alreadyrunningerror
(
self
.
request
)
# pylint: disable=assignment-from-no-return
resp
=
view_alreadyrunningerror
(
self
.
request
)
# pylint: disable=assignment-from-no-return
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertEqual
(
resp
.
status_code
,
400
)
result
=
json
.
loads
(
resp
.
content
)
self
.
assertIn
(
"Requested task is already running"
,
resp
.
content
)
self
.
assertIn
(
"Task is already running"
,
result
[
"error"
])
@ddt.data
(
True
,
False
)
def
test_queue_connection_error
(
self
,
is_ajax
):
"""
Tests that QueueConnectionError exception is handled in common_exception_400.
"""
self
.
request
.
is_ajax
.
return_value
=
is_ajax
resp
=
view_queue_connection_error
(
self
.
request
)
# pylint: disable=assignment-from-no-return
self
.
assertEqual
(
resp
.
status_code
,
400
)
self
.
assertIn
(
'Error occured. Please try again later'
,
resp
.
content
)
@attr
(
shard
=
1
)
@attr
(
shard
=
1
)
...
@@ -401,6 +423,7 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
...
@@ -401,6 +423,7 @@ class TestInstructorAPIDenyLevels(SharedModuleStoreTestCase, LoginEnrollmentTest
(
'get_proctored_exam_results'
,
{}),
(
'get_proctored_exam_results'
,
{}),
(
'get_problem_responses'
,
{}),
(
'get_problem_responses'
,
{}),
(
'export_ora2_data'
,
{}),
(
'export_ora2_data'
,
{}),
]
]
# Endpoints that only Instructors can access
# Endpoints that only Instructors can access
self
.
instructor_level_endpoints
=
[
self
.
instructor_level_endpoints
=
[
...
@@ -2680,14 +2703,15 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -2680,14 +2703,15 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
'get_problem_responses'
,
'get_problem_responses'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)}
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)}
)
)
task_type
=
'problem_responses_csv'
already_running_status
=
generate_already_running_error_message
(
task_type
)
with
patch
(
'lms.djangoapps.instructor_task.api.submit_calculate_problem_responses_csv'
)
as
submit_task_function
:
with
patch
(
'lms.djangoapps.instructor_task.api.submit_calculate_problem_responses_csv'
)
as
submit_task_function
:
error
=
AlreadyRunningError
()
error
=
AlreadyRunningError
(
already_running_status
)
submit_task_function
.
side_effect
=
error
submit_task_function
.
side_effect
=
error
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
res_json
=
json
.
loads
(
response
.
content
)
self
.
assertIn
(
'status'
,
res_json
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertIn
(
'already in progress'
,
res_json
[
'status'
]
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
def
test_get_students_features
(
self
):
def
test_get_students_features
(
self
):
"""
"""
...
@@ -2757,17 +2781,16 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -2757,17 +2781,16 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
)
)
# Successful case:
# Successful case:
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
res_json
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertIn
(
'status'
,
res_json
)
self
.
assertNotIn
(
'currently being created'
,
res_json
[
'status'
])
# CSV generation already in progress:
# CSV generation already in progress:
task_type
=
'may_enroll_info_csv'
already_running_status
=
generate_already_running_error_message
(
task_type
)
with
patch
(
'lms.djangoapps.instructor_task.api.submit_calculate_may_enroll_csv'
)
as
submit_task_function
:
with
patch
(
'lms.djangoapps.instructor_task.api.submit_calculate_may_enroll_csv'
)
as
submit_task_function
:
error
=
AlreadyRunningError
()
error
=
AlreadyRunningError
(
already_running_status
)
submit_task_function
.
side_effect
=
error
submit_task_function
.
side_effect
=
error
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
res_json
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertIn
(
'status'
,
res_json
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
self
.
assertIn
(
'currently being created'
,
res_json
[
'status'
])
def
test_get_student_exam_results
(
self
):
def
test_get_student_exam_results
(
self
):
"""
"""
...
@@ -2778,19 +2801,19 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -2778,19 +2801,19 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
'get_proctored_exam_results'
,
'get_proctored_exam_results'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)}
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)}
)
)
# Successful case:
# Successful case:
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
res_json
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertIn
(
'status'
,
res_json
)
self
.
assertNotIn
(
'currently being created'
,
res_json
[
'status'
])
# CSV generation already in progress:
# CSV generation already in progress:
task_type
=
'proctored_exam_results_report'
already_running_status
=
generate_already_running_error_message
(
task_type
)
with
patch
(
'lms.djangoapps.instructor_task.api.submit_proctored_exam_results_report'
)
as
submit_task_function
:
with
patch
(
'lms.djangoapps.instructor_task.api.submit_proctored_exam_results_report'
)
as
submit_task_function
:
error
=
AlreadyRunningError
()
error
=
AlreadyRunningError
(
already_running_status
)
submit_task_function
.
side_effect
=
error
submit_task_function
.
side_effect
=
error
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
res_json
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertIn
(
'status'
,
res_json
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
self
.
assertIn
(
'currently being created'
,
res_json
[
'status'
])
def
test_access_course_finance_admin_with_invalid_course_key
(
self
):
def
test_access_course_finance_admin_with_invalid_course_key
(
self
):
"""
"""
...
@@ -3045,10 +3068,11 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -3045,10 +3068,11 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
def
test_executive_summary_report_success
(
def
test_executive_summary_report_success
(
self
,
self
,
report_type
,
report_type
,
task_type
,
instructor_api_endpoint
,
instructor_api_endpoint
,
task_api_endpoint
,
task_api_endpoint
,
extra_instructor_api_kwargs
extra_instructor_api_kwargs
):
):
# pylint: disable=unused-argument
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)}
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)}
kwargs
.
update
(
extra_instructor_api_kwargs
)
kwargs
.
update
(
extra_instructor_api_kwargs
)
url
=
reverse
(
instructor_api_endpoint
,
kwargs
=
kwargs
)
url
=
reverse
(
instructor_api_endpoint
,
kwargs
=
kwargs
)
...
@@ -3066,6 +3090,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -3066,6 +3090,7 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
def
test_executive_summary_report_already_running
(
def
test_executive_summary_report_already_running
(
self
,
self
,
report_type
,
report_type
,
task_type
,
instructor_api_endpoint
,
instructor_api_endpoint
,
task_api_endpoint
,
task_api_endpoint
,
extra_instructor_api_kwargs
extra_instructor_api_kwargs
...
@@ -3075,14 +3100,12 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -3075,14 +3100,12 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
url
=
reverse
(
instructor_api_endpoint
,
kwargs
=
kwargs
)
url
=
reverse
(
instructor_api_endpoint
,
kwargs
=
kwargs
)
CourseFinanceAdminRole
(
self
.
course
.
id
)
.
add_users
(
self
.
instructor
)
CourseFinanceAdminRole
(
self
.
course
.
id
)
.
add_users
(
self
.
instructor
)
already_running_status
=
generate_already_running_error_message
(
task_type
)
with
patch
(
task_api_endpoint
)
as
mock
:
with
patch
(
task_api_endpoint
)
as
mock
:
mock
.
side_effect
=
AlreadyRunningError
()
mock
.
side_effect
=
AlreadyRunningError
(
already_running_status
)
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
already_running_status
=
"The {report_type} report is currently being created."
\
" To view the status of the report, see Pending Tasks below."
\
self
.
assertEqual
(
response
.
status_code
,
400
)
" You will be able to download the report"
\
" when it is"
\
" complete."
.
format
(
report_type
=
report_type
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
def
test_get_ora2_responses_success
(
self
):
def
test_get_ora2_responses_success
(
self
):
...
@@ -3091,16 +3114,19 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
...
@@ -3091,16 +3114,19 @@ class TestInstructorAPILevelsDataDump(SharedModuleStoreTestCase, LoginEnrollment
with
patch
(
'lms.djangoapps.instructor_task.api.submit_export_ora2_data'
)
as
mock_submit_ora2_task
:
with
patch
(
'lms.djangoapps.instructor_task.api.submit_export_ora2_data'
)
as
mock_submit_ora2_task
:
mock_submit_ora2_task
.
return_value
=
True
mock_submit_ora2_task
.
return_value
=
True
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
success_status
=
"The ORA data report is being
gener
ated."
success_status
=
"The ORA data report is being
cre
ated."
self
.
assertIn
(
success_status
,
response
.
content
)
self
.
assertIn
(
success_status
,
response
.
content
)
def
test_get_ora2_responses_already_running
(
self
):
def
test_get_ora2_responses_already_running
(
self
):
url
=
reverse
(
'export_ora2_data'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
url
=
reverse
(
'export_ora2_data'
,
kwargs
=
{
'course_id'
:
unicode
(
self
.
course
.
id
)})
task_type
=
'export_ora2_data'
already_running_status
=
generate_already_running_error_message
(
task_type
)
with
patch
(
'lms.djangoapps.instructor_task.api.submit_export_ora2_data'
)
as
mock_submit_ora2_task
:
with
patch
(
'lms.djangoapps.instructor_task.api.submit_export_ora2_data'
)
as
mock_submit_ora2_task
:
mock_submit_ora2_task
.
side_effect
=
AlreadyRunningError
()
mock_submit_ora2_task
.
side_effect
=
AlreadyRunningError
(
already_running_status
)
response
=
self
.
client
.
post
(
url
,
{})
response
=
self
.
client
.
post
(
url
,
{})
already_running_status
=
"An ORA data report generation task is already in progress."
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
self
.
assertIn
(
already_running_status
,
response
.
content
)
def
test_get_student_progress_url
(
self
):
def
test_get_student_progress_url
(
self
):
...
...
lms/djangoapps/instructor/views/api.py
View file @
d1da0445
...
@@ -71,7 +71,7 @@ from lms.djangoapps.instructor.enrollment import (
...
@@ -71,7 +71,7 @@ from lms.djangoapps.instructor.enrollment import (
from
lms.djangoapps.instructor.views
import
INVOICE_KEY
from
lms.djangoapps.instructor.views
import
INVOICE_KEY
from
lms.djangoapps.instructor.views.instructor_task_helpers
import
extract_email_features
,
extract_task_features
from
lms.djangoapps.instructor.views.instructor_task_helpers
import
extract_email_features
,
extract_task_features
from
lms.djangoapps.instructor_task.api
import
submit_override_score
from
lms.djangoapps.instructor_task.api
import
submit_override_score
from
lms.djangoapps.instructor_task.api_helper
import
AlreadyRunningError
from
lms.djangoapps.instructor_task.api_helper
import
AlreadyRunningError
,
QueueConnectionError
from
lms.djangoapps.instructor_task.models
import
ReportStore
from
lms.djangoapps.instructor_task.models
import
ReportStore
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
openedx.core.djangoapps.course_groups.cohorts
import
is_course_cohorted
from
openedx.core.djangoapps.course_groups.cohorts
import
is_course_cohorted
...
@@ -133,29 +133,31 @@ log = logging.getLogger(__name__)
...
@@ -133,29 +133,31 @@ log = logging.getLogger(__name__)
TASK_SUBMISSION_OK
=
'created'
TASK_SUBMISSION_OK
=
'created'
SUCCESS_MESSAGE_TEMPLATE
=
_
(
"The {report_type} report is being created. "
"To view the status of the report, see Pending Tasks below."
)
def
common_exceptions_400
(
func
):
def
common_exceptions_400
(
func
):
"""
"""
Catches common exceptions and renders matching 400 errors.
Catches common exceptions and renders matching 400 errors.
(decorator without arguments)
(decorator without arguments)
"""
"""
def
wrapped
(
request
,
*
args
,
**
kwargs
):
# pylint: disable=missing-docstring
def
wrapped
(
request
,
*
args
,
**
kwargs
):
# pylint: disable=missing-docstring
use_json
=
(
request
.
is_ajax
()
or
use_json
=
(
request
.
is_ajax
()
or
request
.
META
.
get
(
"HTTP_ACCEPT"
,
""
)
.
startswith
(
"application/json"
))
request
.
META
.
get
(
"HTTP_ACCEPT"
,
""
)
.
startswith
(
"application/json"
))
try
:
try
:
return
func
(
request
,
*
args
,
**
kwargs
)
return
func
(
request
,
*
args
,
**
kwargs
)
except
User
.
DoesNotExist
:
except
User
.
DoesNotExist
:
message
=
_
(
"User does not exist."
)
message
=
_
(
'User does not exist.'
)
if
use_json
:
except
(
AlreadyRunningError
,
QueueConnectionError
)
as
err
:
return
JsonResponse
({
"error"
:
message
},
400
)
message
=
str
(
err
)
else
:
return
HttpResponseBadRequest
(
message
)
if
use_json
:
except
AlreadyRunningError
:
return
JsonResponseBadRequest
(
message
)
message
=
_
(
"Task is already running."
)
else
:
if
use_json
:
return
HttpResponseBadRequest
(
message
)
return
JsonResponse
({
"error"
:
message
},
400
)
else
:
return
HttpResponseBadRequest
(
message
)
return
wrapped
return
wrapped
...
@@ -829,12 +831,12 @@ def bulk_beta_modify_access(request, course_id):
...
@@ -829,12 +831,12 @@ def bulk_beta_modify_access(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'instructor'
)
@require_level
(
'instructor'
)
@common_exceptions_400
@require_post_params
(
@require_post_params
(
unique_student_identifier
=
"email or username of user to change access"
,
unique_student_identifier
=
"email or username of user to change access"
,
rolename
=
"'instructor', 'staff', 'beta', or 'ccx_coach'"
,
rolename
=
"'instructor', 'staff', 'beta', or 'ccx_coach'"
,
action
=
"'allow' or 'revoke'"
action
=
"'allow' or 'revoke'"
)
)
@common_exceptions_400
def
modify_access
(
request
,
course_id
):
def
modify_access
(
request
,
course_id
):
"""
"""
Modify staff/instructor access of other user.
Modify staff/instructor access of other user.
...
@@ -964,6 +966,7 @@ def list_course_role_members(request, course_id):
...
@@ -964,6 +966,7 @@ def list_course_role_members(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
get_problem_responses
(
request
,
course_id
):
def
get_problem_responses
(
request
,
course_id
):
"""
"""
Initiate generation of a CSV file containing all student answers
Initiate generation of a CSV file containing all student answers
...
@@ -978,6 +981,7 @@ def get_problem_responses(request, course_id):
...
@@ -978,6 +981,7 @@ def get_problem_responses(request, course_id):
"""
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
course_key
=
CourseKey
.
from_string
(
course_id
)
problem_location
=
request
.
POST
.
get
(
'problem_location'
,
''
)
problem_location
=
request
.
POST
.
get
(
'problem_location'
,
''
)
report_type
=
_
(
'problem responses'
)
try
:
try
:
problem_key
=
UsageKey
.
from_string
(
problem_location
)
problem_key
=
UsageKey
.
from_string
(
problem_location
)
...
@@ -990,20 +994,10 @@ def get_problem_responses(request, course_id):
...
@@ -990,20 +994,10 @@ def get_problem_responses(request, course_id):
except
InvalidKeyError
:
except
InvalidKeyError
:
return
JsonResponseBadRequest
(
_
(
"Could not find problem with this location."
))
return
JsonResponseBadRequest
(
_
(
"Could not find problem with this location."
))
try
:
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_problem_responses_csv
(
request
,
course_key
,
problem_location
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_problem_responses_csv
(
request
,
course_key
,
problem_location
)
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
success_status
=
_
(
"The problem responses report is being created."
return
JsonResponse
({
"status"
:
success_status
})
" To view the status of the report, see Pending Tasks below."
)
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"A problem responses report generation task is already in progress. "
"Check the 'Pending Tasks' table for the status of the task. "
"When completed, the report will be available for download in the table below."
)
return
JsonResponse
({
"status"
:
already_running_status
})
@require_POST
@require_POST
...
@@ -1209,6 +1203,7 @@ def get_issued_certificates(request, course_id):
...
@@ -1209,6 +1203,7 @@ def get_issued_certificates(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
get_students_features
(
request
,
course_id
,
csv
=
False
):
# pylint: disable=redefined-outer-name
def
get_students_features
(
request
,
course_id
,
csv
=
False
):
# pylint: disable=redefined-outer-name
"""
"""
Respond with json which contains a summary of all enrolled students profile information.
Respond with json which contains a summary of all enrolled students profile information.
...
@@ -1220,7 +1215,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
...
@@ -1220,7 +1215,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
"""
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
course_key
=
CourseKey
.
from_string
(
course_id
)
course
=
get_course_by_id
(
course_key
)
course
=
get_course_by_id
(
course_key
)
report_type
=
_
(
'enrolled learner profile'
)
available_features
=
instructor_analytics
.
basic
.
AVAILABLE_FEATURES
available_features
=
instructor_analytics
.
basic
.
AVAILABLE_FEATURES
# Allow for sites to be able to define additional columns.
# Allow for sites to be able to define additional columns.
...
@@ -1285,22 +1280,16 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
...
@@ -1285,22 +1280,16 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
'available_features'
:
available_features
,
'available_features'
:
available_features
,
}
}
return
JsonResponse
(
response_payload
)
return
JsonResponse
(
response_payload
)
else
:
else
:
try
:
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_students_features_csv
(
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_students_features_csv
(
request
,
request
,
course_key
,
course_key
,
query_features
query_features
)
)
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
success_status
=
_
(
"The enrolled learner profile report is being created."
" To view the status of the report, see Pending Tasks below."
)
return
JsonResponse
({
"status"
:
success_status
})
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"This enrollment report is currently being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
already_running_status
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -1308,6 +1297,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
...
@@ -1308,6 +1297,7 @@ def get_students_features(request, course_id, csv=False): # pylint: disable=red
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
get_students_who_may_enroll
(
request
,
course_id
):
def
get_students_who_may_enroll
(
request
,
course_id
):
"""
"""
Initiate generation of a CSV file containing information about
Initiate generation of a CSV file containing information about
...
@@ -1319,21 +1309,11 @@ def get_students_who_may_enroll(request, course_id):
...
@@ -1319,21 +1309,11 @@ def get_students_who_may_enroll(request, course_id):
"""
"""
course_key
=
CourseKey
.
from_string
(
course_id
)
course_key
=
CourseKey
.
from_string
(
course_id
)
query_features
=
[
'email'
]
query_features
=
[
'email'
]
try
:
report_type
=
_
(
'enrollment'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_may_enroll_csv
(
request
,
course_key
,
query_features
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_may_enroll_csv
(
request
,
course_key
,
query_features
)
success_status
=
_
(
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
"The enrollment report is being created. This report contains"
" information about learners who can enroll in the course."
return
JsonResponse
({
"status"
:
success_status
})
" To view the status of the report, see Pending Tasks below."
)
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"This enrollment report is currently being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
already_running_status
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -1341,6 +1321,7 @@ def get_students_who_may_enroll(request, course_id):
...
@@ -1341,6 +1321,7 @@ def get_students_who_may_enroll(request, course_id):
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_POST
@require_POST
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
add_users_to_cohorts
(
request
,
course_id
):
def
add_users_to_cohorts
(
request
,
course_id
):
"""
"""
View method that accepts an uploaded file (using key "uploaded-file")
View method that accepts an uploaded file (using key "uploaded-file")
...
@@ -1417,23 +1398,17 @@ def get_coupon_codes(request, course_id): # pylint: disable=unused-argument
...
@@ -1417,23 +1398,17 @@ def get_coupon_codes(request, course_id): # pylint: disable=unused-argument
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@require_finance_admin
@require_finance_admin
@common_exceptions_400
def
get_enrollment_report
(
request
,
course_id
):
def
get_enrollment_report
(
request
,
course_id
):
"""
"""
get the enrollment report for the particular course.
get the enrollment report for the particular course.
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
report_type
=
_
(
'detailed enrollment'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_detailed_enrollment_features_csv
(
request
,
course_key
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_detailed_enrollment_features_csv
(
request
,
course_key
)
success_status
=
_
(
"The detailed enrollment report is being created."
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
" To view the status of the report, see Pending Tasks below."
)
return
JsonResponse
({
"status"
:
success_status
})
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"The detailed enrollment report is being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
already_running_status
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -1442,24 +1417,17 @@ def get_enrollment_report(request, course_id):
...
@@ -1442,24 +1417,17 @@ def get_enrollment_report(request, course_id):
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@require_finance_admin
@require_finance_admin
@common_exceptions_400
def
get_exec_summary_report
(
request
,
course_id
):
def
get_exec_summary_report
(
request
,
course_id
):
"""
"""
get the executive summary report for the particular course.
get the executive summary report for the particular course.
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
report_type
=
_
(
'executive summary'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_executive_summary_report
(
request
,
course_key
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_executive_summary_report
(
request
,
course_key
)
status_response
=
_
(
"The executive summary report is being created."
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
" To view the status of the report, see Pending Tasks below."
)
except
AlreadyRunningError
:
return
JsonResponse
({
"status"
:
success_status
})
status_response
=
_
(
"The executive summary report is currently being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
status_response
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -1467,24 +1435,17 @@ def get_exec_summary_report(request, course_id):
...
@@ -1467,24 +1435,17 @@ def get_exec_summary_report(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
get_course_survey_results
(
request
,
course_id
):
def
get_course_survey_results
(
request
,
course_id
):
"""
"""
get the survey results report for the particular course.
get the survey results report for the particular course.
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
report_type
=
_
(
'survey'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_course_survey_report
(
request
,
course_key
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_course_survey_report
(
request
,
course_key
)
status_response
=
_
(
"The survey report is being created."
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
" To view the status of the report, see Pending Tasks below."
)
except
AlreadyRunningError
:
return
JsonResponse
({
"status"
:
success_status
})
status_response
=
_
(
"The survey report is currently being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
status_response
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -1492,6 +1453,7 @@ def get_course_survey_results(request, course_id):
...
@@ -1492,6 +1453,7 @@ def get_course_survey_results(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
get_proctored_exam_results
(
request
,
course_id
):
def
get_proctored_exam_results
(
request
,
course_id
):
"""
"""
get the proctored exam resultsreport for the particular course.
get the proctored exam resultsreport for the particular course.
...
@@ -1508,19 +1470,11 @@ def get_proctored_exam_results(request, course_id):
...
@@ -1508,19 +1470,11 @@ def get_proctored_exam_results(request, course_id):
]
]
course_key
=
CourseKey
.
from_string
(
course_id
)
course_key
=
CourseKey
.
from_string
(
course_id
)
try
:
report_type
=
_
(
'proctored exam results'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_proctored_exam_results_report
(
request
,
course_key
,
query_features
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_proctored_exam_results_report
(
request
,
course_key
,
query_features
)
status_response
=
_
(
"The proctored exam results report is being created."
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
" To view the status of the report, see Pending Tasks below."
)
except
AlreadyRunningError
:
return
JsonResponse
({
"status"
:
success_status
})
status_response
=
_
(
"The proctored exam results report is currently being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
status_response
})
def
save_registration_code
(
user
,
course_id
,
mode_slug
,
invoice
=
None
,
order
=
None
,
invoice_item
=
None
):
def
save_registration_code
(
user
,
course_id
,
mode_slug
,
invoice
=
None
,
order
=
None
,
invoice_item
=
None
):
...
@@ -1901,11 +1855,11 @@ def get_anon_ids(request, course_id): # pylint: disable=unused-argument
...
@@ -1901,11 +1855,11 @@ def get_anon_ids(request, course_id): # pylint: disable=unused-argument
@require_POST
@require_POST
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@common_exceptions_400
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@require_post_params
(
@require_post_params
(
unique_student_identifier
=
"email or username of student for whom to get progress url"
unique_student_identifier
=
"email or username of student for whom to get progress url"
)
)
@common_exceptions_400
def
get_student_progress_url
(
request
,
course_id
):
def
get_student_progress_url
(
request
,
course_id
):
"""
"""
Get the progress url of a student.
Get the progress url of a student.
...
@@ -2147,6 +2101,7 @@ def rescore_problem(request, course_id):
...
@@ -2147,6 +2101,7 @@ def rescore_problem(request, course_id):
)
)
except
NotImplementedError
as
exc
:
except
NotImplementedError
as
exc
:
return
HttpResponseBadRequest
(
exc
.
message
)
return
HttpResponseBadRequest
(
exc
.
message
)
elif
all_students
:
elif
all_students
:
try
:
try
:
lms
.
djangoapps
.
instructor_task
.
api
.
submit_rescore_problem_for_all_students
(
lms
.
djangoapps
.
instructor_task
.
api
.
submit_rescore_problem_for_all_students
(
...
@@ -2453,25 +2408,17 @@ def list_financial_report_downloads(_request, course_id):
...
@@ -2453,25 +2408,17 @@ def list_financial_report_downloads(_request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
export_ora2_data
(
request
,
course_id
):
def
export_ora2_data
(
request
,
course_id
):
"""
"""
Pushes a Celery task which will aggregate ora2 responses for a course into a .csv
Pushes a Celery task which will aggregate ora2 responses for a course into a .csv
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
report_type
=
_
(
'ORA data'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_export_ora2_data
(
request
,
course_key
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_export_ora2_data
(
request
,
course_key
)
success_status
=
_
(
"The ORA data report is being generated."
)
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"An ORA data report generation task is already in "
"progress. Check the 'Pending Tasks' table "
"for the status of the task. When completed, the report "
"will be available for download in the table below."
)
return
JsonResponse
({
"status"
:
already_running
_status
})
return
JsonResponse
({
"status"
:
success
_status
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -2479,21 +2426,17 @@ def export_ora2_data(request, course_id):
...
@@ -2479,21 +2426,17 @@ def export_ora2_data(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
calculate_grades_csv
(
request
,
course_id
):
def
calculate_grades_csv
(
request
,
course_id
):
"""
"""
AlreadyRunningError is raised if the course's grades are already being updated.
AlreadyRunningError is raised if the course's grades are already being updated.
"""
"""
report_type
=
_
(
'grade'
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_grades_csv
(
request
,
course_key
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_calculate_grades_csv
(
request
,
course_key
)
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
success_status
=
_
(
"The grade report is being created."
" To view the status of the report, see Pending Tasks below."
)
return
JsonResponse
({
"status"
:
success_status
})
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"The grade report is currently being created."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
already_running_status
})
@transaction.non_atomic_requests
@transaction.non_atomic_requests
...
@@ -2501,6 +2444,7 @@ def calculate_grades_csv(request, course_id):
...
@@ -2501,6 +2444,7 @@ def calculate_grades_csv(request, course_id):
@ensure_csrf_cookie
@ensure_csrf_cookie
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@common_exceptions_400
def
problem_grade_report
(
request
,
course_id
):
def
problem_grade_report
(
request
,
course_id
):
"""
"""
Request a CSV showing students' grades for all problems in the
Request a CSV showing students' grades for all problems in the
...
@@ -2510,18 +2454,11 @@ def problem_grade_report(request, course_id):
...
@@ -2510,18 +2454,11 @@ def problem_grade_report(request, course_id):
updated.
updated.
"""
"""
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
course_key
=
SlashSeparatedCourseKey
.
from_deprecated_string
(
course_id
)
try
:
report_type
=
_
(
'problem grade'
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_problem_grade_report
(
request
,
course_key
)
lms
.
djangoapps
.
instructor_task
.
api
.
submit_problem_grade_report
(
request
,
course_key
)
success_status
=
_
(
"The problem grade report is being created."
success_status
=
SUCCESS_MESSAGE_TEMPLATE
.
format
(
report_type
=
report_type
)
" To view the status of the report, see Pending Tasks below."
)
return
JsonResponse
({
"status"
:
success_status
})
return
JsonResponse
({
"status"
:
success_status
})
except
AlreadyRunningError
:
already_running_status
=
_
(
"A problem grade report is already being generated."
" To view the status of the report, see Pending Tasks below."
" You will be able to download the report when it is complete."
)
return
JsonResponse
({
"status"
:
already_running_status
})
@require_POST
@require_POST
...
@@ -2601,6 +2538,7 @@ def list_forum_members(request, course_id):
...
@@ -2601,6 +2538,7 @@ def list_forum_members(request, course_id):
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_level
(
'staff'
)
@require_level
(
'staff'
)
@require_post_params
(
send_to
=
"sending to whom"
,
subject
=
"subject line"
,
message
=
"message text"
)
@require_post_params
(
send_to
=
"sending to whom"
,
subject
=
"subject line"
,
message
=
"message text"
)
@common_exceptions_400
def
send_email
(
request
,
course_id
):
def
send_email
(
request
,
course_id
):
"""
"""
Send an email to self, staff, cohorts, or everyone involved in a course.
Send an email to self, staff, cohorts, or everyone involved in a course.
...
@@ -2667,6 +2605,7 @@ def send_email(request, course_id):
...
@@ -2667,6 +2605,7 @@ def send_email(request, course_id):
'course_id'
:
course_id
.
to_deprecated_string
(),
'course_id'
:
course_id
.
to_deprecated_string
(),
'success'
:
True
,
'success'
:
True
,
}
}
return
JsonResponse
(
response_payload
)
return
JsonResponse
(
response_payload
)
...
@@ -2944,6 +2883,7 @@ def mark_student_can_skip_entrance_exam(request, course_id): # pylint: disable=
...
@@ -2944,6 +2883,7 @@ def mark_student_can_skip_entrance_exam(request, course_id): # pylint: disable=
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_global_staff
@require_global_staff
@require_POST
@require_POST
@common_exceptions_400
def
start_certificate_generation
(
request
,
course_id
):
def
start_certificate_generation
(
request
,
course_id
):
"""
"""
Start generating certificates for all students enrolled in given course.
Start generating certificates for all students enrolled in given course.
...
@@ -2956,6 +2896,7 @@ def start_certificate_generation(request, course_id):
...
@@ -2956,6 +2896,7 @@ def start_certificate_generation(request, course_id):
'message'
:
message
,
'message'
:
message
,
'task_id'
:
task
.
task_id
'task_id'
:
task
.
task_id
}
}
return
JsonResponse
(
response_payload
)
return
JsonResponse
(
response_payload
)
...
@@ -2964,6 +2905,7 @@ def start_certificate_generation(request, course_id):
...
@@ -2964,6 +2905,7 @@ def start_certificate_generation(request, course_id):
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_global_staff
@require_global_staff
@require_POST
@require_POST
@common_exceptions_400
def
start_certificate_regeneration
(
request
,
course_id
):
def
start_certificate_regeneration
(
request
,
course_id
):
"""
"""
Start regenerating certificates for students whose certificate statuses lie with in 'certificate_statuses'
Start regenerating certificates for students whose certificate statuses lie with in 'certificate_statuses'
...
@@ -2990,11 +2932,8 @@ def start_certificate_regeneration(request, course_id):
...
@@ -2990,11 +2932,8 @@ def start_certificate_regeneration(request, course_id):
{
'message'
:
_
(
'Please select certificate statuses from the list only.'
)},
{
'message'
:
_
(
'Please select certificate statuses from the list only.'
)},
status
=
400
status
=
400
)
)
try
:
lms
.
djangoapps
.
instructor_task
.
api
.
regenerate_certificates
(
request
,
course_key
,
certificates_statuses
)
except
AlreadyRunningError
as
error
:
return
JsonResponse
({
'message'
:
error
.
message
},
status
=
400
)
lms
.
djangoapps
.
instructor_task
.
api
.
regenerate_certificates
(
request
,
course_key
,
certificates_statuses
)
response_payload
=
{
response_payload
=
{
'message'
:
_
(
'Certificate regeneration task has been started. '
'message'
:
_
(
'Certificate regeneration task has been started. '
'You can view the status of the generation task in the "Pending Tasks" section.'
),
'You can view the status of the generation task in the "Pending Tasks" section.'
),
...
@@ -3183,6 +3122,7 @@ def get_student(username_or_email, course_key):
...
@@ -3183,6 +3122,7 @@ def get_student(username_or_email, course_key):
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@cache_control
(
no_cache
=
True
,
no_store
=
True
,
must_revalidate
=
True
)
@require_global_staff
@require_global_staff
@require_POST
@require_POST
@common_exceptions_400
def
generate_certificate_exceptions
(
request
,
course_id
,
generate_for
=
None
):
def
generate_certificate_exceptions
(
request
,
course_id
,
generate_for
=
None
):
"""
"""
Generate Certificate for students in the Certificate White List.
Generate Certificate for students in the Certificate White List.
...
@@ -3213,7 +3153,6 @@ def generate_certificate_exceptions(request, course_id, generate_for=None):
...
@@ -3213,7 +3153,6 @@ def generate_certificate_exceptions(request, course_id, generate_for=None):
)
)
lms
.
djangoapps
.
instructor_task
.
api
.
generate_certificates_for_students
(
request
,
course_key
,
student_set
=
students
)
lms
.
djangoapps
.
instructor_task
.
api
.
generate_certificates_for_students
(
request
,
course_key
,
student_set
=
students
)
response_payload
=
{
response_payload
=
{
'success'
:
True
,
'success'
:
True
,
'message'
:
_
(
'Certificate generation started for white listed students.'
),
'message'
:
_
(
'Certificate generation started for white listed students.'
),
...
@@ -3401,6 +3340,7 @@ def invalidate_certificate(request, generated_certificate, certificate_invalidat
...
@@ -3401,6 +3340,7 @@ def invalidate_certificate(request, generated_certificate, certificate_invalidat
}
}
@common_exceptions_400
def
re_validate_certificate
(
request
,
course_key
,
generated_certificate
):
def
re_validate_certificate
(
request
,
course_key
,
generated_certificate
):
"""
"""
Remove certificate invalidation from db and start certificate generation task for this student.
Remove certificate invalidation from db and start certificate generation task for this student.
...
@@ -3421,6 +3361,7 @@ def re_validate_certificate(request, course_key, generated_certificate):
...
@@ -3421,6 +3361,7 @@ def re_validate_certificate(request, course_key, generated_certificate):
# We need to generate certificate only for a single student here
# We need to generate certificate only for a single student here
student
=
certificate_invalidation
.
generated_certificate
.
user
student
=
certificate_invalidation
.
generated_certificate
.
user
lms
.
djangoapps
.
instructor_task
.
api
.
generate_certificates_for_students
(
lms
.
djangoapps
.
instructor_task
.
api
.
generate_certificates_for_students
(
request
,
course_key
,
student_set
=
"specific_student"
,
specific_student_id
=
student
.
id
request
,
course_key
,
student_set
=
"specific_student"
,
specific_student_id
=
student
.
id
)
)
...
...
lms/djangoapps/instructor_task/api_helper.py
View file @
d1da0445
...
@@ -25,7 +25,26 @@ log = logging.getLogger(__name__)
...
@@ -25,7 +25,26 @@ log = logging.getLogger(__name__)
class
AlreadyRunningError
(
Exception
):
class
AlreadyRunningError
(
Exception
):
"""Exception indicating that a background task is already running"""
"""Exception indicating that a background task is already running"""
pass
message
=
_
(
'Requested task is already running'
)
def
__init__
(
self
,
message
=
None
):
if
not
message
:
message
=
self
.
message
super
(
AlreadyRunningError
,
self
)
.
__init__
(
message
)
class
QueueConnectionError
(
Exception
):
"""
Exception indicating that celery task was not created successfully.
"""
message
=
_
(
'Error occured. Please try again later.'
)
def
__init__
(
self
,
message
=
None
):
if
not
message
:
message
=
self
.
message
super
(
QueueConnectionError
,
self
)
.
__init__
(
message
)
def
_task_is_running
(
course_id
,
task_type
,
task_key
):
def
_task_is_running
(
course_id
,
task_type
,
task_key
):
...
@@ -57,7 +76,8 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester):
...
@@ -57,7 +76,8 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester):
if
_task_is_running
(
course_id
,
task_type
,
task_key
):
if
_task_is_running
(
course_id
,
task_type
,
task_key
):
log
.
warning
(
"Duplicate task found for task_type
%
s and task_key
%
s"
,
task_type
,
task_key
)
log
.
warning
(
"Duplicate task found for task_type
%
s and task_key
%
s"
,
task_type
,
task_key
)
raise
AlreadyRunningError
(
"requested task is already running"
)
error_message
=
generate_already_running_error_message
(
task_type
)
raise
AlreadyRunningError
(
error_message
)
try
:
try
:
most_recent_id
=
InstructorTask
.
objects
.
latest
(
'id'
)
.
id
most_recent_id
=
InstructorTask
.
objects
.
latest
(
'id'
)
.
id
...
@@ -75,6 +95,37 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester):
...
@@ -75,6 +95,37 @@ def _reserve_task(course_id, task_type, task_key, task_input, requester):
return
InstructorTask
.
create
(
course_id
,
task_type
,
task_key
,
task_input
,
requester
)
return
InstructorTask
.
create
(
course_id
,
task_type
,
task_key
,
task_input
,
requester
)
def
generate_already_running_error_message
(
task_type
):
"""
Returns already running error message for given task type.
"""
message
=
''
report_types
=
{
'grade_problems'
:
_
(
'problem grade'
),
'problem_responses_csv'
:
_
(
'problem responses'
),
'profile_info_csv'
:
_
(
'enrolled learner profile'
),
'may_enroll_info_csv'
:
_
(
'enrollment'
),
'detailed_enrollment_report'
:
_
(
'detailed enrollment'
),
'exec_summary_report'
:
_
(
'executive summary'
),
'course_survey_report'
:
_
(
'survey'
),
'proctored_exam_results_report'
:
_
(
'proctored exam results'
),
'export_ora2_data'
:
_
(
'ORA data'
),
'grade_course'
:
_
(
'grade'
),
}
if
report_types
.
get
(
task_type
):
message
=
_
(
"The {report_type} report is being created. "
"To view the status of the report, see Pending Tasks below. "
"You will be able to download the report when it is complete."
)
.
format
(
report_type
=
report_types
.
get
(
task_type
))
return
message
def
_get_xmodule_instance_args
(
request
,
task_id
):
def
_get_xmodule_instance_args
(
request
,
task_id
):
"""
"""
Calculate parameters needed for instantiating xmodule instances.
Calculate parameters needed for instantiating xmodule instances.
...
@@ -190,6 +241,27 @@ def _update_instructor_task(instructor_task, task_result):
...
@@ -190,6 +241,27 @@ def _update_instructor_task(instructor_task, task_result):
instructor_task
.
save
()
instructor_task
.
save
()
def
_update_instructor_task_state
(
instructor_task
,
task_state
,
message
=
None
):
"""
Update state and output of InstructorTask object.
"""
instructor_task
.
task_state
=
task_state
if
message
:
instructor_task
.
task_output
=
message
instructor_task
.
save
()
def
_handle_instructor_task_failure
(
instructor_task
,
error
):
"""
Do required operations if task creation was not complete.
"""
log
.
info
(
"instructor task (
%
s) failed, result:
%
s"
,
instructor_task
.
task_id
,
error
.
message
)
_update_instructor_task_state
(
instructor_task
,
FAILURE
,
error
.
message
)
raise
QueueConnectionError
()
def
get_updated_instructor_task
(
task_id
):
def
get_updated_instructor_task
(
task_id
):
"""
"""
Returns InstructorTask object corresponding to a given `task_id`.
Returns InstructorTask object corresponding to a given `task_id`.
...
@@ -365,6 +437,10 @@ def submit_task(request, task_type, task_class, course_key, task_input, task_key
...
@@ -365,6 +437,10 @@ def submit_task(request, task_type, task_class, course_key, task_input, task_key
task_id
=
instructor_task
.
task_id
task_id
=
instructor_task
.
task_id
task_args
=
[
instructor_task
.
id
,
_get_xmodule_instance_args
(
request
,
task_id
)]
task_args
=
[
instructor_task
.
id
,
_get_xmodule_instance_args
(
request
,
task_id
)]
task_class
.
apply_async
(
task_args
,
task_id
=
task_id
)
try
:
task_class
.
apply_async
(
task_args
,
task_id
=
task_id
)
except
Exception
as
error
:
_handle_instructor_task_failure
(
instructor_task
,
error
)
return
instructor_task
return
instructor_task
lms/djangoapps/instructor_task/tests/test_api.py
View file @
d1da0445
...
@@ -32,7 +32,7 @@ from lms.djangoapps.instructor_task.api import (
...
@@ -32,7 +32,7 @@ from lms.djangoapps.instructor_task.api import (
submit_reset_problem_attempts_for_all_students
,
submit_reset_problem_attempts_for_all_students
,
submit_reset_problem_attempts_in_entrance_exam
submit_reset_problem_attempts_in_entrance_exam
)
)
from
lms.djangoapps.instructor_task.api_helper
import
AlreadyRunningError
from
lms.djangoapps.instructor_task.api_helper
import
AlreadyRunningError
,
QueueConnectionError
from
lms.djangoapps.instructor_task.models
import
PROGRESS
,
InstructorTask
from
lms.djangoapps.instructor_task.models
import
PROGRESS
,
InstructorTask
from
lms.djangoapps.instructor_task.tasks
import
export_ora2_data
from
lms.djangoapps.instructor_task.tasks
import
export_ora2_data
from
lms.djangoapps.instructor_task.tests.test_base
import
(
from
lms.djangoapps.instructor_task.tests.test_base
import
(
...
@@ -43,6 +43,7 @@ from lms.djangoapps.instructor_task.tests.test_base import (
...
@@ -43,6 +43,7 @@ from lms.djangoapps.instructor_task.tests.test_base import (
TestReportMixin
TestReportMixin
)
)
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
xmodule.modulestore.exceptions
import
ItemNotFoundError
from
celery.states
import
FAILURE
class
InstructorTaskReportTest
(
InstructorTaskTestCase
):
class
InstructorTaskReportTest
(
InstructorTaskTestCase
):
...
@@ -164,15 +165,31 @@ class InstructorTaskModuleSubmitTest(InstructorTaskModuleTestCase):
...
@@ -164,15 +165,31 @@ class InstructorTaskModuleSubmitTest(InstructorTaskModuleTestCase):
)
)
@ddt.unpack
@ddt.unpack
def
test_submit_task
(
self
,
task_function
,
expected_task_type
,
params
=
None
):
def
test_submit_task
(
self
,
task_function
,
expected_task_type
,
params
=
None
):
"""
Tests submission of instructor task.
"""
if
params
is
None
:
if
params
is
None
:
params
=
{}
params
=
{}
if
params
.
get
(
'student'
):
if
params
.
get
(
'student'
):
params
[
'student'
]
=
self
.
student
params
[
'student'
]
=
self
.
student
# tests submit, and then tests a second identical submission.
problem_url_name
=
'H1P1'
problem_url_name
=
'H1P1'
self
.
define_option_problem
(
problem_url_name
)
self
.
define_option_problem
(
problem_url_name
)
location
=
InstructorTaskModuleTestCase
.
problem_location
(
problem_url_name
)
location
=
InstructorTaskModuleTestCase
.
problem_location
(
problem_url_name
)
# unsuccessful submission, exception raised while submitting.
with
patch
(
'lms.djangoapps.instructor_task.tasks_base.BaseInstructorTask.apply_async'
)
as
apply_async
:
error
=
Exception
()
apply_async
.
side_effect
=
error
with
self
.
assertRaises
(
QueueConnectionError
):
instructor_task
=
task_function
(
self
.
create_task_request
(
self
.
instructor
),
location
,
**
params
)
most_recent_task
=
InstructorTask
.
objects
.
latest
(
'id'
)
self
.
assertEquals
(
most_recent_task
.
task_state
,
FAILURE
)
# successful submission
instructor_task
=
task_function
(
self
.
create_task_request
(
self
.
instructor
),
location
,
**
params
)
instructor_task
=
task_function
(
self
.
create_task_request
(
self
.
instructor
),
location
,
**
params
)
self
.
assertEquals
(
instructor_task
.
task_type
,
expected_task_type
)
self
.
assertEquals
(
instructor_task
.
task_type
,
expected_task_type
)
...
...
lms/static/js/instructor_dashboard/data_download.js
View file @
d1da0445
...
@@ -122,16 +122,18 @@
...
@@ -122,16 +122,18 @@
});
});
this
.
$proctored_exam_csv_btn
.
click
(
function
()
{
this
.
$proctored_exam_csv_btn
.
click
(
function
()
{
var
url
=
dataDownloadObj
.
$proctored_exam_csv_btn
.
data
(
'endpoint'
);
var
url
=
dataDownloadObj
.
$proctored_exam_csv_btn
.
data
(
'endpoint'
);
var
errorMessage
=
gettext
(
'Error generating proctored exam results. Please try again.'
);
return
$
.
ajax
({
return
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
dataType
:
'json'
,
dataType
:
'json'
,
url
:
url
,
url
:
url
,
error
:
function
()
{
error
:
function
(
error
)
{
if
(
error
.
responseText
)
{
errorMessage
=
JSON
.
parse
(
error
.
responseText
);
}
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
$reports_request_response_error
.
text
(
dataDownloadObj
.
$reports_request_response_error
.
text
(
errorMessage
);
gettext
(
'Error generating proctored exam results. Please try again.'
)
return
dataDownloadObj
.
$reports_request_response_error
.
css
({
);
return
$
(
'.msg-error'
).
css
({
display
:
'block'
display
:
'block'
});
});
},
},
...
@@ -146,16 +148,18 @@
...
@@ -146,16 +148,18 @@
});
});
this
.
$survey_results_csv_btn
.
click
(
function
()
{
this
.
$survey_results_csv_btn
.
click
(
function
()
{
var
url
=
dataDownloadObj
.
$survey_results_csv_btn
.
data
(
'endpoint'
);
var
url
=
dataDownloadObj
.
$survey_results_csv_btn
.
data
(
'endpoint'
);
var
errorMessage
=
gettext
(
'Error generating survey results. Please try again.'
);
return
$
.
ajax
({
return
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
dataType
:
'json'
,
dataType
:
'json'
,
url
:
url
,
url
:
url
,
error
:
function
()
{
error
:
function
(
error
)
{
if
(
error
.
responseText
)
{
errorMessage
=
JSON
.
parse
(
error
.
responseText
);
}
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
$reports_request_response_error
.
text
(
dataDownloadObj
.
$reports_request_response_error
.
text
(
errorMessage
);
gettext
(
'Error generating survey results. Please try again.'
)
return
dataDownloadObj
.
$reports_request_response_error
.
css
({
);
return
$
(
'.msg-error'
).
css
({
display
:
'block'
display
:
'block'
});
});
},
},
...
@@ -170,16 +174,18 @@
...
@@ -170,16 +174,18 @@
});
});
this
.
$list_studs_csv_btn
.
click
(
function
()
{
this
.
$list_studs_csv_btn
.
click
(
function
()
{
var
url
=
dataDownloadObj
.
$list_studs_csv_btn
.
data
(
'endpoint'
)
+
'/csv'
;
var
url
=
dataDownloadObj
.
$list_studs_csv_btn
.
data
(
'endpoint'
)
+
'/csv'
;
var
errorMessage
=
gettext
(
'Error generating student profile information. Please try again.'
);
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
return
$
.
ajax
({
return
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
dataType
:
'json'
,
dataType
:
'json'
,
url
:
url
,
url
:
url
,
error
:
function
()
{
error
:
function
(
error
)
{
dataDownloadObj
.
$reports_request_response_error
.
text
(
if
(
error
.
responseText
)
{
gettext
(
'Error generating student profile information. Please try again.'
)
errorMessage
=
JSON
.
parse
(
error
.
responseText
);
);
}
return
$
(
'.msg-error'
).
css
({
dataDownloadObj
.
$reports_request_response_error
.
text
(
errorMessage
);
return
dataDownloadObj
.
$reports_request_response_error
.
css
({
display
:
'block'
display
:
'block'
});
});
},
},
...
@@ -201,9 +207,13 @@
...
@@ -201,9 +207,13 @@
url
:
url
,
url
:
url
,
error
:
function
()
{
error
:
function
()
{
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
return
dataDownloadObj
.
$download_request_response_error
.
text
(
dataDownloadObj
.
$download_request_response_error
.
text
(
gettext
(
'Error getting student list.'
)
gettext
(
'Error getting student list.'
)
);
);
return
dataDownloadObj
.
$download_request_response_error
.
css
({
display
:
'block'
});
},
},
success
:
function
(
data
)
{
success
:
function
(
data
)
{
var
$tablePlaceholder
,
columns
,
feature
,
gridData
,
options
;
var
$tablePlaceholder
,
columns
,
feature
,
gridData
,
options
;
...
@@ -251,7 +261,7 @@
...
@@ -251,7 +261,7 @@
dataDownloadObj
.
$reports_request_response_error
.
text
(
dataDownloadObj
.
$reports_request_response_error
.
text
(
JSON
.
parse
(
error
.
responseText
)
JSON
.
parse
(
error
.
responseText
)
);
);
return
$
(
'.msg-error'
)
.
css
({
return
dataDownloadObj
.
$reports_request_response_error
.
css
({
display
:
'block'
display
:
'block'
});
});
},
},
...
@@ -265,16 +275,18 @@
...
@@ -265,16 +275,18 @@
});
});
this
.
$list_may_enroll_csv_btn
.
click
(
function
()
{
this
.
$list_may_enroll_csv_btn
.
click
(
function
()
{
var
url
=
dataDownloadObj
.
$list_may_enroll_csv_btn
.
data
(
'endpoint'
);
var
url
=
dataDownloadObj
.
$list_may_enroll_csv_btn
.
data
(
'endpoint'
);
var
errorMessage
=
gettext
(
'Error generating list of students who may enroll. Please try again.'
);
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
return
$
.
ajax
({
return
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
dataType
:
'json'
,
dataType
:
'json'
,
url
:
url
,
url
:
url
,
error
:
function
()
{
error
:
function
(
error
)
{
dataDownloadObj
.
$reports_request_response_error
.
text
(
if
(
error
.
responseText
)
{
gettext
(
'Error generating list of students who may enroll. Please try again.'
)
errorMessage
=
JSON
.
parse
(
error
.
responseText
);
);
}
return
$
(
'.msg-error'
).
css
({
dataDownloadObj
.
$reports_request_response_error
.
text
(
errorMessage
);
return
dataDownloadObj
.
$reports_request_response_error
.
css
({
display
:
'block'
display
:
'block'
});
});
},
},
...
@@ -294,9 +306,12 @@
...
@@ -294,9 +306,12 @@
url
:
url
,
url
:
url
,
error
:
function
()
{
error
:
function
()
{
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
return
dataDownloadObj
.
$download_request_response_error
.
text
(
dataDownloadObj
.
$download_request_response_error
.
text
(
gettext
(
'Error retrieving grading configuration.'
)
gettext
(
'Error retrieving grading configuration.'
)
);
);
return
dataDownloadObj
.
$download_request_response_error
.
css
({
display
:
'block'
});
},
},
success
:
function
(
data
)
{
success
:
function
(
data
)
{
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
...
@@ -307,29 +322,27 @@
...
@@ -307,29 +322,27 @@
});
});
this
.
$async_report_btn
.
click
(
function
(
e
)
{
this
.
$async_report_btn
.
click
(
function
(
e
)
{
var
url
=
$
(
e
.
target
).
data
(
'endpoint'
);
var
url
=
$
(
e
.
target
).
data
(
'endpoint'
);
var
errorMessage
=
''
;
dataDownloadObj
.
clear_display
();
dataDownloadObj
.
clear_display
();
return
$
.
ajax
({
return
$
.
ajax
({
type
:
'POST'
,
type
:
'POST'
,
dataType
:
'json'
,
dataType
:
'json'
,
url
:
url
,
url
:
url
,
error
:
statusAjaxError
(
function
(
)
{
error
:
function
(
error
)
{
if
(
e
.
target
.
name
===
'calculate-grades-csv'
)
{
if
(
e
rror
.
responseText
)
{
dataDownloadObj
.
$grades_request_response_error
.
text
(
errorMessage
=
JSON
.
parse
(
error
.
responseText
);
gettext
(
'Error generating grades. Please try again.'
)
}
else
if
(
e
.
target
.
name
===
'calculate-grades-csv'
)
{
);
errorMessage
=
gettext
(
'Error generating grades. Please try again.'
);
}
else
if
(
e
.
target
.
name
===
'problem-grade-report'
)
{
}
else
if
(
e
.
target
.
name
===
'problem-grade-report'
)
{
dataDownloadObj
.
$grades_request_response_error
.
text
(
errorMessage
=
gettext
(
'Error generating problem grade report. Please try again.'
);
gettext
(
'Error generating problem grade report. Please try again.'
)
);
}
else
if
(
e
.
target
.
name
===
'export-ora2-data'
)
{
}
else
if
(
e
.
target
.
name
===
'export-ora2-data'
)
{
dataDownloadObj
.
$grades_request_response_error
.
text
(
errorMessage
=
gettext
(
'Error generating ORA data report. Please try again.'
);
gettext
(
'Error generating ORA data report. Please try again.'
)
);
}
}
return
$
(
'.msg-error'
).
css
({
dataDownloadObj
.
$reports_request_response_error
.
text
(
errorMessage
);
return
dataDownloadObj
.
$reports_request_response_error
.
css
({
display
:
'block'
display
:
'block'
});
});
}
)
,
},
success
:
function
(
data
)
{
success
:
function
(
data
)
{
dataDownloadObj
.
$reports_request_response
.
text
(
data
.
status
);
dataDownloadObj
.
$reports_request_response
.
text
(
data
.
status
);
return
$
(
'.msg-confirm'
).
css
({
return
$
(
'.msg-confirm'
).
css
({
...
...
lms/static/js/spec/staff_debug_actions_spec.js
View file @
d1da0445
...
@@ -96,7 +96,7 @@ define([
...
@@ -96,7 +96,7 @@ define([
error_msg
:
'Failed to reset attempts for user.'
error_msg
:
'Failed to reset attempts for user.'
};
};
StaffDebug
.
doInstructorDashAction
(
action
);
StaffDebug
.
doInstructorDashAction
(
action
);
AjaxHelpers
.
respondWithError
(
requests
);
AjaxHelpers
.
respondWith
Text
Error
(
requests
);
expect
(
$
(
'#idash_msg'
).
text
()).
toBe
(
'Failed to reset attempts for user. '
);
expect
(
$
(
'#idash_msg'
).
text
()).
toBe
(
'Failed to reset attempts for user. '
);
$
(
'#result_'
+
locationName
).
remove
();
$
(
'#result_'
+
locationName
).
remove
();
});
});
...
...
lms/static/js/staff_debug_actions.js
View file @
d1da0445
...
@@ -54,12 +54,12 @@ var StaffDebug = (function() {
...
@@ -54,12 +54,12 @@ var StaffDebug = (function() {
try
{
try
{
responseJSON
=
$
.
parseJSON
(
request
.
responseText
);
responseJSON
=
$
.
parseJSON
(
request
.
responseText
);
}
catch
(
e
)
{
}
catch
(
e
)
{
responseJSON
=
{
error
:
gettext
(
'Unknown Error Occurred.'
)}
;
responseJSON
=
'Unknown Error Occurred.'
;
}
}
var
text
=
_
.
template
(
'{error_msg} {error}'
,
{
interpolate
:
/
\{(
.+
?)\}
/g
})(
var
text
=
_
.
template
(
'{error_msg} {error}'
,
{
interpolate
:
/
\{(
.+
?)\}
/g
})(
{
{
error_msg
:
action
.
error_msg
,
error_msg
:
action
.
error_msg
,
error
:
responseJSON
.
error
error
:
gettext
(
responseJSON
)
}
}
);
);
var
html
=
_
.
template
(
'<p id="idash_msg" class="error">{text}</p>'
,
{
interpolate
:
/
\{(
.+
?)\}
/g
})(
var
html
=
_
.
template
(
'<p id="idash_msg" class="error">{text}</p>'
,
{
interpolate
:
/
\{(
.+
?)\}
/g
})(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment