Skip to content

Commit 36a7089

Browse files
Merge pull request openedx#38423 from openedx/iahmad/DEPR-36108-import-export
feat: Simplify import/export page redirects to always use MFE for courses
2 parents fd54b24 + f81f028 commit 36a7089

9 files changed

Lines changed: 26 additions & 137 deletions

File tree

cms/djangoapps/contentstore/rest_api/v1/serializers/course_waffle_flags.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,13 @@ def get_use_new_import_page(self, obj):
111111
"""
112112
Method to get the use_new_import_page switch
113113
"""
114-
course_key = self.get_course_key()
115-
return toggles.use_new_import_page(course_key)
114+
return True
116115

117116
def get_use_new_export_page(self, obj):
118117
"""
119118
Method to get the use_new_export_page switch
120119
"""
121-
course_key = self.get_course_key()
122-
return toggles.use_new_export_page(course_key)
120+
return True
123121

124122
def get_use_new_files_uploads_page(self, obj):
125123
"""

cms/djangoapps/contentstore/tests/test_contentstore.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,11 +1487,11 @@ def test_get_json(handler):
14871487
self.assertContains(resp, 'Chapter 2')
14881488

14891489
# go to various pages
1490-
with override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True):
1491-
test_get_html('import_handler')
1492-
with override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True):
1493-
test_get_html('export_handler')
14941490
with override_settings(COURSE_AUTHORING_MICROFRONTEND_URL='https://mfe.example'):
1491+
resp = self.client.get_html(get_url('import_handler', course_key, 'course_key_string'))
1492+
self.assertEqual(resp.status_code, 302) # noqa: PT009
1493+
resp = self.client.get_html(get_url('export_handler', course_key, 'course_key_string'))
1494+
self.assertEqual(resp.status_code, 302) # noqa: PT009
14951495
resp = self.client.get_html(get_url('course_team_handler', course_key, 'course_key_string'))
14961496
self.assertEqual(resp.status_code, 302) # noqa: PT009
14971497
with override_settings(COURSE_AUTHORING_MICROFRONTEND_URL='https://mfe.example'):

cms/djangoapps/contentstore/tests/test_course_settings.py

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
from pytz import UTC
3030
from xblock.fields import Date
3131

32-
from cms.djangoapps.contentstore import toggles
33-
from cms.djangoapps.contentstore.utils import get_advanced_settings_url, reverse_course_url, reverse_usage_url
32+
from cms.djangoapps.contentstore.utils import reverse_course_url, reverse_usage_url
3433
from cms.djangoapps.models.settings.course_grading import (
3534
GRADING_POLICY_CHANGED_EVENT_TYPE,
3635
CourseGradingModel,
@@ -160,45 +159,17 @@ def test_discussion_fields_available(self, is_pages_and_resources_enabled,
160159
self.assertEqual('discussion_topics' in data, fields_visible) # noqa: PT009
161160

162161
@ddt.data(False, True)
163-
@override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True)
164-
@override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True)
165162
def test_disable_advanced_settings_feature(self, disable_advanced_settings):
166163
"""
167-
If this feature is enabled, only Django Staff/Superuser should be able to access the "Advanced Settings" page.
168-
For non-staff users the "Advanced Settings" tab link should not be visible.
164+
When DISABLE_ADVANCED_SETTINGS is enabled, non-staff users should receive
165+
a 403 on the advanced settings URL; staff users should always be redirected.
169166
"""
170167
with override_settings(FEATURES={
171168
'DISABLE_ADVANCED_SETTINGS': disable_advanced_settings,
172169
}, COURSE_AUTHORING_MICROFRONTEND_URL='https://mfe.example'):
173-
advanced_settings_link_html = (
174-
f'<a href="{get_advanced_settings_url(self.course.id)}">Advanced Settings</a>'
175-
).encode()
176-
for handler in (
177-
'import_handler',
178-
'export_handler',
179-
):
180-
# Test that non-staff users don't see the "Advanced Settings" tab link.
181-
response = self.non_staff_client.get_html(
182-
get_url(self.course.id, handler)
183-
)
184-
self.assertEqual(response.status_code, 200) # noqa: PT009
185-
if disable_advanced_settings:
186-
self.assertNotIn(advanced_settings_link_html, response.content) # noqa: PT009
187-
else:
188-
self.assertIn(advanced_settings_link_html, response.content) # noqa: PT009
189-
190-
# Test that staff users see the "Advanced Settings" tab link.
191-
response = self.client.get_html(
192-
get_url(self.course.id, handler)
193-
)
194-
self.assertEqual(response.status_code, 200) # noqa: PT009
195-
self.assertIn(advanced_settings_link_html, response.content) # noqa: PT009
196-
197-
# Test that non-staff users can't access the "Advanced Settings" page.
198170
response = self.non_staff_client.get_html(self.course_setting_url)
199171
self.assertEqual(response.status_code, 403 if disable_advanced_settings else 302) # noqa: PT009
200172

201-
# Test that staff users are redirected to the MFE advanced settings page.
202173
response = self.client.get_html(self.course_setting_url)
203174
self.assertEqual(response.status_code, 302) # noqa: PT009
204175

cms/djangoapps/contentstore/tests/tests.py

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
This test file will test registration, login, activation, and session activity timeouts
33
44
TODO: Rewrite several of these assertions so that they check the output of the REST or Python
5-
APIs rather than parsing HTML from the deprecated legacy frontend pages. In particular, any
6-
test case using override_waffle_flag(toggles.LEGACY_STUDIO_*, True) will need to be fixed.
7-
Part of https://github.com/openedx/edx-platform/issues/36275.
5+
APIs rather than parsing HTML from the deprecated legacy frontend pages.
86
"""
97

