diff --git a/cms/djangoapps/contentstore/views/item.py b/cms/djangoapps/contentstore/views/item.py index 4b48de1265..750be4d667 100644 --- a/cms/djangoapps/contentstore/views/item.py +++ b/cms/djangoapps/contentstore/views/item.py @@ -68,6 +68,7 @@ from xmodule.modulestore.inheritance import own_metadata from xmodule.services import ConfigurationService, SettingsService from xmodule.tabs import CourseTabList from xmodule.x_module import DEPRECATION_VSCOMPAT_EVENT, PREVIEW_VIEWS, STUDENT_VIEW, STUDIO_VIEW +from edx_proctoring.api import get_exam_configuration_dashboard_url __all__ = [ 'orphan_handler', 'xblock_handler', 'xblock_view_handler', 'xblock_outline_handler', 'xblock_container_handler' @@ -1221,6 +1222,12 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F }) elif xblock.category == 'sequential': rules_url = settings.PROCTORING_SETTINGS.get('LINK_URLS', {}).get('online_proctoring_rules', "") + + proctoring_exam_configuration_link = None + if xblock.is_proctored_exam: + proctoring_exam_configuration_link = get_exam_configuration_dashboard_url( + course.id, xblock_info['id']) + xblock_info.update({ 'is_proctored_exam': xblock.is_proctored_exam, 'online_proctoring_rules': rules_url, @@ -1228,6 +1235,7 @@ def create_xblock_info(xblock, data=None, metadata=None, include_ancestor_info=F 'is_time_limited': xblock.is_time_limited, 'exam_review_rules': xblock.exam_review_rules, 'default_time_limit_minutes': xblock.default_time_limit_minutes, + 'proctoring_exam_configuration_link': proctoring_exam_configuration_link, }) # Update with gating info diff --git a/cms/djangoapps/contentstore/views/tests/test_item.py b/cms/djangoapps/contentstore/views/tests/test_item.py index dc50c5959d..2c95afb31f 100644 --- a/cms/djangoapps/contentstore/views/tests/test_item.py +++ b/cms/djangoapps/contentstore/views/tests/test_item.py @@ -2786,7 +2786,8 @@ class TestXBlockInfo(ItemTest): self.assertIsNone(xblock_info.get('child_info', None)) @patch.dict('django.conf.settings.FEATURES', {'ENABLE_SPECIAL_EXAMS': True}) - def test_proctored_exam_xblock_info(self): + @patch('contentstore.views.item.get_exam_configuration_dashboard_url') + def test_proctored_exam_xblock_info(self, get_exam_configuration_dashboard_url_patch): self.course.enable_proctored_exams = True self.course.save() self.store.update_item(self.course, self.user.id) @@ -2807,6 +2808,8 @@ class TestXBlockInfo(ItemTest): default_time_limit_minutes=100 ) sequential = modulestore().get_item(sequential.location) + + get_exam_configuration_dashboard_url_patch.return_value = 'test_url' xblock_info = create_xblock_info( sequential, include_child_info=True, @@ -2816,6 +2819,8 @@ class TestXBlockInfo(ItemTest): self.assertEqual(xblock_info['is_proctored_exam'], True) self.assertEqual(xblock_info['is_time_limited'], True) self.assertEqual(xblock_info['default_time_limit_minutes'], 100) + self.assertEqual(xblock_info['proctoring_exam_configuration_link'], 'test_url') + get_exam_configuration_dashboard_url_patch.assert_called_with(self.course.id, xblock_info['id']) class TestLibraryXBlockInfo(ModuleStoreTestCase): diff --git a/cms/static/js/views/course_outline.js b/cms/static/js/views/course_outline.js index bd1d2c854d..5233bb7061 100644 --- a/cms/static/js/views/course_outline.js +++ b/cms/static/js/views/course_outline.js @@ -157,22 +157,23 @@ define(['jquery', 'underscore', 'js/views/xblock_outline', 'common/js/components }, editXBlock: function() { - var enable_proctored_exams = false; - var enable_timed_exams = false; + var modal; + var enableProctoredExams = false; + var enableTimedExams = false; if (this.model.get('category') === 'sequential') { if (this.parentView.parentView.model.has('enable_proctored_exams')) { - enable_proctored_exams = this.parentView.parentView.model.get('enable_proctored_exams'); + enableProctoredExams = this.parentView.parentView.model.get('enable_proctored_exams'); } if (this.parentView.parentView.model.has('enable_timed_exams')) { - enable_timed_exams = this.parentView.parentView.model.get('enable_timed_exams'); + enableTimedExams = this.parentView.parentView.model.get('enable_timed_exams'); } } - var modal = CourseOutlineModalsFactory.getModal('edit', this.model, { + modal = CourseOutlineModalsFactory.getModal('edit', this.model, { onSave: this.refresh.bind(this), parentInfo: this.parentInfo, - enable_proctored_exams: enable_proctored_exams, - enable_timed_exams: enable_timed_exams, + enable_proctored_exams: enableProctoredExams, + enable_timed_exams: enableTimedExams, xblockType: XBlockViewUtils.getXBlockType( this.model.get('category'), this.parentView.model, true ) diff --git a/cms/static/sass/views/_outline.scss b/cms/static/sass/views/_outline.scss index 8e4142081d..d11417f2d1 100644 --- a/cms/static/sass/views/_outline.scss +++ b/cms/static/sass/views/_outline.scss @@ -429,7 +429,7 @@ .subsection-header-details { @include float(left); - width: flex-grid(6, 9); + width: flex-grid(5, 9); .icon, .wrapper-subsection-title { display: inline-block; @@ -459,7 +459,7 @@ .subsection-header-actions { @include float(right); - width: flex-grid(3, 9); + width: flex-grid(4, 9); margin-top: -($baseline/4); @include text-align(right); @@ -469,6 +469,10 @@ @extend %t-action2; margin-right: ($baseline/2); + + .proctoring-configuration-button { + @extend %ui-btn-flat-outline; + } } } diff --git a/cms/templates/js/course-outline.underscore b/cms/templates/js/course-outline.underscore index 72b780ce4a..b201328c9a 100644 --- a/cms/templates/js/course-outline.underscore +++ b/cms/templates/js/course-outline.underscore @@ -122,9 +122,15 @@ if (is_proctored_exam) { <% } %> -