From 332d2b03685f7d661475933b5998d3edea99708a Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Wed, 31 Dec 2014 19:31:42 +0000 Subject: [PATCH] Addressed notes from reviewers about Library content filters. --- common/lib/capa/capa/responsetypes.py | 18 ++++++++ .../xmodule/xmodule/library_content_module.py | 42 +++++++------------ .../test/acceptance/tests/lms/test_library.py | 11 +++-- .../studio/test_studio_library_container.py | 6 +-- 4 files changed, 42 insertions(+), 35 deletions(-) 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])