diff --git a/cms/djangoapps/contentstore/rest_api/v0/views/tabs.py b/cms/djangoapps/contentstore/rest_api/v0/views/tabs.py
index fa38dccc4977..968af2246aa3 100644
--- a/cms/djangoapps/contentstore/rest_api/v0/views/tabs.py
+++ b/cms/djangoapps/contentstore/rest_api/v0/views/tabs.py
@@ -13,7 +13,6 @@
from common.djangoapps.student.auth import has_studio_read_access, has_studio_write_access
from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin, verify_course_exists, view_auth_classes
from ..serializers import CourseTabSerializer, CourseTabUpdateSerializer, TabIDLocatorSerializer
-from ....toggles import use_new_custom_pages
from ....views.tabs import edit_tab_handler, get_course_tabs, reorder_tabs_handler
@@ -79,24 +78,20 @@ def get(self, request: Request, course_id: str) -> Response:
```
"""
course_key = CourseKey.from_string(course_id)
- if not use_new_custom_pages(course_key):
- return Response(status=status.HTTP_403_FORBIDDEN)
if not has_studio_read_access(request.user, course_key):
self.permission_denied(request)
course_block = modulestore().get_course(course_key)
tabs_to_render = get_course_tabs(course_block, request.user)
serializedCourseTabs = CourseTabSerializer(tabs_to_render, many=True).data
- if use_new_custom_pages(course_key):
- json_tabs = []
- for tab in serializedCourseTabs:
- if tab.get('type') == 'static_tab':
- url_slug = tab.get('settings').get('url_slug')
- static_tab_loc = course_block.id.make_usage_key("static_tab", url_slug)
- tab["id"] = str(static_tab_loc)
- json_tabs.append(tab)
- return Response(json_tabs)
- return Response(serializedCourseTabs)
+ json_tabs = []
+ for tab in serializedCourseTabs:
+ if tab.get('type') == 'static_tab':
+ url_slug = tab.get('settings').get('url_slug')
+ static_tab_loc = course_block.id.make_usage_key("static_tab", url_slug)
+ tab["id"] = str(static_tab_loc)
+ json_tabs.append(tab)
+ return Response(json_tabs)
@view_auth_classes(is_authenticated=True)
diff --git a/cms/djangoapps/contentstore/rest_api/v1/serializers/course_waffle_flags.py b/cms/djangoapps/contentstore/rest_api/v1/serializers/course_waffle_flags.py
index bb8667ea9cdf..2d0785459069 100644
--- a/cms/djangoapps/contentstore/rest_api/v1/serializers/course_waffle_flags.py
+++ b/cms/djangoapps/contentstore/rest_api/v1/serializers/course_waffle_flags.py
@@ -52,10 +52,15 @@ def get_use_new_home_page(self, obj):
def get_use_new_custom_pages(self, obj):
"""
- Method to get the use_new_custom_pages switch
+ Method to indicate whether or not to use the new custom pages
+
+ This used to be based on a waffle flag but the flag is being removed so we
+ default it to true for now until we can remove the need for it from the consumers
+ of this serializer and the related APIs.
+
+ See https://github.com/openedx/edx-platform/issues/37497
"""
- course_key = self.get_course_key()
- return toggles.use_new_custom_pages(course_key)
+ return True
def get_use_new_schedule_details_page(self, obj):
"""
diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py
index ebd14a470125..1be328d76590 100644
--- a/cms/djangoapps/contentstore/tests/test_contentstore.py
+++ b/cms/djangoapps/contentstore/tests/test_contentstore.py
@@ -1498,8 +1498,6 @@ def test_get_json(handler):
test_get_html('export_handler')
with override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True):
test_get_html('course_team_handler')
- with override_waffle_flag(toggles.LEGACY_STUDIO_CUSTOM_PAGES, True):
- test_get_html('tabs_handler')
with override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True):
test_get_html('settings_handler')
with override_waffle_flag(toggles.LEGACY_STUDIO_GRADING, True):
@@ -1518,6 +1516,11 @@ def test_get_json(handler):
resp = self.client.get(course_updates_url)
assert resp.status_code == 200
+ resp = self.client.get(
+ get_url('cms.djangoapps.contentstore:v0:course_tab_list', course_key, 'course_id')
+ )
+ self.assertEqual(resp.status_code, 200)
+
# go look at the Edit page
unit_key = course_key.make_usage_key('vertical', 'test_vertical')
with override_waffle_flag(toggles.LEGACY_STUDIO_UNIT_EDITOR, True):
diff --git a/cms/djangoapps/contentstore/tests/test_course_settings.py b/cms/djangoapps/contentstore/tests/test_course_settings.py
index 605549d2e427..ac8d9d3ebae9 100644
--- a/cms/djangoapps/contentstore/tests/test_course_settings.py
+++ b/cms/djangoapps/contentstore/tests/test_course_settings.py
@@ -167,7 +167,6 @@ def test_discussion_fields_available(self, is_pages_and_resources_enabled,
@override_waffle_flag(toggles.LEGACY_STUDIO_IMPORT, True)
@override_waffle_flag(toggles.LEGACY_STUDIO_EXPORT, True)
@override_waffle_flag(toggles.LEGACY_STUDIO_COURSE_TEAM, True)
- @override_waffle_flag(toggles.LEGACY_STUDIO_CUSTOM_PAGES, True)
@override_waffle_flag(toggles.LEGACY_STUDIO_SCHEDULE_DETAILS, True)
@override_waffle_flag(toggles.LEGACY_STUDIO_GRADING, True)
def test_disable_advanced_settings_feature(self, disable_advanced_settings):
@@ -184,7 +183,6 @@ def test_disable_advanced_settings_feature(self, disable_advanced_settings):
'import_handler',
'export_handler',
'course_team_handler',
- 'tabs_handler',
'settings_handler',
'grading_handler',
):
diff --git a/cms/djangoapps/contentstore/toggles.py b/cms/djangoapps/contentstore/toggles.py
index bca1bb336373..1f5924163bd2 100644
--- a/cms/djangoapps/contentstore/toggles.py
+++ b/cms/djangoapps/contentstore/toggles.py
@@ -162,25 +162,6 @@ def individualize_anonymous_user_id(course_id):
return INDIVIDUALIZE_ANONYMOUS_USER_ID.is_enabled(course_id)
-# .. toggle_name: legacy_studio.custom_pages
-# .. toggle_implementation: WaffleFlag
-# .. toggle_default: False
-# .. toggle_description: Temporarily fall back to the old Studio custom pages tab.
-# .. toggle_use_cases: temporary
-# .. toggle_creation_date: 2025-03-14
-# .. toggle_target_removal_date: 2025-09-14
-# .. toggle_tickets: https://github.com/openedx/edx-platform/issues/36275
-# .. toggle_warning: In Ulmo, this toggle will be removed. Only the new (React-based) experience will be available.
-LEGACY_STUDIO_CUSTOM_PAGES = CourseWaffleFlag("legacy_studio.custom_pages", __name__)
-
-
-def use_new_custom_pages(course_key):
- """
- Returns a boolean if new studio custom pages mfe is enabled
- """
- return not LEGACY_STUDIO_CUSTOM_PAGES.is_enabled(course_key)
-
-
# .. toggle_name: contentstore.use_react_markdown_editor
# .. toggle_implementation: CourseWaffleFlag
# .. toggle_default: False
diff --git a/cms/djangoapps/contentstore/utils.py b/cms/djangoapps/contentstore/utils.py
index 6fe495a0d4e7..e04d9884ea64 100644
--- a/cms/djangoapps/contentstore/utils.py
+++ b/cms/djangoapps/contentstore/utils.py
@@ -44,7 +44,6 @@
use_new_advanced_settings_page,
use_new_certificates_page,
use_new_course_team_page,
- use_new_custom_pages,
use_new_export_page,
use_new_grading_page,
use_new_group_configurations_page,
@@ -514,11 +513,10 @@ def get_custom_pages_url(course_locator) -> str:
Gets course authoring microfrontend URL for custom pages view.
"""
custom_pages_url = None
- if use_new_custom_pages(course_locator):
- mfe_base_url = get_course_authoring_url(course_locator)
- course_mfe_url = f'{mfe_base_url}/course/{course_locator}/custom-pages'
- if mfe_base_url:
- custom_pages_url = course_mfe_url
+ mfe_base_url = get_course_authoring_url(course_locator)
+ course_mfe_url = f'{mfe_base_url}/course/{course_locator}/custom-pages'
+ if mfe_base_url:
+ custom_pages_url = course_mfe_url
return custom_pages_url
diff --git a/cms/djangoapps/contentstore/views/tabs.py b/cms/djangoapps/contentstore/views/tabs.py
index 20426933f342..8fa9d024458d 100644
--- a/cms/djangoapps/contentstore/views/tabs.py
+++ b/cms/djangoapps/contentstore/views/tabs.py
@@ -17,11 +17,9 @@
from xmodule.modulestore.django import modulestore
from xmodule.tabs import CourseTab, CourseTabList, InvalidTabsException, StaticTab
-from common.djangoapps.edxmako.shortcuts import render_to_response
from common.djangoapps.student.auth import has_course_author_access
from common.djangoapps.util.json_request import JsonResponse, JsonResponseBadRequest, expect_json
-from ..toggles import use_new_custom_pages
-from ..utils import get_lms_link_for_item, get_pages_and_resources_url, get_custom_pages_url
+from ..utils import get_pages_and_resources_url, get_custom_pages_url
__all__ = ["tabs_handler", "update_tabs_handler"]
@@ -65,18 +63,7 @@ def tabs_handler(request, course_key_string):
elif request.method == "GET": # assume html
# get all tabs from the tabs list: static tabs (a.k.a. user-created tabs) and built-in tabs
# present in the same order they are displayed in LMS
- if use_new_custom_pages(course_key):
- return redirect(get_custom_pages_url(course_key))
- tabs_to_render = list(get_course_tabs(course_item, request.user))
-
- return render_to_response(
- "edit-tabs.html",
- {
- "context_course": course_item,
- "tabs_to_render": tabs_to_render,
- "lms_link": get_lms_link_for_item(course_item.location),
- },
- )
+ return redirect(get_custom_pages_url(course_key))
else:
return HttpResponseNotFound()
diff --git a/cms/djangoapps/contentstore/views/tests/test_tabs.py b/cms/djangoapps/contentstore/views/tests/test_tabs.py
index 715fb6eec401..b4e4d17181ef 100644
--- a/cms/djangoapps/contentstore/views/tests/test_tabs.py
+++ b/cms/djangoapps/contentstore/views/tests/test_tabs.py
@@ -4,9 +4,6 @@
import json
import random
-from edx_toggles.toggles.testutils import override_waffle_flag
-
-from cms.djangoapps.contentstore import toggles
from cms.djangoapps.contentstore.tests.utils import CourseTestCase
from cms.djangoapps.contentstore.utils import reverse_course_url
from cms.djangoapps.contentstore.views import tabs
@@ -68,12 +65,11 @@ def test_not_implemented(self):
data={'invalid_request': None},
)
- @override_waffle_flag(toggles.LEGACY_STUDIO_CUSTOM_PAGES, True)
def test_view_index(self):
"""Basic check that the Pages page responds correctly"""
resp = self.client.get_html(self.url)
- self.assertContains(resp, 'course-nav-list')
+ assert resp.status_code == 302
def test_reorder_tabs(self):
"""Test re-ordering of tabs"""
diff --git a/cms/static/cms/js/spec/main.js b/cms/static/cms/js/spec/main.js
index 5d8daf5597fa..e56b95ef2826 100644
--- a/cms/static/cms/js/spec/main.js
+++ b/cms/static/cms/js/spec/main.js
@@ -242,7 +242,6 @@
'js/spec/video/transcripts/editor_spec',
'js/spec/video/transcripts/file_uploader_spec',
'js/spec/models/component_template_spec',
- 'js/spec/models/explicit_url_spec',
'js/spec/models/xblock_info_spec',
'js/spec/models/xblock_validation_spec',
'js/spec/models/license_spec',
diff --git a/cms/static/js/factories/edit_tabs.js b/cms/static/js/factories/edit_tabs.js
deleted file mode 100644
index 68bbba27bd73..000000000000
--- a/cms/static/js/factories/edit_tabs.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import * as TabsModel from 'js/models/explicit_url';
-import * as TabsEditView from 'js/views/tabs';
-import * as xmoduleLoader from 'xmodule';
-import './base';
-import 'cms/js/main';
-import 'xblock/cms.runtime.v1';
-import 'xmodule/js/src/xmodule'; // Force the XBlockToXModuleShim to load for Static Tabs
-
-// eslint-disable-next-line no-unused-expressions
-'use strict';
-export default function EditTabsFactory(courseLocation, explicitUrl) {
- xmoduleLoader.done(function() {
- var model = new TabsModel({
- id: courseLocation,
- explicit_url: explicitUrl
- }),
- editView;
-
- editView = new TabsEditView({
- el: $('.tab-list'),
- model: model,
- mast: $('.wrapper-mast')
- });
- });
-}
-
-export {EditTabsFactory};
diff --git a/cms/static/js/models/explicit_url.js b/cms/static/js/models/explicit_url.js
deleted file mode 100644
index 3ee510074fef..000000000000
--- a/cms/static/js/models/explicit_url.js
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * A model that simply allows the update URL to be passed
- * in as an argument.
- */
-define(['backbone'], function(Backbone) {
- return Backbone.Model.extend({
- defaults: {
- explicit_url: ''
- },
- url: function() {
- return this.get('explicit_url');
- }
- });
-});
diff --git a/cms/static/js/spec/models/explicit_url_spec.js b/cms/static/js/spec/models/explicit_url_spec.js
deleted file mode 100644
index d281d8b28cf7..000000000000
--- a/cms/static/js/spec/models/explicit_url_spec.js
+++ /dev/null
@@ -1,12 +0,0 @@
-define(['js/models/explicit_url'],
- function(Model) {
- describe('Model ', function() {
- it('allows url to be passed in constructor', function() {
- expect(new Model({explicit_url: '/fancy/url'}).url()).toBe('/fancy/url');
- });
- it('returns empty string if url not set', function() {
- expect(new Model().url()).toBe('');
- });
- });
- }
-);
diff --git a/cms/static/js/spec/views/module_edit_spec.js b/cms/static/js/spec/views/module_edit_spec.js
deleted file mode 100644
index 301d31441880..000000000000
--- a/cms/static/js/spec/views/module_edit_spec.js
+++ /dev/null
@@ -1,266 +0,0 @@
-import $ from 'jquery';
-import ViewUtils from 'common/js/components/utils/view_utils';
-import edit_helpers from 'js/spec_helpers/edit_helpers';
-import ModuleEdit from 'js/views/module_edit';
-import ModuleModel from 'js/models/module_info';
-import 'xmodule/js/src/xmodule';
-
-describe('ModuleEdit', function() {
- beforeEach(function() {
- this.stubModule = new ModuleModel({
- id: 'stub-id'
- });
- setFixtures('
\n'
- + '\n'
- + ' \n'
- + '
\n'
- // eslint-disable-next-line no-template-curly-in-string
- + ' ${editor}\n'
- + '
\n'
- + '
Save \n'
- + '
Cancel \n'
- + '
\n'
- + ' \n'
- + ' \n'
- + ' \n'
- + ' \n'
- + ' ');
- edit_helpers.installEditTemplates(true);
- spyOn($, 'ajax').and.returnValue(this.moduleData);
- this.moduleEdit = new ModuleEdit({
- el: $('.component'),
- model: this.stubModule,
- onDelete: jasmine.createSpy()
- });
- return this.moduleEdit;
- });
- describe('class definition', function() {
- it('sets the correct tagName', function() {
- return expect(this.moduleEdit.tagName).toEqual('li');
- });
- it('sets the correct className', function() {
- return expect(this.moduleEdit.className).toEqual('component');
- });
- });
- describe('methods', function() {
- describe('initialize', function() {
- beforeEach(function() {
- spyOn(ModuleEdit.prototype, 'render');
- this.moduleEdit = new ModuleEdit({
- el: $('.component'),
- model: this.stubModule,
- onDelete: jasmine.createSpy()
- });
- return this.moduleEdit;
- });
- it('renders the module editor', function() {
- return expect(ModuleEdit.prototype.render).toHaveBeenCalled();
- });
- });
- describe('render', function() {
- beforeEach(function() {
- edit_helpers.installEditTemplates(true);
- spyOn(this.moduleEdit, 'loadDisplay');
- spyOn(this.moduleEdit, 'delegateEvents');
- spyOn($.fn, 'append');
- spyOn(ViewUtils, 'loadJavaScript').and.returnValue($.Deferred().resolve().promise());
- window.MockXBlock = function() {
- return {};
- };
- // eslint-disable-next-line no-void
- window.loadedXBlockResources = void 0;
- this.moduleEdit.render();
- return $.ajax.calls.mostRecent().args[0].success({
- html: 'Response html
',
- resources: [
- [
- 'hash1', {
- kind: 'text',
- mimetype: 'text/css',
- data: 'inline-css'
- }
- ], [
- 'hash2', {
- kind: 'url',
- mimetype: 'text/css',
- data: 'css-url'
- }
- ], [
- 'hash3', {
- kind: 'text',
- mimetype: 'application/javascript',
- data: 'inline-js'
- }
- ], [
- 'hash4', {
- kind: 'url',
- mimetype: 'application/javascript',
- data: 'js-url'
- }
- ], [
- 'hash5', {
- placement: 'head',
- mimetype: 'text/html',
- data: 'head-html'
- }
- ], [
- 'hash6', {
- placement: 'not-head',
- mimetype: 'text/html',
- data: 'not-head-html'
- }
- ]
- ]
- });
- });
- afterEach(function() {
- window.MockXBlock = null;
- return window.MockXBlock;
- });
- it('loads the module preview via ajax on the view element', function() {
- expect($.ajax).toHaveBeenCalledWith({
- url: '/xblock/' + this.moduleEdit.model.id + '/student_view',
- type: 'GET',
- cache: false,
- headers: {
- Accept: 'application/json'
- },
- success: jasmine.any(Function)
- });
- expect($.ajax).not.toHaveBeenCalledWith({
- url: '/xblock/' + this.moduleEdit.model.id + '/studio_view',
- type: 'GET',
- headers: {
- Accept: 'application/json'
- },
- success: jasmine.any(Function)
- });
- expect(this.moduleEdit.loadDisplay).toHaveBeenCalled();
- return expect(this.moduleEdit.delegateEvents).toHaveBeenCalled();
- });
- it('loads the editing view via ajax on demand', function() {
- var mockXBlockEditorHtml;
- expect($.ajax).not.toHaveBeenCalledWith({
- url: '/xblock/' + this.moduleEdit.model.id + '/studio_view',
- type: 'GET',
- cache: false,
- headers: {
- Accept: 'application/json'
- },
- success: jasmine.any(Function)
- });
- this.moduleEdit.clickEditButton({
- preventDefault: jasmine.createSpy('event.preventDefault')
- });
- mockXBlockEditorHtml = readFixtures('templates/mock/mock-xblock-editor.underscore');
- $.ajax.calls.mostRecent().args[0].success({
- html: mockXBlockEditorHtml,
- resources: [
- [
- 'hash1', {
- kind: 'text',
- mimetype: 'text/css',
- data: 'inline-css'
- }
- ], [
- 'hash2', {
- kind: 'url',
- mimetype: 'text/css',
- data: 'css-url'
- }
- ], [
- 'hash3', {
- kind: 'text',
- mimetype: 'application/javascript',
- data: 'inline-js'
- }
- ], [
- 'hash4', {
- kind: 'url',
- mimetype: 'application/javascript',
- data: 'js-url'
- }
- ], [
- 'hash5', {
- placement: 'head',
- mimetype: 'text/html',
- data: 'head-html'
- }
- ], [
- 'hash6', {
- placement: 'not-head',
- mimetype: 'text/html',
- data: 'not-head-html'
- }
- ]
- ]
- });
- expect($.ajax).toHaveBeenCalledWith({
- url: '/xblock/' + this.moduleEdit.model.id + '/studio_view',
- type: 'GET',
- cache: false,
- headers: {
- Accept: 'application/json'
- },
- success: jasmine.any(Function)
- });
- return expect(this.moduleEdit.delegateEvents).toHaveBeenCalled();
- });
- it('loads inline css from fragments', function() {
- var args = '';
- return expect($('head').append).toHaveBeenCalledWith(args);
- });
- it('loads css urls from fragments', function() {
- var args = ' ';
- return expect($('head').append).toHaveBeenCalledWith(args);
- });
- it('loads inline js from fragments', function() {
- return expect($('head').append).toHaveBeenCalledWith('');
- });
- it('loads js urls from fragments', function() {
- return expect(ViewUtils.loadJavaScript).toHaveBeenCalledWith('js-url');
- });
- it('loads head html', function() {
- return expect($('head').append).toHaveBeenCalledWith('head-html');
- });
- it("doesn't load body html", function() {
- return expect($.fn.append).not.toHaveBeenCalledWith('not-head-html');
- });
- it("doesn't reload resources", function() {
- var count;
- count = $('head').append.calls.count();
- $.ajax.calls.mostRecent().args[0].success({
- html: 'Response html 2
',
- resources: [
- [
- 'hash1', {
- kind: 'text',
- mimetype: 'text/css',
- data: 'inline-css'
- }
- ]
- ]
- });
- return expect($('head').append.calls.count()).toBe(count);
- });
- });
- describe('loadDisplay', function() {
- beforeEach(function() {
- spyOn(XBlock, 'initializeBlock');
- return this.moduleEdit.loadDisplay();
- });
- it('loads the .xmodule-display inside the module editor', function() {
- expect(XBlock.initializeBlock).toHaveBeenCalled();
- var sel = '.xblock-student_view';
- return expect(XBlock.initializeBlock.calls.mostRecent().args[0].get(0)).toBe($(sel).get(0));
- });
- });
- });
-});
diff --git a/cms/static/js/views/module_edit.js b/cms/static/js/views/module_edit.js
deleted file mode 100644
index f58f02a9c94f..000000000000
--- a/cms/static/js/views/module_edit.js
+++ /dev/null
@@ -1,109 +0,0 @@
-(function() {
- 'use strict';
-
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) {
- var key;
- for (key in parent) {
- if (__hasProp.call(parent, key)) {
- child[key] = parent[key];
- }
- }
- function Ctor() {
- this.constructor = child;
- }
- Ctor.prototype = parent.prototype;
- child.prototype = new Ctor();
- child.__super__ = parent.prototype;
- return child;
- };
-
- define(['jquery', 'underscore', 'gettext', 'xblock/runtime.v1', 'js/views/xblock', 'js/views/modals/edit_xblock'],
- function($, _, gettext, XBlock, XBlockView, EditXBlockModal) {
- var ModuleEdit = (function(_super) {
- __extends(ModuleEdit, _super);
-
- // eslint-disable-next-line no-shadow
- function ModuleEdit() {
- return ModuleEdit.__super__.constructor.apply(this, arguments);
- }
-
- ModuleEdit.prototype.tagName = 'li';
-
- ModuleEdit.prototype.className = 'component';
-
- ModuleEdit.prototype.editorMode = 'editor-mode';
-
- ModuleEdit.prototype.events = {
- 'click .edit-button': 'clickEditButton',
- 'click .delete-button': 'onDelete'
- };
-
- ModuleEdit.prototype.initialize = function() {
- this.onDelete = this.options.onDelete;
- return this.render();
- };
-
- ModuleEdit.prototype.loadDisplay = function() {
- var xblockElement;
- xblockElement = this.$el.find('.xblock-student_view');
- if (xblockElement.length > 0) {
- return XBlock.initializeBlock(xblockElement);
- }
- };
-
- ModuleEdit.prototype.createItem = function(parent, payload, callback) {
- var _this = this;
- if (_.isNull(callback)) {
- callback = function() {};
- }
- payload.parent_locator = parent;
- return $.postJSON(this.model.urlRoot + '/', payload, function(data) {
- _this.model.set({
- id: data.locator
- });
- _this.$el.data('locator', data.locator);
- _this.$el.data('courseKey', data.courseKey);
- return _this.render();
- }).success(callback);
- };
-
- ModuleEdit.prototype.loadView = function(viewName, target, callback) {
- var _this = this;
- if (this.model.id) {
- return $.ajax({
- url: '' + (decodeURIComponent(this.model.url())) + '/' + viewName,
- type: 'GET',
- cache: false,
- headers: {
- Accept: 'application/json'
- },
- success: function(fragment) {
- return _this.renderXBlockFragment(fragment, target).done(callback);
- }
- });
- }
- };
-
- ModuleEdit.prototype.render = function() {
- var _this = this;
- return this.loadView('student_view', this.$el, function() {
- _this.loadDisplay();
- return _this.delegateEvents();
- });
- };
-
- ModuleEdit.prototype.clickEditButton = function(event) {
- var modal;
- event.preventDefault();
- modal = new EditXBlockModal();
- return modal.edit(this.$el, this.model, {
- refresh: _.bind(this.render, this)
- });
- };
-
- return ModuleEdit;
- }(XBlockView));
- return ModuleEdit;
- });
-}).call(this);
diff --git a/cms/static/js/views/tabs.js b/cms/static/js/views/tabs.js
deleted file mode 100644
index 129bec4d2b4b..000000000000
--- a/cms/static/js/views/tabs.js
+++ /dev/null
@@ -1,203 +0,0 @@
-/* globals analytics, course_location_analytics */
-
-(function(analytics, course_location_analytics) {
- 'use strict';
-
- var __hasProp = {}.hasOwnProperty,
- __extends = function(child, parent) {
- var key;
- for (key in parent) {
- if (__hasProp.call(parent, key)) {
- child[key] = parent[key];
- }
- }
- function Ctor() {
- this.constructor = child;
- }
- Ctor.prototype = parent.prototype;
- child.prototype = new Ctor();
- child.__super__ = parent.prototype;
- return child;
- };
-
- define(['underscore', 'jquery', 'jquery.ui', 'backbone', 'common/js/components/views/feedback_prompt',
- 'common/js/components/views/feedback_notification', 'js/views/module_edit',
- 'js/models/module_info', 'js/utils/module'],
- function(_, $, ui, Backbone, PromptView, NotificationView, ModuleEditView, ModuleModel, ModuleUtils) {
- var TabsEdit;
- TabsEdit = (function(_super) {
- __extends(TabsEdit, _super);
-
- // eslint-disable-next-line no-shadow
- function TabsEdit() {
- var self = this;
- this.deleteTab = function() {
- return TabsEdit.prototype.deleteTab.apply(self, arguments);
- };
- this.addNewTab = function() {
- return TabsEdit.prototype.addNewTab.apply(self, arguments);
- };
- this.tabMoved = function() {
- return TabsEdit.prototype.tabMoved.apply(self, arguments);
- };
- this.toggleVisibilityOfTab = function() {
- return TabsEdit.prototype.toggleVisibilityOfTab.apply(self, arguments);
- };
- this.initialize = function() {
- return TabsEdit.prototype.initialize.apply(self, arguments);
- };
- return TabsEdit.__super__.constructor.apply(this, arguments);
- }
-
- TabsEdit.prototype.initialize = function(options) {
- var self = this;
- this.$('.component').each(function(idx, element) {
- var model;
- model = new ModuleModel({
- id: $(element).data('locator')
- });
- return new ModuleEditView({
- el: element,
- onDelete: self.deleteTab,
- model: model
- });
- });
- this.options = _.extend({}, options);
- this.options.mast.find('.new-tab').on('click', this.addNewTab);
- $('.add-pages .new-tab').on('click', this.addNewTab);
- $('.toggle-checkbox').on('click', this.toggleVisibilityOfTab);
- return this.$('.course-nav-list').sortable({
- handle: '.drag-handle',
- update: this.tabMoved,
- helper: 'clone',
- opacity: '0.5',
- placeholder: 'component-placeholder',
- forcePlaceholderSize: true,
- axis: 'y',
- items: '> .is-movable'
- });
- };
-
- TabsEdit.prototype.toggleVisibilityOfTab = function(event) {
- var checkbox_element, saving, tab_element;
- checkbox_element = event.target;
- tab_element = $(checkbox_element).parents('.course-tab')[0];
- saving = new NotificationView.Mini({
- title: gettext('Saving')
- });
- saving.show();
- return $.ajax({
- type: 'POST',
- url: this.model.url(),
- data: JSON.stringify({
- tab_id_locator: {
- tab_id: $(tab_element).data('tab-id'),
- tab_locator: $(tab_element).data('locator')
- },
- is_hidden: $(checkbox_element).is(':checked')
- }),
- contentType: 'application/json'
- }).success(function() {
- return saving.hide();
- });
- };
-
- TabsEdit.prototype.tabMoved = function() {
- var saving, tabs;
- tabs = [];
- this.$('.course-tab').each(function(idx, element) {
- return tabs.push({
- tab_id: $(element).data('tab-id'),
- tab_locator: $(element).data('locator')
- });
- });
- analytics.track('Reordered Pages', {
- course: course_location_analytics
- });
- saving = new NotificationView.Mini({
- title: gettext('Saving')
- });
- saving.show();
- return $.ajax({
- type: 'POST',
- url: this.model.url(),
- data: JSON.stringify({
- tabs: tabs
- }),
- contentType: 'application/json'
- }).success(function() {
- return saving.hide();
- });
- };
-
- TabsEdit.prototype.addNewTab = function(event) {
- var editor;
- event.preventDefault();
- editor = new ModuleEditView({
- onDelete: this.deleteTab,
- model: new ModuleModel()
- });
- $('.new-component-item').before(editor.$el);
- editor.$el.addClass('course-tab is-movable');
- editor.$el.addClass('new');
- setTimeout(function() {
- return editor.$el.removeClass('new');
- }, 1000);
- $('html, body').animate({
- scrollTop: $('.new-component-item').offset().top
- }, 500);
- editor.createItem(this.model.get('id'), {
- category: 'static_tab'
- });
- return analytics.track('Added Page', {
- course: course_location_analytics
- });
- };
-
- TabsEdit.prototype.deleteTab = function(event) {
- var confirm;
- confirm = new PromptView.Warning({
- title: gettext('Delete Page Confirmation'),
- message: gettext('Are you sure you want to delete this page? This action cannot be undone.'),
- actions: {
- primary: {
- text: gettext('OK'),
- click: function(view) {
- var $component, deleting;
- view.hide();
- $component = $(event.currentTarget).parents('.component');
- analytics.track('Deleted Page', {
- course: course_location_analytics,
- id: $component.data('locator')
- });
- deleting = new NotificationView.Mini({
- title: gettext('Deleting')
- });
- deleting.show();
- return $.ajax({
- type: 'DELETE',
- url: ModuleUtils.getUpdateUrl($component.data('locator'))
- }).success(function() {
- $component.remove();
- return deleting.hide();
- });
- }
- },
- secondary: [
- {
- text: gettext('Cancel'),
- click: function(view) {
- return view.hide();
- }
- }
- ]
- }
- });
- return confirm.show();
- };
-
- return TabsEdit;
- }(Backbone.View));
- return TabsEdit;
- });
-}).call(this, analytics, course_location_analytics);
diff --git a/cms/static/karma_cms_webpack.conf.js b/cms/static/karma_cms_webpack.conf.js
index f389e78f8d4e..489d9fbff6e1 100644
--- a/cms/static/karma_cms_webpack.conf.js
+++ b/cms/static/karma_cms_webpack.conf.js
@@ -25,7 +25,6 @@ var options = {
// {pattern: 'js/factories/xblock_validation.js', webpack: true},
// {pattern: 'js/factories/container.js', webpack: true},
// {pattern: 'js/factories/context_course.js', webpack: true},
- // {pattern: 'js/factories/edit_tabs.js', webpack: true},
// {pattern: 'js/factories/library.js', webpack: true},
// ],
diff --git a/cms/templates/edit-tabs.html b/cms/templates/edit-tabs.html
deleted file mode 100644
index 7952da338623..000000000000
--- a/cms/templates/edit-tabs.html
+++ /dev/null
@@ -1,213 +0,0 @@
-<%page expression_filter="h"/>
-<%inherit file="base.html" />
-<%def name="online_help_token()"><% return "pages" %>%def>
-<%namespace name='static' file='static_content.html'/>
-<%!
- from django.utils.translation import gettext as _
- from django.urls import reverse
- from xmodule.tabs import StaticTab
- from openedx.core.djangolib.js_utils import js_escaped_string
- from cms.djangoapps.contentstore.utils import get_pages_and_resources_url
-%>
-<%block name="title">${_("Custom pages")}%block>
-<%block name="bodyclass">is-signedin course view-static-pages%block>
-
-<%block name="header_extras">
-% for template_name in ["basic-modal", "modal-button", "edit-xblock-modal", "editor-mode-button"]:
-
-% endfor
-%block>
-
-<%block name="page_bundle">
- <%static:webpack entry="js/factories/edit_tabs">
- EditTabsFactory("${context_course.location | n, js_escaped_string}", "${reverse('tabs_handler', kwargs={'course_key_string': context_course.id}) | n, js_escaped_string}");
- %static:webpack>
-%block>
-
-<%block name="content">
-
- % if context_course:
- <%
- pages_and_resources_mfe_url = get_pages_and_resources_url(context_course.id)
- pages_and_resources_mfe_enabled = bool(pages_and_resources_mfe_url)
- %>
- % endif
-
- % if pages_and_resources_mfe_enabled:
-
-
-
- % else:
-
-
- % endif
-
-
- ${_("Page Actions")}
-
-
-
-
-
-
-
-
-
-
-
${_("Note: Pages are publicly visible. If users know the URL of a page, they can view the page even if they are not registered for or logged in to your course.")}
-
-
-
-
-
-
-
-
-
- % for tab in tabs_to_render:
- <%
- css_class = "course-tab"
- if tab.is_movable:
- css_class = css_class + " is-movable"
- elif (not tab.is_movable) and (not tab.is_hideable):
- css_class = css_class + " is-fixed"
- %>
-
- % if isinstance(tab, StaticTab):
-
-
- % else:
-
-
-
-
-
- % if tab.is_movable:
-
- ${_("Drag to reorder")}
-
- % else:
-
- ${_("This page cannot be reordered")}
-
- % endif
-
-
- % endif
- % endfor
-
-
-
-
-
-
-
${_("You can add additional custom pages to your course.")} ${_("Add a New Page")}
-
-
-
-
-
- % if pages_and_resources_mfe_enabled:
-
-
-
${_("What are pages?")}
-
${_("Pages are listed horizontally at the top of your course. Default pages (Home, Course, Discussion, Wiki, and Progress) are followed by textbooks and custom pages that you create.")}
-
-
-
${_("Custom pages")}
-
${_("You can create and edit custom pages to provide students with additional course content. For example, you can create pages for the grading policy, course slides, and a course calendar. ")}
-
-
-
${_("How do pages look to students in my course?")}
-
${_("Students see the default and custom pages at the top of your course and use these links to navigate.")} ${_("See an example")}
-
-
- % else:
-
-
-
${_("What are custom pages?")}
-
${_("You can create and edit custom pages to provide students with additional course content. For example, you can create pages for the grading policy, course syllabus, and a course calendar. ")}
-
-
-
${_("How do custom pages look to students in my course?")}
-
${_("Custom pages are listed horizontally at the top of your course after default pages.")} ${_("See an example")}
-
-
- % endif
-
-
-
-
-
-
${_("Pages in Your Course")}
-
-
- ${_("Pages appear in your course's top navigation bar. The default pages (Home, Course, Discussion, Wiki, and Progress) are followed by textbooks and custom pages.")}
-
-
-
-
- ${_("close modal")}
-
-
-%block>
diff --git a/webpack.common.config.js b/webpack.common.config.js
index e52a79a1bfc9..cd9d0f53af59 100644
--- a/webpack.common.config.js
+++ b/webpack.common.config.js
@@ -104,7 +104,6 @@ module.exports = Merge.merge({
'js/factories/context_course': './cms/static/js/factories/context_course.js',
'js/factories/library': './cms/static/js/factories/library.js',
'js/factories/xblock_validation': './cms/static/js/factories/xblock_validation.js',
- 'js/factories/edit_tabs': './cms/static/js/factories/edit_tabs.js',
'js/sock': './cms/static/js/sock.js',
'js/factories/tag_count': './cms/static/js/factories/tag_count.js',