refactor:moved mfe proctoring to central point

refactor:fixed variable names

refactor:fixed linter errors

refactor:fixed linter errors

refactor:fixed checklist view variable names

fix: removed redundant variables

refactor:moved exam settings to toggles

refactor: changed function params and added tests

refactor: moved toggle to method

fix: updated toggle and method docs
This commit is contained in:
Ahtisham Shahid
2021-06-02 21:22:28 +05:00
parent b62ce901b4
commit ec980a2ba8
16 changed files with 114 additions and 72 deletions

View File

@@ -62,3 +62,20 @@ def bypass_olx_failure_enabled():
Check if bypass is enabled for course olx validation errors. Check if bypass is enabled for course olx validation errors.
""" """
return BYPASS_OLX_FAILURE.is_enabled() return BYPASS_OLX_FAILURE.is_enabled()
# .. toggle_name: FEATURES['ENABLE_EXAM_SETTINGS_HTML_VIEW']
# .. toggle_implementation: SettingDictToggle
# .. toggle_default: False
# .. toggle_description: When enabled, users can access the new course authoring view for proctoring exams
# .. toggle_warnings: None
# .. toggle_creation_date: 2020-07-23
ENABLE_EXAM_SETTINGS_HTML_VIEW = SettingDictToggle(
"FEATURES", "ENABLE_EXAM_SETTINGS_HTML_VIEW", default=False, module_name=__name__
)
def exam_setting_view_enabled():
"""
Returns a boolean if proctoring exam setting mfe view is enabled.
"""
return ENABLE_EXAM_SETTINGS_HTML_VIEW.is_enabled()

View File

@@ -2,7 +2,6 @@
Common utility functions useful throughout the contentstore Common utility functions useful throughout the contentstore
""" """
import logging import logging
from contextlib import contextmanager from contextlib import contextmanager
from datetime import datetime from datetime import datetime
@@ -16,6 +15,7 @@ from opaque_keys.edx.locator import LibraryLocator
from pytz import UTC from pytz import UTC
from cms.djangoapps.contentstore.config.waffle import ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND from cms.djangoapps.contentstore.config.waffle import ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND
from cms.djangoapps.contentstore.toggles import exam_setting_view_enabled
from common.djangoapps.student import auth from common.djangoapps.student import auth
from common.djangoapps.student.models import CourseEnrollment from common.djangoapps.student.models import CourseEnrollment
from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole from common.djangoapps.student.roles import CourseInstructorRole, CourseStaffRole
@@ -157,37 +157,39 @@ def get_lms_link_for_certificate_web_view(course_key, mode):
) )
def get_course_authoring_url(course_module): def get_course_authoring_url(course_locator):
""" """
Gets course authoring microfrontend URL Gets course authoring microfrontend URL
""" """
return configuration_helpers.get_value_for_org( return configuration_helpers.get_value_for_org(
course_module.location.org, course_locator.org,
'COURSE_AUTHORING_MICROFRONTEND_URL', 'COURSE_AUTHORING_MICROFRONTEND_URL',
settings.COURSE_AUTHORING_MICROFRONTEND_URL settings.COURSE_AUTHORING_MICROFRONTEND_URL
) )
def get_pages_and_resources_url(course_module): def get_pages_and_resources_url(course_locator):
""" """
Gets course authoring microfrontend URL for Pages and Resources view. Gets course authoring microfrontend URL for Pages and Resources view.
""" """
pages_and_resources_url = None pages_and_resources_url = None
if ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND.is_enabled(course_module.id): if ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND.is_enabled(course_locator):
mfe_base_url = get_course_authoring_url(course_module) mfe_base_url = get_course_authoring_url(course_locator)
if mfe_base_url: if mfe_base_url:
pages_and_resources_url = f'{mfe_base_url}/course/{course_module.id}/pages-and-resources' pages_and_resources_url = f'{mfe_base_url}/course/{course_locator}/pages-and-resources'
return pages_and_resources_url return pages_and_resources_url
def get_proctored_exam_settings_url(course_module): def get_proctored_exam_settings_url(course_locator) -> str:
""" """
Gets course authoring microfrontend URL for links to proctored exam settings page Gets course authoring microfrontend URL for links to proctored exam settings page
""" """
course_authoring_microfrontend_url = '' proctored_exam_settings_url = ''
if settings.FEATURES.get('ENABLE_EXAM_SETTINGS_HTML_VIEW'): if exam_setting_view_enabled():
course_authoring_microfrontend_url = get_course_authoring_url(course_module) mfe_base_url = get_course_authoring_url(course_locator)
return course_authoring_microfrontend_url if mfe_base_url:
proctored_exam_settings_url = f'{mfe_base_url}/course/{course_locator}/proctored-exam-settings'
return proctored_exam_settings_url
def course_import_olx_validation_is_enabled(): def course_import_olx_validation_is_enabled():

