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
e4ee1c6c
Commit
e4ee1c6c
authored
Jun 24, 2013
by
Carlos Andrés Rocha
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Rename arguments of modx_dispatch and handle_ajax related functions
Refactor a bit modx_dispatch
parent
2f02496c
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
254 additions
and
230 deletions
+254
-230
common/lib/capa/capa/capa_problem.py
+4
-4
common/lib/capa/capa/inputtypes.py
+11
-11
common/lib/capa/capa/tests/test_inputtypes.py
+4
-4
common/lib/xmodule/xmodule/capa_module.py
+38
-35
common/lib/xmodule/xmodule/combined_open_ended_module.py
+2
-3
common/lib/xmodule/xmodule/conditional_module.py
+1
-1
common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
+20
-20
common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
+21
-21
common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
+20
-20
common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
+17
-17
common/lib/xmodule/xmodule/peer_grading_module.py
+35
-38
common/lib/xmodule/xmodule/poll_module.py
+2
-2
common/lib/xmodule/xmodule/seq_module.py
+2
-2
common/lib/xmodule/xmodule/tests/test_logic.py
+2
-2
common/lib/xmodule/xmodule/timelimit_module.py
+1
-2
common/lib/xmodule/xmodule/video_module.py
+2
-2
common/lib/xmodule/xmodule/videoalpha_module.py
+2
-2
common/lib/xmodule/xmodule/word_cloud_module.py
+3
-3
common/lib/xmodule/xmodule/x_module.py
+2
-2
lms/djangoapps/courseware/module_render.py
+64
-36
lms/urls.py
+1
-3
No files found.
common/lib/capa/capa/capa_problem.py
View file @
e4ee1c6c
...
@@ -373,7 +373,7 @@ class LoncapaProblem(object):
...
@@ -373,7 +373,7 @@ class LoncapaProblem(object):
html
=
contextualize_text
(
etree
.
tostring
(
self
.
_extract_html
(
self
.
tree
)),
self
.
context
)
html
=
contextualize_text
(
etree
.
tostring
(
self
.
_extract_html
(
self
.
tree
)),
self
.
context
)
return
html
return
html
def
handle_input_ajax
(
self
,
get
):
def
handle_input_ajax
(
self
,
data
):
'''
'''
InputTypes can support specialized AJAX calls. Find the correct input and pass along the correct data
InputTypes can support specialized AJAX calls. Find the correct input and pass along the correct data
...
@@ -381,10 +381,10 @@ class LoncapaProblem(object):
...
@@ -381,10 +381,10 @@ class LoncapaProblem(object):
'''
'''
# pull out the id
# pull out the id
input_id
=
get
[
'input_id'
]
input_id
=
data
[
'input_id'
]
if
self
.
inputs
[
input_id
]:
if
self
.
inputs
[
input_id
]:
dispatch
=
get
[
'dispatch'
]
dispatch
=
data
[
'dispatch'
]
return
self
.
inputs
[
input_id
]
.
handle_ajax
(
dispatch
,
get
)
return
self
.
inputs
[
input_id
]
.
handle_ajax
(
dispatch
,
data
)
else
:
else
:
log
.
warning
(
"Could not find matching input for id:
%
s"
%
input_id
)
log
.
warning
(
"Could not find matching input for id:
%
s"
%
input_id
)
return
{}
return
{}
...
...
common/lib/capa/capa/inputtypes.py
View file @
e4ee1c6c
...
@@ -223,13 +223,13 @@ class InputTypeBase(object):
...
@@ -223,13 +223,13 @@ class InputTypeBase(object):
"""
"""
pass
pass
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""
"""
InputTypes that need to handle specialized AJAX should override this.
InputTypes that need to handle specialized AJAX should override this.
Input:
Input:
dispatch: a string that can be used to determine how to handle the data passed in
dispatch: a string that can be used to determine how to handle the data passed in
get
: a dictionary containing the data that was sent with the ajax call
data
: a dictionary containing the data that was sent with the ajax call
Output:
Output:
a dictionary object that can be serialized into JSON. This will be sent back to the Javascript.
a dictionary object that can be serialized into JSON. This will be sent back to the Javascript.
...
@@ -677,20 +677,20 @@ class MatlabInput(CodeInput):
...
@@ -677,20 +677,20 @@ class MatlabInput(CodeInput):
self
.
queue_len
=
1
self
.
queue_len
=
1
self
.
msg
=
self
.
plot_submitted_msg
self
.
msg
=
self
.
plot_submitted_msg
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
'''
'''
Handle AJAX calls directed to this input
Handle AJAX calls directed to this input
Args:
Args:
- dispatch (str) - indicates how we want this ajax call to be handled
- dispatch (str) - indicates how we want this ajax call to be handled
-
get
(dict) - dictionary of key-value pairs that contain useful data
-
data
(dict) - dictionary of key-value pairs that contain useful data
Returns:
Returns:
dict - 'success' - whether or not we successfully queued this submission
dict - 'success' - whether or not we successfully queued this submission
- 'message' - message to be rendered in case of error
- 'message' - message to be rendered in case of error
'''
'''
if
dispatch
==
'plot'
:
if
dispatch
==
'plot'
:
return
self
.
_plot_data
(
get
)
return
self
.
_plot_data
(
data
)
return
{}
return
{}
def
ungraded_response
(
self
,
queue_msg
,
queuekey
):
def
ungraded_response
(
self
,
queue_msg
,
queuekey
):
...
@@ -751,7 +751,7 @@ class MatlabInput(CodeInput):
...
@@ -751,7 +751,7 @@ class MatlabInput(CodeInput):
msg
=
result
[
'msg'
]
msg
=
result
[
'msg'
]
return
msg
return
msg
def
_plot_data
(
self
,
get
):
def
_plot_data
(
self
,
data
):
'''
'''
AJAX handler for the plot button
AJAX handler for the plot button
Args:
Args:
...
@@ -765,7 +765,7 @@ class MatlabInput(CodeInput):
...
@@ -765,7 +765,7 @@ class MatlabInput(CodeInput):
return
{
'success'
:
False
,
'message'
:
'Cannot connect to the queue'
}
return
{
'success'
:
False
,
'message'
:
'Cannot connect to the queue'
}
# pull relevant info out of get
# pull relevant info out of get
response
=
get
[
'submission'
]
response
=
data
[
'submission'
]
# construct xqueue headers
# construct xqueue headers
qinterface
=
self
.
system
.
xqueue
[
'interface'
]
qinterface
=
self
.
system
.
xqueue
[
'interface'
]
...
@@ -951,16 +951,16 @@ class ChemicalEquationInput(InputTypeBase):
...
@@ -951,16 +951,16 @@ class ChemicalEquationInput(InputTypeBase):
"""
"""
return
{
'previewer'
:
'/static/js/capa/chemical_equation_preview.js'
,
}
return
{
'previewer'
:
'/static/js/capa/chemical_equation_preview.js'
,
}
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
'''
'''
Since we only have chemcalc preview this input, check to see if it
Since we only have chemcalc preview this input, check to see if it
matches the corresponding dispatch and send it through if it does
matches the corresponding dispatch and send it through if it does
'''
'''
if
dispatch
==
'preview_chemcalc'
:
if
dispatch
==
'preview_chemcalc'
:
return
self
.
preview_chemcalc
(
get
)
return
self
.
preview_chemcalc
(
data
)
return
{}
return
{}
def
preview_chemcalc
(
self
,
get
):
def
preview_chemcalc
(
self
,
data
):
"""
"""
Render an html preview of a chemical formula or equation. get should
Render an html preview of a chemical formula or equation. get should
contain a key 'formula' and value 'some formula string'.
contain a key 'formula' and value 'some formula string'.
...
@@ -974,7 +974,7 @@ class ChemicalEquationInput(InputTypeBase):
...
@@ -974,7 +974,7 @@ class ChemicalEquationInput(InputTypeBase):
result
=
{
'preview'
:
''
,
result
=
{
'preview'
:
''
,
'error'
:
''
}
'error'
:
''
}
formula
=
get
[
'formula'
]
formula
=
data
[
'formula'
]
if
formula
is
None
:
if
formula
is
None
:
result
[
'error'
]
=
"No formula specified."
result
[
'error'
]
=
"No formula specified."
return
result
return
result
...
...
common/lib/capa/capa/tests/test_inputtypes.py
View file @
e4ee1c6c
...
@@ -467,8 +467,8 @@ class MatlabTest(unittest.TestCase):
...
@@ -467,8 +467,8 @@ class MatlabTest(unittest.TestCase):
self
.
assertEqual
(
context
,
expected
)
self
.
assertEqual
(
context
,
expected
)
def
test_plot_data
(
self
):
def
test_plot_data
(
self
):
get
=
{
'submission'
:
'x = 1234;'
}
data
=
{
'submission'
:
'x = 1234;'
}
response
=
self
.
the_input
.
handle_ajax
(
"plot"
,
get
)
response
=
self
.
the_input
.
handle_ajax
(
"plot"
,
data
)
test_system
()
.
xqueue
[
'interface'
]
.
send_to_queue
.
assert_called_with
(
header
=
ANY
,
body
=
ANY
)
test_system
()
.
xqueue
[
'interface'
]
.
send_to_queue
.
assert_called_with
(
header
=
ANY
,
body
=
ANY
)
...
@@ -477,10 +477,10 @@ class MatlabTest(unittest.TestCase):
...
@@ -477,10 +477,10 @@ class MatlabTest(unittest.TestCase):
self
.
assertEqual
(
self
.
the_input
.
input_state
[
'queuestate'
],
'queued'
)
self
.
assertEqual
(
self
.
the_input
.
input_state
[
'queuestate'
],
'queued'
)
def
test_plot_data_failure
(
self
):
def
test_plot_data_failure
(
self
):
get
=
{
'submission'
:
'x = 1234;'
}
data
=
{
'submission'
:
'x = 1234;'
}
error_message
=
'Error message!'
error_message
=
'Error message!'
test_system
()
.
xqueue
[
'interface'
]
.
send_to_queue
.
return_value
=
(
1
,
error_message
)
test_system
()
.
xqueue
[
'interface'
]
.
send_to_queue
.
return_value
=
(
1
,
error_message
)
response
=
self
.
the_input
.
handle_ajax
(
"plot"
,
get
)
response
=
self
.
the_input
.
handle_ajax
(
"plot"
,
data
)
self
.
assertFalse
(
response
[
'success'
])
self
.
assertFalse
(
response
[
'success'
])
self
.
assertEqual
(
response
[
'message'
],
error_message
)
self
.
assertEqual
(
response
[
'message'
],
error_message
)
self
.
assertTrue
(
'queuekey'
not
in
self
.
the_input
.
input_state
)
self
.
assertTrue
(
'queuekey'
not
in
self
.
the_input
.
input_state
)
...
...
common/lib/xmodule/xmodule/capa_module.py
View file @
e4ee1c6c
...
@@ -519,11 +519,11 @@ class CapaModule(CapaFields, XModule):
...
@@ -519,11 +519,11 @@ class CapaModule(CapaFields, XModule):
# now do the substitutions which are filesystem based, e.g. '/static/' prefixes
# now do the substitutions which are filesystem based, e.g. '/static/' prefixes
return
self
.
system
.
replace_urls
(
html
)
return
self
.
system
.
replace_urls
(
html
)
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""
"""
This is called by courseware.module_render, to handle an AJAX call.
This is called by courseware.module_render, to handle an AJAX call.
`
get
` is request.POST.
`
data
` is request.POST.
Returns a json dictionary:
Returns a json dictionary:
{ 'progress_changed' : True/False,
{ 'progress_changed' : True/False,
...
@@ -547,18 +547,19 @@ class CapaModule(CapaFields, XModule):
...
@@ -547,18 +547,19 @@ class CapaModule(CapaFields, XModule):
before
=
self
.
get_progress
()
before
=
self
.
get_progress
()
try
:
try
:
d
=
handlers
[
dispatch
](
get
)
result
=
handlers
[
dispatch
](
data
)
except
Exception
as
err
:
except
Exception
as
err
:
_
,
_
,
traceback_obj
=
sys
.
exc_info
()
_
,
_
,
traceback_obj
=
sys
.
exc_info
()
raise
ProcessingError
,
err
.
message
,
traceback_obj
raise
ProcessingError
(
err
.
message
,
traceback_obj
)
after
=
self
.
get_progress
()
after
=
self
.
get_progress
()
d
.
update
({
result
.
update
({
'progress_changed'
:
after
!=
before
,
'progress_changed'
:
after
!=
before
,
'progress_status'
:
Progress
.
to_js_status_str
(
after
),
'progress_status'
:
Progress
.
to_js_status_str
(
after
),
})
})
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
return
json
.
dumps
(
result
,
cls
=
ComplexEncoder
)
def
is_past_due
(
self
):
def
is_past_due
(
self
):
"""
"""
...
@@ -633,32 +634,32 @@ class CapaModule(CapaFields, XModule):
...
@@ -633,32 +634,32 @@ class CapaModule(CapaFields, XModule):
return
False
return
False
def
update_score
(
self
,
get
):
def
update_score
(
self
,
data
):
"""
"""
Delivers grading response (e.g. from asynchronous code checking) to
Delivers grading response (e.g. from asynchronous code checking) to
the capa problem, so its score can be updated
the capa problem, so its score can be updated
`get` must have a field `response`
which is a string that contains the
'data' must have a key 'response'
which is a string that contains the
grader's response
grader's response
No ajax return is needed. Return empty dict.
No ajax return is needed. Return empty dict.
"""
"""
queuekey
=
get
[
'queuekey'
]
queuekey
=
data
[
'queuekey'
]
score_msg
=
get
[
'xqueue_body'
]
score_msg
=
data
[
'xqueue_body'
]
self
.
lcp
.
update_score
(
score_msg
,
queuekey
)
self
.
lcp
.
update_score
(
score_msg
,
queuekey
)
self
.
set_state_from_lcp
()
self
.
set_state_from_lcp
()
self
.
publish_grade
()
self
.
publish_grade
()
return
dict
()
# No AJAX return is needed
return
dict
()
# No AJAX return is needed
def
handle_ungraded_response
(
self
,
get
):
def
handle_ungraded_response
(
self
,
data
):
"""
"""
Delivers a response from the XQueue to the capa problem
Delivers a response from the XQueue to the capa problem
The score of the problem will not be updated
The score of the problem will not be updated
Args:
Args:
-
get
(dict) must contain keys:
-
data
(dict) must contain keys:
queuekey - a key specific to this response
queuekey - a key specific to this response
xqueue_body - the body of the response
xqueue_body - the body of the response
Returns:
Returns:
...
@@ -666,28 +667,30 @@ class CapaModule(CapaFields, XModule):
...
@@ -666,28 +667,30 @@ class CapaModule(CapaFields, XModule):
No ajax return is needed, so an empty dict is returned
No ajax return is needed, so an empty dict is returned
"""
"""
queuekey
=
get
[
'queuekey'
]
queuekey
=
data
[
'queuekey'
]
score_msg
=
get
[
'xqueue_body'
]
score_msg
=
data
[
'xqueue_body'
]
# pass along the xqueue message to the problem
# pass along the xqueue message to the problem
self
.
lcp
.
ungraded_response
(
score_msg
,
queuekey
)
self
.
lcp
.
ungraded_response
(
score_msg
,
queuekey
)
self
.
set_state_from_lcp
()
self
.
set_state_from_lcp
()
return
dict
()
return
dict
()
def
handle_input_ajax
(
self
,
get
):
def
handle_input_ajax
(
self
,
data
):
"""
"""
Handle ajax calls meant for a particular input in the problem
Handle ajax calls meant for a particular input in the problem
Args:
Args:
-
get
(dict) - data that should be passed to the input
-
data
(dict) - data that should be passed to the input
Returns:
Returns:
- dict containing the response from the input
- dict containing the response from the input
"""
"""
response
=
self
.
lcp
.
handle_input_ajax
(
get
)
response
=
self
.
lcp
.
handle_input_ajax
(
data
)
# save any state changes that may occur
# save any state changes that may occur
self
.
set_state_from_lcp
()
self
.
set_state_from_lcp
()
return
response
return
response
def
get_answer
(
self
,
get
):
def
get_answer
(
self
,
data
):
"""
"""
For the "show answer" button.
For the "show answer" button.
...
@@ -717,10 +720,9 @@ class CapaModule(CapaFields, XModule):
...
@@ -717,10 +720,9 @@ class CapaModule(CapaFields, XModule):
return
{
'answers'
:
new_answers
}
return
{
'answers'
:
new_answers
}
# Figure out if we should move these to capa_problem?
# Figure out if we should move these to capa_problem?
def
get_problem
(
self
,
get
):
def
get_problem
(
self
,
_data
):
"""
"""
Return results of get_problem_html, as a simple dict for json-ing.
Return results of get_problem_html, as a simple dict for json-ing.
{ 'html': <the-html> }
{ 'html': <the-html> }
Used if we want to reconfirm we have the right thing e.g. after
Used if we want to reconfirm we have the right thing e.g. after
...
@@ -729,27 +731,27 @@ class CapaModule(CapaFields, XModule):
...
@@ -729,27 +731,27 @@ class CapaModule(CapaFields, XModule):
return
{
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
return
{
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
@staticmethod
@staticmethod
def
make_dict_of_responses
(
get
):
def
make_dict_of_responses
(
data
):
"""
"""
Make dictionary of student responses (aka "answers")
Make dictionary of student responses (aka "answers")
`
get
` is POST dictionary (Django QueryDict).
`
data
` is POST dictionary (Django QueryDict).
The `
get
` dict has keys of the form 'x_y', which are mapped
The `
data
` dict has keys of the form 'x_y', which are mapped
to key 'y' in the returned dict. For example,
to key 'y' in the returned dict. For example,
'input_1_2_3' would be mapped to '1_2_3' in the returned dict.
'input_1_2_3' would be mapped to '1_2_3' in the returned dict.
Some inputs always expect a list in the returned dict
Some inputs always expect a list in the returned dict
(e.g. checkbox inputs). The convention is that
(e.g. checkbox inputs). The convention is that
keys in the `
get
` dict that end with '[]' will always
keys in the `
data
` dict that end with '[]' will always
have list values in the returned dict.
have list values in the returned dict.
For example, if the `
get
` dict contains {'input_1[]': 'test' }
For example, if the `
data
` dict contains {'input_1[]': 'test' }
then the output dict would contain {'1': ['test'] }
then the output dict would contain {'1': ['test'] }
(the value is a list).
(the value is a list).
Raises an exception if:
Raises an exception if:
-A key in the `
get
` dictionary does not contain at least one underscore
-A key in the `
data
` dictionary does not contain at least one underscore
(e.g. "input" is invalid, but "input_1" is valid)
(e.g. "input" is invalid, but "input_1" is valid)
-Two keys end up with the same name in the returned dict.
-Two keys end up with the same name in the returned dict.
...
@@ -758,7 +760,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -758,7 +760,7 @@ class CapaModule(CapaFields, XModule):
"""
"""
answers
=
dict
()
answers
=
dict
()
for
key
in
get
:
for
key
in
data
:
# e.g. input_resistor_1 ==> resistor_1
# e.g. input_resistor_1 ==> resistor_1
_
,
_
,
name
=
key
.
partition
(
'_'
)
_
,
_
,
name
=
key
.
partition
(
'_'
)
...
@@ -777,9 +779,9 @@ class CapaModule(CapaFields, XModule):
...
@@ -777,9 +779,9 @@ class CapaModule(CapaFields, XModule):
name
=
name
[:
-
2
]
if
is_list_key
else
name
name
=
name
[:
-
2
]
if
is_list_key
else
name
if
is_list_key
:
if
is_list_key
:
val
=
get
.
getlist
(
key
)
val
=
data
.
getlist
(
key
)
else
:
else
:
val
=
get
[
key
]
val
=
data
[
key
]
# If the name already exists, then we don't want
# If the name already exists, then we don't want
# to override it. Raise an error instead
# to override it. Raise an error instead
...
@@ -801,7 +803,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -801,7 +803,7 @@ class CapaModule(CapaFields, XModule):
'max_value'
:
score
[
'total'
],
'max_value'
:
score
[
'total'
],
})
})
def
check_problem
(
self
,
get
):
def
check_problem
(
self
,
data
):
"""
"""
Checks whether answers to a problem are correct
Checks whether answers to a problem are correct
...
@@ -813,8 +815,9 @@ class CapaModule(CapaFields, XModule):
...
@@ -813,8 +815,9 @@ class CapaModule(CapaFields, XModule):
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
answers
=
self
.
make_dict_of_responses
(
get
)
answers
=
self
.
make_dict_of_responses
(
data
)
event_info
[
'answers'
]
=
convert_files_to_filenames
(
answers
)
event_info
[
'answers'
]
=
convert_files_to_filenames
(
answers
)
# Too late. Cannot submit
# Too late. Cannot submit
if
self
.
closed
():
if
self
.
closed
():
event_info
[
'failure'
]
=
'closed'
event_info
[
'failure'
]
=
'closed'
...
@@ -972,7 +975,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -972,7 +975,7 @@ class CapaModule(CapaFields, XModule):
return
{
'success'
:
success
}
return
{
'success'
:
success
}
def
save_problem
(
self
,
get
):
def
save_problem
(
self
,
data
):
"""
"""
Save the passed in answers.
Save the passed in answers.
Returns a dict { 'success' : bool, 'msg' : message }
Returns a dict { 'success' : bool, 'msg' : message }
...
@@ -982,7 +985,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -982,7 +985,7 @@ class CapaModule(CapaFields, XModule):
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
answers
=
self
.
make_dict_of_responses
(
get
)
answers
=
self
.
make_dict_of_responses
(
data
)
event_info
[
'answers'
]
=
answers
event_info
[
'answers'
]
=
answers
# Too late. Cannot submit
# Too late. Cannot submit
...
@@ -1011,7 +1014,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -1011,7 +1014,7 @@ class CapaModule(CapaFields, XModule):
return
{
'success'
:
True
,
return
{
'success'
:
True
,
'msg'
:
msg
}
'msg'
:
msg
}
def
reset_problem
(
self
,
get
):
def
reset_problem
(
self
,
_data
):
"""
"""
Changes problem state to unfinished -- removes student answers,
Changes problem state to unfinished -- removes student answers,
and causes problem to rerender itself.
and causes problem to rerender itself.
...
...
common/lib/xmodule/xmodule/combined_open_ended_module.py
View file @
e4ee1c6c
...
@@ -204,9 +204,9 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
...
@@ -204,9 +204,9 @@ class CombinedOpenEndedModule(CombinedOpenEndedFields, XModule):
return_value
=
self
.
child_module
.
get_html
()
return_value
=
self
.
child_module
.
get_html
()
return
return_value
return
return_value
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
self
.
save_instance_data
()
self
.
save_instance_data
()
return_value
=
self
.
child_module
.
handle_ajax
(
dispatch
,
get
)
return_value
=
self
.
child_module
.
handle_ajax
(
dispatch
,
data
)
self
.
save_instance_data
()
self
.
save_instance_data
()
return
return_value
return
return_value
...
@@ -266,4 +266,3 @@ class CombinedOpenEndedDescriptor(CombinedOpenEndedFields, RawDescriptor):
...
@@ -266,4 +266,3 @@ class CombinedOpenEndedDescriptor(CombinedOpenEndedFields, RawDescriptor):
non_editable_fields
.
extend
([
CombinedOpenEndedDescriptor
.
due
,
CombinedOpenEndedDescriptor
.
graceperiod
,
non_editable_fields
.
extend
([
CombinedOpenEndedDescriptor
.
due
,
CombinedOpenEndedDescriptor
.
graceperiod
,
CombinedOpenEndedDescriptor
.
markdown
,
CombinedOpenEndedDescriptor
.
version
])
CombinedOpenEndedDescriptor
.
markdown
,
CombinedOpenEndedDescriptor
.
version
])
return
non_editable_fields
return
non_editable_fields
common/lib/xmodule/xmodule/conditional_module.py
View file @
e4ee1c6c
...
@@ -135,7 +135,7 @@ class ConditionalModule(ConditionalFields, XModule):
...
@@ -135,7 +135,7 @@ class ConditionalModule(ConditionalFields, XModule):
'depends'
:
';'
.
join
(
self
.
required_html_ids
)
'depends'
:
';'
.
join
(
self
.
required_html_ids
)
})
})
def
handle_ajax
(
self
,
dispatch
,
post
):
def
handle_ajax
(
self
,
_dispatch
,
_data
):
"""This is called by courseware.moduleodule_render, to handle
"""This is called by courseware.moduleodule_render, to handle
an AJAX call.
an AJAX call.
"""
"""
...
...
common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py
View file @
e4ee1c6c
...
@@ -500,10 +500,10 @@ class CombinedOpenEndedV1Module():
...
@@ -500,10 +500,10 @@ class CombinedOpenEndedV1Module():
pass
pass
return
return_html
return
return_html
def
get_rubric
(
self
,
get
):
def
get_rubric
(
self
,
_data
):
"""
"""
Gets the results of a given grader via ajax.
Gets the results of a given grader via ajax.
Input: AJAX
get
dictionary
Input: AJAX
data
dictionary
Output: Dictionary to be rendered via ajax that contains the result html.
Output: Dictionary to be rendered via ajax that contains the result html.
"""
"""
all_responses
=
[]
all_responses
=
[]
...
@@ -532,10 +532,10 @@ class CombinedOpenEndedV1Module():
...
@@ -532,10 +532,10 @@ class CombinedOpenEndedV1Module():
html
=
self
.
system
.
render_template
(
'{0}/combined_open_ended_results.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
html
=
self
.
system
.
render_template
(
'{0}/combined_open_ended_results.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
return
{
'html'
:
html
,
'success'
:
True
}
return
{
'html'
:
html
,
'success'
:
True
}
def
get_legend
(
self
,
get
):
def
get_legend
(
self
,
_data
):
"""
"""
Gets the results of a given grader via ajax.
Gets the results of a given grader via ajax.
Input: AJAX
get
dictionary
Input: AJAX
data
dictionary
Output: Dictionary to be rendered via ajax that contains the result html.
Output: Dictionary to be rendered via ajax that contains the result html.
"""
"""
context
=
{
context
=
{
...
@@ -544,10 +544,10 @@ class CombinedOpenEndedV1Module():
...
@@ -544,10 +544,10 @@ class CombinedOpenEndedV1Module():
html
=
self
.
system
.
render_template
(
'{0}/combined_open_ended_legend.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
html
=
self
.
system
.
render_template
(
'{0}/combined_open_ended_legend.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
return
{
'html'
:
html
,
'success'
:
True
}
return
{
'html'
:
html
,
'success'
:
True
}
def
get_results
(
self
,
get
):
def
get_results
(
self
,
_data
):
"""
"""
Gets the results of a given grader via ajax.
Gets the results of a given grader via ajax.
Input: AJAX
get
dictionary
Input: AJAX
data
dictionary
Output: Dictionary to be rendered via ajax that contains the result html.
Output: Dictionary to be rendered via ajax that contains the result html.
"""
"""
self
.
update_task_states
()
self
.
update_task_states
()
...
@@ -588,19 +588,19 @@ class CombinedOpenEndedV1Module():
...
@@ -588,19 +588,19 @@ class CombinedOpenEndedV1Module():
html
=
self
.
system
.
render_template
(
'{0}/combined_open_ended_results.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
html
=
self
.
system
.
render_template
(
'{0}/combined_open_ended_results.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
return
{
'html'
:
html
,
'success'
:
True
}
return
{
'html'
:
html
,
'success'
:
True
}
def
get_status_ajax
(
self
,
get
):
def
get_status_ajax
(
self
,
_data
):
"""
"""
Gets the results of a given grader via ajax.
Gets the results of a given grader via ajax.
Input: AJAX
get
dictionary
Input: AJAX
data
dictionary
Output: Dictionary to be rendered via ajax that contains the result html.
Output: Dictionary to be rendered via ajax that contains the result html.
"""
"""
html
=
self
.
get_status
(
True
)
html
=
self
.
get_status
(
True
)
return
{
'html'
:
html
,
'success'
:
True
}
return
{
'html'
:
html
,
'success'
:
True
}
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""
"""
This is called by courseware.module_render, to handle an AJAX call.
This is called by courseware.module_render, to handle an AJAX call.
"
get
" is request.POST.
"
data
" is request.POST.
Returns a json dictionary:
Returns a json dictionary:
{ 'progress_changed' : True/False,
{ 'progress_changed' : True/False,
...
@@ -618,30 +618,30 @@ class CombinedOpenEndedV1Module():
...
@@ -618,30 +618,30 @@ class CombinedOpenEndedV1Module():
}
}
if
dispatch
not
in
handlers
:
if
dispatch
not
in
handlers
:
return_html
=
self
.
current_task
.
handle_ajax
(
dispatch
,
get
,
self
.
system
)
return_html
=
self
.
current_task
.
handle_ajax
(
dispatch
,
data
,
self
.
system
)
return
self
.
update_task_states_ajax
(
return_html
)
return
self
.
update_task_states_ajax
(
return_html
)
d
=
handlers
[
dispatch
](
get
)
d
=
handlers
[
dispatch
](
data
)
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
def
next_problem
(
self
,
get
):
def
next_problem
(
self
,
_data
):
"""
"""
Called via ajax to advance to the next problem.
Called via ajax to advance to the next problem.
Input: AJAX
get
request.
Input: AJAX
data
request.
Output: Dictionary to be rendered
Output: Dictionary to be rendered
"""
"""
self
.
update_task_states
()
self
.
update_task_states
()
return
{
'success'
:
True
,
'html'
:
self
.
get_html_nonsystem
(),
'allow_reset'
:
self
.
ready_to_reset
}
return
{
'success'
:
True
,
'html'
:
self
.
get_html_nonsystem
(),
'allow_reset'
:
self
.
ready_to_reset
}
def
reset
(
self
,
get
):
def
reset
(
self
,
data
):
"""
"""
If resetting is allowed, reset the state of the combined open ended module.
If resetting is allowed, reset the state of the combined open ended module.
Input: AJAX
get
dictionary
Input: AJAX
data
dictionary
Output: AJAX dictionary to tbe rendered
Output: AJAX dictionary to tbe rendered
"""
"""
if
self
.
state
!=
self
.
DONE
:
if
self
.
state
!=
self
.
DONE
:
if
not
self
.
ready_to_reset
:
if
not
self
.
ready_to_reset
:
return
self
.
out_of_sync_error
(
get
)
return
self
.
out_of_sync_error
(
data
)
if
self
.
student_attempts
>
self
.
attempts
:
if
self
.
student_attempts
>
self
.
attempts
:
return
{
return
{
...
@@ -789,13 +789,13 @@ class CombinedOpenEndedV1Module():
...
@@ -789,13 +789,13 @@ class CombinedOpenEndedV1Module():
return
progress_object
return
progress_object
def
out_of_sync_error
(
self
,
get
,
msg
=
''
):
def
out_of_sync_error
(
self
,
data
,
msg
=
''
):
"""
"""
return dict out-of-sync error message, and also log.
return dict out-of-sync error message, and also log.
"""
"""
#This is a dev_facing_error
#This is a dev_facing_error
log
.
warning
(
"Combined module state out sync. state:
%
r,
get
:
%
r.
%
s"
,
log
.
warning
(
"Combined module state out sync. state:
%
r,
data
:
%
r.
%
s"
,
self
.
state
,
get
,
msg
)
self
.
state
,
data
,
msg
)
#This is a student_facing_error
#This is a student_facing_error
return
{
'success'
:
False
,
return
{
'success'
:
False
,
'error'
:
'The problem state got out-of-sync. Please try reloading the page.'
}
'error'
:
'The problem state got out-of-sync. Please try reloading the page.'
}
...
...
common/lib/xmodule/xmodule/open_ended_grading_classes/open_ended_module.py
View file @
e4ee1c6c
...
@@ -122,17 +122,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -122,17 +122,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
self
.
payload
=
{
'grader_payload'
:
updated_grader_payload
}
self
.
payload
=
{
'grader_payload'
:
updated_grader_payload
}
def
skip_post_assessment
(
self
,
get
,
system
):
def
skip_post_assessment
(
self
,
_data
,
system
):
"""
"""
Ajax function that allows one to skip the post assessment phase
Ajax function that allows one to skip the post assessment phase
@param
get
: AJAX dictionary
@param
data
: AJAX dictionary
@param system: ModuleSystem
@param system: ModuleSystem
@return: Success indicator
@return: Success indicator
"""
"""
self
.
child_state
=
self
.
DONE
self
.
child_state
=
self
.
DONE
return
{
'success'
:
True
}
return
{
'success'
:
True
}
def
message_post
(
self
,
get
,
system
):
def
message_post
(
self
,
data
,
system
):
"""
"""
Handles a student message post (a reaction to the grade they received from an open ended grader type)
Handles a student message post (a reaction to the grade they received from an open ended grader type)
Returns a boolean success/fail and an error message
Returns a boolean success/fail and an error message
...
@@ -141,7 +141,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -141,7 +141,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
event_info
=
dict
()
event_info
=
dict
()
event_info
[
'problem_id'
]
=
self
.
location_string
event_info
[
'problem_id'
]
=
self
.
location_string
event_info
[
'student_id'
]
=
system
.
anonymous_student_id
event_info
[
'student_id'
]
=
system
.
anonymous_student_id
event_info
[
'survey_responses'
]
=
get
event_info
[
'survey_responses'
]
=
data
survey_responses
=
event_info
[
'survey_responses'
]
survey_responses
=
event_info
[
'survey_responses'
]
for
tag
in
[
'feedback'
,
'submission_id'
,
'grader_id'
,
'score'
]:
for
tag
in
[
'feedback'
,
'submission_id'
,
'grader_id'
,
'score'
]:
...
@@ -587,10 +587,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -587,10 +587,10 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
html
=
system
.
render_template
(
'{0}/open_ended_evaluation.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
html
=
system
.
render_template
(
'{0}/open_ended_evaluation.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
return
html
return
html
def
handle_ajax
(
self
,
dispatch
,
get
,
system
):
def
handle_ajax
(
self
,
dispatch
,
data
,
system
):
'''
'''
This is called by courseware.module_render, to handle an AJAX call.
This is called by courseware.module_render, to handle an AJAX call.
"
get
" is request.POST.
"
data
" is request.POST.
Returns a json dictionary:
Returns a json dictionary:
{ 'progress_changed' : True/False,
{ 'progress_changed' : True/False,
...
@@ -612,7 +612,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -612,7 +612,7 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
return
json
.
dumps
({
'error'
:
'Error handling action. Please try again.'
,
'success'
:
False
})
return
json
.
dumps
({
'error'
:
'Error handling action. Please try again.'
,
'success'
:
False
})
before
=
self
.
get_progress
()
before
=
self
.
get_progress
()
d
=
handlers
[
dispatch
](
get
,
system
)
d
=
handlers
[
dispatch
](
data
,
system
)
after
=
self
.
get_progress
()
after
=
self
.
get_progress
()
d
.
update
({
d
.
update
({
'progress_changed'
:
after
!=
before
,
'progress_changed'
:
after
!=
before
,
...
@@ -620,20 +620,20 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -620,20 +620,20 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
})
})
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
def
check_for_score
(
self
,
get
,
system
):
def
check_for_score
(
self
,
_data
,
system
):
"""
"""
Checks to see if a score has been received yet.
Checks to see if a score has been received yet.
@param
get: AJAX get
dictionary
@param
data: AJAX
dictionary
@param system: Modulesystem (needed to align with other ajax functions)
@param system: Modulesystem (needed to align with other ajax functions)
@return: Returns the current state
@return: Returns the current state
"""
"""
state
=
self
.
child_state
state
=
self
.
child_state
return
{
'state'
:
state
}
return
{
'state'
:
state
}
def
save_answer
(
self
,
get
,
system
):
def
save_answer
(
self
,
data
,
system
):
"""
"""
Saves a student answer
Saves a student answer
@param
get: AJAX get
dictionary
@param
data: AJAX
dictionary
@param system: modulesystem
@param system: modulesystem
@return: Success indicator
@return: Success indicator
"""
"""
...
@@ -644,17 +644,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -644,17 +644,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
return
msg
return
msg
if
self
.
child_state
!=
self
.
INITIAL
:
if
self
.
child_state
!=
self
.
INITIAL
:
return
self
.
out_of_sync_error
(
get
)
return
self
.
out_of_sync_error
(
data
)
# add new history element with answer and empty score and hint.
# add new history element with answer and empty score and hint.
success
,
get
=
self
.
append_image_to_student_answer
(
get
)
success
,
data
=
self
.
append_image_to_student_answer
(
data
)
error_message
=
""
error_message
=
""
if
success
:
if
success
:
success
,
allowed_to_submit
,
error_message
=
self
.
check_if_student_can_submit
()
success
,
allowed_to_submit
,
error_message
=
self
.
check_if_student_can_submit
()
if
allowed_to_submit
:
if
allowed_to_submit
:
get
[
'student_answer'
]
=
OpenEndedModule
.
sanitize_html
(
get
[
'student_answer'
])
data
[
'student_answer'
]
=
OpenEndedModule
.
sanitize_html
(
data
[
'student_answer'
])
self
.
new_history_entry
(
get
[
'student_answer'
])
self
.
new_history_entry
(
data
[
'student_answer'
])
self
.
send_to_grader
(
get
[
'student_answer'
],
system
)
self
.
send_to_grader
(
data
[
'student_answer'
],
system
)
self
.
change_state
(
self
.
ASSESSING
)
self
.
change_state
(
self
.
ASSESSING
)
else
:
else
:
# Error message already defined
# Error message already defined
...
@@ -666,17 +666,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
...
@@ -666,17 +666,17 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
return
{
return
{
'success'
:
success
,
'success'
:
success
,
'error'
:
error_message
,
'error'
:
error_message
,
'student_response'
:
get
[
'student_answer'
]
'student_response'
:
data
[
'student_answer'
]
}
}
def
update_score
(
self
,
get
,
system
):
def
update_score
(
self
,
data
,
system
):
"""
"""
Updates the current score via ajax. Called by xqueue.
Updates the current score via ajax. Called by xqueue.
Input: AJAX
get
dictionary, modulesystem
Input: AJAX
data
dictionary, modulesystem
Output: None
Output: None
"""
"""
queuekey
=
get
[
'queuekey'
]
queuekey
=
data
[
'queuekey'
]
score_msg
=
get
[
'xqueue_body'
]
score_msg
=
data
[
'xqueue_body'
]
# TODO: Remove need for cmap
# TODO: Remove need for cmap
self
.
_update_score
(
score_msg
,
queuekey
,
system
)
self
.
_update_score
(
score_msg
,
queuekey
,
system
)
...
...
common/lib/xmodule/xmodule/open_ended_grading_classes/openendedchild.py
View file @
e4ee1c6c
...
@@ -272,13 +272,13 @@ class OpenEndedChild(object):
...
@@ -272,13 +272,13 @@ class OpenEndedChild(object):
return
None
return
None
return
None
return
None
def
out_of_sync_error
(
self
,
get
,
msg
=
''
):
def
out_of_sync_error
(
self
,
data
,
msg
=
''
):
"""
"""
return dict out-of-sync error message, and also log.
return dict out-of-sync error message, and also log.
"""
"""
# This is a dev_facing_error
# This is a dev_facing_error
log
.
warning
(
"Open ended child state out sync. state:
%
r,
get
:
%
r.
%
s"
,
log
.
warning
(
"Open ended child state out sync. state:
%
r,
data
:
%
r.
%
s"
,
self
.
child_state
,
get
,
msg
)
self
.
child_state
,
data
,
msg
)
# This is a student_facing_error
# This is a student_facing_error
return
{
'success'
:
False
,
return
{
'success'
:
False
,
'error'
:
'The problem state got out-of-sync. Please try reloading the page.'
}
'error'
:
'The problem state got out-of-sync. Please try reloading the page.'
}
...
@@ -345,24 +345,24 @@ class OpenEndedChild(object):
...
@@ -345,24 +345,24 @@ class OpenEndedChild(object):
return
success
,
image_ok
,
s3_public_url
return
success
,
image_ok
,
s3_public_url
def
check_for_image_and_upload
(
self
,
get_
data
):
def
check_for_image_and_upload
(
self
,
data
):
"""
"""
Checks to see if an image was passed back in the AJAX query. If so, it will upload it to S3
Checks to see if an image was passed back in the AJAX query. If so, it will upload it to S3
@param
get_data: AJAX get
data
@param
data: AJAX
data
@return: Success, whether or not a file was in the
get
dictionary,
@return: Success, whether or not a file was in the
data
dictionary,
and the html corresponding to the uploaded image
and the html corresponding to the uploaded image
"""
"""
has_file_to_upload
=
False
has_file_to_upload
=
False
uploaded_to_s3
=
False
uploaded_to_s3
=
False
image_tag
=
""
image_tag
=
""
image_ok
=
False
image_ok
=
False
if
'can_upload_files'
in
get_
data
:
if
'can_upload_files'
in
data
:
if
get_
data
[
'can_upload_files'
]
in
[
'true'
,
'1'
]:
if
data
[
'can_upload_files'
]
in
[
'true'
,
'1'
]:
has_file_to_upload
=
True
has_file_to_upload
=
True
file
=
get_
data
[
'student_file'
][
0
]
student_file
=
data
[
'student_file'
][
0
]
uploaded_to_s3
,
image_ok
,
s3_public_url
=
self
.
upload_image_to_s3
(
file
)
uploaded_to_s3
,
image_ok
,
s3_public_url
=
self
.
upload_image_to_s3
(
student_
file
)
if
uploaded_to_s3
:
if
uploaded_to_s3
:
image_tag
=
self
.
generate_image_tag_from_url
(
s3_public_url
,
file
.
name
)
image_tag
=
self
.
generate_image_tag_from_url
(
s3_public_url
,
student_
file
.
name
)
return
has_file_to_upload
,
uploaded_to_s3
,
image_ok
,
image_tag
return
has_file_to_upload
,
uploaded_to_s3
,
image_ok
,
image_tag
...
@@ -371,27 +371,27 @@ class OpenEndedChild(object):
...
@@ -371,27 +371,27 @@ class OpenEndedChild(object):
Makes an image tag from a given URL
Makes an image tag from a given URL
@param s3_public_url: URL of the image
@param s3_public_url: URL of the image
@param image_name: Name of the image
@param image_name: Name of the image
@return: Boolean success, updated AJAX
get
data
@return: Boolean success, updated AJAX data
"""
"""
image_template
=
"""
image_template
=
"""
<a href="{0}" target="_blank">{1}</a>
<a href="{0}" target="_blank">{1}</a>
"""
.
format
(
s3_public_url
,
image_name
)
"""
.
format
(
s3_public_url
,
image_name
)
return
image_template
return
image_template
def
append_image_to_student_answer
(
self
,
get_
data
):
def
append_image_to_student_answer
(
self
,
data
):
"""
"""
Adds an image to a student answer after uploading it to S3
Adds an image to a student answer after uploading it to S3
@param
get_data: AJAx get
data
@param
data: AJAx
data
@return: Boolean success, updated AJAX
get
data
@return: Boolean success, updated AJAX data
"""
"""
overall_success
=
False
overall_success
=
False
if
not
self
.
accept_file_upload
:
if
not
self
.
accept_file_upload
:
# If the question does not accept file uploads, do not do anything
# If the question does not accept file uploads, do not do anything
return
True
,
get_
data
return
True
,
data
has_file_to_upload
,
uploaded_to_s3
,
image_ok
,
image_tag
=
self
.
check_for_image_and_upload
(
get_
data
)
has_file_to_upload
,
uploaded_to_s3
,
image_ok
,
image_tag
=
self
.
check_for_image_and_upload
(
data
)
if
uploaded_to_s3
and
has_file_to_upload
and
image_ok
:
if
uploaded_to_s3
and
has_file_to_upload
and
image_ok
:
get_
data
[
'student_answer'
]
+=
image_tag
data
[
'student_answer'
]
+=
image_tag
overall_success
=
True
overall_success
=
True
elif
has_file_to_upload
and
not
uploaded_to_s3
and
image_ok
:
elif
has_file_to_upload
and
not
uploaded_to_s3
and
image_ok
:
# In this case, an image was submitted by the student, but the image could not be uploaded to S3. Likely
# In this case, an image was submitted by the student, but the image could not be uploaded to S3. Likely
...
@@ -403,12 +403,12 @@ class OpenEndedChild(object):
...
@@ -403,12 +403,12 @@ class OpenEndedChild(object):
overall_success
=
True
overall_success
=
True
elif
not
has_file_to_upload
:
elif
not
has_file_to_upload
:
# If there is no file to upload, probably the student has embedded the link in the answer text
# If there is no file to upload, probably the student has embedded the link in the answer text
success
,
get_data
[
'student_answer'
]
=
self
.
check_for_url_in_text
(
get_
data
[
'student_answer'
])
success
,
data
[
'student_answer'
]
=
self
.
check_for_url_in_text
(
data
[
'student_answer'
])
overall_success
=
success
overall_success
=
success
# log.debug("Has file: {0} Uploaded: {1} Image Ok: {2}".format(has_file_to_upload, uploaded_to_s3, image_ok))
# log.debug("Has file: {0} Uploaded: {1} Image Ok: {2}".format(has_file_to_upload, uploaded_to_s3, image_ok))
return
overall_success
,
get_
data
return
overall_success
,
data
def
check_for_url_in_text
(
self
,
string
):
def
check_for_url_in_text
(
self
,
string
):
"""
"""
...
...
common/lib/xmodule/xmodule/open_ended_grading_classes/self_assessment_module.py
View file @
e4ee1c6c
...
@@ -75,10 +75,10 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -75,10 +75,10 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
html
=
system
.
render_template
(
'{0}/self_assessment_prompt.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
html
=
system
.
render_template
(
'{0}/self_assessment_prompt.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
return
html
return
html
def
handle_ajax
(
self
,
dispatch
,
get
,
system
):
def
handle_ajax
(
self
,
dispatch
,
data
,
system
):
"""
"""
This is called by courseware.module_render, to handle an AJAX call.
This is called by courseware.module_render, to handle an AJAX call.
"
get
" is request.POST.
"
data
" is request.POST.
Returns a json dictionary:
Returns a json dictionary:
{ 'progress_changed' : True/False,
{ 'progress_changed' : True/False,
...
@@ -99,7 +99,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -99,7 +99,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
return
json
.
dumps
({
'error'
:
'Error handling action. Please try again.'
,
'success'
:
False
})
return
json
.
dumps
({
'error'
:
'Error handling action. Please try again.'
,
'success'
:
False
})
before
=
self
.
get_progress
()
before
=
self
.
get_progress
()
d
=
handlers
[
dispatch
](
get
,
system
)
d
=
handlers
[
dispatch
](
data
,
system
)
after
=
self
.
get_progress
()
after
=
self
.
get_progress
()
d
.
update
({
d
.
update
({
'progress_changed'
:
after
!=
before
,
'progress_changed'
:
after
!=
before
,
...
@@ -160,12 +160,12 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -160,12 +160,12 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
return
system
.
render_template
(
'{0}/self_assessment_hint.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
return
system
.
render_template
(
'{0}/self_assessment_hint.html'
.
format
(
self
.
TEMPLATE_DIR
),
context
)
def
save_answer
(
self
,
get
,
system
):
def
save_answer
(
self
,
data
,
system
):
"""
"""
After the answer is submitted, show the rubric.
After the answer is submitted, show the rubric.
Args:
Args:
get: the GET
dictionary passed to the ajax request. Should contain
data: the request
dictionary passed to the ajax request. Should contain
a key 'student_answer'
a key 'student_answer'
Returns:
Returns:
...
@@ -178,16 +178,16 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -178,16 +178,16 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
return
msg
return
msg
if
self
.
child_state
!=
self
.
INITIAL
:
if
self
.
child_state
!=
self
.
INITIAL
:
return
self
.
out_of_sync_error
(
get
)
return
self
.
out_of_sync_error
(
data
)
error_message
=
""
error_message
=
""
# add new history element with answer and empty score and hint.
# add new history element with answer and empty score and hint.
success
,
get
=
self
.
append_image_to_student_answer
(
get
)
success
,
data
=
self
.
append_image_to_student_answer
(
data
)
if
success
:
if
success
:
success
,
allowed_to_submit
,
error_message
=
self
.
check_if_student_can_submit
()
success
,
allowed_to_submit
,
error_message
=
self
.
check_if_student_can_submit
()
if
allowed_to_submit
:
if
allowed_to_submit
:
get
[
'student_answer'
]
=
SelfAssessmentModule
.
sanitize_html
(
get
[
'student_answer'
])
data
[
'student_answer'
]
=
SelfAssessmentModule
.
sanitize_html
(
data
[
'student_answer'
])
self
.
new_history_entry
(
get
[
'student_answer'
])
self
.
new_history_entry
(
data
[
'student_answer'
])
self
.
change_state
(
self
.
ASSESSING
)
self
.
change_state
(
self
.
ASSESSING
)
else
:
else
:
# Error message already defined
# Error message already defined
...
@@ -200,10 +200,10 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -200,10 +200,10 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
'success'
:
success
,
'success'
:
success
,
'rubric_html'
:
self
.
get_rubric_html
(
system
),
'rubric_html'
:
self
.
get_rubric_html
(
system
),
'error'
:
error_message
,
'error'
:
error_message
,
'student_response'
:
get
[
'student_answer'
],
'student_response'
:
data
[
'student_answer'
],
}
}
def
save_assessment
(
self
,
get
,
system
):
def
save_assessment
(
self
,
data
,
_
system
):
"""
"""
Save the assessment. If the student said they're right, don't ask for a
Save the assessment. If the student said they're right, don't ask for a
hint, and go straight to the done state. Otherwise, do ask for a hint.
hint, and go straight to the done state. Otherwise, do ask for a hint.
...
@@ -219,11 +219,11 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -219,11 +219,11 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
"""
"""
if
self
.
child_state
!=
self
.
ASSESSING
:
if
self
.
child_state
!=
self
.
ASSESSING
:
return
self
.
out_of_sync_error
(
get
)
return
self
.
out_of_sync_error
(
data
)
try
:
try
:
score
=
int
(
get
[
'assessment'
])
score
=
int
(
data
[
'assessment'
])
score_list
=
get
.
getlist
(
'score_list[]'
)
score_list
=
data
.
getlist
(
'score_list[]'
)
for
i
in
xrange
(
0
,
len
(
score_list
)):
for
i
in
xrange
(
0
,
len
(
score_list
)):
score_list
[
i
]
=
int
(
score_list
[
i
])
score_list
[
i
]
=
int
(
score_list
[
i
])
except
ValueError
:
except
ValueError
:
...
@@ -244,7 +244,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -244,7 +244,7 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
d
[
'state'
]
=
self
.
child_state
d
[
'state'
]
=
self
.
child_state
return
d
return
d
def
save_hint
(
self
,
get
,
system
):
def
save_hint
(
self
,
data
,
_
system
):
'''
'''
Not used currently, as hints have been removed from the system.
Not used currently, as hints have been removed from the system.
Save the hint.
Save the hint.
...
@@ -258,9 +258,9 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
...
@@ -258,9 +258,9 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
if
self
.
child_state
!=
self
.
POST_ASSESSMENT
:
if
self
.
child_state
!=
self
.
POST_ASSESSMENT
:
# Note: because we only ask for hints on wrong answers, may not have
# Note: because we only ask for hints on wrong answers, may not have
# the same number of hints and answers.
# the same number of hints and answers.
return
self
.
out_of_sync_error
(
get
)
return
self
.
out_of_sync_error
(
data
)
self
.
record_latest_post_assessment
(
get
[
'hint'
])
self
.
record_latest_post_assessment
(
data
[
'hint'
])
self
.
change_state
(
self
.
DONE
)
self
.
change_state
(
self
.
DONE
)
return
{
'success'
:
True
,
return
{
'success'
:
True
,
...
...
common/lib/xmodule/xmodule/peer_grading_module.py
View file @
e4ee1c6c
...
@@ -133,8 +133,8 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -133,8 +133,8 @@ class PeerGradingModule(PeerGradingFields, XModule):
"""
"""
return
{
'success'
:
False
,
'error'
:
msg
}
return
{
'success'
:
False
,
'error'
:
msg
}
def
_check_required
(
self
,
get
,
required
):
def
_check_required
(
self
,
data
,
required
):
actual
=
set
(
get
.
keys
())
actual
=
set
(
data
.
keys
())
missing
=
required
-
actual
missing
=
required
-
actual
if
len
(
missing
)
>
0
:
if
len
(
missing
)
>
0
:
return
False
,
"Missing required keys: {0}"
.
format
(
', '
.
join
(
missing
))
return
False
,
"Missing required keys: {0}"
.
format
(
', '
.
join
(
missing
))
...
@@ -153,7 +153,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -153,7 +153,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
else
:
else
:
return
self
.
peer_grading_problem
({
'location'
:
self
.
link_to_location
})[
'html'
]
return
self
.
peer_grading_problem
({
'location'
:
self
.
link_to_location
})[
'html'
]
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""
"""
Needs to be implemented by child modules. Handles AJAX events.
Needs to be implemented by child modules. Handles AJAX events.
@return:
@return:
...
@@ -173,7 +173,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -173,7 +173,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
# This is a dev_facing_error
# This is a dev_facing_error
return
json
.
dumps
({
'error'
:
'Error handling action. Please try again.'
,
'success'
:
False
})
return
json
.
dumps
({
'error'
:
'Error handling action. Please try again.'
,
'success'
:
False
})
d
=
handlers
[
dispatch
](
get
)
d
=
handlers
[
dispatch
](
data
)
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
return
json
.
dumps
(
d
,
cls
=
ComplexEncoder
)
...
@@ -244,7 +244,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -244,7 +244,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
max_grade
=
self
.
max_grade
max_grade
=
self
.
max_grade
return
max_grade
return
max_grade
def
get_next_submission
(
self
,
get
):
def
get_next_submission
(
self
,
data
):
"""
"""
Makes a call to the grading controller for the next essay that should be graded
Makes a call to the grading controller for the next essay that should be graded
Returns a json dict with the following keys:
Returns a json dict with the following keys:
...
@@ -263,11 +263,11 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -263,11 +263,11 @@ class PeerGradingModule(PeerGradingFields, XModule):
'error': if success is False, will have an error message with more info.
'error': if success is False, will have an error message with more info.
"""
"""
required
=
set
([
'location'
])
required
=
set
([
'location'
])
success
,
message
=
self
.
_check_required
(
get
,
required
)
success
,
message
=
self
.
_check_required
(
data
,
required
)
if
not
success
:
if
not
success
:
return
self
.
_err_response
(
message
)
return
self
.
_err_response
(
message
)
grader_id
=
self
.
system
.
anonymous_student_id
grader_id
=
self
.
system
.
anonymous_student_id
location
=
get
[
'location'
]
location
=
data
[
'location'
]
try
:
try
:
response
=
self
.
peer_gs
.
get_next_submission
(
location
,
grader_id
)
response
=
self
.
peer_gs
.
get_next_submission
(
location
,
grader_id
)
...
@@ -280,7 +280,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -280,7 +280,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
return
{
'success'
:
False
,
return
{
'success'
:
False
,
'error'
:
EXTERNAL_GRADER_NO_CONTACT_ERROR
}
'error'
:
EXTERNAL_GRADER_NO_CONTACT_ERROR
}
def
save_grade
(
self
,
get
):
def
save_grade
(
self
,
data
):
"""
"""
Saves the grade of a given submission.
Saves the grade of a given submission.
Input:
Input:
...
@@ -298,18 +298,18 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -298,18 +298,18 @@ class PeerGradingModule(PeerGradingFields, XModule):
required
=
set
([
'location'
,
'submission_id'
,
'submission_key'
,
'score'
,
'feedback'
,
'rubric_scores[]'
,
required
=
set
([
'location'
,
'submission_id'
,
'submission_key'
,
'score'
,
'feedback'
,
'rubric_scores[]'
,
'submission_flagged'
])
'submission_flagged'
])
success
,
message
=
self
.
_check_required
(
get
,
required
)
success
,
message
=
self
.
_check_required
(
data
,
required
)
if
not
success
:
if
not
success
:
return
self
.
_err_response
(
message
)
return
self
.
_err_response
(
message
)
grader_id
=
self
.
system
.
anonymous_student_id
grader_id
=
self
.
system
.
anonymous_student_id
location
=
get
.
get
(
'location'
)
location
=
data
.
get
(
'location'
)
submission_id
=
get
.
get
(
'submission_id'
)
submission_id
=
data
.
get
(
'submission_id'
)
score
=
get
.
get
(
'score'
)
score
=
data
.
get
(
'score'
)
feedback
=
get
.
get
(
'feedback'
)
feedback
=
data
.
get
(
'feedback'
)
submission_key
=
get
.
get
(
'submission_key'
)
submission_key
=
data
.
get
(
'submission_key'
)
rubric_scores
=
get
.
getlist
(
'rubric_scores[]'
)
rubric_scores
=
data
.
getlist
(
'rubric_scores[]'
)
submission_flagged
=
get
.
get
(
'submission_flagged'
)
submission_flagged
=
data
.
get
(
'submission_flagged'
)
try
:
try
:
response
=
self
.
peer_gs
.
save_grade
(
location
,
grader_id
,
submission_id
,
response
=
self
.
peer_gs
.
save_grade
(
location
,
grader_id
,
submission_id
,
...
@@ -328,7 +328,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -328,7 +328,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
'error'
:
EXTERNAL_GRADER_NO_CONTACT_ERROR
'error'
:
EXTERNAL_GRADER_NO_CONTACT_ERROR
}
}
def
is_student_calibrated
(
self
,
get
):
def
is_student_calibrated
(
self
,
data
):
"""
"""
Calls the grading controller to see if the given student is calibrated
Calls the grading controller to see if the given student is calibrated
on the given problem
on the given problem
...
@@ -347,12 +347,12 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -347,12 +347,12 @@ class PeerGradingModule(PeerGradingFields, XModule):
"""
"""
required
=
set
([
'location'
])
required
=
set
([
'location'
])
success
,
message
=
self
.
_check_required
(
get
,
required
)
success
,
message
=
self
.
_check_required
(
data
,
required
)
if
not
success
:
if
not
success
:
return
self
.
_err_response
(
message
)
return
self
.
_err_response
(
message
)
grader_id
=
self
.
system
.
anonymous_student_id
grader_id
=
self
.
system
.
anonymous_student_id
location
=
get
[
'location'
]
location
=
data
[
'location'
]
try
:
try
:
response
=
self
.
peer_gs
.
is_student_calibrated
(
location
,
grader_id
)
response
=
self
.
peer_gs
.
is_student_calibrated
(
location
,
grader_id
)
...
@@ -367,7 +367,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -367,7 +367,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
'error'
:
EXTERNAL_GRADER_NO_CONTACT_ERROR
'error'
:
EXTERNAL_GRADER_NO_CONTACT_ERROR
}
}
def
show_calibration_essay
(
self
,
get
):
def
show_calibration_essay
(
self
,
data
):
"""
"""
Fetch the next calibration essay from the grading controller and return it
Fetch the next calibration essay from the grading controller and return it
Inputs:
Inputs:
...
@@ -392,13 +392,13 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -392,13 +392,13 @@ class PeerGradingModule(PeerGradingFields, XModule):
"""
"""
required
=
set
([
'location'
])
required
=
set
([
'location'
])
success
,
message
=
self
.
_check_required
(
get
,
required
)
success
,
message
=
self
.
_check_required
(
data
,
required
)
if
not
success
:
if
not
success
:
return
self
.
_err_response
(
message
)
return
self
.
_err_response
(
message
)
grader_id
=
self
.
system
.
anonymous_student_id
grader_id
=
self
.
system
.
anonymous_student_id
location
=
get
[
'location'
]
location
=
data
[
'location'
]
try
:
try
:
response
=
self
.
peer_gs
.
show_calibration_essay
(
location
,
grader_id
)
response
=
self
.
peer_gs
.
show_calibration_essay
(
location
,
grader_id
)
return
response
return
response
...
@@ -417,8 +417,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -417,8 +417,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
return
{
'success'
:
False
,
return
{
'success'
:
False
,
'error'
:
'Error displaying submission. Please notify course staff.'
}
'error'
:
'Error displaying submission. Please notify course staff.'
}
def
save_calibration_essay
(
self
,
data
):
def
save_calibration_essay
(
self
,
get
):
"""
"""
Saves the grader's grade of a given calibration.
Saves the grader's grade of a given calibration.
Input:
Input:
...
@@ -437,17 +436,17 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -437,17 +436,17 @@ class PeerGradingModule(PeerGradingFields, XModule):
"""
"""
required
=
set
([
'location'
,
'submission_id'
,
'submission_key'
,
'score'
,
'feedback'
,
'rubric_scores[]'
])
required
=
set
([
'location'
,
'submission_id'
,
'submission_key'
,
'score'
,
'feedback'
,
'rubric_scores[]'
])
success
,
message
=
self
.
_check_required
(
get
,
required
)
success
,
message
=
self
.
_check_required
(
data
,
required
)
if
not
success
:
if
not
success
:
return
self
.
_err_response
(
message
)
return
self
.
_err_response
(
message
)
grader_id
=
self
.
system
.
anonymous_student_id
grader_id
=
self
.
system
.
anonymous_student_id
location
=
get
.
get
(
'location'
)
location
=
data
.
get
(
'location'
)
calibration_essay_id
=
get
.
get
(
'submission_id'
)
calibration_essay_id
=
data
.
get
(
'submission_id'
)
submission_key
=
get
.
get
(
'submission_key'
)
submission_key
=
data
.
get
(
'submission_key'
)
score
=
get
.
get
(
'score'
)
score
=
data
.
get
(
'score'
)
feedback
=
get
.
get
(
'feedback'
)
feedback
=
data
.
get
(
'feedback'
)
rubric_scores
=
get
.
getlist
(
'rubric_scores[]'
)
rubric_scores
=
data
.
getlist
(
'rubric_scores[]'
)
try
:
try
:
response
=
self
.
peer_gs
.
save_calibration_essay
(
location
,
grader_id
,
calibration_essay_id
,
response
=
self
.
peer_gs
.
save_calibration_essay
(
location
,
grader_id
,
calibration_essay_id
,
...
@@ -473,8 +472,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -473,8 +472,7 @@ class PeerGradingModule(PeerGradingFields, XModule):
})
})
return
html
return
html
def
peer_grading
(
self
,
_data
=
None
):
def
peer_grading
(
self
,
get
=
None
):
'''
'''
Show a peer grading interface
Show a peer grading interface
'''
'''
...
@@ -553,11 +551,11 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -553,11 +551,11 @@ class PeerGradingModule(PeerGradingFields, XModule):
return
html
return
html
def
peer_grading_problem
(
self
,
get
=
None
):
def
peer_grading_problem
(
self
,
data
=
None
):
'''
'''
Show individual problem interface
Show individual problem interface
'''
'''
if
get
is
None
or
get
.
get
(
'location'
)
is
None
:
if
data
is
None
or
data
.
get
(
'location'
)
is
None
:
if
not
self
.
use_for_single_location
:
if
not
self
.
use_for_single_location
:
# This is an error case, because it must be set to use a single location to be called without get parameters
# This is an error case, because it must be set to use a single location to be called without get parameters
# This is a dev_facing_error
# This is a dev_facing_error
...
@@ -566,8 +564,8 @@ class PeerGradingModule(PeerGradingFields, XModule):
...
@@ -566,8 +564,8 @@ class PeerGradingModule(PeerGradingFields, XModule):
return
{
'html'
:
""
,
'success'
:
False
}
return
{
'html'
:
""
,
'success'
:
False
}
problem_location
=
self
.
link_to_location
problem_location
=
self
.
link_to_location
elif
get
.
get
(
'location'
)
is
not
None
:
elif
data
.
get
(
'location'
)
is
not
None
:
problem_location
=
get
.
get
(
'location'
)
problem_location
=
data
.
get
(
'location'
)
ajax_url
=
self
.
ajax_url
ajax_url
=
self
.
ajax_url
html
=
self
.
system
.
render_template
(
'peer_grading/peer_grading_problem.html'
,
{
html
=
self
.
system
.
render_template
(
'peer_grading/peer_grading_problem.html'
,
{
...
@@ -617,4 +615,3 @@ class PeerGradingDescriptor(PeerGradingFields, RawDescriptor):
...
@@ -617,4 +615,3 @@ class PeerGradingDescriptor(PeerGradingFields, RawDescriptor):
non_editable_fields
.
extend
([
PeerGradingFields
.
due_date
,
PeerGradingFields
.
grace_period_string
,
non_editable_fields
.
extend
([
PeerGradingFields
.
due_date
,
PeerGradingFields
.
grace_period_string
,
PeerGradingFields
.
max_grade
])
PeerGradingFields
.
max_grade
])
return
non_editable_fields
return
non_editable_fields
common/lib/xmodule/xmodule/poll_module.py
View file @
e4ee1c6c
...
@@ -47,12 +47,12 @@ class PollModule(PollFields, XModule):
...
@@ -47,12 +47,12 @@ class PollModule(PollFields, XModule):
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/poll/display.scss'
)]}
css
=
{
'scss'
:
[
resource_string
(
__name__
,
'css/poll/display.scss'
)]}
js_module_name
=
"Poll"
js_module_name
=
"Poll"
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""Ajax handler.
"""Ajax handler.
Args:
Args:
dispatch: string request slug
dispatch: string request slug
get: dict request get
parameters
data: dict request data
parameters
Returns:
Returns:
json string
json string
...
...
common/lib/xmodule/xmodule/seq_module.py
View file @
e4ee1c6c
...
@@ -62,10 +62,10 @@ class SequenceModule(SequenceFields, XModule):
...
@@ -62,10 +62,10 @@ class SequenceModule(SequenceFields, XModule):
progress
=
reduce
(
Progress
.
add_counts
,
progresses
)
progress
=
reduce
(
Progress
.
add_counts
,
progresses
)
return
progress
return
progress
def
handle_ajax
(
self
,
dispatch
,
get
):
# TODO: bounds checking
def
handle_ajax
(
self
,
dispatch
,
data
):
# TODO: bounds checking
''' get = request.POST instance '''
''' get = request.POST instance '''
if
dispatch
==
'goto_position'
:
if
dispatch
==
'goto_position'
:
self
.
position
=
int
(
get
[
'position'
])
self
.
position
=
int
(
data
[
'position'
])
return
json
.
dumps
({
'success'
:
True
})
return
json
.
dumps
({
'success'
:
True
})
raise
NotFoundError
(
'Unexpected dispatch type'
)
raise
NotFoundError
(
'Unexpected dispatch type'
)
...
...
common/lib/xmodule/xmodule/tests/test_logic.py
View file @
e4ee1c6c
...
@@ -40,9 +40,9 @@ class LogicTest(unittest.TestCase):
...
@@ -40,9 +40,9 @@ class LogicTest(unittest.TestCase):
self
.
raw_model_data
self
.
raw_model_data
)
)
def
ajax_request
(
self
,
dispatch
,
get
):
def
ajax_request
(
self
,
dispatch
,
data
):
"""Call Xmodule.handle_ajax."""
"""Call Xmodule.handle_ajax."""
return
json
.
loads
(
self
.
xmodule
.
handle_ajax
(
dispatch
,
get
))
return
json
.
loads
(
self
.
xmodule
.
handle_ajax
(
dispatch
,
data
))
class
PollModuleTest
(
LogicTest
):
class
PollModuleTest
(
LogicTest
):
...
...
common/lib/xmodule/xmodule/timelimit_module.py
View file @
e4ee1c6c
...
@@ -98,7 +98,7 @@ class TimeLimitModule(TimeLimitFields, XModule):
...
@@ -98,7 +98,7 @@ class TimeLimitModule(TimeLimitFields, XModule):
progress
=
reduce
(
Progress
.
add_counts
,
progresses
)
progress
=
reduce
(
Progress
.
add_counts
,
progresses
)
return
progress
return
progress
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
_dispatch
,
_data
):
raise
NotFoundError
(
'Unexpected dispatch type'
)
raise
NotFoundError
(
'Unexpected dispatch type'
)
def
render
(
self
):
def
render
(
self
):
...
@@ -141,4 +141,3 @@ class TimeLimitDescriptor(TimeLimitFields, XMLEditingDescriptor, XmlDescriptor):
...
@@ -141,4 +141,3 @@ class TimeLimitDescriptor(TimeLimitFields, XMLEditingDescriptor, XmlDescriptor):
xml_object
.
append
(
xml_object
.
append
(
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
)))
etree
.
fromstring
(
child
.
export_to_xml
(
resource_fs
)))
return
xml_object
return
xml_object
common/lib/xmodule/xmodule/video_module.py
View file @
e4ee1c6c
...
@@ -54,9 +54,9 @@ class VideoModule(VideoFields, XModule):
...
@@ -54,9 +54,9 @@ class VideoModule(VideoFields, XModule):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
XModule
.
__init__
(
self
,
*
args
,
**
kwargs
)
XModule
.
__init__
(
self
,
*
args
,
**
kwargs
)
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""This is not being called right now and we raise 404 error."""
"""This is not being called right now and we raise 404 error."""
log
.
debug
(
u"GET {0}"
.
format
(
get
))
log
.
debug
(
u"GET {0}"
.
format
(
data
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
raise
Http404
()
raise
Http404
()
...
...
common/lib/xmodule/xmodule/videoalpha_module.py
View file @
e4ee1c6c
...
@@ -125,9 +125,9 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
...
@@ -125,9 +125,9 @@ class VideoAlphaModule(VideoAlphaFields, XModule):
return
parse_time
(
xmltree
.
get
(
'start_time'
)),
parse_time
(
xmltree
.
get
(
'end_time'
))
return
parse_time
(
xmltree
.
get
(
'start_time'
)),
parse_time
(
xmltree
.
get
(
'end_time'
))
def
handle_ajax
(
self
,
dispatch
,
get
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""This is not being called right now and we raise 404 error."""
"""This is not being called right now and we raise 404 error."""
log
.
debug
(
u"GET {0}"
.
format
(
get
))
log
.
debug
(
u"GET {0}"
.
format
(
data
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
log
.
debug
(
u"DISPATCH {0}"
.
format
(
dispatch
))
raise
Http404
()
raise
Http404
()
...
...
common/lib/xmodule/xmodule/word_cloud_module.py
View file @
e4ee1c6c
...
@@ -168,12 +168,12 @@ class WordCloudModule(WordCloudFields, XModule):
...
@@ -168,12 +168,12 @@ class WordCloudModule(WordCloudFields, XModule):
)[:
amount
]
)[:
amount
]
)
)
def
handle_ajax
(
self
,
dispatch
,
post
):
def
handle_ajax
(
self
,
dispatch
,
data
):
"""Ajax handler.
"""Ajax handler.
Args:
Args:
dispatch: string request slug
dispatch: string request slug
post
: dict request get parameters
data
: dict request get parameters
Returns:
Returns:
json string
json string
...
@@ -187,7 +187,7 @@ class WordCloudModule(WordCloudFields, XModule):
...
@@ -187,7 +187,7 @@ class WordCloudModule(WordCloudFields, XModule):
# Student words from client.
# Student words from client.
# FIXME: we must use raw JSON, not a post data (multipart/form-data)
# FIXME: we must use raw JSON, not a post data (multipart/form-data)
raw_student_words
=
post
.
getlist
(
'student_words[]'
)
raw_student_words
=
data
.
getlist
(
'student_words[]'
)
student_words
=
filter
(
None
,
map
(
self
.
good_word
,
raw_student_words
))
student_words
=
filter
(
None
,
map
(
self
.
good_word
,
raw_student_words
))
self
.
student_words
=
student_words
self
.
student_words
=
student_words
...
...
common/lib/xmodule/xmodule/x_module.py
View file @
e4ee1c6c
...
@@ -272,9 +272,9 @@ class XModule(XModuleFields, HTMLSnippet, XBlock):
...
@@ -272,9 +272,9 @@ class XModule(XModuleFields, HTMLSnippet, XBlock):
'''
'''
return
None
return
None
def
handle_ajax
(
self
,
_dispatch
,
_
get
):
def
handle_ajax
(
self
,
_dispatch
,
_
data
):
''' dispatch is last part of the URL.
''' dispatch is last part of the URL.
get is a dictionary-like object
'''
data is a dictionary-like object with the content of the request
'''
return
""
return
""
...
...
lms/djangoapps/courseware/module_render.py
View file @
e4ee1c6c
...
@@ -223,7 +223,7 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours
...
@@ -223,7 +223,7 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours
relative_xqueue_callback_url
=
reverse
(
'xqueue_callback'
,
relative_xqueue_callback_url
=
reverse
(
'xqueue_callback'
,
kwargs
=
dict
(
course_id
=
course_id
,
kwargs
=
dict
(
course_id
=
course_id
,
userid
=
str
(
user
.
id
),
userid
=
str
(
user
.
id
),
id
=
descriptor
.
location
.
url
(),
mod_
id
=
descriptor
.
location
.
url
(),
dispatch
=
dispatch
),
dispatch
=
dispatch
),
)
)
return
xqueue_callback_url_prefix
+
relative_xqueue_callback_url
return
xqueue_callback_url_prefix
+
relative_xqueue_callback_url
...
@@ -399,40 +399,47 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours
...
@@ -399,40 +399,47 @@ def get_module_for_descriptor_internal(user, descriptor, model_data_cache, cours
@csrf_exempt
@csrf_exempt
def
xqueue_callback
(
request
,
course_id
,
userid
,
id
,
dispatch
):
def
xqueue_callback
(
request
,
course_id
,
userid
,
mod_
id
,
dispatch
):
'''
'''
Entry point for graded results from the queueing system.
Entry point for graded results from the queueing system.
'''
'''
data
=
request
.
POST
.
copy
()
# Test xqueue package, which we expect to be:
# Test xqueue package, which we expect to be:
# xpackage = {'xqueue_header': json.dumps({'lms_key':'secretkey',...}),
# xpackage = {'xqueue_header': json.dumps({'lms_key':'secretkey',...}),
# 'xqueue_body' : 'Message from grader'}
# 'xqueue_body' : 'Message from grader'}
get
=
request
.
POST
.
copy
()
for
key
in
[
'xqueue_header'
,
'xqueue_body'
]:
for
key
in
[
'xqueue_header'
,
'xqueue_body'
]:
if
not
get
.
has_key
(
key
)
:
if
key
not
in
data
:
raise
Http404
raise
Http404
header
=
json
.
loads
(
get
[
'xqueue_header'
])
if
not
isinstance
(
header
,
dict
)
or
not
header
.
has_key
(
'lms_key'
):
header
=
json
.
loads
(
data
[
'xqueue_header'
])
if
not
isinstance
(
header
,
dict
)
or
'lms_key'
not
in
header
:
raise
Http404
raise
Http404
# Retrieve target StudentModule
# Retrieve target StudentModule
user
=
User
.
objects
.
get
(
id
=
userid
)
user
=
User
.
objects
.
get
(
id
=
userid
)
model_data_cache
=
ModelDataCache
.
cache_for_descriptor_descendents
(
model_data_cache
=
ModelDataCache
.
cache_for_descriptor_descendents
(
course_id
,
course_id
,
user
,
modulestore
()
.
get_instance
(
course_id
,
id
),
depth
=
0
,
select_for_update
=
True
)
user
,
instance
=
get_module
(
user
,
request
,
id
,
model_data_cache
,
course_id
,
grade_bucket_type
=
'xqueue'
)
modulestore
()
.
get_instance
(
course_id
,
mod_id
),
depth
=
0
,
select_for_update
=
True
)
instance
=
get_module
(
user
,
request
,
mod_id
,
model_data_cache
,
course_id
,
grade_bucket_type
=
'xqueue'
)
if
instance
is
None
:
if
instance
is
None
:
log
.
debug
(
"No module {0} for user {1}--access denied?"
.
format
(
id
,
user
))
msg
=
"No module {0} for user {1}--access denied?"
.
format
(
mod_id
,
user
)
log
.
debug
(
msg
)
raise
Http404
raise
Http404
# Transfer 'queuekey' from xqueue response header to
'get'. This is required to
# Transfer 'queuekey' from xqueue response header to
the data.
#
use the interface defined by 'handle_ajax'
#
This is required to
use the interface defined by 'handle_ajax'
get
.
update
({
'queuekey'
:
header
[
'lms_key'
]})
data
.
update
({
'queuekey'
:
header
[
'lms_key'
]})
# We go through the "AJAX" path
# We go through the "AJAX" path
#
So far, the only dispatch from xqueue will be 'score_update'
# So far, the only dispatch from xqueue will be 'score_update'
try
:
try
:
# Can ignore the return value--not used for xqueue_callback
# Can ignore the return value--not used for xqueue_callback
instance
.
handle_ajax
(
dispatch
,
get
)
instance
.
handle_ajax
(
dispatch
,
data
)
except
:
except
:
log
.
exception
(
"error processing ajax call"
)
log
.
exception
(
"error processing ajax call"
)
raise
raise
...
@@ -466,23 +473,15 @@ def modx_dispatch(request, dispatch, location, course_id):
...
@@ -466,23 +473,15 @@ def modx_dispatch(request, dispatch, location, course_id):
if
not
request
.
user
.
is_authenticated
():
if
not
request
.
user
.
is_authenticated
():
raise
PermissionDenied
raise
PermissionDenied
# Check for submitted files and basic file size checks
# Get the submitted data
p
=
request
.
POST
.
copy
()
data
=
request
.
POST
.
copy
()
if
request
.
FILES
:
for
fileinput_id
in
request
.
FILES
.
keys
():
inputfiles
=
request
.
FILES
.
getlist
(
fileinput_id
)
if
len
(
inputfiles
)
>
settings
.
MAX_FILEUPLOADS_PER_INPUT
:
# Get and check submitted files
too_many_files_msg
=
'Submission aborted! Maximum
%
d files may be submitted at once'
%
\
files
=
request
.
FILES
or
{}
settings
.
MAX_FILEUPLOADS_PER_INPUT
error_msg
=
_check_files_limits
(
files
)
return
HttpResponse
(
json
.
dumps
({
'success'
:
too_many_files_msg
}))
if
error_msg
:
return
HttpResponse
(
json
.
dumps
({
'success'
:
error_msg
}))
for
inputfile
in
inputfiles
:
data
.
update
(
files
)
# Merge files into data dictionary
if
inputfile
.
size
>
settings
.
STUDENT_FILEUPLOAD_MAX_SIZE
:
# Bytes
file_too_big_msg
=
'Submission aborted! Your file "
%
s" is too large (max size:
%
d MB)'
%
\
(
inputfile
.
name
,
settings
.
STUDENT_FILEUPLOAD_MAX_SIZE
/
(
1000
**
2
))
return
HttpResponse
(
json
.
dumps
({
'success'
:
file_too_big_msg
}))
p
[
fileinput_id
]
=
inputfiles
try
:
try
:
descriptor
=
modulestore
()
.
get_instance
(
course_id
,
location
)
descriptor
=
modulestore
()
.
get_instance
(
course_id
,
location
)
...
@@ -495,8 +494,11 @@ def modx_dispatch(request, dispatch, location, course_id):
...
@@ -495,8 +494,11 @@ def modx_dispatch(request, dispatch, location, course_id):
)
)
raise
Http404
raise
Http404
model_data_cache
=
ModelDataCache
.
cache_for_descriptor_descendents
(
course_id
,
model_data_cache
=
ModelDataCache
.
cache_for_descriptor_descendents
(
request
.
user
,
descriptor
)
course_id
,
request
.
user
,
descriptor
)
instance
=
get_module
(
request
.
user
,
request
,
location
,
model_data_cache
,
course_id
,
grade_bucket_type
=
'ajax'
)
instance
=
get_module
(
request
.
user
,
request
,
location
,
model_data_cache
,
course_id
,
grade_bucket_type
=
'ajax'
)
if
instance
is
None
:
if
instance
is
None
:
...
@@ -507,7 +509,7 @@ def modx_dispatch(request, dispatch, location, course_id):
...
@@ -507,7 +509,7 @@ def modx_dispatch(request, dispatch, location, course_id):
# Let the module handle the AJAX
# Let the module handle the AJAX
try
:
try
:
ajax_return
=
instance
.
handle_ajax
(
dispatch
,
p
)
ajax_return
=
instance
.
handle_ajax
(
dispatch
,
data
)
# If we can't find the module, respond with a 404
# If we can't find the module, respond with a 404
except
NotFoundError
:
except
NotFoundError
:
...
@@ -529,7 +531,6 @@ def modx_dispatch(request, dispatch, location, course_id):
...
@@ -529,7 +531,6 @@ def modx_dispatch(request, dispatch, location, course_id):
return
HttpResponse
(
ajax_return
)
return
HttpResponse
(
ajax_return
)
def
get_score_bucket
(
grade
,
max_grade
):
def
get_score_bucket
(
grade
,
max_grade
):
"""
"""
Function to split arbitrary score ranges into 3 buckets.
Function to split arbitrary score ranges into 3 buckets.
...
@@ -542,3 +543,30 @@ def get_score_bucket(grade, max_grade):
...
@@ -542,3 +543,30 @@ def get_score_bucket(grade, max_grade):
score_bucket
=
"correct"
score_bucket
=
"correct"
return
score_bucket
return
score_bucket
def
_check_files_limits
(
files
):
"""
Check if the files in a request are under the limits defined by
`settings.MAX_FILEUPLOADS_PER_INPUT` and
`settings.STUDENT_FILEUPLOAD_MAX_SIZE`.
Returns None if files are correct or an error messages otherwise.
"""
for
fileinput_id
in
files
.
keys
():
inputfiles
=
files
.
getlist
(
fileinput_id
)
# Check number of files submitted
if
len
(
inputfiles
)
>
settings
.
MAX_FILEUPLOADS_PER_INPUT
:
msg
=
'Submission aborted! Maximum
%
d files may be submitted at once'
%
\
settings
.
MAX_FILEUPLOADS_PER_INPUT
return
msg
# Check file sizes
for
inputfile
in
inputfiles
:
if
inputfile
.
size
>
settings
.
STUDENT_FILEUPLOAD_MAX_SIZE
:
# Bytes
msg
=
'Submission aborted! Your file "
%
s" is too large (max size:
%
d MB)'
%
\
(
inputfile
.
name
,
settings
.
STUDENT_FILEUPLOAD_MAX_SIZE
/
(
1000
**
2
))
return
msg
return
None
lms/urls.py
View file @
e4ee1c6c
...
@@ -188,7 +188,7 @@ if settings.COURSEWARE_ENABLED:
...
@@ -188,7 +188,7 @@ if settings.COURSEWARE_ENABLED:
# into the database.
# into the database.
url
(
r'^software-licenses$'
,
'licenses.views.user_software_license'
,
name
=
"user_software_license"
),
url
(
r'^software-licenses$'
,
'licenses.views.user_software_license'
,
name
=
"user_software_license"
),
url
(
r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/xqueue/(?P<userid>[^/]*)/(?P<id>.*?)/(?P<dispatch>[^/]*)$'
,
url
(
r'^courses/(?P<course_id>[^/]+/[^/]+/[^/]+)/xqueue/(?P<userid>[^/]*)/(?P<
mod_
id>.*?)/(?P<dispatch>[^/]*)$'
,
'courseware.module_render.xqueue_callback'
,
'courseware.module_render.xqueue_callback'
,
name
=
'xqueue_callback'
),
name
=
'xqueue_callback'
),
url
(
r'^change_setting$'
,
'student.views.change_setting'
,
url
(
r'^change_setting$'
,
'student.views.change_setting'
,
...
@@ -438,5 +438,3 @@ if settings.DEBUG:
...
@@ -438,5 +438,3 @@ if settings.DEBUG:
#Custom error pages
#Custom error pages
handler404
=
'static_template_view.views.render_404'
handler404
=
'static_template_view.views.render_404'
handler500
=
'static_template_view.views.render_500'
handler500
=
'static_template_view.views.render_500'
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