diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index be120824a42a..c871e8146e26 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -45,7 +45,12 @@ from cms.djangoapps.contentstore.config import waffle from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, CourseTestCase, get_url, parse_json -from cms.djangoapps.contentstore.utils import delete_course, reverse_course_url, reverse_url +from cms.djangoapps.contentstore.utils import ( + delete_course, + reverse_course_url, + reverse_url, + get_taxonomy_tags_widget_url, +) from cms.djangoapps.contentstore.views.component import ADVANCED_COMPONENT_TYPES from common.djangoapps.course_action_state.managers import CourseActionStateItemNotFoundError from common.djangoapps.course_action_state.models import CourseRerunState, CourseRerunUIStateManager @@ -1376,11 +1381,14 @@ def test_course_overview_view_with_course(self): self.assertEqual(resp.status_code, 404) return + taxonomy_tags_widget_url = get_taxonomy_tags_widget_url(course.id) + self.assertContains( resp, - '
'.format( # lint-amnesty, pylint: disable=line-too-long + '
'.format( # lint-amnesty, pylint: disable=line-too-long locator=str(course.location), course_key=str(course.id), + taxonomy_tags_widget_url=taxonomy_tags_widget_url, ), status_code=200, html=True diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py index c6ebe173b5dc..a4c69e55b7ea 100644 --- a/cms/djangoapps/contentstore/utils.py +++ b/cms/djangoapps/contentstore/utils.py @@ -395,6 +395,21 @@ def get_taxonomy_list_url(): return taxonomy_list_url +def get_taxonomy_tags_widget_url(course_locator) -> str: + """ + Gets course authoring microfrontend URL for taxonomy tags drawer widget view. + + The `content_id` needs to be appended to the end of the URL when using it. + """ + taxonomy_tags_widget_url = None + # Uses the same waffle flag as taxonomy list page + if use_tagging_taxonomy_list_page(): + mfe_base_url = get_course_authoring_url(course_locator) + if mfe_base_url: + taxonomy_tags_widget_url = f'{mfe_base_url}/tagging/components/widget/' + return taxonomy_tags_widget_url + + def course_import_olx_validation_is_enabled(): """ Check if course olx validation is enabled on course import. diff --git a/cms/djangoapps/contentstore/views/block.py b/cms/djangoapps/contentstore/views/block.py index c65aaace82d8..ecaa6928c0b9 100644 --- a/cms/djangoapps/contentstore/views/block.py +++ b/cms/djangoapps/contentstore/views/block.py @@ -33,6 +33,7 @@ from xblock.fields import Scope from cms.djangoapps.contentstore.config.waffle import SHOW_REVIEW_RULES_FLAG +from cms.djangoapps.contentstore.toggles import use_tagging_taxonomy_list_page from cms.djangoapps.models.settings.course_grading import CourseGradingModel from cms.lib.xblock.authoring_mixin import VISIBILITY_VIEW from common.djangoapps.edxmako.services import MakoService @@ -1375,6 +1376,11 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F xblock_info['has_partition_group_components'] = has_children_visible_to_specific_partition_groups( xblock ) + + # If the ENABLE_TAGGING_TAXONOMY_LIST_PAGE feature flag is enabled, we show the "Manage Tags" options + if use_tagging_taxonomy_list_page(): + xblock_info["use_tagging_taxonomy_list_page"] = True + xblock_info['user_partition_info'] = get_visibility_partition_info(xblock, course=course) return xblock_info diff --git a/cms/djangoapps/contentstore/views/course.py b/cms/djangoapps/contentstore/views/course.py index 40abb093fdf4..ca471ea10355 100644 --- a/cms/djangoapps/contentstore/views/course.py +++ b/cms/djangoapps/contentstore/views/course.py @@ -94,6 +94,7 @@ get_home_context, get_lms_link_for_item, get_proctored_exam_settings_url, + get_taxonomy_tags_widget_url, get_course_rerun_context, initialize_permissions, remove_all_instructors, @@ -686,6 +687,7 @@ def course_index(request, course_key): 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_block.id), 'advance_settings_url': reverse_course_url('advanced_settings_handler', course_block.id), 'proctoring_errors': proctoring_errors, + 'taxonomy_tags_widget_url': get_taxonomy_tags_widget_url(course_block.id), }) diff --git a/cms/static/js/views/course_outline.js b/cms/static/js/views/course_outline.js index 3eeeff5b1e07..ed30c1b34ddc 100644 --- a/cms/static/js/views/course_outline.js +++ b/cms/static/js/views/course_outline.js @@ -215,6 +215,43 @@ function( } }, + closeManageTagsDrawer(drawer, drawerCover) { + $(drawerCover).css('display', 'none'); + $(drawer).empty(); + $(drawer).css('display', 'none'); + $('body').removeClass('drawer-open'); + }, + + openManageTagsDrawer(event) { + const drawer = document.querySelector("#manage-tags-drawer"); + const drawerCover = document.querySelector(".drawer-cover") + const article = document.querySelector('[data-taxonomy-tags-widget-url]'); + const taxonomyTagsWidgetUrl = $(article).attr('data-taxonomy-tags-widget-url'); + const contentId = this.model.get('id'); + + // Add handler to close drawer when dark background is clicked + $(drawerCover).click(function() { + this.closeManageTagsDrawer(drawer, drawerCover); + }.bind(this)); + + // Add event listen to close drawer when close button is clicked from within the Iframe + window.addEventListener("message", function (event) { + if (event.data === 'closeManageTagsDrawer') { + this.closeManageTagsDrawer(drawer, drawerCover) + } + }.bind(this)); + + $(drawerCover).css('display', 'block'); + // xss-lint: disable=javascript-jquery-html + $(drawer).html( + `` + ); + $(drawer).css('display', 'block'); + + // Prevent background from being scrollable when drawer is open + $('body').addClass('drawer-open'); + }, + addButtonActions: function(element) { XBlockOutlineView.prototype.addButtonActions.apply(this, arguments); element.find('.configure-button').click(function(event) { @@ -231,6 +268,10 @@ function( this.highlightsXBlock(); } }.bind(this)); + element.find('.manage-tags-button').click((event) => { + event.preventDefault(); + this.openManageTagsDrawer(); + }); }, makeContentDraggable: function(element) { diff --git a/cms/static/js/views/xblock_outline.js b/cms/static/js/views/xblock_outline.js index 1f1538e502fe..dd97506b0295 100644 --- a/cms/static/js/views/xblock_outline.js +++ b/cms/static/js/views/xblock_outline.js @@ -109,7 +109,8 @@ function($, _, gettext, BaseView, ViewUtils, XBlockViewUtils, XBlockStringFieldE includesChildren: this.shouldRenderChildren(), hasExplicitStaffLock: this.model.get('has_explicit_staff_lock'), staffOnlyMessage: this.model.get('staff_only_message'), - course: course + course: course, + useTaggingTaxonomyListPage: this.model.get("use_tagging_taxonomy_list_page"), // ENABLE_TAGGING_TAXONOMY_LIST_PAGE waffle flag }; }, diff --git a/cms/static/sass/_build-v1.scss b/cms/static/sass/_build-v1.scss index 2a32c688e5a1..46d258bd6af7 100644 --- a/cms/static/sass/_build-v1.scss +++ b/cms/static/sass/_build-v1.scss @@ -55,6 +55,7 @@ @import 'elements/uploaded-assets'; // layout for asset tables @import 'elements/creative-commons'; @import 'elements/tooltip'; +@import 'elements/drawer'; // +Base - Specific Views // ==================== diff --git a/cms/static/sass/elements/_drawer.scss b/cms/static/sass/elements/_drawer.scss new file mode 100644 index 000000000000..c18073be9864 --- /dev/null +++ b/cms/static/sass/elements/_drawer.scss @@ -0,0 +1,30 @@ +// studio - elements - side drawers +// ==================== + +.drawer-cover { + @extend %ui-depth3; + + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.8); +} + +.drawer { + @extend %ui-depth4; + + display: none; + position: fixed; + top: 0; + right: 0; + width: 33.33vw; + height: 100vh; + background-color: $gray-l4; +} + +body.drawer-open { + overflow: hidden; +} diff --git a/cms/templates/course_outline.html b/cms/templates/course_outline.html index f9f499c87bd8..9dd30f8ea8a8 100644 --- a/cms/templates/course_outline.html +++ b/cms/templates/course_outline.html @@ -279,7 +279,7 @@

${_("Page Actions")}

course_locator = context_course.location %>

${_("Course Outline")}

-
+
@@ -319,4 +319,7 @@

${_("Changing the content learners see")}

+ +
+
diff --git a/cms/templates/js/course-outline.underscore b/cms/templates/js/course-outline.underscore index 4550d102a6ad..a780156ba5da 100644 --- a/cms/templates/js/course-outline.underscore +++ b/cms/templates/js/course-outline.underscore @@ -187,6 +187,17 @@ if (is_proctored_exam) { <% } %> + + <% if (xblockInfo.isVertical() && typeof useTaggingTaxonomyListPage !== "undefined" && useTaggingTaxonomyListPage) { %> +
  • + + + ? + <%- gettext('Manage Tags') %> + +
  • + <% } %> + <% if (xblockInfo.isDraggable()) { %>