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
7af36eb6
Commit
7af36eb6
authored
Mar 06, 2013
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1598 from MITx/diana/capa-input-ajax
Give InputTypes the ability to handle their own AJAX
parents
69601047
4b7d1deb
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
75 additions
and
7 deletions
+75
-7
common/lib/capa/capa/capa_problem.py
+37
-6
common/lib/capa/capa/inputtypes.py
+12
-0
common/lib/capa/capa/tests/test_html_render.py
+2
-0
common/lib/xmodule/xmodule/capa_module.py
+2
-0
common/lib/xmodule/xmodule/js/src/capa/display.coffee
+18
-0
common/lib/xmodule/xmodule/tests/test_capa_module.py
+4
-1
No files found.
common/lib/capa/capa/capa_problem.py
View file @
7af36eb6
...
@@ -146,6 +146,13 @@ class LoncapaProblem(object):
...
@@ -146,6 +146,13 @@ class LoncapaProblem(object):
if
not
self
.
student_answers
:
# True when student_answers is an empty dict
if
not
self
.
student_answers
:
# True when student_answers is an empty dict
self
.
set_initial_display
()
self
.
set_initial_display
()
# dictionary of InputType objects associated with this problem
# input_id string -> InputType object
self
.
inputs
=
{}
self
.
extracted_tree
=
self
.
_extract_html
(
self
.
tree
)
def
do_reset
(
self
):
def
do_reset
(
self
):
'''
'''
Reset internal state to unfinished, with no answers
Reset internal state to unfinished, with no answers
...
@@ -324,7 +331,27 @@ class LoncapaProblem(object):
...
@@ -324,7 +331,27 @@ class LoncapaProblem(object):
'''
'''
Main method called externally to get the HTML to be rendered for this capa Problem.
Main method called externally to get the HTML to be rendered for this capa Problem.
'''
'''
return
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
def
handle_input_ajax
(
self
,
get
):
'''
InputTypes can support specialized AJAX calls. Find the correct input and pass along the correct data
Also, parse out the dispatch from the get so that it can be passed onto the input type nicely
'''
# pull out the id
input_id
=
get
[
'input_id'
]
if
self
.
inputs
[
input_id
]:
dispatch
=
get
[
'dispatch'
]
return
self
.
inputs
[
input_id
]
.
handle_ajax
(
dispatch
,
get
)
else
:
log
.
warning
(
"Could not find matching input for id:
%
s"
%
problem_id
)
return
{}
# ======= Private Methods Below ========
# ======= Private Methods Below ========
...
@@ -458,6 +485,8 @@ class LoncapaProblem(object):
...
@@ -458,6 +485,8 @@ class LoncapaProblem(object):
finally
:
finally
:
sys
.
path
=
original_path
sys
.
path
=
original_path
def
_extract_html
(
self
,
problemtree
):
# private
def
_extract_html
(
self
,
problemtree
):
# private
'''
'''
Main (private) function which converts Problem XML tree to HTML.
Main (private) function which converts Problem XML tree to HTML.
...
@@ -468,6 +497,7 @@ class LoncapaProblem(object):
...
@@ -468,6 +497,7 @@ class LoncapaProblem(object):
Used by get_html.
Used by get_html.
'''
'''
if
(
problemtree
.
tag
==
'script'
and
problemtree
.
get
(
'type'
)
if
(
problemtree
.
tag
==
'script'
and
problemtree
.
get
(
'type'
)
and
'javascript'
in
problemtree
.
get
(
'type'
)):
and
'javascript'
in
problemtree
.
get
(
'type'
)):
# leave javascript intact.
# leave javascript intact.
...
@@ -484,8 +514,9 @@ class LoncapaProblem(object):
...
@@ -484,8 +514,9 @@ class LoncapaProblem(object):
msg
=
''
msg
=
''
hint
=
''
hint
=
''
hintmode
=
None
hintmode
=
None
input_id
=
problemtree
.
get
(
'id'
)
if
problemid
in
self
.
correct_map
:
if
problemid
in
self
.
correct_map
:
pid
=
problemtree
.
get
(
'id'
)
pid
=
input_id
status
=
self
.
correct_map
.
get_correctness
(
pid
)
status
=
self
.
correct_map
.
get_correctness
(
pid
)
msg
=
self
.
correct_map
.
get_msg
(
pid
)
msg
=
self
.
correct_map
.
get_msg
(
pid
)
hint
=
self
.
correct_map
.
get_hint
(
pid
)
hint
=
self
.
correct_map
.
get_hint
(
pid
)
...
@@ -496,17 +527,17 @@ class LoncapaProblem(object):
...
@@ -496,17 +527,17 @@ class LoncapaProblem(object):
value
=
self
.
student_answers
[
problemid
]
value
=
self
.
student_answers
[
problemid
]
# do the rendering
# do the rendering
state
=
{
'value'
:
value
,
state
=
{
'value'
:
value
,
'status'
:
status
,
'status'
:
status
,
'id'
:
problemtree
.
get
(
'id'
)
,
'id'
:
input_id
,
'feedback'
:
{
'message'
:
msg
,
'feedback'
:
{
'message'
:
msg
,
'hint'
:
hint
,
'hint'
:
hint
,
'hintmode'
:
hintmode
,
}}
'hintmode'
:
hintmode
,
}}
input_type_cls
=
inputtypes
.
registry
.
get_class_for_tag
(
problemtree
.
tag
)
input_type_cls
=
inputtypes
.
registry
.
get_class_for_tag
(
problemtree
.
tag
)
the_input
=
input_type_cls
(
self
.
system
,
problemtree
,
state
)
# save the input type so that we can make ajax calls on it if we need to
return
the_input
.
get_html
()
self
.
inputs
[
input_id
]
=
input_type_cls
(
self
.
system
,
problemtree
,
state
)
return
self
.
inputs
[
input_id
]
.
get_html
()
# let each Response render itself
# let each Response render itself
if
problemtree
in
self
.
responders
:
if
problemtree
in
self
.
responders
:
...
...
common/lib/capa/capa/inputtypes.py
View file @
7af36eb6
...
@@ -215,6 +215,18 @@ class InputTypeBase(object):
...
@@ -215,6 +215,18 @@ class InputTypeBase(object):
"""
"""
pass
pass
def
handle_ajax
(
self
,
dispatch
,
get
):
"""
InputTypes that need to handle specialized AJAX should override this.
Input:
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
Output:
a dictionary object that can be serialized into JSON. This will be sent back to the Javascript.
"""
pass
def
_get_render_context
(
self
):
def
_get_render_context
(
self
):
"""
"""
...
...
common/lib/capa/capa/tests/test_html_render.py
View file @
7af36eb6
...
@@ -125,6 +125,8 @@ class CapaHtmlRenderTest(unittest.TestCase):
...
@@ -125,6 +125,8 @@ class CapaHtmlRenderTest(unittest.TestCase):
expected_solution_context
=
{
'id'
:
'1_solution_1'
}
expected_solution_context
=
{
'id'
:
'1_solution_1'
}
expected_calls
=
[
mock
.
call
(
'textline.html'
,
expected_textline_context
),
expected_calls
=
[
mock
.
call
(
'textline.html'
,
expected_textline_context
),
mock
.
call
(
'solutionspan.html'
,
expected_solution_context
),
mock
.
call
(
'textline.html'
,
expected_textline_context
),
mock
.
call
(
'solutionspan.html'
,
expected_solution_context
)]
mock
.
call
(
'solutionspan.html'
,
expected_solution_context
)]
self
.
assertEqual
(
test_system
.
render_template
.
call_args_list
,
self
.
assertEqual
(
test_system
.
render_template
.
call_args_list
,
...
...
common/lib/xmodule/xmodule/capa_module.py
View file @
7af36eb6
...
@@ -412,6 +412,7 @@ class CapaModule(XModule):
...
@@ -412,6 +412,7 @@ class CapaModule(XModule):
'weight'
:
self
.
descriptor
.
weight
,
'weight'
:
self
.
descriptor
.
weight
,
}
}
context
=
{
'problem'
:
content
,
context
=
{
'problem'
:
content
,
'id'
:
self
.
id
,
'id'
:
self
.
id
,
'check_button'
:
check_button
,
'check_button'
:
check_button
,
...
@@ -449,6 +450,7 @@ class CapaModule(XModule):
...
@@ -449,6 +450,7 @@ class CapaModule(XModule):
'problem_save'
:
self
.
save_problem
,
'problem_save'
:
self
.
save_problem
,
'problem_show'
:
self
.
get_answer
,
'problem_show'
:
self
.
get_answer
,
'score_update'
:
self
.
update_score
,
'score_update'
:
self
.
update_score
,
'input_ajax'
:
self
.
lcp
.
handle_input_ajax
}
}
if
dispatch
not
in
handlers
:
if
dispatch
not
in
handlers
:
...
...
common/lib/xmodule/xmodule/js/src/capa/display.coffee
View file @
7af36eb6
...
@@ -76,6 +76,24 @@ class @Problem
...
@@ -76,6 +76,24 @@ class @Problem
# TODO: Some logic to dynamically adjust polling rate based on queuelen
# TODO: Some logic to dynamically adjust polling rate based on queuelen
window
.
queuePollerID
=
window
.
setTimeout
(
@
poll
,
1000
)
window
.
queuePollerID
=
window
.
setTimeout
(
@
poll
,
1000
)
# Use this if you want to make an ajax call on the input type object
# static method so you don't have to instantiate a Problem in order to use it
# Input:
# url: the AJAX url of the problem
# input_id: the input_id of the input you would like to make the call on
# NOTE: the id is the ${id} part of "input_${id}" during rendering
# If this function is passed the entire prefixed id, the backend may have trouble
# finding the correct input
# dispatch: string that indicates how this data should be handled by the inputtype
# callback: the function that will be called once the AJAX call has been completed.
# It will be passed a response object
@
inputAjax
:
(
url
,
input_id
,
dispatch
,
data
,
callback
)
->
data
[
'dispatch'
]
=
dispatch
data
[
'input_id'
]
=
input_id
$
.
postWithPrefix
"
#{
url
}
/input_ajax"
,
data
,
callback
render
:
(
content
)
->
render
:
(
content
)
->
if
content
if
content
@
el
.
html
(
content
)
@
el
.
html
(
content
)
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
7af36eb6
...
@@ -108,7 +108,9 @@ class CapaFactory(object):
...
@@ -108,7 +108,9 @@ class CapaFactory(object):
else
:
else
:
instance_state
=
None
instance_state
=
None
module
=
CapaModule
(
test_system
(),
location
,
system
=
test_system
()
system
.
render_template
=
Mock
(
return_value
=
"<div>Test Template HTML</div>"
)
module
=
CapaModule
(
system
,
location
,
definition
,
descriptor
,
definition
,
descriptor
,
instance_state
,
None
,
metadata
=
metadata
)
instance_state
,
None
,
metadata
=
metadata
)
...
@@ -185,6 +187,7 @@ class CapaModuleTest(unittest.TestCase):
...
@@ -185,6 +187,7 @@ class CapaModuleTest(unittest.TestCase):
max_attempts
=
"1"
,
max_attempts
=
"1"
,
attempts
=
"0"
,
attempts
=
"0"
,
due
=
self
.
yesterday_str
)
due
=
self
.
yesterday_str
)
self
.
assertTrue
(
after_due_date
.
answer_available
())
self
.
assertTrue
(
after_due_date
.
answer_available
())
...
...
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