From 2f57a9dc71d1786cf0f7ee335c178e96f629dcd3 Mon Sep 17 00:00:00 2001 From: "Kyle D. McCormick" Date: Wed, 15 Jan 2025 09:22:19 -0500 Subject: [PATCH] refactor: Remove broken Force-Publish UI from Studio --- cms/djangoapps/maintenance/tests.py | 112 ------------------ cms/djangoapps/maintenance/urls.py | 2 - cms/djangoapps/maintenance/views.py | 108 ----------------- .../js/maintenance/force_publish_course.js | 83 ------------- .../maintenance/_force_publish_course.html | 33 ------ cms/templates/maintenance/container.html | 8 -- 6 files changed, 346 deletions(-) delete mode 100644 cms/static/js/maintenance/force_publish_course.js delete mode 100644 cms/templates/maintenance/_force_publish_course.html diff --git a/cms/djangoapps/maintenance/tests.py b/cms/djangoapps/maintenance/tests.py index a487f8e37faa..db8a4261d6c6 100644 --- a/cms/djangoapps/maintenance/tests.py +++ b/cms/djangoapps/maintenance/tests.py @@ -122,118 +122,6 @@ def test_non_global_staff_access(self, url): ) -@ddt.ddt -class TestForcePublish(MaintenanceViewTestCase): - """ - Tests for the force publish view. - """ - - def setUp(self): - super().setUp() - self.view_url = reverse('maintenance:force_publish_course') - - def setup_test_course(self): - """ - Creates the course and add some changes to it. - - Returns: - course: a course object - """ - course = CourseFactory.create() - # Add some changes to course - chapter = BlockFactory.create(category='chapter', parent_location=course.location) - self.store.create_child( - self.user.id, - chapter.location, - 'html', - block_id='html_component' - ) - # verify that course has changes. - self.assertTrue(self.store.has_changes(self.store.get_item(course.location))) - return course - - @ddt.data( - ('', COURSE_KEY_ERROR_MESSAGES['empty_course_key']), - ('edx', COURSE_KEY_ERROR_MESSAGES['invalid_course_key']), - ('course-v1:e+d+X', COURSE_KEY_ERROR_MESSAGES['course_key_not_found']), - ) - @ddt.unpack - def test_invalid_course_key_messages(self, course_key, error_message): - """ - Test all error messages for invalid course keys. - """ - # validate that course key contains error message - self.verify_error_message( - data={'course-id': course_key}, - error_message=error_message - ) - - def test_already_published(self): - """ - Test that when a course is forcefully publish, we get a 'course is already published' message. - """ - course = self.setup_test_course() - - # publish the course - source_store = modulestore()._get_modulestore_for_courselike(course.id) # pylint: disable=protected-access - source_store.force_publish_course(course.id, self.user.id, commit=True) - - # now course is published, we should get `already published course` error. - self.verify_error_message( - data={'course-id': str(course.id)}, - error_message='Course is already in published state.' - ) - - def verify_versions_are_different(self, course): - """ - Verify draft and published versions point to different locations. - - Arguments: - course (object): a course object. - """ - # get draft and publish branch versions - versions = get_course_versions(str(course.id)) - - # verify that draft and publish point to different versions - self.assertNotEqual(versions['draft-branch'], versions['published-branch']) - - def get_force_publish_course_response(self, course): - """ - Get force publish the course response. - - Arguments: - course (object): a course object. - - Returns: - response : response from force publish post view. - """ - # Verify versions point to different locations initially - self.verify_versions_are_different(course) - - # force publish course view - data = { - 'course-id': str(course.id) - } - response = self.client.post(self.view_url, data=data, HTTP_X_REQUESTED_WITH='XMLHttpRequest') - response_data = json.loads(response.content.decode('utf-8')) - return response_data - - def test_force_publish_dry_run(self): - """ - Test that dry run does not publishes the course but shows possible outcome if force published is executed. - """ - course = self.setup_test_course() - response = self.get_force_publish_course_response(course) - - self.assertIn('current_versions', response) - - # verify that course still has changes as we just dry ran force publish course. - self.assertTrue(self.store.has_changes(self.store.get_item(course.location))) - - # verify that both branch versions are still different - self.verify_versions_are_different(course) - - @ddt.ddt class TestAnnouncementsViews(MaintenanceViewTestCase): """ diff --git a/cms/djangoapps/maintenance/urls.py b/cms/djangoapps/maintenance/urls.py index 42febd139512..2937727bfa39 100644 --- a/cms/djangoapps/maintenance/urls.py +++ b/cms/djangoapps/maintenance/urls.py @@ -9,7 +9,6 @@ AnnouncementDeleteView, AnnouncementEditView, AnnouncementIndexView, - ForcePublishCourseView, MaintenanceIndexView ) @@ -17,7 +16,6 @@ urlpatterns = [ path('', MaintenanceIndexView.as_view(), name='maintenance_index'), - re_path(r'^force_publish_course/?$', ForcePublishCourseView.as_view(), name='force_publish_course'), re_path(r'^announcements/(?P\d+)?$', AnnouncementIndexView.as_view(), name='announcement_index'), path('announcements/create', AnnouncementCreateView.as_view(), name='announcement_create'), re_path(r'^announcements/edit/(?P\d+)?$', AnnouncementEditView.as_view(), name='announcement_edit'), diff --git a/cms/djangoapps/maintenance/views.py b/cms/djangoapps/maintenance/views.py index 357f64e90ebd..7448a972f327 100644 --- a/cms/djangoapps/maintenance/views.py +++ b/cms/djangoapps/maintenance/views.py @@ -30,16 +30,6 @@ # This dict maintains all the views that will be used Maintenance app. MAINTENANCE_VIEWS = { - 'force_publish_course': { - 'url': 'maintenance:force_publish_course', - 'name': _('Force Publish Course'), - 'slug': 'force_publish_course', - 'description': _( - 'Sometimes the draft and published branches of a course can get out of sync. Force publish course command ' - 'resets the published branch of a course to point to the draft branch, effectively force publishing the ' - 'course. This view dry runs the force publish command' - ), - }, 'announcement_index': { 'url': 'maintenance:announcement_index', 'name': _('Edit Announcements'), @@ -131,104 +121,6 @@ def validate_course_key(self, course_key, branch=ModuleStoreEnum.BranchName.draf return course_usage_key -class ForcePublishCourseView(MaintenanceBaseView): - """ - View for force publishing state of the course, used by the global staff. - - This view uses `force_publish_course` method of modulestore which publishes the draft state of the course. After - the course has been forced published, both draft and publish draft point to same location. - """ - - def __init__(self): - super().__init__(MAINTENANCE_VIEWS['force_publish_course']) - self.context.update({ - 'current_versions': [], - 'updated_versions': [], - 'form_data': { - 'course_id': '', - 'is_dry_run': True - } - }) - - def get_course_branch_versions(self, versions): - """ - Returns a dict containing unicoded values of draft and published draft versions. - """ - return { - 'draft-branch': str(versions['draft-branch']), - 'published-branch': str(versions['published-branch']) - } - - @transaction.atomic - @method_decorator(require_global_staff) - def post(self, request): - """ - This method force publishes a course if dry-run argument is not selected. If dry-run is selected, this view - shows possible outcome if the `force_publish_course` modulestore method is executed. - - Arguments: - course_id (string): a request parameter containing course id - is_dry_run (string): a request parameter containing dry run value. - It is obtained from checkbox so it has either values 'on' or ''. - """ - course_id = request.POST.get('course-id') - - self.context.update({ - 'form_data': { - 'course_id': course_id - } - }) - - try: - course_usage_key = self.validate_course_key(course_id) - except InvalidKeyError: - self.context['error'] = True - self.context['msg'] = COURSE_KEY_ERROR_MESSAGES['invalid_course_key'] - except ItemNotFoundError as exc: - self.context['error'] = True - self.context['msg'] = str(exc) - except ValidationError as exc: - self.context['error'] = True - self.context['msg'] = str(exc) - - if self.context['error']: - return self.render_response() - - source_store = modulestore()._get_modulestore_for_courselike(course_usage_key) # pylint: disable=protected-access - if not hasattr(source_store, 'force_publish_course'): - self.context['msg'] = _('Force publishing course is not supported with old mongo courses.') - log.warning( - 'Force publishing course is not supported with old mongo courses. \ - %s attempted to force publish the course %s.', - request.user, - course_id, - exc_info=True - ) - return self.render_response() - - current_versions = self.get_course_branch_versions(get_course_versions(course_id)) - - # if publish and draft are NOT different - if current_versions['published-branch'] == current_versions['draft-branch']: - self.context['msg'] = _('Course is already in published state.') - log.warning( - 'Course is already in published state. %s attempted to force publish the course %s.', - request.user, - course_id, - exc_info=True - ) - return self.render_response() - - self.context['current_versions'] = current_versions - log.info( - '%s dry ran force publish the course %s.', - request.user, - course_id, - exc_info=True - ) - return self.render_response() - - class AnnouncementBaseView(View): """ Base view for Announcements pages diff --git a/cms/static/js/maintenance/force_publish_course.js b/cms/static/js/maintenance/force_publish_course.js deleted file mode 100644 index 642b5bea4f2b..000000000000 --- a/cms/static/js/maintenance/force_publish_course.js +++ /dev/null @@ -1,83 +0,0 @@ -define([ // jshint ignore:line - 'jquery', - 'underscore', - 'gettext', - 'common/js/components/utils/view_utils', - 'edx-ui-toolkit/js/utils/string-utils', - 'edx-ui-toolkit/js/utils/html-utils' -], -function($, _, gettext, ViewUtils, StringUtils, HtmlUtils) { - 'use strict'; - - return function(maintenanceViewURL) { - var showError; - // Reset values - $('#reset-button').click(function(e) { - e.preventDefault(); - $('#course-id').val(''); - $('#dry-run').prop('checked', true); - // clear out result container - $('#result-container').html(''); - }); - - showError = function(containerElSelector, error) { - var errorWrapperElSelector, errorHtml; - errorWrapperElSelector = containerElSelector + ' .wrapper-error'; - errorHtml = HtmlUtils.joinHtml( - HtmlUtils.HTML('
'), - error, - HtmlUtils.HTML('
') - ); - HtmlUtils.setHtml($(errorWrapperElSelector), HtmlUtils.HTML(errorHtml)); - $(errorWrapperElSelector).css('display', 'inline-block'); - $(errorWrapperElSelector).fadeOut(5000); - }; - - $('form#force_publish').submit(function(event) { - var attrs, forcePublishedTemplate, $submitButton, deferred, promise, data; - event.preventDefault(); - - // clear out result container - $('#result-container').html(''); - - $submitButton = $('#submit_force_publish'); - deferred = new $.Deferred(); - promise = deferred.promise(); - - data = $('#force_publish').serialize(); - - // disable submit button while executing. - ViewUtils.disableElementWhileRunning($submitButton, function() { return promise; }); - - $.ajax({ - type: 'POST', - url: maintenanceViewURL, - dataType: 'json', - data: data - }) - .done(function(response) { - if (response.error) { - showError('#course-id-container', response.msg); - } else { - if (response.msg) { - showError('#result-error', response.msg); - } else { - attrs = $.extend({}, response, {StringUtils: StringUtils}); - forcePublishedTemplate = HtmlUtils.template( - $('#force-published-course-response-tpl').text() - ); - HtmlUtils.setHtml($('#result-container'), forcePublishedTemplate(attrs)); - } - } - }) - .fail(function() { - // response.responseText here because it would show some strange output, it may output Traceback - // sometimes if unexpected issue arises. Better to show just internal error when getting 500 error. - showError('#result-error', gettext('Internal Server Error.')); - }) - .always(function() { - deferred.resolve(); - }); - }); - }; -}); diff --git a/cms/templates/maintenance/_force_publish_course.html b/cms/templates/maintenance/_force_publish_course.html deleted file mode 100644 index 31cc1e8887dc..000000000000 --- a/cms/templates/maintenance/_force_publish_course.html +++ /dev/null @@ -1,33 +0,0 @@ -<%page expression_filter="h"/> -<%namespace name='static' file='../static_content.html'/> -<%! -from django.utils.translation import gettext as _ -from openedx.core.djangolib.markup import HTML, Text -%> -
-
- -
-
- ${_("Required data to force publish course.")} -
-
- - -
${_('course-v1:edX+DemoX+Demo_Course')}
-
-
-
-
-
-
- - - -
-
-
-
-
diff --git a/cms/templates/maintenance/container.html b/cms/templates/maintenance/container.html index 417471a1bd66..319a57bfe995 100644 --- a/cms/templates/maintenance/container.html +++ b/cms/templates/maintenance/container.html @@ -18,14 +18,6 @@

-<%block name="header_extras"> -% for template_name in ["force-published-course-response"]: - -% endfor - - <%block name="requirejs"> require(["js/maintenance/${view['slug'] | n, js_escaped_string}"], function(MaintenanceFactory) { MaintenanceFactory("${reverse(view['url']) | n, js_escaped_string}");