View File

@@ -411,11 +411,7 @@ def certificates_list_handler(request, course_key_string):
) )
else: else:
certificate_web_view_url = None certificate_web_view_url = None
is_active, certificates = CertificateManager.is_activated(course) is_active, certificates = CertificateManager.is_activated(course)
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course)
return render_to_response('certificates.html', { return render_to_response('certificates.html', {
'context_course': course, 'context_course': course,
'certificate_url': certificate_url, 'certificate_url': certificate_url,
@@ -428,7 +424,7 @@ def certificates_list_handler(request, course_key_string):
'is_active': is_active, 'is_active': is_active,
'is_global_staff': GlobalStaff().has_user(request.user), 'is_global_staff': GlobalStaff().has_user(request.user),
'certificate_activation_handler_url': activation_handler_url, 'certificate_activation_handler_url': activation_handler_url,
'course_authoring_microfrontend_url': course_authoring_microfrontend_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course.id),
}) })
elif "application/json" in request.META.get('HTTP_ACCEPT'): elif "application/json" in request.META.get('HTTP_ACCEPT'):
# Retrieve the list of certificates for the specified course # Retrieve the list of certificates for the specified course

View File

@@ -28,17 +28,8 @@ def checklists_handler(request, course_key_string=None):
raise PermissionDenied() raise PermissionDenied()
course_module = modulestore().get_course(course_key) course_module = modulestore().get_course(course_key)
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course_module)
proctored_exam_settings_url = (
'{course_authoring_microfrontend_url}/proctored-exam-settings/{course_key_string}'.format(
course_authoring_microfrontend_url=course_authoring_microfrontend_url,
course_key_string=course_key_string,
)
)
return render_to_response('checklists.html', { return render_to_response('checklists.html', {
'language_code': request.LANGUAGE_CODE, 'language_code': request.LANGUAGE_CODE,
'context_course': course_module, 'context_course': course_module,
'proctored_exam_settings_url': proctored_exam_settings_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_module.id),
}) })

View File

