Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: New link on studio home to Taxonomy list and flag added [FC-0036] #33439

Merged
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cms/djangoapps/contentstore/rest_api/v1/serializers/home.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ class CourseHomeSerializer(serializers.Serializer):
in_process_course_actions = UnsucceededCourseSerializer(many=True, required=False, allow_null=True)
libraries = LibraryViewSerializer(many=True, required=False, allow_null=True)
libraries_enabled = serializers.BooleanField()
taxonomies_enabled = serializers.BooleanField()
library_authoring_mfe_url = serializers.CharField()
taxonomy_list_mfe_url = serializers.CharField()
optimization_enabled = serializers.BooleanField()
redirect_to_library_authoring_mfe = serializers.BooleanField()
request_course_creator_url = serializers.CharField()
Expand Down
17 changes: 16 additions & 1 deletion cms/djangoapps/contentstore/rest_api/v1/views/tests/test_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
import ddt
from django.conf import settings
from django.urls import reverse
from edx_toggles.toggles.testutils import override_waffle_switch
from edx_toggles.toggles.testutils import (
override_waffle_switch,
override_waffle_flag,
)
from rest_framework import status

from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from cms.djangoapps.contentstore.views.course import ENABLE_GLOBAL_STAFF_OPTIMIZATION
from cms.djangoapps.contentstore.toggles import ENABLE_TAGGING_TAXONOMY_LIST_PAGE
from openedx.core.djangoapps.content.course_overviews.tests.factories import CourseOverviewFactory
from xmodule.modulestore.tests.factories import CourseFactory

Expand Down Expand Up @@ -49,7 +53,9 @@ def test_home_page_response(self):
"in_process_course_actions": [],
"libraries": [],
"libraries_enabled": True,
"taxonomies_enabled": False,
"library_authoring_mfe_url": settings.LIBRARY_AUTHORING_MICROFRONTEND_URL,
"taxonomy_list_mfe_url": None,
"optimization_enabled": False,
"redirect_to_library_authoring_mfe": False,
"request_course_creator_url": "/request_course_creator",
Expand Down Expand Up @@ -87,3 +93,12 @@ def test_org_query_if_empty(self):
response = self.client.get(self.url)
self.assertEqual(len(response.data['courses']), 0)
self.assertEqual(response.status_code, status.HTTP_200_OK)

@override_waffle_flag(ENABLE_TAGGING_TAXONOMY_LIST_PAGE, True)
def test_taxonomy_list_link(self):
response = self.client.get(self.url)
self.assertTrue(response.data['taxonomies_enabled'])
self.assertEqual(
response.data['taxonomy_list_mfe_url'],
f'{settings.COURSE_AUTHORING_MICROFRONTEND_URL}/taxonomy-list'
)
18 changes: 18 additions & 0 deletions cms/djangoapps/contentstore/toggles.py
Original file line number Diff line number Diff line change
Expand Up @@ -537,3 +537,21 @@ def default_enable_flexible_peer_openassessments(course_key):
level to opt in/out of rolling forward this feature.
"""
return DEFAULT_ENABLE_FLEXIBLE_PEER_OPENASSESSMENTS.is_enabled(course_key)


# .. toggle_name: new_studio_mfe.use_tagging_taxonomy_list_page
# .. toggle_implementation: WaffleFlag
# .. toggle_default: False
# .. toggle_description: This flag enables the use of the taxonomy list page.
# .. toggle_use_cases: temporary
# .. toggle_creation_date: 2023-10-06
# .. toggle_target_removal_date: TBA
# .. toggle_warning:
ENABLE_TAGGING_TAXONOMY_LIST_PAGE = WaffleFlag('new_studio_mfe.use_tagging_taxonomy_list_page', __name__)


def use_tagging_taxonomy_list_page():
"""
Returns a boolean if taxonomy list page is enabled
"""
return ENABLE_TAGGING_TAXONOMY_LIST_PAGE.is_enabled()
15 changes: 15 additions & 0 deletions cms/djangoapps/contentstore/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
use_new_video_editor,
use_new_video_uploads_page,
use_new_custom_pages,
use_tagging_taxonomy_list_page,
)
from cms.djangoapps.models.settings.course_grading import CourseGradingModel
from xmodule.library_tools import LibraryToolsService
Expand Down Expand Up @@ -433,6 +434,18 @@ def get_custom_pages_url(course_locator) -> str:
return custom_pages_url


def get_taxonomy_list_url():
"""
Gets course authoring microfrontend URL for taxonomy list page view.
"""
taxonomy_list_url = None
if use_tagging_taxonomy_list_page():
mfe_base_url = settings.COURSE_AUTHORING_MICROFRONTEND_URL
if mfe_base_url:
taxonomy_list_url = f'{mfe_base_url}/taxonomy-list'
return taxonomy_list_url


def course_import_olx_validation_is_enabled():
"""
Check if course olx validation is enabled on course import.
Expand Down Expand Up @@ -1514,8 +1527,10 @@ def format_in_process_course_view(uca):
'archived_courses': archived_courses,
'in_process_course_actions': in_process_course_actions,
'libraries_enabled': LIBRARIES_ENABLED,
'taxonomies_enabled': use_tagging_taxonomy_list_page(),
'redirect_to_library_authoring_mfe': should_redirect_to_library_authoring_mfe(),
'library_authoring_mfe_url': LIBRARY_AUTHORING_MICROFRONTEND_URL,
'taxonomy_list_mfe_url': get_taxonomy_list_url(),
'libraries': libraries,
'show_new_library_button': user_can_create_library(user) and not should_redirect_to_library_authoring_mfe(),
'user': user,
Expand Down
3 changes: 3 additions & 0 deletions cms/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,9 @@ <h3 class="course-title">${course_info['display_name']}</h3>
</li>
% endif
% endif
% if taxonomies_enabled:
<li><a href="${taxonomy_list_mfe_url}">${_("Taxonomies")}</li>
% endif
</ul>
% endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,18 +270,18 @@ def test_list_invalid_page(self):
assert response.status_code == status.HTTP_404_NOT_FOUND

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_200_OK),
("user", "ot2", status.HTTP_404_NOT_FOUND),
("user", "st1", status.HTTP_200_OK),
Expand Down Expand Up @@ -336,7 +336,7 @@ def test_detail_taxonomy(self, user_attr, taxonomy_attr, expected_status):
check_taxonomy(response.data, taxonomy.pk, **(TaxonomySerializer(taxonomy.cast()).data))

