diff --git a/cms/djangoapps/contentstore/views/component.py b/cms/djangoapps/contentstore/views/component.py index c8173c7228..da15dc5c84 100644 --- a/cms/djangoapps/contentstore/views/component.py +++ b/cms/djangoapps/contentstore/views/component.py @@ -41,12 +41,14 @@ __all__ = [ log = logging.getLogger(__name__) # NOTE: This list is disjoint from ADVANCED_COMPONENT_TYPES -COMPONENT_TYPES = ['discussion', 'html', 'openassessment', 'problem', 'video'] +COMPONENT_TYPES = ['discussion', 'library', 'html', 'openassessment', 'problem', 'video'] ADVANCED_COMPONENT_TYPES = sorted({name for name, class_ in XBlock.load_classes()} - set(COMPONENT_TYPES)) ADVANCED_PROBLEM_TYPES = settings.ADVANCED_PROBLEM_TYPES +LIBRARY_BLOCK_TYPES = settings.LIBRARY_BLOCK_TYPES + CONTAINER_TEMPLATES = [ "basic-modal", "modal-button", "edit-xblock-modal", "editor-mode-button", "upload-dialog", @@ -278,7 +280,8 @@ def get_component_templates(courselike, library=False): # lint-amnesty, pylint: 'html': _("Text"), 'problem': _("Problem"), 'video': _("Video"), - 'openassessment': _("Open Response") + 'openassessment': _("Open Response"), + 'library': _("Library Content"), } component_templates = [] @@ -287,8 +290,8 @@ def get_component_templates(courselike, library=False): # lint-amnesty, pylint: # by the components in the order listed in COMPONENT_TYPES. component_types = COMPONENT_TYPES[:] - # Libraries do not support discussions and openassessment - component_not_supported_by_library = ['discussion', 'openassessment'] + # Libraries do not support discussions and openassessment and other libraries + component_not_supported_by_library = ['discussion', 'library', 'openassessment'] if library: component_types = [component for component in component_types if component not in set(component_not_supported_by_library)] @@ -307,7 +310,7 @@ def get_component_templates(courselike, library=False): # lint-amnesty, pylint: templates_for_category = [] component_class = _load_mixed_class(category) - if support_level_without_template: + if support_level_without_template and category != 'library': # add the default template with localized display name # TODO: Once mixins are defined per-application, rather than per-runtime, # this should use a cms mixed-in class. (cpennington) @@ -383,6 +386,37 @@ def get_component_templates(courselike, library=False): # lint-amnesty, pylint: ) categories.add(component) + # Add library block types. + if category == 'library' and not library: + disabled_block_names = [block.name for block in disabled_xblocks()] + library_block_types = [problem_type for problem_type in LIBRARY_BLOCK_TYPES + if problem_type['component'] not in disabled_block_names] + for library_block_type in library_block_types: + component = library_block_type['component'] + boilerplate_name = library_block_type['boilerplate_name'] + authorable_variations = authorable_xblocks(allow_unsupported=allow_unsupported, name=component) + library_component_support_level = component_support_level( + authorable_variations, component, boilerplate_name + ) + if library_component_support_level: + try: + component_display_name = xblock_type_display_name(component, default_display_name=component) + except PluginMissingError: + log.warning( + "Unable to load xblock type %s to read display_name", + component + ) + else: + templates_for_category.append( + create_template_dict( + component_display_name, + component, + library_component_support_level, + boilerplate_name + ) + ) + categories.add(component) + component_templates.append({ "type": category, "templates": templates_for_category, diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index f182d02d3e..055cea6401 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -2253,6 +2253,9 @@ class TestComponentTemplates(CourseTestCase): XBlockStudioConfiguration.objects.create(name='video', enabled=True, support_level="us") # ORA Block has it's own category. XBlockStudioConfiguration.objects.create(name='openassessment', enabled=True, support_level="us") + # Library Sourced Block and Library Content block has it's own category. + XBlockStudioConfiguration.objects.create(name='library_sourced', enabled=True, support_level="fs") + XBlockStudioConfiguration.objects.create(name='library_content', enabled=True, support_level="fs") # XBlock masquerading as a problem XBlockStudioConfiguration.objects.create(name='drag-and-drop-v2', enabled=True, support_level="fs") XBlockStudioConfiguration.objects.create(name='staffgradedxblock', enabled=True, support_level="us") @@ -2295,6 +2298,7 @@ class TestComponentTemplates(CourseTestCase): self._verify_basic_component_display_name("discussion", "Discussion") self._verify_basic_component_display_name("video", "Video") self._verify_basic_component_display_name("openassessment", "Open Response") + self.assertGreater(len(self.get_templates_of_type('library')), 0) self.assertGreater(len(self.get_templates_of_type('html')), 0) self.assertGreater(len(self.get_templates_of_type('problem')), 0) self.assertIsNone(self.get_templates_of_type('advanced')) diff --git a/cms/djangoapps/contentstore/views/tests/test_library.py b/cms/djangoapps/contentstore/views/tests/test_library.py index b99dbd3b22..746e61cb31 100644 --- a/cms/djangoapps/contentstore/views/tests/test_library.py +++ b/cms/djangoapps/contentstore/views/tests/test_library.py @@ -337,6 +337,7 @@ class UnitTestLibraries(CourseTestCase): self.assertNotIn('discussion', templates) self.assertNotIn('advanced', templates) self.assertNotIn('openassessment', templates) + self.assertNotIn('library', templates) def test_advanced_problem_types(self): """ diff --git a/cms/envs/common.py b/cms/envs/common.py index f7f8a2fc20..cdb597b670 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -1975,6 +1975,17 @@ ADVANCED_PROBLEM_TYPES = [ } ] +LIBRARY_BLOCK_TYPES = [ + { + 'component': 'library_sourced', + 'boilerplate_name': None + }, + { + 'component': 'library_content', + 'boilerplate_name': None + } +] + ############### Settings for Retirement ##################### # See annotations in lms/envs/common.py for details. RETIRED_USERNAME_PREFIX = 'retired__user_' diff --git a/cms/static/images/large-library-icon.png b/cms/static/images/large-library-icon.png new file mode 100644 index 0000000000..c9f5622492 Binary files /dev/null and b/cms/static/images/large-library-icon.png differ diff --git a/cms/static/sass/assets/_graphics.scss b/cms/static/sass/assets/_graphics.scss index 881445f0d8..5839711197 100644 --- a/cms/static/sass/assets/_graphics.scss +++ b/cms/static/sass/assets/_graphics.scss @@ -52,3 +52,10 @@ height: ($baseline*3); background: url('#{$static-path}/images/large-openassessment-icon.png') center no-repeat; } + +.large-library-icon { + display: inline-block; + width: ($baseline*3); + height: ($baseline*3); + background: url('#{$static-path}/images/large-library-icon.png') center no-repeat; +}