@@ -700,9 +700,6 @@ def course_index(request, course_key):
'FRONTEND_APP_PUBLISHER_URL', 'FRONTEND_APP_PUBLISHER_URL',
settings.FEATURES.get('FRONTEND_APP_PUBLISHER_URL', False) settings.FEATURES.get('FRONTEND_APP_PUBLISHER_URL', False)
) )
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course_module)
# gather any errors in the currently stored proctoring settings. # gather any errors in the currently stored proctoring settings.
advanced_dict = CourseMetadata.fetch(course_module) advanced_dict = CourseMetadata.fetch(course_module)
proctoring_errors = CourseMetadata.validate_proctoring_settings(course_module, advanced_dict, request.user) proctoring_errors = CourseMetadata.validate_proctoring_settings(course_module, advanced_dict, request.user)
@@ -727,7 +724,7 @@ def course_index(request, course_key):
}, },
) if current_action else None, ) if current_action else None,
'frontend_app_publisher_url': frontend_app_publisher_url, 'frontend_app_publisher_url': frontend_app_publisher_url,
'course_authoring_microfrontend_url': course_authoring_microfrontend_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_module.id),
'advance_settings_url': reverse_course_url('advanced_settings_handler', course_module.id), 'advance_settings_url': reverse_course_url('advanced_settings_handler', course_module.id),
'proctoring_errors': proctoring_errors, 'proctoring_errors': proctoring_errors,
}) })
@@ -1142,9 +1139,6 @@ def settings_handler(request, course_key_string): # lint-amnesty, pylint: disab
verified_mode = CourseMode.verified_mode_for_course(course_key, include_expired=True) verified_mode = CourseMode.verified_mode_for_course(course_key, include_expired=True)
upgrade_deadline = (verified_mode and verified_mode.expiration_datetime and upgrade_deadline = (verified_mode and verified_mode.expiration_datetime and
verified_mode.expiration_datetime.isoformat()) verified_mode.expiration_datetime.isoformat())
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course_module)
settings_context = { settings_context = {
'context_course': course_module, 'context_course': course_module,
'course_locator': course_key, 'course_locator': course_key,
@@ -1168,7 +1162,7 @@ def settings_handler(request, course_key_string): # lint-amnesty, pylint: disab
'is_entrance_exams_enabled': core_toggles.ENTRANCE_EXAMS.is_enabled(), 'is_entrance_exams_enabled': core_toggles.ENTRANCE_EXAMS.is_enabled(),
'enable_extended_course_details': enable_extended_course_details, 'enable_extended_course_details': enable_extended_course_details,
'upgrade_deadline': upgrade_deadline, 'upgrade_deadline': upgrade_deadline,
'course_authoring_microfrontend_url': course_authoring_microfrontend_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_module.id),
} }
if is_prerequisite_courses_enabled(): if is_prerequisite_courses_enabled():
courses, in_process_course_actions = get_courses_accessible_to_user(request) courses, in_process_course_actions = get_courses_accessible_to_user(request)
@@ -1282,16 +1276,13 @@ def grading_handler(request, course_key_string, grader_index=None):
if 'text/html' in request.META.get('HTTP_ACCEPT', '') and request.method == 'GET': if 'text/html' in request.META.get('HTTP_ACCEPT', '') and request.method == 'GET':
course_details = CourseGradingModel.fetch(course_key) course_details = CourseGradingModel.fetch(course_key)
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course_module)
return render_to_response('settings_graders.html', { return render_to_response('settings_graders.html', {
'context_course': course_module, 'context_course': course_module,
'course_locator': course_key, 'course_locator': course_key,
'course_details': course_details, 'course_details': course_details,
'grading_url': reverse_course_url('grading_handler', course_key), 'grading_url': reverse_course_url('grading_handler', course_key),
'is_credit_course': is_credit_course(course_key), 'is_credit_course': is_credit_course(course_key),
'course_authoring_microfrontend_url': course_authoring_microfrontend_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_module.id),
}) })
elif 'application/json' in request.META.get('HTTP_ACCEPT', ''): elif 'application/json' in request.META.get('HTTP_ACCEPT', ''):
if request.method == 'GET': if request.method == 'GET':
@@ -1388,9 +1379,6 @@ def advanced_settings_handler(request, course_key_string):
'ENABLE_PUBLISHER', 'ENABLE_PUBLISHER',
settings.FEATURES.get('ENABLE_PUBLISHER', False) settings.FEATURES.get('ENABLE_PUBLISHER', False)
) )
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course_module)
# gather any errors in the currently stored proctoring settings. # gather any errors in the currently stored proctoring settings.
proctoring_errors = CourseMetadata.validate_proctoring_settings(course_module, advanced_dict, request.user) proctoring_errors = CourseMetadata.validate_proctoring_settings(course_module, advanced_dict, request.user)
@@ -1399,7 +1387,7 @@ def advanced_settings_handler(request, course_key_string):
'advanced_dict': advanced_dict, 'advanced_dict': advanced_dict,
'advanced_settings_url': reverse_course_url('advanced_settings_handler', course_key), 'advanced_settings_url': reverse_course_url('advanced_settings_handler', course_key),
'publisher_enabled': publisher_enabled, 'publisher_enabled': publisher_enabled,
'course_authoring_microfrontend_url': course_authoring_microfrontend_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course_module.id),
'proctoring_errors': proctoring_errors, 'proctoring_errors': proctoring_errors,
}) })
elif 'application/json' in request.META.get('HTTP_ACCEPT', ''): elif 'application/json' in request.META.get('HTTP_ACCEPT', ''):
@@ -1743,9 +1731,6 @@ def group_configurations_list_handler(request, course_key_string):
# This will add ability to add new groups in the view. # This will add ability to add new groups in the view.
if not has_content_groups: if not has_content_groups:
displayable_partitions.append(GroupConfiguration.get_or_create_content_group(store, course)) displayable_partitions.append(GroupConfiguration.get_or_create_content_group(store, course))
course_authoring_microfrontend_url = get_proctored_exam_settings_url(course)
return render_to_response('group_configurations.html', { return render_to_response('group_configurations.html', {
'context_course': course, 'context_course': course,
'group_configuration_url': group_configuration_url, 'group_configuration_url': group_configuration_url,
@@ -1754,7 +1739,7 @@ def group_configurations_list_handler(request, course_key_string):
'should_show_experiment_groups': should_show_experiment_groups, 'should_show_experiment_groups': should_show_experiment_groups,
'all_group_configurations': displayable_partitions, 'all_group_configurations': displayable_partitions,
'should_show_enrollment_track': should_show_enrollment_track, 'should_show_enrollment_track': should_show_enrollment_track,
'course_authoring_microfrontend_url': course_authoring_microfrontend_url, 'mfe_proctored_exam_settings_url': get_proctored_exam_settings_url(course.id),
}) })
elif "application/json" in request.META.get('HTTP_ACCEPT'): elif "application/json" in request.META.get('HTTP_ACCEPT'):
if request.method == 'POST': if request.method == 'POST':