@ddt.data(
(None, status.HTTP_403_FORBIDDEN),
(None, status.HTTP_401_UNAUTHORIZED),
("user", status.HTTP_403_FORBIDDEN),
("userA", status.HTTP_403_FORBIDDEN),
("userS", status.HTTP_201_CREATED),
Expand Down Expand Up @@ -368,18 +368,18 @@ def test_create_taxonomy(self, user_attr, expected_status):
check_taxonomy(response.data, response.data["id"], **create_data)

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_403_FORBIDDEN),
("user", "ot2", status.HTTP_403_FORBIDDEN),
("user", "st1", status.HTTP_403_FORBIDDEN),
Expand Down Expand Up @@ -465,18 +465,18 @@ def test_update_taxonomy_system_defined(self, update_value, expected_status):
assert response.data["system_defined"] is True

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_403_FORBIDDEN),
("user", "ot2", status.HTTP_403_FORBIDDEN),
("user", "st1", status.HTTP_403_FORBIDDEN),
Expand Down Expand Up @@ -560,18 +560,18 @@ def test_patch_taxonomy_system_defined(self, update_value, expected_status):
assert response.data["system_defined"] is True

@ddt.data(
(None, "ot1", status.HTTP_403_FORBIDDEN),
(None, "ot2", status.HTTP_403_FORBIDDEN),
(None, "st1", status.HTTP_403_FORBIDDEN),
(None, "st2", status.HTTP_403_FORBIDDEN),
(None, "t1", status.HTTP_403_FORBIDDEN),
(None, "t2", status.HTTP_403_FORBIDDEN),
(None, "tA1", status.HTTP_403_FORBIDDEN),
(None, "tA2", status.HTTP_403_FORBIDDEN),
(None, "tB1", status.HTTP_403_FORBIDDEN),
(None, "tB2", status.HTTP_403_FORBIDDEN),
(None, "tC1", status.HTTP_403_FORBIDDEN),
(None, "tC2", status.HTTP_403_FORBIDDEN),
(None, "ot1", status.HTTP_401_UNAUTHORIZED),
(None, "ot2", status.HTTP_401_UNAUTHORIZED),
(None, "st1", status.HTTP_401_UNAUTHORIZED),
(None, "st2", status.HTTP_401_UNAUTHORIZED),
(None, "t1", status.HTTP_401_UNAUTHORIZED),
(None, "t2", status.HTTP_401_UNAUTHORIZED),
(None, "tA1", status.HTTP_401_UNAUTHORIZED),
(None, "tA2", status.HTTP_401_UNAUTHORIZED),
(None, "tB1", status.HTTP_401_UNAUTHORIZED),
(None, "tB2", status.HTTP_401_UNAUTHORIZED),
(None, "tC1", status.HTTP_401_UNAUTHORIZED),
(None, "tC2", status.HTTP_401_UNAUTHORIZED),
("user", "ot1", status.HTTP_403_FORBIDDEN),
("user", "ot2", status.HTTP_403_FORBIDDEN),
("user", "st1", status.HTTP_403_FORBIDDEN),
Expand Down Expand Up @@ -695,24 +695,24 @@ def setUp(self):

@ddt.data(
# userA and userS are staff in courseA and can tag using enabled taxonomies
(None, "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["Tag 1"], status.HTTP_200_OK),
("userS", "tA1", ["Tag 1"], status.HTTP_200_OK),
(None, "tA1", [], status.HTTP_403_FORBIDDEN),
(None, "tA1", [], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", [], status.HTTP_403_FORBIDDEN),
("userA", "tA1", [], status.HTTP_200_OK),
("userS", "tA1", [], status.HTTP_200_OK),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
("userS", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
(None, "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
(None, "open_taxonomy", ["tag1"], status.HTTP_401_UNAUTHORIZED),
("user", "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
("userA", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
("userS", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
# Only userS is Tagging Admin and can tag objects using disabled taxonomies
(None, "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA2", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userS", "tA2", ["Tag 1"], status.HTTP_200_OK),
Expand All @@ -736,11 +736,11 @@ def test_tag_course(self, user_attr, taxonomy_attr, tag_values, expected_status)

@ddt.data(
# Can't add invalid tags to a object using a closed taxonomy
(None, "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
Expand All @@ -763,24 +763,24 @@ def test_tag_course_invalid(self, user_attr, taxonomy_attr, tag_values, expected

@ddt.data(
# userA and userS are staff in courseA (owner of xblockA) and can tag using enabled taxonomies
(None, "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["Tag 1"], status.HTTP_200_OK),
("userS", "tA1", ["Tag 1"], status.HTTP_200_OK),
(None, "tA1", [], status.HTTP_403_FORBIDDEN),
(None, "tA1", [], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", [], status.HTTP_403_FORBIDDEN),
("userA", "tA1", [], status.HTTP_200_OK),
("userS", "tA1", [], status.HTTP_200_OK),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
("userS", "multiple_taxonomy", ["Tag 1", "Tag 2"], status.HTTP_200_OK),
(None, "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
(None, "open_taxonomy", ["tag1"], status.HTTP_401_UNAUTHORIZED),
("user", "open_taxonomy", ["tag1"], status.HTTP_403_FORBIDDEN),
("userA", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
("userS", "open_taxonomy", ["tag1"], status.HTTP_200_OK),
# Only userS is Tagging Admin and can tag objects using disabled taxonomies
(None, "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
(None, "tA2", ["Tag 1"], status.HTTP_401_UNAUTHORIZED),
("user", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userA", "tA2", ["Tag 1"], status.HTTP_403_FORBIDDEN),
("userS", "tA2", ["Tag 1"], status.HTTP_200_OK),
Expand All @@ -804,11 +804,11 @@ def test_tag_xblock(self, user_attr, taxonomy_attr, tag_values, expected_status)

@ddt.data(
# Can't add invalid tags to a object using a closed taxonomy
(None, "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "tA1", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "tA1", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "tA1", ["invalid"], status.HTTP_400_BAD_REQUEST),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
(None, "multiple_taxonomy", ["invalid"], status.HTTP_401_UNAUTHORIZED),
("user", "multiple_taxonomy", ["invalid"], status.HTTP_403_FORBIDDEN),
("userA", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
("userS", "multiple_taxonomy", ["invalid"], status.HTTP_400_BAD_REQUEST),
Expand Down
2 changes: 1 addition & 1 deletion requirements/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ libsass==0.10.0
click==8.1.6

# pinning this version to avoid updates while the library is being developed
openedx-learning==0.2.3
openedx-learning==0.2.4
bradenmacdonald marked this conversation as resolved.
Show resolved Hide resolved

# lti-consumer-xblock 9.6.2 contains a breaking change that makes
# existing custom parameter configurations unusable.
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -785,7 +785,7 @@ openedx-filters==1.6.0
# via
# -r requirements/edx/kernel.in
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/kernel.in
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1318,7 +1318,7 @@ openedx-filters==1.6.0
# -r requirements/edx/doc.txt
# -r requirements/edx/testing.txt
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/doc.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ openedx-filters==1.6.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ openedx-filters==1.6.0
# via
# -r requirements/edx/base.txt
# lti-consumer-xblock
openedx-learning==0.2.3
openedx-learning==0.2.4
# via
# -c requirements/edx/../constraints.txt
# -r requirements/edx/base.txt
Expand Down
Loading