108

@@ -17,10 +15,8 @@
1715
from django.core.cache import cache
1816
from django.test.utils import override_settings
1917
from django.urls import reverse
20-
from edx_toggles.toggles.testutils import override_waffle_flag
2118
from pytz import UTC
2219

23-
from cms.djangoapps.contentstore import toggles
2420
from cms.djangoapps.contentstore.tests.test_course_settings import CourseTestCase
2521
from cms.djangoapps.contentstore.tests.utils import AjaxEnabledTestClient, parse_json, registration, user
2622
from cms.djangoapps.contentstore.utils import get_studio_home_url
@@ -237,20 +233,19 @@ def setUp(self):
237233
super().setUp()
238234
self.course = CourseFactory.create(org='edX', number='test_course_key', display_name='Test Course')
239235

240-
@data(('edX/test_course_key/Test_Course', 200), ('garbage:edX+test_course_key+Test_Course', 404))
236+
@data(('edX/test_course_key/Test_Course', 302, 200), ('garbage:edX+test_course_key+Test_Course', 404, 404))
241237
@unpack
242-
@override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True)
243-
def test_course_key_decorator(self, course_key, status_code):
238+
def test_course_key_decorator(self, course_key, import_status_code, import_status_handler_code):
244239
"""
245240
Tests for the ensure_valid_course_key decorator.
246241
"""
247242
url = f'/import/{course_key}'
248243
resp = self.client.get_html(url)
249-
self.assertEqual(resp.status_code, status_code) # noqa: PT009
244+
self.assertEqual(resp.status_code, import_status_code) # noqa: PT009
250245

251246
url = '/import_status/{course_key}/{filename}'.format(
252247
course_key=course_key,
253248
filename='xyz.tar.gz'
254249
)
255250
resp = self.client.get_html(url)
256-
self.assertEqual(resp.status_code, status_code) # noqa: PT009
251+
self.assertEqual(resp.status_code, import_status_handler_code) # noqa: PT009

cms/djangoapps/contentstore/toggles.py

Lines changed: 0 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -161,43 +161,6 @@ def use_react_markdown_editor(course_key):
161161

162162

163163

