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
60855242
Commit
60855242
authored
Mar 05, 2013
by
Will Daly
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored capa module HTML rendering, isolating logic for
determining which buttons to show
parent
42043d2c
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
242 additions
and
50 deletions
+242
-50
common/lib/xmodule/xmodule/capa_module.py
+80
-50
common/lib/xmodule/xmodule/tests/test_capa_module.py
+162
-0
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
60855242
...
@@ -136,7 +136,7 @@ class CapaModule(XModule):
...
@@ -136,7 +136,7 @@ class CapaModule(XModule):
self
.
close_date
=
self
.
display_due_date
self
.
close_date
=
self
.
display_due_date
max_attempts
=
self
.
metadata
.
get
(
'attempts'
,
None
)
max_attempts
=
self
.
metadata
.
get
(
'attempts'
,
None
)
if
max_attempts
:
if
max_attempts
is
not
None
:
self
.
max_attempts
=
int
(
max_attempts
)
self
.
max_attempts
=
int
(
max_attempts
)
else
:
else
:
self
.
max_attempts
=
None
self
.
max_attempts
=
None
...
@@ -247,6 +247,78 @@ class CapaModule(XModule):
...
@@ -247,6 +247,78 @@ class CapaModule(XModule):
'progress'
:
Progress
.
to_js_status_str
(
self
.
get_progress
())
'progress'
:
Progress
.
to_js_status_str
(
self
.
get_progress
())
})
})
def
check_button_name
(
self
):
"""
Determine the name for the "check" button.
Usually it is just "Check", but if this is the student's
final attempt, change the name to "Final Check"
"""
if
self
.
max_attempts
is
not
None
:
final_check
=
(
self
.
attempts
>=
self
.
max_attempts
-
1
)
else
:
final_check
=
False
return
"Final Check"
if
final_check
else
"Check"
def
should_show_check_button
(
self
):
"""
Return True/False to indicate whether to show the "Check" button.
"""
submitted_without_reset
=
(
self
.
is_completed
()
and
self
.
rerandomize
==
"always"
)
# If the problem is closed (past due / too many attempts)
# then we do NOT show the "check" button
# Also, do not show the "check" button if we're waiting
# for the user to reset a randomized problem
if
self
.
closed
()
or
submitted_without_reset
:
return
False
else
:
return
True
def
should_show_reset_button
(
self
):
"""
Return True/False to indicate whether to show the "Reset" button.
"""
survey_question
=
(
self
.
max_attempts
==
0
)
if
self
.
rerandomize
in
[
"always"
,
"onreset"
]:
# If the problem is closed (and not a survey question with max_attempts==0),
# then do NOT show the reset button.
# If the problem hasn't been submitted yet, then do NOT show
# the reset button.
if
(
self
.
closed
()
and
not
survey_question
)
or
not
self
.
is_completed
():
return
False
else
:
return
True
# Only randomized problems need a "reset" button
else
:
return
False
def
should_show_save_button
(
self
):
"""
Return True/False to indicate whether to show the "Save" button.
"""
# If the user has forced the save button to display,
# then show it as long as the problem is not closed
# (past due / too many attempts)
if
self
.
force_save_button
==
"true"
:
return
not
self
.
closed
()
else
:
survey_question
=
(
self
.
max_attempts
==
0
)
needs_reset
=
self
.
is_completed
()
and
self
.
rerandomize
==
"always"
# If the problem is closed (and not a survey question with max_attempts==0),
# then do NOT show the reset button
# If we're waiting for the user to reset a randomized problem
# then do NOT show the reset button
if
(
self
.
closed
()
and
not
survey_question
)
or
needs_reset
:
return
False
else
:
return
True
def
get_problem_html
(
self
,
encapsulate
=
True
):
def
get_problem_html
(
self
,
encapsulate
=
True
):
'''Return html for the problem. Adds check, reset, save buttons
'''Return html for the problem. Adds check, reset, save buttons
as necessary based on the problem config and state.'''
as necessary based on the problem config and state.'''
...
@@ -313,57 +385,14 @@ class CapaModule(XModule):
...
@@ -313,57 +385,14 @@ class CapaModule(XModule):
'weight'
:
self
.
descriptor
.
weight
,
'weight'
:
self
.
descriptor
.
weight
,
}
}
# We using strings as truthy values, because the terminology of the
# check button is context-specific.
# Put a "Check" button if unlimited attempts or still some left
if
self
.
max_attempts
is
None
or
self
.
attempts
<
self
.
max_attempts
-
1
:
check_button
=
"Check"
else
:
# Will be final check so let user know that
check_button
=
"Final Check"
reset_button
=
True
save_button
=
True
# If we're after deadline, or user has exhausted attempts,
# question is read-only.
if
self
.
closed
():
check_button
=
False
reset_button
=
False
save_button
=
False
# If attempts=0 then show just check and reset buttons; this is for survey questions using capa
if
self
.
max_attempts
==
0
:
check_button
=
False
reset_button
=
True
save_button
=
True
# User submitted a problem, and hasn't reset. We don't want
# more submissions.
if
self
.
lcp
.
done
and
self
.
rerandomize
==
"always"
:
check_button
=
False
save_button
=
False
# Only show the reset button if pressing it will show different values
if
self
.
rerandomize
not
in
[
"always"
,
"onreset"
]:
reset_button
=
False
# User hasn't submitted an answer yet -- we don't want resets
if
not
self
.
lcp
.
done
:
reset_button
=
False
# We may not need a "save" button if infinite number of attempts and
# non-randomized. The problem author can force it. It's a bit weird for
# randomization to control this; should perhaps be cleaned up.
if
(
self
.
force_save_button
==
"false"
)
and
(
self
.
max_attempts
is
None
and
self
.
rerandomize
!=
"always"
):
save_button
=
False
context
=
{
'problem'
:
content
,
context
=
{
'problem'
:
content
,
'id'
:
self
.
id
,
'id'
:
self
.
id
,
'check_button'
:
check_button
,
'reset_button'
:
reset_button
,
# Pass in the name of the check button or False
'save_button'
:
save_button
,
# if we do not need a check button
'check_button'
:
self
.
check_button_name
()
if
self
.
should_show_check_button
()
else
False
,
'reset_button'
:
self
.
should_show_reset_button
(),
'save_button'
:
self
.
should_show_save_button
(),
'answer_available'
:
self
.
answer_available
(),
'answer_available'
:
self
.
answer_available
(),
'ajax_url'
:
self
.
system
.
ajax_url
,
'ajax_url'
:
self
.
system
.
ajax_url
,
'attempts_used'
:
self
.
attempts
,
'attempts_used'
:
self
.
attempts
,
...
@@ -732,6 +761,7 @@ class CapaModule(XModule):
...
@@ -732,6 +761,7 @@ class CapaModule(XModule):
# in next line)
# in next line)
self
.
lcp
.
seed
=
None
self
.
lcp
.
seed
=
None
self
.
lcp
=
LoncapaProblem
(
self
.
definition
[
'data'
],
self
.
lcp
=
LoncapaProblem
(
self
.
definition
[
'data'
],
self
.
location
.
html_id
(),
self
.
lcp
.
get_state
(),
self
.
location
.
html_id
(),
self
.
lcp
.
get_state
(),
system
=
self
.
system
)
system
=
self
.
system
)
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
60855242
...
@@ -3,6 +3,7 @@ import json
...
@@ -3,6 +3,7 @@ import json
from
mock
import
Mock
,
MagicMock
,
patch
from
mock
import
Mock
,
MagicMock
,
patch
from
pprint
import
pprint
from
pprint
import
pprint
import
unittest
import
unittest
import
random
import
xmodule
import
xmodule
import
capa
import
capa
...
@@ -618,3 +619,164 @@ class CapaModuleTest(unittest.TestCase):
...
@@ -618,3 +619,164 @@ class CapaModuleTest(unittest.TestCase):
# Expect that we succeed
# Expect that we succeed
self
.
assertTrue
(
'success'
in
result
and
result
[
'success'
])
self
.
assertTrue
(
'success'
in
result
and
result
[
'success'
])
def
test_check_button_name
(
self
):
# If last attempt, button name changes to "Final Check"
# Just in case, we also check what happens if we have
# more attempts than allowed.
attempts
=
random
.
randint
(
1
,
10
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
1
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Final Check"
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Final Check"
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
+
1
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Final Check"
)
# Otherwise, button name is "Check"
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
2
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
3
,
max_attempts
=
attempts
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
# If no limit on attempts, then always show "Check"
module
=
CapaFactory
.
create
(
attempts
=
attempts
-
3
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
module
=
CapaFactory
.
create
(
attempts
=
0
)
self
.
assertEqual
(
module
.
check_button_name
(),
"Check"
)
def
test_should_show_check_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
# If we're after the deadline, do NOT show check button
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
)
self
.
assertFalse
(
module
.
should_show_check_button
())
# If user is out of attempts, do NOT show the check button
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
self
.
assertFalse
(
module
.
should_show_check_button
())
# If survey question (max_attempts = 0), do NOT show the check button
module
=
CapaFactory
.
create
(
max_attempts
=
0
)
self
.
assertFalse
(
module
.
should_show_check_button
())
# If user submitted a problem but hasn't reset,
# do NOT show the check button
# Note: we can only reset when rerandomize="always"
module
=
CapaFactory
.
create
(
rerandomize
=
"always"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_check_button
())
# Otherwise, DO show the check button
module
=
CapaFactory
.
create
()
self
.
assertTrue
(
module
.
should_show_check_button
())
# If the user has submitted the problem
# and we do NOT have a reset button, then we can show the check button
# Setting rerandomize to "never" ensures that the reset button
# is not shown
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_check_button
())
def
test_should_show_reset_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
# If we're after the deadline, do NOT show the reset button
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_reset_button
())
# If the user is out of attempts, do NOT show the reset button
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_reset_button
())
# If we're NOT randomizing, then do NOT show the reset button
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_reset_button
())
# If the user hasn't submitted an answer yet,
# then do NOT show the reset button
module
=
CapaFactory
.
create
()
module
.
lcp
.
done
=
False
self
.
assertFalse
(
module
.
should_show_reset_button
())
# Otherwise, DO show the reset button
module
=
CapaFactory
.
create
()
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_reset_button
())
# If survey question for capa (max_attempts = 0),
# DO show the reset button
module
=
CapaFactory
.
create
(
max_attempts
=
0
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_reset_button
())
def
test_should_show_save_button
(
self
):
attempts
=
random
.
randint
(
1
,
10
)
# If we're after the deadline, do NOT show the save button
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# If the user is out of attempts, do NOT show the save button
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# If user submitted a problem but hasn't reset, do NOT show the save button
module
=
CapaFactory
.
create
(
rerandomize
=
"always"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# Otherwise, DO show the save button
module
=
CapaFactory
.
create
()
module
.
lcp
.
done
=
False
self
.
assertTrue
(
module
.
should_show_save_button
())
# If we're not randomizing, then we can re-save
module
=
CapaFactory
.
create
(
rerandomize
=
"never"
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_save_button
())
# If survey question for capa (max_attempts = 0),
# DO show the save button
module
=
CapaFactory
.
create
(
max_attempts
=
0
)
module
.
lcp
.
done
=
False
self
.
assertTrue
(
module
.
should_show_save_button
())
def
test_should_show_save_button_force_save_button
(
self
):
# If we're after the deadline, do NOT show the save button
# even though we're forcing a save
module
=
CapaFactory
.
create
(
due
=
self
.
yesterday_str
,
force_save_button
=
"true"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# If the user is out of attempts, do NOT show the save button
attempts
=
random
.
randint
(
1
,
10
)
module
=
CapaFactory
.
create
(
attempts
=
attempts
,
max_attempts
=
attempts
,
force_save_button
=
"true"
)
module
.
lcp
.
done
=
True
self
.
assertFalse
(
module
.
should_show_save_button
())
# Otherwise, if we force the save button,
# then show it even if we would ordinarily
# require a reset first
module
=
CapaFactory
.
create
(
force_save_button
=
"true"
,
rerandomize
=
"always"
)
module
.
lcp
.
done
=
True
self
.
assertTrue
(
module
.
should_show_save_button
())
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