diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/vertical_block.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/vertical_block.py index 9c73036fbf7d..fe4a3cdecd89 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/serializers/vertical_block.py +++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/vertical_block.py @@ -123,7 +123,22 @@ def get_actions(self, obj): # pylint: disable=unused-argument """ can_manage_tags = use_tagging_taxonomy_list_page() + xblock = obj["xblock"] + is_course = xblock.scope_ids.usage_id.context_key.is_course + xblock_url = xblock_studio_url(xblock) + # Responsible for the ability to edit container xblock(copy, duplicate, move and manage access). + # It was used in the legacy and transferred here with simplification. + # After the investigation it was determined that the "show_other_action" + # condition below is sufficient to enable/disable actions on each xblock. + show_inline = xblock.has_children and not xblock_url + # All except delete and manage tags + show_other_action = not show_inline and is_course actions = { + "can_copy": show_other_action, + "can_duplicate": show_other_action, + "can_move": show_other_action, + "can_manage_access": show_other_action, + "can_delete": is_course, "can_manage_tags": can_manage_tags, } diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_vertical_block.py b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_vertical_block.py index b8e4a52bd17e..0d0475a333ec 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_vertical_block.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/tests/test_vertical_block.py @@ -196,6 +196,11 @@ def test_children_content(self): "user_partition_info": expected_user_partition_info, "user_partitions": expected_user_partitions, "actions": { + "can_copy": True, + "can_duplicate": True, + "can_move": True, + "can_manage_access": True, + "can_delete": True, "can_manage_tags": True, }, "validation_messages": [], @@ -206,6 +211,11 @@ def test_children_content(self): "block_id": str(self.html_unit_second.location), "block_type": self.html_unit_second.location.block_type, "actions": { + "can_copy": True, + "can_duplicate": True, + "can_move": True, + "can_manage_access": True, + "can_delete": True, "can_manage_tags": True, }, "user_partition_info": expected_user_partition_info, diff --git a/cms/djangoapps/contentstore/rest_api/v1/views/vertical_block.py b/cms/djangoapps/contentstore/rest_api/v1/views/vertical_block.py index f41ddc73f1eb..670b94afbbe0 100644 --- a/cms/djangoapps/contentstore/rest_api/v1/views/vertical_block.py +++ b/cms/djangoapps/contentstore/rest_api/v1/views/vertical_block.py @@ -1,5 +1,6 @@ """ API Views for unit page """ +import logging import edx_api_doc_tools as apidocs from django.http import HttpResponseBadRequest from rest_framework.request import Request @@ -26,6 +27,9 @@ from cms.djangoapps.contentstore.rest_api.v1.mixins import ContainerHandlerMixin +log = logging.getLogger(__name__) + + @view_auth_classes(is_authenticated=True) class ContainerHandlerView(APIView, ContainerHandlerMixin): """ @@ -195,6 +199,11 @@ def get(self, request: Request, usage_key_string: str): "user_partition_info": {}, "user_partitions": {} "actions": { + "can_copy": true, + "can_duplicate": true, + "can_move": true, + "can_manage_access": true, + "can_delete": true, "can_manage_tags": true, }, "has_validation_error": false, @@ -207,6 +216,11 @@ def get(self, request: Request, usage_key_string: str): "user_partition_info": {}, "user_partitions": {} "actions": { + "can_copy": true, + "can_duplicate": true, + "can_move": true, + "can_manage_access": true, + "can_delete": true, "can_manage_tags": true, } "validation_messages": [], @@ -219,6 +233,11 @@ def get(self, request: Request, usage_key_string: str): "user_partition_info": {}, "user_partitions": {}, "actions": { + "can_copy": true, + "can_duplicate": true, + "can_move": true, + "can_manage_access": true, + "can_delete": true, "can_manage_tags": true, }, "validation_messages": [ @@ -230,35 +249,48 @@ def get(self, request: Request, usage_key_string: str): "render_error": "Unterminated control keyword: 'if' in file '../problem.html'", }, ], - "is_published": false + "is_published": false, + "can_paste_component": true, } ``` """ usage_key = self.get_object(usage_key_string) current_xblock = get_xblock(usage_key, request.user) + is_course = current_xblock.scope_ids.usage_id.context_key.is_course with modulestore().bulk_operations(usage_key.course_key): # load course once to reuse it for user_partitions query course = modulestore().get_course(current_xblock.location.course_key) children = [] - for child in current_xblock.children: - child_info = modulestore().get_item(child) - user_partition_info = get_visibility_partition_info(child_info, course=course) - user_partitions = get_user_partition_info(child_info, course=course) - validation_messages = get_xblock_validation_messages(child_info) - render_error = get_xblock_render_error(request, child_info) + if hasattr(current_xblock, "children"): + for child in current_xblock.children: + child_info = modulestore().get_item(child) + user_partition_info = get_visibility_partition_info(child_info, course=course) + user_partitions = get_user_partition_info(child_info, course=course) + validation_messages = get_xblock_validation_messages(child_info) + render_error = get_xblock_render_error(request, child_info) + + children.append({ + "xblock": child_info, + "name": child_info.display_name_with_default, + "block_id": child_info.location, + "block_type": child_info.location.block_type, + "user_partition_info": user_partition_info, + "user_partitions": user_partitions, + "validation_messages": validation_messages, + "render_error": render_error, + }) - children.append({ - "name": child_info.display_name_with_default, - "block_id": child_info.location, - "block_type": child_info.location.block_type, - "user_partition_info": user_partition_info, - "user_partitions": user_partitions, - "validation_messages": validation_messages, - "render_error": render_error, - }) + is_published = False + try: + is_published = not modulestore().has_changes(current_xblock) + except ItemNotFoundError: + logging.error('Could not find any changes for block [%s]', usage_key) - is_published = not modulestore().has_changes(current_xblock) - container_data = {"children": children, "is_published": is_published} + container_data = { + "children": children, + "is_published": is_published, + "can_paste_component": is_course, + } serializer = VerticalContainerSerializer(container_data) return Response(serializer.data)