diff --git a/cms/api.py b/cms/api.py index 3b32fedca..093e23605 100644 --- a/cms/api.py +++ b/cms/api.py @@ -9,7 +9,11 @@ from wagtail.models import Page, Site from cms import models as cms_models -from cms.constants import CERTIFICATE_INDEX_SLUG, ENTERPRISE_PAGE_SLUG, CatalogSorting +from cms.constants import ( + CERTIFICATE_INDEX_SLUG, + ENTERPRISE_PAGE_SLUG, + CatalogSorting, +) log = logging.getLogger(__name__) DEFAULT_HOMEPAGE_PROPS = dict(title="Home Page", subhead="This is the home page") # noqa: C408 diff --git a/cms/constants.py b/cms/constants.py index ec99d74d6..1a571ca30 100644 --- a/cms/constants.py +++ b/cms/constants.py @@ -12,6 +12,7 @@ COMMON_COURSEWARE_COMPONENT_INDEX_SLUG = "common-courseware-component-pages" ALL_TOPICS = "All Topics" +ALL_LANGUAGES = "All Languages" ALL_TAB = "all-tab" # ************** CONSTANTS FOR WEBINARS ************** diff --git a/cms/models.py b/cms/models.py index cffaac70a..df7704a4a 100644 --- a/cms/models.py +++ b/cms/models.py @@ -61,6 +61,7 @@ from cms.constants import ( ALL_TAB, ALL_TOPICS, + ALL_LANGUAGES, BLOG_INDEX_SLUG, CERTIFICATE_INDEX_SLUG, COMMON_COURSEWARE_COMPONENT_INDEX_SLUG, @@ -90,8 +91,11 @@ Program, ProgramCertificate, ProgramRun, + CourseLanguage, ) from ecommerce.models import Product +from mitol.olposthog.features import is_enabled +from mitxpro.features import CATALOG_LANGUAGE_FILTER from mitxpro.utils import now_in_utc from mitxpro.views import get_base_context @@ -516,6 +520,9 @@ def get_context(self, request, *args, **kwargs): # noqa: ARG002 Populate the context with live programs, courses and programs + courses """ topic_filter = request.GET.get("topic", ALL_TOPICS) + language_filter = request.GET.get("language", ALL_LANGUAGES) + + is_language_filter_enabled = is_enabled(CATALOG_LANGUAGE_FILTER, default=False) # Best Match is the default sorting. sort_by = request.GET.get("sort-by", CatalogSorting.BEST_MATCH.sorting_value) @@ -556,10 +563,19 @@ def get_context(self, request, *args, **kwargs): # noqa: ARG002 .order_by("title") ) + if language_filter != ALL_LANGUAGES: + program_page_qset = program_page_qset.filter(language__name=language_filter) + external_program_qset = external_program_qset.filter( + language__name=language_filter + ) + course_page_qset = course_page_qset.filter(language__name=language_filter) + external_course_qset = external_course_qset.filter( + language__name=language_filter + ) + if topic_filter != ALL_TOPICS: program_page_qset = program_page_qset.related_pages(topic_filter) external_program_qset = external_program_qset.related_pages(topic_filter) - course_page_qset = course_page_qset.related_pages(topic_filter) external_course_qset = external_course_qset.related_pages(topic_filter) @@ -647,6 +663,15 @@ def get_context(self, request, *args, **kwargs): # noqa: ARG002 } for sorting_option in CatalogSorting ], + show_language_filter=is_language_filter_enabled, + selected_language=language_filter, + language_options=[ALL_LANGUAGES] + + [ + course_language.name + for course_language in CourseLanguage.objects.filter(is_active=True) + ] + if is_language_filter_enabled + else [], ) diff --git a/cms/models_test.py b/cms/models_test.py index a9bff4715..e240abff2 100644 --- a/cms/models_test.py +++ b/cms/models_test.py @@ -24,8 +24,10 @@ UPCOMING_WEBINAR, UPCOMING_WEBINAR_BUTTON_TITLE, WEBINAR_HEADER_BANNER, + ALL_LANGUAGES, ) from cms.factories import ( + CatalogPageFactory, CertificatePageFactory, CommonComponentIndexPageFactory, CompaniesLogoCarouselPageFactory, @@ -88,6 +90,7 @@ CourseRunFactory, ProgramCertificateFactory, ) +from courses.models import CourseLanguage from ecommerce.factories import ProductFactory, ProductVersionFactory pytestmark = [pytest.mark.django_db] @@ -240,6 +243,78 @@ def test_webinar_detail_page_button_title(): assert upcoming_webinar.detail_page_button_title == UPCOMING_WEBINAR_BUTTON_TITLE +@pytest.mark.parametrize( + "languages, selected_language", + [ + (None, ALL_LANGUAGES), + ( + [ + "Languag1", + "Language2", + ], + "Language2", + ), + (["Languag1", "Language2", "Language3"], "Languag1"), + ], +) +def test_catalog_page_language_context( + mocker, staff_user, languages, selected_language +): + """ + Verify the language context is properly passed to the catalog_page.html + """ + mocker.patch("cms.models.is_enabled", return_value=True) + CourseLanguage.objects.all().delete() + catalog_page = CatalogPageFactory.create() + if languages: + CourseLanguageFactory.create_batch( + len(languages), name=factory.Iterator(languages) + ) + + rf = RequestFactory() + request = rf.get(f"/?language={selected_language}") + request.user = staff_user + context = catalog_page.get_context(request=request) + + assert context.get("self") == catalog_page + assert context.get("page") == catalog_page + assert context.get("request") == request + assert context.get("selected_language") == selected_language + assert ( + context.get("language_options") == [ALL_LANGUAGES] + languages + if languages + else ALL_LANGUAGES + ) + + +@pytest.mark.parametrize( + "is_enabled", + [True, False], +) +def test_catalog_page_language_feature_flag(mocker, staff_user, is_enabled): + """ + Verify the language context is properly passed to the catalog_page.html + """ + mocker.patch("cms.models.is_enabled", return_value=is_enabled) + CourseLanguage.objects.all().delete() + catalog_page = CatalogPageFactory.create() + languages = CourseLanguageFactory.create_batch(2) + + rf = RequestFactory() + request = rf.get("/") + request.user = staff_user + context = catalog_page.get_context(request=request) + + assert context.get("selected_language") == ALL_LANGUAGES + assert context.get("show_language_filter") == is_enabled + expected_languages = ( + [ALL_LANGUAGES] + [language.name for language in languages] + if is_enabled + else [] + ) + assert context.get("language_options") == expected_languages + + def test_course_page_program_page(): """ Verify `program_page` property from the course page returns expected value diff --git a/cms/templates/catalog_page.html b/cms/templates/catalog_page.html index 1d18d0293..e97ecdd1a 100644 --- a/cms/templates/catalog_page.html +++ b/cms/templates/catalog_page.html @@ -21,234 +21,310 @@