Redirect to the courseware MFE when the ‘courseware’ view is loaded

This commit is contained in:
David Joy
2020-02-06 17:35:04 -05:00
parent d96ff272e2
commit fe1942561a
5 changed files with 88 additions and 27 deletions

View File

@@ -4,6 +4,7 @@ Tests courseware views.py
"""
import logging
import itertools
import json
import unittest
@@ -36,6 +37,7 @@ from xblock.core import XBlock
from xblock.fields import Scope, String
import lms.djangoapps.courseware.views.views as views
from lms.djangoapps.courseware.toggles import REDIRECT_TO_COURSEWARE_MICROFRONTEND
import shoppingcart
from capa.tests.response_xml_factory import MultipleChoiceResponseXMLFactory
@@ -68,6 +70,7 @@ from openedx.core.djangoapps.content.course_overviews.models import CourseOvervi
from openedx.core.djangoapps.crawlers.models import CrawlersConfig
from openedx.core.djangoapps.credit.api import set_credit_requirements
from openedx.core.djangoapps.credit.models import CreditCourse, CreditProvider
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
from openedx.core.djangoapps.waffle_utils.testutils import WAFFLE_TABLES, override_waffle_flag
from openedx.core.djangolib.testing.utils import get_mock_request
from openedx.core.lib.gating import api as gating_api
@@ -103,9 +106,10 @@ QUERY_COUNT_TABLE_BLACKLIST = WAFFLE_TABLES
FEATURES_WITH_DISABLE_HONOR_CERTIFICATE = settings.FEATURES.copy()
FEATURES_WITH_DISABLE_HONOR_CERTIFICATE['DISABLE_HONOR_CERTIFICATES'] = True
LOGGER = logging.getLogger(__name__)
@ddt.ddt
class TestJumpTo(ModuleStoreTestCase):
class TestJumpTo(ModuleStoreTestCase, SiteMixin):
"""
Check the jumpto link for a course.
"""
@@ -250,6 +254,51 @@ class TestJumpTo(ModuleStoreTestCase):
self.assertEqual(expected_url, get_redirect_url(course_key, usage_key, request))
def test_jump_to_with_microfrontend_enabled(self):
course = CourseFactory.create()
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
section = ItemFactory.create(category='sequential', parent_location=chapter.location)
unit = ItemFactory.create(category='vertical', parent_location=section.location)
course_key = CourseKey.from_string(six.text_type(course.id))
# unit position is hard coded here for simplicity - is there a simple way to get it from here?
expected = '/courses/{course_id}/courseware/{chapter_id}/{section_id}/1?{activate_block_id}'.format(
course_id=six.text_type(course.id),
chapter_id=chapter.url_name,
section_id=section.url_name,
activate_block_id=urlencode({'activate_block_id': six.text_type(unit.location)})
)
jumpto_url = '{0}/{1}/jump_to/{2}'.format(
'/courses',
six.text_type(course.id),
six.text_type(unit.location),
)
microfrontend_expected = 'http://learning-mfe/course/{course_key}/{section_id}/{unit_id}'.format(
course_key=course_key,
section_id=section.location,
unit_id=unit.location
)
"""
http://learning-mfe/course/org.0/course_0/Run_0/i4x://org.0/course_0/sequential/sequential_2/i4x://org.0/course_0/vertical/vertical_3',
http://learning-mfe/course/org.0/course_0/Run_0/i4x://org.0/course_0/sequential/sequential_2/vertical_3
"""
with override_waffle_flag(REDIRECT_TO_COURSEWARE_MICROFRONTEND, active=True):
response = self.client.get(jumpto_url)
self.assertRedirects(response, expected, status_code=302, target_status_code=302)
# Test with waffle flag active and site setting enabled, redirects to microfrontend
site_domain = 'othersite.example.com'
self.set_up_site(site_domain, {
'SITE_NAME': site_domain,
'ENABLE_COURSEWARE_MICROFRONTEND': True
})
response = self.client.get(jumpto_url)
LOGGER.error(response.url) # None/course/org.0/course_0/Run_0/i4x://org.0/course_0/sequential/sequential_2
self.assertRedirects(response, microfrontend_expected, fetch_redirect_response=False, status_code=302, target_status_code=302)
@ddt.ddt
class IndexQueryTestCase(ModuleStoreTestCase):

View File

@@ -18,7 +18,7 @@ WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='courseware')
# .. toggle_creation_date: 2020-01-29
# .. toggle_expiration_date: 2020-12-31
# .. toggle_warnings: Also set settings.LEARNING_MICROFRONTEND_URL and ENABLE_COURSEWARE_MICROFRONTEND.
# .. toggle_tickets:
# .. toggle_tickets: TNL-6982
# .. toggle_status: supported
REDIRECT_TO_COURSEWARE_MICROFRONTEND = CourseWaffleFlag(WAFFLE_FLAG_NAMESPACE, 'redirect_to_microfrontend')

View File

@@ -11,6 +11,7 @@ from xmodule.modulestore.django import modulestore
from xmodule.modulestore.search import navigation_index, path_to_location
from lms.djangoapps.courseware.toggles import should_redirect_to_courseware_microfrontend
def get_redirect_url(course_key, usage_key, request=None):
""" Returns the redirect url back to courseware
@@ -26,8 +27,8 @@ def get_redirect_url(course_key, usage_key, request=None):
"""
if should_redirect_to_courseware_microfrontend(course_key):
path = path_to_location(modulestore(), usage_key, request, full_path=True)
return get_microfrontend_redirect_url(course_key, path)
path = path_to_location(modulestore(), usage_key, request, full_path=True)
return get_microfrontend_redirect_url(course_key, path)
(
course_key, chapter, section, vertical_unused,
@@ -57,8 +58,9 @@ def get_redirect_url(course_key, usage_key, request=None):
redirect_url += "?{}".format(urlencode({'activate_block_id': six.text_type(final_target_id)}))
return redirect_url
def get_microfrontend_redirect_url(course_key, path):
"""
def get_microfrontend_redirect_url(course_key, path=None):
"""
The micro-frontend determines the user's position in the vertical via
a separate API call, so all we need here is the course_key, section, and vertical
IDs to format it's URL.
@@ -68,27 +70,30 @@ def get_microfrontend_redirect_url(course_key, path):
We're building a URL like this:
http://localhost:2000/course-v1:edX+DemoX+Demo_Course/block-v1:edX+DemoX+Demo_Course+type@sequential+block@19a30717eff543078a5d94ae9d6c18a5/block-v1:edX+DemoX+Demo_Course+type@vertical+block@4a1bba2a403f40bca5ec245e945b0d76
"""
"""
redirect_url = '{base_url}/{prefix}/{course_key}'.format(
base_url=settings.LEARNING_MICROFRONTEND_URL,
prefix='course/',
course_key=course_key
)
# The first four elements of the path list are the ones we care about here:
# - course
# - chapter
# - sequence
# - vertical
# We skip course because we already have it from our argument above, and we skip chapter because the micro-frontend URL doesn't include it.
if len(path) > 2:
redirect_url += '/{sequence_key}'.format(
sequence_key=path[2]
)
if len(path) > 3:
redirect_url += '/{vertical_key}'.format(
vertical_key=path[3]
redirect_url = '{base_url}/{prefix}/{course_key}'.format(
base_url=settings.LEARNING_MICROFRONTEND_URL,
prefix='course',
course_key=course_key
)
return redirect_url
if path is None:
return redirect_url
# The first four elements of the path list are the ones we care about here:
# - course
# - chapter
# - sequence
# - vertical
# We skip course because we already have it from our argument above, and we skip chapter because the micro-frontend URL doesn't include it.
if len(path) > 2:
redirect_url += '/{sequence_key}'.format(
sequence_key=path[2]
)
if len(path) > 3:
redirect_url += '/{vertical_key}'.format(
vertical_key=path[3]
)
return redirect_url

View File

@@ -16,6 +16,7 @@ from django.conf import settings
from django.contrib.auth.models import User
from django.contrib.auth.views import redirect_to_login
from django.http import Http404
from django.shortcuts import redirect
from django.template.context_processors import csrf
from django.urls import reverse
from django.utils.decorators import method_decorator
@@ -31,6 +32,8 @@ from web_fragments.fragment import Fragment
from edxmako.shortcuts import render_to_response, render_to_string
from lms.djangoapps.courseware.courses import allow_public_access
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
from lms.djangoapps.courseware.toggles import should_redirect_to_courseware_microfrontend
from lms.djangoapps.courseware.url_helpers import get_microfrontend_redirect_url
from lms.djangoapps.experiments.utils import get_experiment_user_metadata_context
from lms.djangoapps.gating.api import get_entrance_exam_score_ratio, get_entrance_exam_usage_key
from lms.djangoapps.grades.api import CourseGradeFactory
@@ -114,6 +117,9 @@ class CoursewareIndex(View):
if not (request.user.is_authenticated or self.enable_unenrolled_access):
return redirect_to_login(request.get_full_path())
if should_redirect_to_courseware_microfrontend(self.course_key):
return redirect(get_microfrontend_redirect_url(self.course_key))
self.original_chapter_url_name = chapter
self.original_section_url_name = section
self.chapter_url_name = chapter

View File

@@ -593,6 +593,7 @@ PDF_RECEIPT_TAX_ID_LABEL = 'Tax ID'
PROFILE_MICROFRONTEND_URL = "http://profile-mfe/abc/"
ORDER_HISTORY_MICROFRONTEND_URL = "http://order-history-mfe/"
ACCOUNT_MICROFRONTEND_URL = "http://account-mfe/"
LEARNING_MICROFRONTEND_URL = "http://learning-mfe"
########################## limiting dashboard courses ######################