View File

@@ -71,7 +71,7 @@ def tabs_handler(request, course_key_string):
'context_course': course_item, 'context_course': course_item,
'tabs_to_render': tabs_to_render, 'tabs_to_render': tabs_to_render,
'lms_link': get_lms_link_for_item(course_item.location), 'lms_link': get_lms_link_for_item(course_item.location),
'pages_and_resources_mfe_link': get_pages_and_resources_url(course_item), 'pages_and_resources_mfe_link': get_pages_and_resources_url(course_item.id),
}) })
else: else:
return HttpResponseNotFound() return HttpResponseNotFound()

View File

@@ -6,6 +6,7 @@ Unit tests for getting the list of courses and the course outline.
import datetime import datetime
import json import json
from unittest import mock from unittest import mock
from unittest.mock import patch
import ddt import ddt
import lxml import lxml
@@ -19,7 +20,12 @@ from search.api import perform_search
from cms.djangoapps.contentstore.courseware_index import CoursewareSearchIndexer, SearchIndexingError from cms.djangoapps.contentstore.courseware_index import CoursewareSearchIndexer, SearchIndexingError
from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from cms.djangoapps.contentstore.utils import add_instructor, reverse_course_url, reverse_usage_url from cms.djangoapps.contentstore.utils import (
add_instructor,
get_proctored_exam_settings_url,
reverse_course_url,
reverse_usage_url
)
from common.djangoapps.course_action_state.managers import CourseRerunUIStateManager from common.djangoapps.course_action_state.managers import CourseRerunUIStateManager
from common.djangoapps.course_action_state.models import CourseRerunState from common.djangoapps.course_action_state.models import CourseRerunState
from common.djangoapps.student.auth import has_course_author_access from common.djangoapps.student.auth import has_course_author_access
@@ -589,6 +595,28 @@ class TestCourseOutline(CourseTestCase):
expected_block_types expected_block_types
) )
@override_settings(FEATURES={'ENABLE_EXAM_SETTINGS_HTML_VIEW': True})
@patch('cms.djangoapps.models.settings.course_metadata.CourseMetadata.validate_proctoring_settings')
def test_proctoring_link_is_visible(self, mock_validate_proctoring_settings):
"""
Test to check proctored exam settings mfe url is rendering properly
"""
mock_validate_proctoring_settings.return_value = [
{
'key': 'proctoring_provider',
'message': 'error message',
'model': {'display_name': 'proctoring_provider'}
},
{
'key': 'proctoring_provider',
'message': 'error message',
'model': {'display_name': 'proctoring_provider'}
}
]
response = self.client.get_html(reverse_course_url('course_handler', self.course.id))
proctored_exam_settings_url = get_proctored_exam_settings_url(self.course.id)
self.assertContains(response, proctored_exam_settings_url, 2)
class TestCourseReIndex(CourseTestCase): class TestCourseReIndex(CourseTestCase):
""" """

View File

