diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py
index e857bf11f0..30d3dc577f 100644
--- a/common/lib/capa/capa/responsetypes.py
+++ b/common/lib/capa/capa/responsetypes.py
@@ -58,6 +58,8 @@ registry = TagRegistry()
CorrectMap = correctmap.CorrectMap # pylint: disable=invalid-name
CORRECTMAP_PY = None
+# Make '_' a no-op so we can scrape strings
+_ = lambda text: text
#-----------------------------------------------------------------------------
# Exceptions
@@ -439,6 +441,7 @@ class JavascriptResponse(LoncapaResponse):
Javascript using Node.js.
"""
+ human_name = _('Javascript Input')
tags = ['javascriptresponse']
max_inputfields = 1
allowed_inputfields = ['javascriptinput']
@@ -684,6 +687,7 @@ class ChoiceResponse(LoncapaResponse):
"""
+ human_name = _('Checkboxes')
tags = ['choiceresponse']
max_inputfields = 1
allowed_inputfields = ['checkboxgroup', 'radiogroup']
@@ -754,6 +758,7 @@ class MultipleChoiceResponse(LoncapaResponse):
"""
# TODO: handle direction and randomize
+ human_name = _('Multiple Choice')
tags = ['multiplechoiceresponse']
max_inputfields = 1
allowed_inputfields = ['choicegroup']
@@ -1042,6 +1047,7 @@ class MultipleChoiceResponse(LoncapaResponse):
@registry.register
class TrueFalseResponse(MultipleChoiceResponse):
+ human_name = _('True/False Choice')
tags = ['truefalseresponse']
def mc_setup_response(self):
@@ -1073,6 +1079,7 @@ class OptionResponse(LoncapaResponse):
TODO: handle direction and randomize
"""
+ human_name = _('Dropdown')
tags = ['optionresponse']
hint_tag = 'optionhint'
allowed_inputfields = ['optioninput']
@@ -1108,6 +1115,7 @@ class NumericalResponse(LoncapaResponse):
to a number (e.g. `4+5/2^2`), and accepts with a tolerance.
"""
+ human_name = _('Numerical Input')
tags = ['numericalresponse']
hint_tag = 'numericalhint'
allowed_inputfields = ['textline', 'formulaequationinput']
@@ -1308,6 +1316,7 @@ class StringResponse(LoncapaResponse):
"""
+ human_name = _('Text Input')
tags = ['stringresponse']
hint_tag = 'stringhint'
allowed_inputfields = ['textline']
@@ -1426,6 +1435,7 @@ class CustomResponse(LoncapaResponse):
or in a
"""
+ human_name = _('Custom Evaluated Script')
tags = ['customresponse']
allowed_inputfields = ['textline', 'textbox', 'crystallography',
@@ -1800,6 +1810,7 @@ class SymbolicResponse(CustomResponse):
Symbolic math response checking, using symmath library.
"""
+ human_name = _('Symbolic Math Input')
tags = ['symbolicresponse']
max_inputfields = 1
@@ -1868,6 +1879,7 @@ class CodeResponse(LoncapaResponse):
"""
+ human_name = _('Code Input')
tags = ['coderesponse']
allowed_inputfields = ['textbox', 'filesubmission', 'matlabinput']
max_inputfields = 1
@@ -2145,6 +2157,7 @@ class ExternalResponse(LoncapaResponse):
"""
+ human_name = _('External Grader')
tags = ['externalresponse']
allowed_inputfields = ['textline', 'textbox']
awdmap = {
@@ -2302,6 +2315,7 @@ class FormulaResponse(LoncapaResponse):
Checking of symbolic math response using numerical sampling.
"""
+ human_name = _('Math Expression Input')
tags = ['formularesponse']
hint_tag = 'formulahint'
allowed_inputfields = ['textline', 'formulaequationinput']
@@ -2514,6 +2528,7 @@ class SchematicResponse(LoncapaResponse):
"""
Circuit schematic response type.
"""
+ human_name = _('Circuit Schematic Builder')
tags = ['schematicresponse']
allowed_inputfields = ['schematic']
@@ -2592,6 +2607,7 @@ class ImageResponse(LoncapaResponse):
True, if click is inside any region or rectangle. Otherwise False.
"""
+ human_name = _('Image Mapped Input')
tags = ['imageresponse']
allowed_inputfields = ['imageinput']
@@ -2710,6 +2726,7 @@ class AnnotationResponse(LoncapaResponse):
The response contains both a comment (student commentary) and an option (student tag).
Only the tag is currently graded. Answers may be incorrect, partially correct, or correct.
"""
+ human_name = _('Annotation Input')
tags = ['annotationresponse']
allowed_inputfields = ['annotationinput']
max_inputfields = 1
@@ -2834,6 +2851,7 @@ class ChoiceTextResponse(LoncapaResponse):
ChoiceResponse.
"""
+ human_name = _('Checkboxes With Text Input')
tags = ['choicetextresponse']
max_inputfields = 1
allowed_inputfields = ['choicetextgroup',
diff --git a/common/lib/xmodule/xmodule/library_content_module.py b/common/lib/xmodule/xmodule/library_content_module.py
index 0d2886ac9d..c6e728bb8a 100644
--- a/common/lib/xmodule/xmodule/library_content_module.py
+++ b/common/lib/xmodule/xmodule/library_content_module.py
@@ -5,6 +5,7 @@ LibraryContent: The XBlock used to include blocks from a library in a course.
from bson.objectid import ObjectId, InvalidId
from collections import namedtuple
from copy import copy
+from capa.responsetypes import registry
from .mako_module import MakoModuleDescriptor
from opaque_keys import InvalidKeyError
@@ -33,34 +34,18 @@ def enum(**enums):
return type('Enum', (), enums)
+def _get_human_name(problem_class):
+ """
+ Get the human-friendly name for a problem type.
+ """
+ return getattr(problem_class, 'human_name', problem_class.__name__)
+
+
def _get_capa_types():
"""
Gets capa types tags and labels
"""
- capa_types = {
- # basic tab
- 'choiceresponse': _('Checkboxes'),
- 'optionresponse': _('Dropdown'),
- 'multiplechoiceresponse': _('Multiple Choice'),
- 'truefalseresponse': _('True/False Choice'),
- 'numericalresponse': _('Numerical Input'),
- 'stringresponse': _('Text Input'),
-
- # advanced tab
- 'schematicresponse': _('Circuit Schematic Builder'),
- 'customresponse': _('Custom Evaluated Script'),
- 'imageresponse': _('Image Mapped Input'),
- 'formularesponse': _('Math Expression Input'),
- 'jsmeresponse': _('Molecular Structure'),
-
- # not in "Add Component" menu
- 'javascriptresponse': _('Javascript Input'),
- 'symbolicresponse': _('Symbolic Math Input'),
- 'coderesponse': _('Code Input'),
- 'externalresponse': _('External Grader'),
- 'annotationresponse': _('Annotation Input'),
- 'choicetextresponse': _('Checkboxes With Text Input'),
- }
+ capa_types = {tag: _get_human_name(registry.get_class_for_tag(tag)) for tag in registry.registered_tags()}
return [{'value': ANY_CAPA_TYPE_VALUE, 'display_name': _('Any Type')}] + sorted([
{'value': capa_type, 'display_name': caption}
@@ -429,9 +414,9 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
validation,
StudioValidationMessage(
StudioValidationMessage.WARNING,
- _(u'There are no content matching configured filters in the selected libraries.'),
+ _(u'There are no matching problem types in the specified libraries.'),
action_class='edit-button',
- action_label=_(u"Edit Problem Type Filter")
+ action_label=_(u"Select another problem type")
)
)
@@ -440,10 +425,11 @@ class LibraryContentDescriptor(LibraryContentFields, MakoModuleDescriptor, XmlDe
validation,
StudioValidationMessage(
StudioValidationMessage.WARNING,
- _(u'Configured to fetch {count} blocks, library and filter settings yield only {actual} blocks.')
+ _(u'The specified libraries are configured to fetch {count} problems, '
+ u'but there are only {actual} matching problems.')
.format(actual=matching_children_count, count=self.max_count),
action_class='edit-button',
- action_label=_(u"Edit block configuration")
+ action_label=_(u"Edit configuration")
)
)
diff --git a/common/test/acceptance/tests/lms/test_library.py b/common/test/acceptance/tests/lms/test_library.py
index cd28f81da2..d152f43386 100644
--- a/common/test/acceptance/tests/lms/test_library.py
+++ b/common/test/acceptance/tests/lms/test_library.py
@@ -28,7 +28,10 @@ class LibraryContentTestBase(UniqueCourseTest):
STAFF_EMAIL = "staff101@example.com"
def populate_library_fixture(self, library_fixture):
- pass
+ """
+ To be overwritten by subclassed tests. Used to install a library to
+ run tests on.
+ """
def setUp(self):
"""
@@ -207,7 +210,7 @@ class StudioLibraryContainerCapaFilterTest(LibraryContentTestBase):
def _get_problem_select_text(self, name, items, correct):
""" Generates Select Option CAPA problem XML """
- items_text = ",".join(map(lambda item: "'{0}'".format(item), items))
+ items_text = ",".join(["'{0}'".format(item) for item in items])
return """
{name}
@@ -281,7 +284,7 @@ class StudioLibraryContainerCapaFilterTest(LibraryContentTestBase):
self.assertEqual(len(children_headers), 1)
self.assertLessEqual(
children_headers,
- set(map(lambda header: header.upper(), ["Problem Choice Group 1", "Problem Choice Group 2"]))
+ set([header.upper() for header in ["Problem Choice Group 1", "Problem Choice Group 2"]])
)
# Choice group test
@@ -289,7 +292,7 @@ class StudioLibraryContainerCapaFilterTest(LibraryContentTestBase):
self.assertEqual(len(children_headers), 2)
self.assertLessEqual(
children_headers,
- set(map(lambda header: header.upper(), ["Problem Select 1", "Problem Select 2"]))
+ set([header.upper() for header in ["Problem Select 1", "Problem Select 2"]])
)
# Missing problem type test
diff --git a/common/test/acceptance/tests/studio/test_studio_library_container.py b/common/test/acceptance/tests/studio/test_studio_library_container.py
index 4634fb09ac..c482ce090f 100644
--- a/common/test/acceptance/tests/studio/test_studio_library_container.py
+++ b/common/test/acceptance/tests/studio/test_studio_library_container.py
@@ -189,8 +189,7 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
When I set Problem Type selector so that there are matching content
Then I can see that warning messages are not shown
"""
- expected_text = 'There are no content matching configured filters in the selected libraries. ' \
- 'Edit Problem Type Filter'
+ expected_text = 'There are no matching problem types in the specified libraries. Select another problem type'
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])
@@ -223,7 +222,8 @@ class StudioLibraryContainerTest(StudioLibraryTest, UniqueCourseTest):
And I set Problem Type selector so "Any"
Then I can see that "No matching content" warning is shown
"""
- expected_tpl = "Configured to fetch {count} blocks, library and filter settings yield only {actual} blocks."
+ expected_tpl = "The specified libraries are configured to fetch {count} problems, " \
+ "but there are only {actual} matching problems."
library_container = self._get_library_xblock_wrapper(self.unit_page.xblocks[0])