164-
# .. toggle_name: legacy_studio.import
165-
# .. toggle_implementation: WaffleFlag
166-
# .. toggle_default: False
167-
# .. toggle_description: Temporarily fall back to the old Course Import page.
168-
# .. toggle_use_cases: temporary
169-
# .. toggle_creation_date: 2025-03-14
170-
# .. toggle_target_removal_date: 2025-09-14
171-
# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275
172-
# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available.
173-
LEGACY_STUDIO_IMPORT = CourseWaffleFlag('legacy_studio.import', __name__)
174-
175-
176-
def use_new_import_page(course_key):
177-
"""
178-
Returns a boolean if new studio import mfe is enabled
179-
"""
180-
return not LEGACY_STUDIO_IMPORT.is_enabled(course_key)
181-
182-
183-
# .. toggle_name: legacy_studio.export
184-
# .. toggle_implementation: WaffleFlag
185-
# .. toggle_default: False
186-
# .. toggle_description: Temporarily fall back to the old Course Export page.
187-
# .. toggle_use_cases: temporary
188-
# .. toggle_creation_date: 2025-03-14
189-
# .. toggle_target_removal_date: 2025-09-14
190-
# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275
191-
# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available.
192-
LEGACY_STUDIO_EXPORT = CourseWaffleFlag('legacy_studio.export', __name__)
193-
194-
195-
def use_new_export_page(course_key):
196-
"""
197-
Returns a boolean if new studio export mfe is enabled
198-
"""
199-
return not LEGACY_STUDIO_EXPORT.is_enabled(course_key)
200-
201164

202165
# .. toggle_name: contentstore.new_studio_mfe.use_new_video_uploads_page
203166
# .. toggle_implementation: CourseWaffleFlag

cms/djangoapps/contentstore/utils.py

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
libraries_v1_enabled,
4242
libraries_v2_enabled,
4343
split_library_view_on_dashboard,
44-
use_new_export_page,
45-
use_new_import_page,
4644
use_new_unit_page,
4745
)
4846
from cms.djangoapps.models.settings.course_grading import CourseGradingModel
@@ -346,30 +344,24 @@ def get_updates_url(course_locator) -> str:
346344
return updates_url
347345

348346

349-
def get_import_url(course_locator) -> str:
347+
def get_import_url(course_locator) -> str | None:
350348
"""
351349
Gets course authoring microfrontend URL for import page view.
352350
"""
353-
import_url = None
354-
if use_new_import_page(course_locator):
355-
mfe_base_url = get_course_authoring_url(course_locator)
356-
course_mfe_url = f'{mfe_base_url}/course/{course_locator}/import'
357-
if mfe_base_url:
358-
import_url = course_mfe_url
359-
return import_url
351+
mfe_base_url = get_course_authoring_url(course_locator)
352+
if mfe_base_url:
353+
return f'{mfe_base_url}/course/{course_locator}/import'
354+
return None
360355

361356

362-
def get_export_url(course_locator) -> str:
357+
def get_export_url(course_locator) -> str | None:
363358
"""
364359
Gets course authoring microfrontend URL for export page view.
365360
"""
366-
export_url = None
367-
if use_new_export_page(course_locator):
368-
mfe_base_url = get_course_authoring_url(course_locator)
369-
course_mfe_url = f'{mfe_base_url}/course/{course_locator}/export'
370-
if mfe_base_url:
371-
export_url = course_mfe_url
372-
return export_url
361+
mfe_base_url = get_course_authoring_url(course_locator)
362+
if mfe_base_url:
363+
return f'{mfe_base_url}/course/{course_locator}/export'
364+
return None
373365

374366

375367
def get_optimizer_url(course_locator) -> str:

cms/djangoapps/contentstore/views/import_export.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@
4343

4444
from ..storage import course_import_export_storage
4545
from ..tasks import CourseExportTask, CourseImportTask, export_olx, import_olx
46-
from ..toggles import use_new_export_page, use_new_import_page
4746
from ..utils import IMPORTABLE_FILE_TYPES, get_export_url, get_import_url, reverse_course_url, reverse_library_url
4847