@@ -2,13 +2,15 @@
Exam Settings View Tests Exam Settings View Tests
""" """
from unittest.mock import patch
import ddt import ddt
import lxml import lxml
from django.conf import settings from django.conf import settings
from django.test.utils import override_settings from django.test.utils import override_settings
from cms.djangoapps.contentstore.tests.utils import CourseTestCase from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from cms.djangoapps.contentstore.utils import reverse_course_url from cms.djangoapps.contentstore.utils import get_proctored_exam_settings_url, reverse_course_url
from common.djangoapps.util.testing import UrlResetMixin from common.djangoapps.util.testing import UrlResetMixin
FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy() FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
@@ -164,3 +166,26 @@ class TestExamSettingsView(CourseTestCase, UrlResetMixin):
parsed_html = lxml.html.fromstring(resp.content) parsed_html = lxml.html.fromstring(resp.content)
alert_nodes = parsed_html.find_class('exam-settings-alert') alert_nodes = parsed_html.find_class('exam-settings-alert')
assert len(alert_nodes) == 0 assert len(alert_nodes) == 0
@override_settings(FEATURES={'ENABLE_EXAM_SETTINGS_HTML_VIEW': True})
@patch('cms.djangoapps.models.settings.course_metadata.CourseMetadata.validate_proctoring_settings')
def test_proctoring_link_is_visible(self, mock_validate_proctoring_settings):
"""
Test to check proctored exam settings mfe url is rendering properly
"""
mock_validate_proctoring_settings.return_value = [
{
'key': 'proctoring_provider',
'message': 'error message',
'model': {'display_name': 'proctoring_provider'}
},
{
'key': 'proctoring_provider',
'message': 'error message',
'model': {'display_name': 'proctoring_provider'}
}
]
response = self.client.get_html(reverse_course_url('advanced_settings_handler', self.course.id))
proctored_exam_settings_url = get_proctored_exam_settings_url(self.course.id)
self.assertContains(response, proctored_exam_settings_url, 3)

View File

@@ -118,8 +118,8 @@ CMS.User.isGlobalStaff = '${is_global_staff | n, js_escaped_string}'=='True' ? t
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li> <li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li> <li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li>
<li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li> <li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${course_authoring_microfrontend_url}/proctored-exam-settings/${url_encoded_course_id}">${_("Proctored Exam Settings")}</a></li> <li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif % endif
</ul> </ul>
</nav> </nav>

View File

@@ -67,7 +67,7 @@
"course_updates": ${utils.reverse_course_url('course_info_handler', course_key) | n, dump_js_escaped_json}, "course_updates": ${utils.reverse_course_url('course_info_handler', course_key) | n, dump_js_escaped_json},
"grading_policy": ${utils.reverse_course_url('grading_handler', course_key) | n, dump_js_escaped_json}, "grading_policy": ${utils.reverse_course_url('grading_handler', course_key) | n, dump_js_escaped_json},
"settings": ${utils.reverse_course_url('settings_handler', course_key) | n, dump_js_escaped_json}, "settings": ${utils.reverse_course_url('settings_handler', course_key) | n, dump_js_escaped_json},
"proctored_exam_settings": ${proctored_exam_settings_url | n, dump_js_escaped_json} "proctored_exam_settings": ${mfe_proctored_exam_settings_url | n, dump_js_escaped_json}
} }
} }
</%static:studiofrontend> </%static:studiofrontend>

View File

@@ -115,7 +115,7 @@ from django.urls import reverse
</div> </div>
</div> </div>
%endif %endif
%if proctoring_errors: %if proctoring_errors:
<div class="wrapper wrapper-alert wrapper-alert-error is-shown"> <div class="wrapper wrapper-alert wrapper-alert-error is-shown">
<div class="alert announcement has-actions"> <div class="alert announcement has-actions">
@@ -124,12 +124,11 @@ from django.urls import reverse
<div class="exam-settings-alert copy"> <div class="exam-settings-alert copy">
<h2 class="title title-3">${_("This course has proctored exam settings that are incomplete or invalid.")}</h2> <h2 class="title title-3">${_("This course has proctored exam settings that are incomplete or invalid.")}</h2>
<p> <p>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<% url_encoded_course_id = quote(six.text_type(context_course.id).encode('utf-8'), safe='') %> <% url_encoded_course_id = quote(six.text_type(context_course.id).encode('utf-8'), safe='') %>
${Text(_("To update these settings go to the {link_start}Proctored Exam Settings page{link_end}.")).format( ${Text(_("To update these settings go to the {link_start}Proctored Exam Settings page{link_end}.")).format(
link_start=HTML('<a href="{course_authoring_microfrontend_url}/proctored-exam-settings/{url_encoded_course_id}">').format( link_start=HTML('<a href="${mfe_proctored_exam_settings_url}">').format(
course_authoring_microfrontend_url=course_authoring_microfrontend_url, mfe_proctored_exam_settings_url=mfe_proctored_exam_settings_url
url_encoded_course_id=url_encoded_course_id,
), ),
link_end=HTML("</a>") link_end=HTML("</a>")
)} )}

View File

@@ -128,8 +128,8 @@ from six.moves.urllib.parse import quote
<li class="nav-item"><a href="${grading_url}">${_("Grading")}</a></li> <li class="nav-item"><a href="${grading_url}">${_("Grading")}</a></li>
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li> <li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li> <li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${course_authoring_microfrontend_url}/proctored-exam-settings/${url_encoded_course_id}">${_("Proctored Exam Settings")}</a></li> <li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif % endif
</ul> </ul>
</nav> </nav>

