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
055fd6ea
Commit
055fd6ea
authored
Jun 08, 2016
by
Albert St. Aubin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactored the status icon and span to a unified template and updated tests
parent
04fa2a42
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
175 additions
and
173 deletions
+175
-173
common/lib/capa/capa/inputtypes.py
+34
-27
common/lib/capa/capa/templates/annotationinput.html
+5
-7
common/lib/capa/capa/templates/chemicalequationinput.html
+11
-13
common/lib/capa/capa/templates/choicegroup.html
+10
-8
common/lib/capa/capa/templates/choicetext.html
+1
-3
common/lib/capa/capa/templates/codeinput.html
+3
-6
common/lib/capa/capa/templates/crystallography.html
+1
-3
common/lib/capa/capa/templates/designprotein2dinput.html
+1
-3
common/lib/capa/capa/templates/drag_and_drop_input.html
+2
-1
common/lib/capa/capa/templates/editageneinput.html
+2
-2
common/lib/capa/capa/templates/editamolecule.html
+2
-2
common/lib/capa/capa/templates/formulaequationinput.html
+3
-5
common/lib/capa/capa/templates/imageinput.html
+1
-7
common/lib/capa/capa/templates/javascriptinput.html
+2
-1
common/lib/capa/capa/templates/jsinput.html
+2
-2
common/lib/capa/capa/templates/matlabinput.html
+3
-6
common/lib/capa/capa/templates/optioninput.html
+2
-6
common/lib/capa/capa/templates/schematicinput.html
+2
-2
common/lib/capa/capa/templates/solutionspan.html
+1
-0
common/lib/capa/capa/templates/status_span.html
+13
-0
common/lib/capa/capa/templates/textline.html
+3
-5
common/lib/capa/capa/tests/helpers.py
+2
-1
common/lib/capa/capa/tests/test_html_render.py
+7
-6
common/lib/capa/capa/tests/test_input_templates.py
+21
-29
common/lib/capa/capa/tests/test_inputtypes.py
+0
-0
common/lib/xmodule/xmodule/css/capa/display.scss
+18
-11
common/lib/xmodule/xmodule/js/src/capa/display.js
+2
-3
common/static/sass/edx-pattern-library-shims/base/_variables.scss
+7
-0
lms/djangoapps/instructor_task/tests/test_tasks_helper.py
+14
-14
No files found.
common/lib/capa/capa/inputtypes.py
View file @
055fd6ea
...
...
@@ -39,25 +39,27 @@ graded status as'status'
# makes sense, but a bunch of problems have markup that assumes block. Bigger TODO: figure out a
# general css and layout strategy for capa, document it, then implement it.
import
time
import
json
import
logging
from
lxml
import
etree
import
re
import
shlex
# for splitting quoted strings
import
sys
import
pyparsing
import
html5lib
import
bleach
import
time
from
datetime
import
datetime
from
.util
import
sanitize_html
from
.registry
import
TagRegistry
from
chem
import
chemcalc
import
bleach
import
html5lib
import
pyparsing
import
re
from
calc.preview
import
latex_preview
from
chem
import
chemcalc
from
lxml
import
etree
from
openedx.core.djangolib.markup
import
HTML
,
Text
import
xqueue_interface
from
xqueue_interface
import
XQUEUE_TIMEOUT
from
datetime
import
datetime
from
xmodule.stringify
import
stringify_children
from
capa.xqueue_interface
import
XQUEUE_TIMEOUT
from
.registry
import
TagRegistry
from
.util
import
sanitize_html
log
=
logging
.
getLogger
(
__name__
)
...
...
@@ -232,7 +234,8 @@ class InputTypeBase(object):
# put hint above msg if it should be displayed
if
self
.
hintmode
==
'always'
:
self
.
msg
=
self
.
hint
+
(
'<br/>'
if
self
.
msg
else
''
)
+
self
.
msg
self
.
msg
=
HTML
(
'{hint}<br/>{msg}'
if
self
.
msg
else
'{hint}'
)
.
format
(
hint
=
HTML
(
self
.
hint
),
msg
=
HTML
(
self
.
msg
))
self
.
status
=
state
.
get
(
'status'
,
'unanswered'
)
...
...
@@ -322,15 +325,18 @@ class InputTypeBase(object):
'msg'
:
self
.
msg
,
'response_data'
:
self
.
response_data
,
'STATIC_URL'
:
self
.
capa_system
.
STATIC_URL
,
'describedby_html'
:
''
,
'describedby_html'
:
HTML
(
''
)
,
}
# Don't add aria-describedby attribute if there are no descriptions
if
self
.
response_data
.
get
(
'descriptions'
):
description_ids
=
' '
.
join
(
self
.
response_data
.
get
(
'descriptions'
)
.
keys
())
context
.
update
(
{
'describedby_html'
:
'aria-describedby="{}"'
.
format
(
description_ids
)}
)
# Generate the list of ids to be used with the aria-describedby field.
# Every list should contain the status id
status_id
=
'status_'
+
self
.
input_id
descriptions
=
list
([
status_id
])
descriptions
.
extend
(
self
.
response_data
.
get
(
'descriptions'
,
{})
.
keys
())
description_ids
=
' '
.
join
(
descriptions
)
context
.
update
(
{
'describedby_html'
:
HTML
(
'aria-describedby="{}"'
)
.
format
(
description_ids
)}
)
context
.
update
(
(
a
,
v
)
for
(
a
,
v
)
in
self
.
loaded_attributes
.
iteritems
()
if
a
in
self
.
to_render
...
...
@@ -522,9 +528,10 @@ class ChoiceGroup(InputTypeBase):
choices
.
append
((
choice
.
get
(
"name"
),
stringify_children
(
choice
)))
else
:
if
choice
.
tag
!=
'compoundhint'
:
msg
=
u'[capa.inputtypes.extract_choices] {error_message}'
.
format
(
# Translators: '<choice>' and '<compoundhint>' are tag names and should not be translated.
error_message
=
_
(
'Expected a <choice> or <compoundhint> tag; got {given_tag} instead'
)
.
format
(
msg
=
Text
(
'[capa.inputtypes.extract_choices] {error_message}'
)
.
format
(
error_message
=
Text
(
# Translators: '<choice>' and '<compoundhint>' are tag names and should not be translated.
_
(
'Expected a <choice> or <compoundhint> tag; got {given_tag} instead'
))
.
format
(
given_tag
=
choice
.
tag
)
)
...
...
@@ -939,13 +946,13 @@ class MatlabInput(CodeInput):
queue_msg
=
self
.
queue_msg
if
len
(
self
.
queue_msg
)
>
0
:
# An empty string cannot be parsed as XML but is okay to include in the template.
try
:
etree
.
XML
(
u'<div>{0}</div>'
.
format
(
self
.
queue_msg
))
etree
.
XML
(
HTML
(
u'<div>{0}</div>'
)
.
format
(
HTML
(
self
.
queue_msg
)
))
except
etree
.
XMLSyntaxError
:
try
:
html5lib
.
parseFragment
(
self
.
queue_msg
,
treebuilder
=
'lxml'
,
namespaceHTMLElements
=
False
)[
0
]
except
(
IndexError
,
ValueError
):
# If neither can parse queue_msg, it contains invalid xml.
queue_msg
=
u"<span>{0}</span>"
.
format
(
_
(
"Error running code."
))
queue_msg
=
HTML
(
"<span>{0}</span>"
)
.
format
(
_
(
"Error running code."
))
extra_context
=
{
'queue_len'
:
str
(
self
.
queue_len
),
...
...
@@ -1797,10 +1804,10 @@ class ChoiceTextGroup(InputTypeBase):
for
choice
in
element
:
if
choice
.
tag
!=
'choice'
:
msg
=
u"[capa.inputtypes.extract_choices] {0}"
.
format
(
msg
=
Text
(
"[capa.inputtypes.extract_choices] {0}"
)
.
format
(
# Translators: a "tag" is an XML element, such as "<b>" in HTML
_
(
"Expected a {expected_tag} tag; got {given_tag} instead"
)
.
format
(
expected_tag
=
u
"<choice>"
,
Text
(
_
(
"Expected a {expected_tag} tag; got {given_tag} instead"
)
)
.
format
(
expected_tag
=
"<choice>"
,
given_tag
=
choice
.
tag
,
)
)
...
...
common/lib/capa/capa/templates/annotationinput.html
View file @
055fd6ea
...
...
@@ -22,12 +22,10 @@
% for option in options:
<li>
% if has_options_value:
% if all([c == 'correct' for c in option['choice'], status]):
<span
class=
"tag-status correct"
id=
"status_${id}"
aria-describedby=
"input_${id}_comment"
><span
class=
"sr"
>
Status: Correct
</span></span>
% elif all([c == 'partially-correct' for c in option['choice'], status]):
<span
class=
"tag-status partially-correct"
id=
"status_${id}"
aria-describedby=
"input_${id}_comment"
><span
class=
"sr"
>
Status: Partially Correct
</span></span>
% elif all([c == 'incorrect' for c in option['choice'], status]):
<span
class=
"tag-status incorrect"
id=
"status_${id}"
aria-describedby=
"input_${id}_comment"
><span
class=
"sr"
>
Status: Incorrect
</span></span>
% if all([c == status.classname for c in option['choice'], status]):
<span
class=
"tag-status ${status.classname}"
aria-describedby=
"input_${id}_comment"
>
<
%
include
file=
"status_span.html"
args=
"status=status"
/>
</span>
% endif
% endif
...
...
@@ -53,7 +51,7 @@
<input
type=
"hidden"
class=
"value"
name=
"input_${id}"
id=
"input_${id}"
value=
"${value|h}"
/>
% endif
<
span
class=
"status ${status.classname}"
id=
"status_${id}"
aria-describedby=
"label_${id}"
><span
class=
"sr"
>
${status.display_name}
</span></span
>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
<p
id=
"answer_${id}"
class=
"answer answer-annotation"
></p>
</div>
...
...
common/lib/capa/capa/templates/chemicalequationinput.html
View file @
055fd6ea
...
...
@@ -2,23 +2,21 @@
<div
id=
"chemicalequationinput_${id}"
class=
"chemicalequationinput"
>
<div
class=
"script_placeholder"
data-src=
"${previewer}"
/>
<div
class=
"${status.classname}"
id=
"status_${id}"
>
<div
class=
"${status.classname}"
>
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
aria-label=
"${remove_markup(response_data['label'])}"
aria-describedby=
"answer_${id}"
data-input-id=
"${id}"
value=
"${value|h}"
%
if
size:
size=
"${size}"
%
endif
/>
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
aria-label=
"${remove_markup(response_data['label'])}"
aria-describedby=
"answer_${id}"
data-input-id=
"${id}"
value=
"${value|h}"
%
if
size:
size=
"${size}"
%
endif
/>
<p
class=
"status"
aria-describedby=
"input_${id}"
>
<p
class=
"status"
>
${value|h}
<
span
class=
"sr"
>
${status.display_name}
</span
>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
</p>
<div
id=
"input_${id}_preview"
class=
"equation"
></div>
<p
id=
"answer_${id}"
class=
"answer"
></p>
% if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']:
</div>
% endif
<p
id=
"answer_${id}"
class=
"answer"
></p>
</div>
</div>
common/lib/capa/capa/templates/choicegroup.html
View file @
055fd6ea
...
...
@@ -7,7 +7,7 @@
))
%
>
<form
class=
"choicegroup capa_inputtype"
id=
"inputtype_${id}"
>
<fieldset
${
HTML
(
describedby_html
)
}
>
<fieldset
${
describedby_html
}
>
% if response_data['label']:
<legend
id=
"${id}-legend"
class=
"response-fieldset-legend field-group-hd"
>
${response_data['label']}
</legend>
% endif
...
...
@@ -37,7 +37,7 @@
% endif
% endif
class="${label_class}"
${
HTML(describedby_html)
}
${
describedby_html
}
>
<input
type=
"${input_type}"
name=
"input_${id}${name_array_suffix}"
id=
"input_${id}_${choice_id}"
class=
"field-input input-${input_type}"
value=
"${choice_id}"
##
If
the
student
selected
this
choice
...
...
...
@@ -49,8 +49,8 @@
/>
${HTML(choice_label)}
% if is_radio_input(choice_id):
% if
status in ('correct', 'partially-correct', 'incorrect') and not show_correctness == 'never
':
<
span
class=
"sr status"
id=
"${id}-${choice_id}-labeltext"
>
${status.display_name}
</span
>
% if
not show_correctness == 'never' and status.classname != 'unanswered
':
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
% endif
% endif
</label>
...
...
@@ -59,10 +59,12 @@
<span
id=
"answer_${id}"
></span>
</fieldset>
<div
class=
"indicator-container"
>
% if input_type == 'checkbox' or not value:
<span
class=
"status ${status.classname if show_correctness != 'never' else 'unanswered'}"
id=
"status_${id}"
aria-describedby=
"${id}-legend"
data-tooltip=
"${status.display_tooltip}"
>
<span
class=
"sr"
>
${status.display_tooltip}
</span>
</span>
% if input_type == 'checkbox' or status.classname == 'unanswered':
% if show_correctness != 'never':
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
% else:
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id, hide_correctness=True"
/>
% endif
% endif
</div>
% if show_correctness == "never" and (value or status not in ['unsubmitted']):
...
...
common/lib/capa/capa/templates/choicetext.html
View file @
055fd6ea
...
...
@@ -66,9 +66,7 @@ from openedx.core.djangolib.markup import HTML
<div
class=
"indicator-container"
>
% if input_type == 'checkbox' or not element_checked:
<span
class=
"status ${status.classname}"
id=
"status_${id}"
>
<span
class=
"sr"
>
${status.display_name}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
% endif
</div>
...
...
common/lib/capa/capa/templates/codeinput.html
View file @
055fd6ea
...
...
@@ -26,12 +26,9 @@ from openedx.core.djangolib.markup import HTML
</span>
<div
class=
"grader-status"
tabindex=
"-1"
>
<span
id=
"status_${id}"
class=
"${status.classname}"
aria-describedby=
"input_${id}"
>
<span
class=
"status sr"
>
${status.display_name}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
% if status == 'queued':
<span
style=
"display:none;"
class=
"xqueue"
id=
"${id}"
>
${queue_len}
</span>
% endif
...
...
common/lib/capa/capa/templates/crystallography.html
View file @
055fd6ea
...
...
@@ -16,9 +16,7 @@
<input
type=
"text"
name=
"input_${id}"
aria-describedby=
"answer_${id}"
id=
"input_${id}"
value=
"${value|h}"
style=
"display:none;"
/>
<p
class=
"status"
aria-describedby=
"input_${id}"
>
<span
class=
"sr"
>
${status.display_name}
</span>
</p>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
<p
id=
"answer_${id}"
class=
"answer"
></p>
...
...
common/lib/capa/capa/templates/designprotein2dinput.html
View file @
055fd6ea
...
...
@@ -10,9 +10,7 @@
<input
type=
"hidden"
name=
"target_shape"
id=
"target_shape"
value =
"${target_shape}"
></input>
<input
type=
"hidden"
name=
"input_${id}"
id=
"input_${id}"
aria-describedby=
"answer_${id}"
value=
"${value|h}"
/>
<p
class=
"status"
aria-describedby=
"input_${id}"
>
<span
class=
"sr"
>
${status.display_name}
</span>
</p>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
<p
id=
"answer_${id}"
class=
"answer"
></p>
% if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']:
...
...
common/lib/capa/capa/templates/drag_and_drop_input.html
View file @
055fd6ea
...
...
@@ -17,8 +17,9 @@
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
aria-describedby=
"answer_${id}"
value=
"${value|h}"
style=
"display:none;"
/>
<p
class=
"status drag-and-drop--status"
aria-describedby=
"input_${id}"
>
<
span
class=
"sr"
>
${status.display_name}
</span
>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
</p>
<p
id=
"answer_${id}"
class=
"answer"
></p>
...
...
common/lib/capa/capa/templates/editageneinput.html
View file @
055fd6ea
...
...
@@ -3,7 +3,7 @@
<div
class=
"script_placeholder"
data-src=
"${applet_loader}"
/>
% if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']:
<div
class=
"${status.classname}"
id=
"status_${id}"
>
<div
class=
"${status.classname}"
>
% endif
<div
id=
"genex_container"
></div>
...
...
@@ -12,7 +12,7 @@
<input
type=
"hidden"
name=
"input_${id}"
aria-describedby=
"answer_${id}"
id=
"input_${id}"
value=
"${value|h}"
/>
<p
class=
"status"
aria-describedby=
"input_${id}"
>
<
span
class=
"sr"
>
${status.display_name}
</span
>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
</p>
<p
id=
"answer_${id}"
class=
"answer"
></p>
...
...
common/lib/capa/capa/templates/editamolecule.html
View file @
055fd6ea
...
...
@@ -2,7 +2,7 @@
<div
class=
"script_placeholder"
data-src=
"${applet_loader}"
/>
% if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']:
<div
class=
"${status.classname}"
id=
"status_${id}"
>
<div
class=
"${status.classname}"
>
% endif
<div
id=
"applet_${id}"
class=
"applet"
data-molfile-src=
"${file}"
style=
"display:block;width:500px;height:400px"
>
...
...
@@ -17,7 +17,7 @@
<p
id=
"answer_${id}"
class=
"answer"
></p>
<p
class=
"status"
aria-describedby=
"input_${id}"
>
<
span
class=
"sr"
>
${status.display_name}
</span
>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
</p>
<div
class=
"error_message"
style=
"padding: 5px 5px 5px 5px; background-color:#FA6666; height:60px;width:400px; display: none"
></div>
...
...
common/lib/capa/capa/templates/formulaequationinput.html
View file @
055fd6ea
...
...
@@ -2,7 +2,7 @@
<
%!
from
openedx
.
core
.
djangolib
.
markup
import
HTML
%
>
<
%
doinline =
'style="display:inline-block;vertical-align:top"'
if
inline
else
""
%
>
<div
id=
"formulaequationinput_${id}"
class=
"inputtype formulaequationinput"
${
doinline
|
n
,
decode
.
utf8
}
>
<div
class=
"${status.classname}"
id=
"status_${id}"
>
<div
class=
"${status.classname}"
>
% if response_data['label']:
<label
class=
"problem-group-label"
for=
"input_${id}"
id=
"label_${id}"
>
${response_data['label']}
</label>
% endif
...
...
@@ -11,16 +11,14 @@
% endfor
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
data-input-id=
"${id}"
value=
"${value}"
${
HTML
(
describedby_html
)
}
${
describedby_html
}
%
if
size:
size=
"${size}"
%
endif
/>
<span
class=
"trailing_text"
>
${trailing_text}
</span>
<span
class=
"status"
id=
"${id}_status"
aria-describedby=
"label_${id}"
data-tooltip=
"${status.display_tooltip}"
>
<span
class=
"sr"
>
${status.display_tooltip}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
<p
id=
"answer_${id}"
class=
"answer"
></p>
...
...
common/lib/capa/capa/templates/imageinput.html
View file @
055fd6ea
...
...
@@ -40,11 +40,5 @@
(
new
ImageInput
(
'${id}'
));
</script>
<span
class=
"status ${status.classname}"
id=
"status_${id}"
aria-describedby=
"input_${id}"
>
<span
class=
"sr"
>
${status.display_name}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
</div>
common/lib/capa/capa/templates/javascriptinput.html
View file @
055fd6ea
<
%
page
expression_filter=
"h"
/>
<form
class=
"javascriptinput capa_inputtype"
id=
"inputtype_${id}"
>
<input
type=
"hidden"
name=
"input_${id}"
id=
"input_${id}"
class=
"javascriptinput_input"
/>
<div
class=
"javascriptinput_data"
data-display_class=
"${display_class}"
data-problem_state=
"${problem_state}"
data-params=
"${params}"
data-submission=
"${value
|h}"
data-evaluation=
"${msg|h
}"
>
data-submission=
"${value
}"
data-evaluation=
"${msg
}"
>
</div>
<div
class=
"script_placeholder"
data-src=
"/static/js/${display_file}"
></div>
<div
class=
"javascriptinput_container"
></div>
...
...
common/lib/capa/capa/templates/jsinput.html
View file @
055fd6ea
...
...
@@ -22,7 +22,7 @@
<div
class=
"script_placeholder"
data-src=
"${jschannel_loader}"
/>
<div
class=
"script_placeholder"
data-src=
"${jsinput_loader}"
/>
% if status in ['unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete']:
<div
class=
"${status.classname}"
id=
"status_${id}"
>
<div
class=
"${status.classname}"
>
% endif
<iframe
name=
"iframe_${id}"
...
...
@@ -42,7 +42,7 @@
<p
id=
"answer_${id}"
class=
"answer"
></p>
<p
class=
"status"
>
<span
class=
"sr"
>
${status.display_name}
</span
>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
</p>
<div
class=
"error_message"
style=
"padding: 5px 5px 5px 5px; background-color:#FA6666; height:60px;width:400px; display: none"
></div>
...
...
common/lib/capa/capa/templates/matlabinput.html
View file @
055fd6ea
...
...
@@ -17,12 +17,9 @@
>
${value|h}
</textarea>
<div
class=
"grader-status"
tabindex=
"-1"
>
<span
id=
"status_${id}"
class=
"${status.classname}"
aria-describedby=
"input_${id}"
>
<span
class=
"status sr"
>
${status.display_name}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
% if status == 'queued':
<span
style=
"display:none;"
class=
"xqueue"
id=
"${id}"
>
${queue_len}
</span>
% endif
...
...
common/lib/capa/capa/templates/optioninput.html
View file @
055fd6ea
...
...
@@ -11,7 +11,7 @@
<p
class=
"question-description"
id=
"${description_id}"
>
${description_text}
</p>
% endfor
<select
name=
"input_${id}"
id=
"input_${id}"
${
HTML
(
describedby_html
)
}
>
<select
name=
"input_${id}"
id=
"input_${id}"
${
describedby_html
}
>
<option
value=
"option_${id}_dummy_default"
>
${default_option_text}
</option>
% for option_id, option_description in options:
<option
value=
"${option_id}"
...
...
@@ -23,11 +23,7 @@
</select>
<div
class=
"indicator-container"
>
<span
class=
"status ${status.classname}"
id=
"status_${id}"
aria-describedby=
"label_${id}"
data-tooltip=
"${status.display_tooltip}"
>
<span
class=
"sr"
>
${status.display_tooltip}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
</div>
<p
class=
"answer"
id=
"answer_${id}"
></p>
% if msg:
...
...
common/lib/capa/capa/templates/schematicinput.html
View file @
055fd6ea
...
...
@@ -18,7 +18,7 @@
<span
id=
"answer_${id}"
></span>
<div
class=
"indicator-container"
>
<
span
class=
"status ${status.classname}"
id=
"status_${id}"
aria-describedby=
"input_${id}"
></span
>
<span
class=
"sr"
>
${status.display_tooltip}
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/
>
</div>
</div>
common/lib/capa/capa/templates/solutionspan.html
View file @
055fd6ea
<
%
page
expression_filter=
"h"
/>
<div
class=
"solution-span"
>
<span
id=
"solution_${id}"
></span>
</div>
common/lib/capa/capa/templates/status_span.html
0 → 100644
View file @
055fd6ea
<
%
page
expression_filter=
"h"
args=
"status, status_id='', hide_correctness=False"
/>
% if status_id == '':
<span
class=
"status ${'' if hide_correctness == True else status.classname}"
data-tooltip=
"${'' if hide_correctness == True else status.display_tooltip}"
>
% else:
<span
class=
"status ${'' if hide_correctness == True else status.classname}"
id=
"status_${status_id}"
data-tooltip=
"${'' if hide_correctness == True else status.display_tooltip}"
>
% endif
% if hide_correctness == False:
<span
class=
"sr"
>
${status.display_name}
</span><span
class=
"status-icon"
aria-hidden=
"true"
></span>
% endif
</span>
common/lib/capa/capa/templates/textline.html
View file @
055fd6ea
...
...
@@ -9,7 +9,7 @@
% endif
% if status in ('unsubmitted', 'correct', 'incorrect', 'partially-correct', 'incomplete'):
<div
class=
"${status.classname} ${doinline}"
id=
"status_${id}"
>
<div
class=
"${status.classname} ${doinline}"
>
% endif
% if hidden:
...
...
@@ -23,7 +23,7 @@
% for description_id, description_text in response_data['descriptions'].items():
<p
class=
"question-description"
id=
"${description_id}"
>
${description_text}
</p>
% endfor
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
${
HTML
(
describedby_html
)
}
value=
"${value}"
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
${
describedby_html
}
value=
"${value}"
%
if
do_math:
class=
"math"
%
endif
...
...
@@ -36,9 +36,7 @@
/>
<span
class=
"trailing_text"
>
${trailing_text}
</span>
<span
class=
"status"
aria-describedby=
"label_${id}"
data-tooltip=
"${status.display_tooltip}"
>
<span
class=
"sr"
>
${status.display_tooltip}
</span>
</span>
<
%
include
file=
"status_span.html"
args=
"status=status, status_id=id"
/>
<p
id=
"answer_${id}"
class=
"answer"
></p>
...
...
common/lib/capa/capa/tests/helpers.py
View file @
055fd6ea
...
...
@@ -22,7 +22,8 @@ def get_template(template_name):
Return template for a capa inputtype.
"""
return
TemplateLookup
(
directories
=
[
path
(
__file__
)
.
dirname
()
.
dirname
()
/
'templates'
]
directories
=
[
path
(
__file__
)
.
dirname
()
.
dirname
()
/
'templates'
],
default_filters
=
[
'decode.utf8'
]
)
.
get_template
(
template_name
)
...
...
common/lib/capa/capa/tests/test_html_render.py
View file @
055fd6ea
"""
CAPA HTML rendering tests.
"""
import
ddt
import
unittest
from
lxml
import
etree
import
os
import
textwrap
import
unittest
import
ddt
import
mock
import
os
from
capa.tests.helpers
import
test_capa_system
,
new_loncapa_problem
from
lxml
import
etree
from
openedx.core.djangolib.markup
import
HTML
from
.response_xml_factory
import
StringResponseXMLFactory
,
CustomResponseXMLFactory
from
capa.tests.helpers
import
test_capa_system
,
new_loncapa_problem
@ddt.ddt
...
...
@@ -190,7 +191,7 @@ class CapaHtmlRenderTest(unittest.TestCase):
'trailing_text'
:
''
,
'size'
:
None
,
'response_data'
:
{
'label'
:
'Test question'
,
'descriptions'
:
{}},
'describedby_html'
:
''
'describedby_html'
:
HTML
(
'aria-describedby="status_1_2_1"'
)
}
expected_solution_context
=
{
'id'
:
'1_solution_1'
}
...
...
common/lib/capa/capa/tests/test_input_templates.py
View file @
055fd6ea
...
...
@@ -2,15 +2,16 @@
Tests for the logic in input type mako templates.
"""
from
collections
import
OrderedDict
import
unittest
import
capa
import
os.path
import
json
import
unittest
from
collections
import
OrderedDict
from
capa.inputtypes
import
Status
from
capa.tests.helpers
import
capa_render_template
from
lxml
import
etree
from
mako.template
import
Template
as
MakoTemplate
from
mako
import
exceptions
from
capa.inputtypes
import
Status
from
openedx.core.djangolib.markup
import
HTML
from
xmodule.stringify
import
stringify_children
...
...
@@ -23,7 +24,7 @@ class TemplateError(Exception):
class
TemplateTestCase
(
unittest
.
TestCase
):
"""
Utiliti
t
es for testing templates.
Utilities for testing templates.
"""
# Subclasses override this to specify the file name of the template
...
...
@@ -46,16 +47,9 @@ class TemplateTestCase(unittest.TestCase):
def
setUp
(
self
):
"""
Load the template under tes
t.
Initialize the contex
t.
"""
super
(
TemplateTestCase
,
self
)
.
setUp
()
capa_path
=
capa
.
__path__
[
0
]
self
.
template_path
=
os
.
path
.
join
(
capa_path
,
'templates'
,
self
.
TEMPLATE_NAME
)
with
open
(
self
.
template_path
)
as
f
:
self
.
template
=
MakoTemplate
(
f
.
read
(),
default_filters
=
[
'decode.utf8'
])
self
.
context
=
{}
def
render_to_xml
(
self
,
context_dict
):
...
...
@@ -66,7 +60,7 @@ class TemplateTestCase(unittest.TestCase):
# add dummy STATIC_URL to template context
context_dict
.
setdefault
(
"STATIC_URL"
,
"/dummy-static/"
)
try
:
xml_str
=
self
.
template
.
render_unicode
(
**
context_dict
)
xml_str
=
capa_render_template
(
self
.
TEMPLATE_NAME
,
context_dict
)
except
:
raise
TemplateError
(
exceptions
.
text_error_template
()
.
render
())
...
...
@@ -196,10 +190,10 @@ class TemplateTestCase(unittest.TestCase):
# (used to by CSS to draw the green check / red x)
self
.
assert_has_text
(
xml
,
"//span[@class=
normalize-space('status {}')
]/span[@class='sr']"
.
format
(
"//span[@class=
'status {}'
]/span[@class='sr']"
.
format
(
div_class
if
status_class
else
''
),
self
.
context
[
'status'
]
.
display_
tooltip
self
.
context
[
'status'
]
.
display_
name
)
def
assert_label
(
self
,
xpath
=
None
,
aria_label
=
False
):
...
...
@@ -259,7 +253,7 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
'name_array_suffix'
:
'1'
,
'value'
:
'3'
,
'response_data'
:
self
.
RESPONSE_DATA
,
'describedby_html'
:
self
.
DESCRIBEDBY
,
'describedby_html'
:
HTML
(
self
.
DESCRIBEDBY
)
,
}
def
test_problem_marked_correct
(
self
):
...
...
@@ -290,11 +284,9 @@ class ChoiceGroupTemplateTest(TemplateTestCase):
(not a particular option) is marked incorrect.
"""
conditions
=
[
{
'status'
:
Status
(
'incorrect'
),
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
Status
(
'incorrect'
),
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'status'
:
Status
(
'incorrect'
),
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
]},
{
'status'
:
Status
(
'incorrect'
),
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
,
'3'
]},
{
'status'
:
Status
(
'incomplete'
),
'input_type'
:
'radio'
,
'value'
:
''
},
{
'status'
:
Status
(
'incomplete'
),
'input_type'
:
'checkbox'
,
'value'
:
[]},
{
'status'
:
Status
(
'incomplete'
),
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
]},
{
'status'
:
Status
(
'incomplete'
),
'input_type'
:
'checkbox'
,
'value'
:
[
'2'
,
'3'
]}]
...
...
@@ -506,7 +498,7 @@ class TextlineTemplateTest(TemplateTestCase):
'preprocessor'
:
None
,
'trailing_text'
:
None
,
'response_data'
:
self
.
RESPONSE_DATA
,
'describedby_html'
:
self
.
DESCRIBEDBY
,
'describedby_html'
:
HTML
(
self
.
DESCRIBEDBY
)
,
}
def
test_section_class
(
self
):
...
...
@@ -526,7 +518,7 @@ class TextlineTemplateTest(TemplateTestCase):
"""
Verify status information.
"""
self
.
assert_status
(
status_
div
=
True
)
self
.
assert_status
(
status_
class
=
True
)
def
test_label
(
self
):
"""
...
...
@@ -632,7 +624,7 @@ class FormulaEquationInputTemplateTest(TemplateTestCase):
'reported_status'
:
'REPORTED_STATUS'
,
'trailing_text'
:
None
,
'response_data'
:
self
.
RESPONSE_DATA
,
'describedby_html'
:
self
.
DESCRIBEDBY
,
'describedby_html'
:
HTML
(
self
.
DESCRIBEDBY
)
,
}
def
test_no_size
(
self
):
...
...
@@ -657,7 +649,7 @@ class FormulaEquationInputTemplateTest(TemplateTestCase):
"""
Verify status information.
"""
self
.
assert_status
(
status_
div
=
True
)
self
.
assert_status
(
status_
class
=
True
)
def
test_label
(
self
):
"""
...
...
@@ -852,7 +844,7 @@ class OptionInputTemplateTest(TemplateTestCase):
'value'
:
0
,
'default_option_text'
:
'Select an option'
,
'response_data'
:
self
.
RESPONSE_DATA
,
'describedby_html'
:
self
.
DESCRIBEDBY
,
'describedby_html'
:
HTML
(
self
.
DESCRIBEDBY
)
,
}
def
test_select_options
(
self
):
...
...
@@ -929,8 +921,8 @@ class DragAndDropTemplateTest(TemplateTestCase):
xpath
=
"//div[@class='{0}']"
.
format
(
expected_css_class
)
self
.
assert_has_xpath
(
xml
,
xpath
,
self
.
context
)
# Expect a <
p
> with the status
xpath
=
"//
p[@class='status drag-and-drop--status']/span[@class='sr']"
# Expect a <
span
> with the status
xpath
=
"//
span[@class='status {0}']/span[@class='sr']"
.
format
(
expected_css_class
)
self
.
assert_has_text
(
xml
,
xpath
,
expected_text
,
exact
=
False
)
def
test_drag_and_drop_json_html
(
self
):
...
...
@@ -1206,7 +1198,7 @@ class CodeinputTemplateTest(TemplateTestCase):
'aria_label'
:
'python editor'
,
'code_mirror_exit_message'
:
'Press ESC then TAB or click outside of the code editor to exit'
,
'response_data'
:
self
.
RESPONSE_DATA
,
'describedby'
:
self
.
DESCRIBEDBY
,
'describedby'
:
HTML
(
self
.
DESCRIBEDBY
)
,
}
def
test_label
(
self
):
...
...
common/lib/capa/capa/tests/test_inputtypes.py
View file @
055fd6ea
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/css/capa/display.scss
View file @
055fd6ea
...
...
@@ -23,9 +23,6 @@
// ====================
$annotation-yellow
:
rgba
(
255
,
255
,
10
,
0
.3
);
$color-copy-tip
:
rgb
(
100
,
100
,
100
);
$correct
:
$green-d2
;
$partially-correct
:
$green-d2
;
$incorrect
:
$red
;
// FontAwesome Icon code
// ====================
...
...
@@ -50,11 +47,13 @@ $asterisk-icon: '\f069'; // .fa-asterisk
// ====================
@mixin
status-icon
(
$color
:
$gray
,
$fontAwesomeIcon
:
"\f00d"
){
&
:after
{
@extend
%use-font-awesome
;
color
:
$color
;
font-size
:
1
.2em
;
content
:
$fontAwesomeIcon
;
.status-icon
{
&
:after
{
@extend
%use-font-awesome
;
color
:
$color
;
font-size
:
1
.2em
;
content
:
$fontAwesomeIcon
;
}
}
}
...
...
@@ -318,6 +317,12 @@ div.problem {
@include
status-icon
(
$incorrect
,
$cross-icon
);
}
&
.unsubmitted
,
&
.unanswered
{
.status-icon
{
content
:
''
;
}
}
}
}
}
...
...
@@ -818,12 +823,14 @@ div.problem {
}
.status
{
&
:after
{
content
:
''
;
// clear out correct or incorrect icon
.status-icon
{
&
:after
{
content
:
''
;
}
}
}
}
}
.trailing_text
{
...
...
common/lib/xmodule/xmodule/js/src/capa/display.js
View file @
055fd6ea
...
...
@@ -962,7 +962,6 @@
$status
=
$
(
'#status_'
+
id
);
if
(
$status
[
0
])
{
$status
.
removeClass
().
addClass
(
'unanswered'
);
$status
.
empty
().
css
(
'display'
,
'inline-block'
);
}
else
{
$
(
'<span>'
,
{
class
:
'unanswered'
,
...
...
@@ -979,8 +978,8 @@
id
=
(
$select
.
attr
(
'id'
).
match
(
/^input_
(
.*
)
$/
))[
1
];
return
$select
.
on
(
'change'
,
function
()
{
return
$
(
'#status_'
+
id
).
removeClass
().
addClass
(
'unanswered'
)
.
find
(
'
span
'
)
.
text
(
gettext
(
'
Status:
unsubmitted'
));
.
find
(
'
.sr
'
)
.
text
(
gettext
(
'unsubmitted'
));
});
},
textline
:
function
(
element
)
{
...
...
common/static/sass/edx-pattern-library-shims/base/_variables.scss
View file @
055fd6ea
...
...
@@ -144,6 +144,13 @@ $success-color: rgb(0, 155, 0) !default;
$warning-color
:
rgb
(
255
,
192
,
31
)
!
default
;
$warning-color-accent
:
rgb
(
255
,
252
,
221
)
!
default
;
// CAPA correctness color to be consistent with Alert styles above
$correct
:
$success-color
;
$partially-correct
:
$success-color
;
$incorrect
:
$error-color
;
// BUTTONS
// disabled button
...
...
lms/djangoapps/instructor_task/tests/test_tasks_helper.py
View file @
055fd6ea
...
...
@@ -617,12 +617,12 @@ class TestProblemGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
metadata
=
{
'graded'
:
True
},
display_name
=
'Problem Vertical'
)
self
.
define_option_problem
(
u'Pr
ö
blem1'
,
parent
=
vertical
)
self
.
define_option_problem
(
u'Pr
o
blem1'
,
parent
=
vertical
)
self
.
submit_student_answer
(
self
.
student_1
.
username
,
u'Pr
ö
blem1'
,
[
'Option 1'
])
self
.
submit_student_answer
(
self
.
student_1
.
username
,
u'Pr
o
blem1'
,
[
'Option 1'
])
result
=
upload_problem_grade_report
(
None
,
None
,
self
.
course
.
id
,
None
,
'graded'
)
self
.
assertDictContainsSubset
({
'action_name'
:
'graded'
,
'attempted'
:
2
,
'succeeded'
:
2
,
'failed'
:
0
},
result
)
problem_name
=
u'Homework 1: Problem - Pr
ö
blem1'
problem_name
=
u'Homework 1: Problem - Pr
o
blem1'
header_row
=
self
.
csv_header_row
+
[
problem_name
+
' (Earned)'
,
problem_name
+
' (Possible)'
]
self
.
verify_rows_in_csv
([
dict
(
zip
(
...
...
@@ -646,7 +646,7 @@ class TestProblemGradeReport(TestReportMixin, InstructorTaskModuleTestCase):
@patch
(
'lms.djangoapps.instructor_task.tasks_helper._get_current_task'
)
@patch
(
'lms.djangoapps.instructor_task.tasks_helper.iterate_grades_for'
)
@ddt.data
(
u'Cann
ö
t grade student'
,
''
)
@ddt.data
(
u'Cann
o
t grade student'
,
''
)
def
test_grading_failure
(
self
,
error_message
,
mock_iterate_grades_for
,
_mock_current_task
):
"""
Test that any grading errors are properly reported in the progress
...
...
@@ -683,8 +683,8 @@ class TestProblemReportSplitTestContent(TestReportMixin, TestConditionalContent,
def
setUp
(
self
):
super
(
TestProblemReportSplitTestContent
,
self
)
.
setUp
()
self
.
problem_a_url
=
u'pr
ö
blem_a_url'
self
.
problem_b_url
=
u'pr
ö
blem_b_url'
self
.
problem_a_url
=
u'pr
o
blem_a_url'
self
.
problem_b_url
=
u'pr
o
blem_b_url'
self
.
define_option_problem
(
self
.
problem_a_url
,
parent
=
self
.
vertical_a
)
self
.
define_option_problem
(
self
.
problem_b_url
,
parent
=
self
.
vertical_b
)
...
...
@@ -711,7 +711,7 @@ class TestProblemReportSplitTestContent(TestReportMixin, TestConditionalContent,
{
'action_name'
:
'graded'
,
'attempted'
:
2
,
'succeeded'
:
2
,
'failed'
:
0
},
result
)
problem_names
=
[
u'Homework 1: Problem - pr
öblem_a_url'
,
u'Homework 1: Problem - prö
blem_b_url'
]
problem_names
=
[
u'Homework 1: Problem - pr
oblem_a_url'
,
u'Homework 1: Problem - pro
blem_b_url'
]
header_row
=
[
u'Student ID'
,
u'Email'
,
u'Username'
,
u'Final Grade'
]
for
problem
in
problem_names
:
header_row
+=
[
problem
+
' (Earned)'
,
problem
+
' (Possible)'
]
...
...
@@ -817,12 +817,12 @@ class TestProblemReportCohortedContent(TestReportMixin, ContentGroupTestCase, In
display_name
=
'Problem Vertical'
)
self
.
define_option_problem
(
u"Pr
ö
blem0"
,
u"Pr
o
blem0"
,
parent
=
vertical
,
group_access
=
{
self
.
course
.
user_partitions
[
0
]
.
id
:
[
self
.
course
.
user_partitions
[
0
]
.
groups
[
0
]
.
id
]}
)
self
.
define_option_problem
(
u"Pr
ö
blem1"
,
u"Pr
o
blem1"
,
parent
=
vertical
,
group_access
=
{
self
.
course
.
user_partitions
[
0
]
.
id
:
[
self
.
course
.
user_partitions
[
0
]
.
groups
[
1
]
.
id
]}
)
...
...
@@ -845,20 +845,20 @@ class TestProblemReportCohortedContent(TestReportMixin, ContentGroupTestCase, In
))
def
test_cohort_content
(
self
):
self
.
submit_student_answer
(
self
.
alpha_user
.
username
,
u'Pr
ö
blem0'
,
[
'Option 1'
,
'Option 1'
])
resp
=
self
.
submit_student_answer
(
self
.
alpha_user
.
username
,
u'Pr
ö
blem1'
,
[
'Option 1'
,
'Option 1'
])
self
.
submit_student_answer
(
self
.
alpha_user
.
username
,
u'Pr
o
blem0'
,
[
'Option 1'
,
'Option 1'
])
resp
=
self
.
submit_student_answer
(
self
.
alpha_user
.
username
,
u'Pr
o
blem1'
,
[
'Option 1'
,
'Option 1'
])
self
.
assertEqual
(
resp
.
status_code
,
404
)
resp
=
self
.
submit_student_answer
(
self
.
beta_user
.
username
,
u'Pr
ö
blem0'
,
[
'Option 1'
,
'Option 2'
])
resp
=
self
.
submit_student_answer
(
self
.
beta_user
.
username
,
u'Pr
o
blem0'
,
[
'Option 1'
,
'Option 2'
])
self
.
assertEqual
(
resp
.
status_code
,
404
)
self
.
submit_student_answer
(
self
.
beta_user
.
username
,
u'Pr
ö
blem1'
,
[
'Option 1'
,
'Option 2'
])
self
.
submit_student_answer
(
self
.
beta_user
.
username
,
u'Pr
o
blem1'
,
[
'Option 1'
,
'Option 2'
])
with
patch
(
'lms.djangoapps.instructor_task.tasks_helper._get_current_task'
):
result
=
upload_problem_grade_report
(
None
,
None
,
self
.
course
.
id
,
None
,
'graded'
)
self
.
assertDictContainsSubset
(
{
'action_name'
:
'graded'
,
'attempted'
:
4
,
'succeeded'
:
4
,
'failed'
:
0
},
result
)
problem_names
=
[
u'Homework 1: Problem - Pr
öblem0'
,
u'Homework 1: Problem - Prö
blem1'
]
problem_names
=
[
u'Homework 1: Problem - Pr
oblem0'
,
u'Homework 1: Problem - Pro
blem1'
]
header_row
=
[
u'Student ID'
,
u'Email'
,
u'Username'
,
u'Final Grade'
]
for
problem
in
problem_names
:
header_row
+=
[
problem
+
' (Earned)'
,
problem
+
' (Possible)'
]
...
...
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