4948
__all__ = [
@@ -99,7 +98,7 @@ def import_handler(request, course_key_string):
9998
return _write_chunk(request, courselike_key)
10099
elif request.method == 'GET': # assume html
101100

102-
if use_new_import_page(courselike_key) and not library:
101+
if not library:
103102
return redirect(get_import_url(courselike_key))
104103
status_url = reverse_course_url(
105104
"import_status_handler", courselike_key, kwargs={'filename': "fillerName"}
@@ -358,7 +357,7 @@ def export_handler(request, course_key_string):
358357
export_olx.delay(request.user.id, course_key_string, request.LANGUAGE_CODE)
359358
return JsonResponse({'ExportStatus': 1})
360359
elif 'text/html' in requested_format:
361-
if use_new_export_page(course_key) and not library:
360+
if not library:
362361
return redirect(get_export_url(course_key))
363362
return render_to_response('export.html', context)
364363
else:

cms/djangoapps/contentstore/views/tests/test_import_export.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
from django.core.exceptions import SuspiciousOperation
2424
from django.core.files.storage import FileSystemStorage
2525
from django.test.utils import override_settings
26-
from edx_toggles.toggles.testutils import override_waffle_flag
2726
from milestones.tests.utils import MilestonesTestCaseMixin
2827
from opaque_keys.edx.locator import LibraryLocator
2928
from openedx_authz.constants.roles import COURSE_DATA_RESEARCHER, COURSE_STAFF
@@ -34,7 +33,6 @@
3433
from user_tasks.models import UserTaskStatus
3534

3635
from cms.djangoapps.contentstore import errors as import_error
37-
from cms.djangoapps.contentstore import toggles
3836
from cms.djangoapps.contentstore.api.tests.base import BaseCourseViewTest
3937
from cms.djangoapps.contentstore.storage import course_import_export_storage
4038
from cms.djangoapps.contentstore.tests.test_libraries import LibraryTestCase
@@ -754,15 +752,6 @@ def setUp(self):
754752
self.url = reverse_course_url('export_handler', self.course.id)
755753
self.status_url = reverse_course_url('export_status_handler', self.course.id)
756754

757-
@override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True)
758-
def test_export_html(self):
759-
"""
760-
Get the HTML for the page.
761-
"""
762-
resp = self.client.get_html(self.url)
763-
self.assertEqual(resp.status_code, 200) # noqa: PT009
764-
self.assertContains(resp, "Export My Course Content")
765-
766755
def test_export_json_unsupported(self):
767756
"""
768757
JSON is unsupported.

cms/templates/widgets/header.html

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,10 @@ <h1 class="branding">
3333
assets_url = reverse('assets_handler', kwargs={'course_key_string': str(course_key)})
3434
textbooks_url = reverse('textbooks_list_handler', kwargs={'course_key_string': str(course_key)})
3535
videos_url = reverse('videos_handler', kwargs={'course_key_string': str(course_key)})
36-
import_url = reverse('import_handler', kwargs={'course_key_string': str(course_key)})
3736
course_info_url = reverse('course_info_handler', kwargs={'course_key_string': str(course_key)})
38-
export_url = reverse('export_handler', kwargs={'course_key_string': str(course_key)})
3937
tabs_url = reverse('tabs_handler', kwargs={'course_key_string': str(course_key)})
4038
checklists_url = reverse('checklists_handler', kwargs={'course_key_string': str(course_key)})
4139
pages_and_resources_mfe_enabled = ENABLE_PAGES_AND_RESOURCES_MICROFRONTEND.is_enabled(context_course.id)
42-
import_mfe_enabled = toggles.use_new_import_page(context_course.id)
43-
export_mfe_enabled = toggles.use_new_export_page(context_course.id)
4440
optimizer_enabled = toggles.enable_course_optimizer(context_course.id)
4541
libraries_v2_enabled = toggles.libraries_v2_enabled()
4642

@@ -149,26 +145,12 @@ <h3 class="title"><span class="label">${_("Tools")}</span> <span class="icon fa
149145
<div class="wrapper wrapper-nav-sub">
150146
<div class="nav-sub">
151147
<ul>
152-
% if not import_mfe_enabled:
153-
<li class="nav-item nav-course-tools-import">
154-
<a href="${import_url}">${_("Import")}</a>
155-
</li>
156-
% endif
157-
% if import_mfe_enabled:
158148
<li class="nav-item nav-course-tools-import">
159149
<a href="${get_import_url(course_key)}">${_("Import")}</a>
160150
</li>
161-
% endif
162-
% if not export_mfe_enabled:
163-
<li class="nav-item nav-course-tools-export">
164-
<a href="${export_url}">${_("Export")}</a>
165-
</li>
166-
% endif
167-
% if export_mfe_enabled:
168151
<li class="nav-item nav-course-tools-export">
169152
<a href="${get_export_url(course_key)}">${_("Export")}</a>
170153
</li>
171-
% endif
172154
% if toggles.EXPORT_GIT.is_enabled() and context_course.giturl:
173155
<li class="nav-item nav-course-tools-export-git">
174156
<a href="${reverse('export_git', kwargs=dict(course_key_string=str(course_key)))}">${_("Export to Git")}</a>

0 commit comments

Comments
 (0)