View File

@@ -669,8 +669,8 @@ CMS.URL.UPLOAD_ASSET = '${upload_asset_url | n, js_escaped_string}'
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li> <li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li> <li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li>
<li class="nav-item"><a href="${advanced_config_url}">${_("Advanced Settings")}</a></li> <li class="nav-item"><a href="${advanced_config_url}">${_("Advanced Settings")}</a></li>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${course_authoring_microfrontend_url}/proctored-exam-settings/${url_encoded_course_id}">${_("Proctored Exam Settings")}</a></li> <li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif % endif
</ul> </ul>
</nav> </nav>

View File

@@ -42,12 +42,11 @@
<div class="exam-settings-alert copy"> <div class="exam-settings-alert copy">
<h2 class="title title-3">${_("This course has proctored exam settings that are incomplete or invalid.")}</h2> <h2 class="title title-3">${_("This course has proctored exam settings that are incomplete or invalid.")}</h2>
<p> <p>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<% url_encoded_course_id = quote(six.text_type(context_course.id).encode('utf-8'), safe='') %> <% url_encoded_course_id = quote(six.text_type(context_course.id).encode('utf-8'), safe='') %>
${Text(_("You will be unable to make changes until the errors are resolved. To update these settings go to the {link_start}Proctored Exam Settings page{link_end}.")).format( ${Text(_("You will be unable to make changes until the errors are resolved. To update these settings go to the {link_start}Proctored Exam Settings page{link_end}.")).format(
link_start=HTML('<a href="{course_authoring_microfrontend_url}/proctored-exam-settings/{url_encoded_course_id}">').format( link_start=HTML('<a href="{mfe_proctored_exam_settings_url}">').format(
course_authoring_microfrontend_url=course_authoring_microfrontend_url, mfe_proctored_exam_settings_url=mfe_proctored_exam_settings_url
url_encoded_course_id=url_encoded_course_id,
), ),
link_end=HTML("</a>") link_end=HTML("</a>")
)} )}
@@ -149,8 +148,8 @@
<li class="nav-item"><a href="${grading_url}">${_("Grading")}</a></li> <li class="nav-item"><a href="${grading_url}">${_("Grading")}</a></li>
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li> <li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li> <li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${course_authoring_microfrontend_url}/proctored-exam-settings/${url_encoded_course_id}">${_("Proctored Exam Settings")}</a></li> <li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif % endif
</ul> </ul>
</nav> </nav>

View File

@@ -166,8 +166,8 @@
<li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li> <li class="nav-item"><a href="${course_team_url}">${_("Course Team")}</a></li>
<li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li> <li class="nav-item"><a href="${utils.reverse_course_url('group_configurations_list_handler', context_course.id)}">${_("Group Configurations")}</a></li>
<li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li> <li class="nav-item"><a href="${advanced_settings_url}">${_("Advanced Settings")}</a></li>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<li class="nav-item"><a href="${course_authoring_microfrontend_url}/proctored-exam-settings/${url_encoded_course_id}">${_("Proctored Exam Settings")}</a></li> <li class="nav-item"><a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a></li>
% endif % endif
</ul> </ul>
</nav> </nav>

View File

@@ -104,9 +104,9 @@
<li class="nav-item nav-course-settings-group-configurations"> <li class="nav-item nav-course-settings-group-configurations">
<a href="${reverse('group_configurations_list_handler', kwargs={'course_key_string': six.text_type(course_key)})}">${_("Group Configurations")}</a> <a href="${reverse('group_configurations_list_handler', kwargs={'course_key_string': six.text_type(course_key)})}">${_("Group Configurations")}</a>
</li> </li>
% if course_authoring_microfrontend_url: % if mfe_proctored_exam_settings_url:
<li class="nav-item nav-course-settings-exams"> <li class="nav-item nav-course-settings-exams">
<a href="${course_authoring_microfrontend_url}/proctored-exam-settings/${url_encoded_course_key}">${_("Proctored Exam Settings")}</a> <a href="${mfe_proctored_exam_settings_url}">${_("Proctored Exam Settings")}</a>
</li> </li>
% endif % endif
<li class="nav-item nav-course-settings-advanced"> <li class="nav-item nav-course-settings-advanced">