-
-
- <%block name="viewtitle">
- %block>
-
-<%block name="viewcontent">%block>
-%block>
diff --git a/cms/templates/maintenance/container.html b/cms/templates/maintenance/container.html
deleted file mode 100644
index 417471a1bd66..000000000000
--- a/cms/templates/maintenance/container.html
+++ /dev/null
@@ -1,33 +0,0 @@
-<%page expression_filter="h"/>
-<%inherit file="base.html" />
-<%namespace name='static' file='../static_content.html'/>
-<%!
-from django.urls import reverse
-from openedx.core.djangolib.js_utils import js_escaped_string
-%>
-<%block name="title">${view['name']}%block>
-<%block name="viewtitle">
-
- ${view['name']}
-
-%block>
-
-<%block name="viewcontent">
-
- <%include file="_${view['slug']}.html"/>
-
-%block>
-
-<%block name="header_extras">
-% for template_name in ["force-published-course-response"]:
-
-% endfor
-%block>
-
-<%block name="requirejs">
- require(["js/maintenance/${view['slug'] | n, js_escaped_string}"], function(MaintenanceFactory) {
- MaintenanceFactory("${reverse(view['url']) | n, js_escaped_string}");
- });
-%block>
diff --git a/cms/templates/maintenance/index.html b/cms/templates/maintenance/index.html
deleted file mode 100644
index 293cb90b4a9c..000000000000
--- a/cms/templates/maintenance/index.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<%page expression_filter="h"/>
-<%inherit file="base.html" />
-<%namespace name='static' file='../static_content.html'/>
-<%!
-from django.utils.translation import gettext as _
-from django.urls import reverse
-%>
-<%block name="title">${_('Maintenance Dashboard')}%block>
-<%block name="viewcontent">
-
-
- % for view in views.values():
- -
- ${view['name']}
- ${view['description']}
-
- % endfor
-
-
-%block>
diff --git a/cms/templates/widgets/user_dropdown.html b/cms/templates/widgets/user_dropdown.html
index 0ec00257ffe1..3fc0934b0db7 100644
--- a/cms/templates/widgets/user_dropdown.html
+++ b/cms/templates/widgets/user_dropdown.html
@@ -21,11 +21,6 @@
${_("{studio_name} Home").format(studio_name=settings.STUDIO_SHORT_NAME)}
- % if GlobalStaff().has_user(user):
-
- ${_("Maintenance")}
-
- % endif
${_("Sign Out")}
diff --git a/cms/urls.py b/cms/urls.py
index d72189445883..2e64d4bbeb79 100644
--- a/cms/urls.py
+++ b/cms/urls.py
@@ -276,8 +276,6 @@
certificates_list_handler, name='certificates_list_handler')
]
-# Maintenance Dashboard
-urlpatterns.append(path('maintenance/', include('cms.djangoapps.maintenance.urls', namespace='maintenance')))
if settings.DEBUG:
try:
diff --git a/lms/static/sass/_build-lms-v1.scss b/lms/static/sass/_build-lms-v1.scss
index 1171e3d14cdf..7a77eb34ca07 100644
--- a/lms/static/sass/_build-lms-v1.scss
+++ b/lms/static/sass/_build-lms-v1.scss
@@ -68,7 +68,6 @@
// features
@import 'features/bookmarks-v1';
-@import "features/announcements";
@import 'features/learner-profile';
@import 'features/_unsupported-browser-alert';
@import 'features/content-type-gating';
diff --git a/lms/static/sass/features/_announcements.scss b/lms/static/sass/features/_announcements.scss
deleted file mode 100644
index 0c3c01fe6077..000000000000
--- a/lms/static/sass/features/_announcements.scss
+++ /dev/null
@@ -1,28 +0,0 @@
-// lms - features - announcements
-// ====================
-.announcements-list {
- display: inline-block;
- width: 100%;
-
- .announcement {
- background-color: $course-profile-bg;
- align-content: center;
- text-align: center;
- padding: 22px 33px;
- margin-bottom: 15px;
- }
-
- .announcement-button {
- display: inline-block;
- padding: 3px 10px;
- font-size: 0.75rem;
- }
-
- .prev {
- float: left;
- }
-
- .next {
- float: right;
- }
-}
diff --git a/openedx/features/announcements/apps.py b/openedx/features/announcements/apps.py
deleted file mode 100644
index 4bf964cae51b..000000000000
--- a/openedx/features/announcements/apps.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""
-Announcements Application Configuration
-"""
-
-
-from django.apps import AppConfig
-from edx_django_utils.plugins import PluginURLs, PluginSettings
-
-from openedx.core.djangoapps.plugins.constants import ProjectType, SettingsType
-
-
-class AnnouncementsConfig(AppConfig):
- """
- Application Configuration for Announcements
- """
- name = 'openedx.features.announcements'
-
- plugin_app = {
- PluginURLs.CONFIG: {
- ProjectType.LMS: {
- PluginURLs.NAMESPACE: 'announcements',
- PluginURLs.REGEX: '^announcements/',
- PluginURLs.RELATIVE_PATH: 'urls',
- }
- },
- PluginSettings.CONFIG: {
- ProjectType.LMS: {
- SettingsType.COMMON: {PluginSettings.RELATIVE_PATH: 'settings.common'},
- SettingsType.TEST: {PluginSettings.RELATIVE_PATH: 'settings.test'},
- }
- }
- }
diff --git a/openedx/features/announcements/forms.py b/openedx/features/announcements/forms.py
deleted file mode 100644
index 879101ca37d0..000000000000
--- a/openedx/features/announcements/forms.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-Forms for the Announcement Editor
-"""
-
-
-from django import forms
-
-from .models import Announcement
-
-
-class AnnouncementForm(forms.ModelForm):
- """
- Form for editing Announcements
- """
- content = forms.CharField(widget=forms.Textarea, label='', required=False)
- active = forms.BooleanField(initial=True, required=False)
-
- class Meta:
- model = Announcement
- fields = ['content', 'active']
diff --git a/openedx/features/announcements/models.py b/openedx/features/announcements/models.py
deleted file mode 100644
index f58f61165db6..000000000000
--- a/openedx/features/announcements/models.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""
-Models for Announcements
-"""
-
-
-from django.db import models
-
-
-class Announcement(models.Model):
- """
- Site-wide announcements to be displayed on the dashboard
-
- .. no_pii:
- """
- class Meta:
- app_label = 'announcements'
-
- content = models.CharField(max_length=1000, null=False, default="lorem ipsum")
- active = models.BooleanField(default=True)
-
- def __str__(self):
- return self.content
diff --git a/openedx/features/announcements/settings/__init__.py b/openedx/features/announcements/settings/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/openedx/features/announcements/settings/common.py b/openedx/features/announcements/settings/common.py
deleted file mode 100644
index 1a1a5ca497ab..000000000000
--- a/openedx/features/announcements/settings/common.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""Common settings for Announcements"""
-
-
-def plugin_settings(settings):
- """
- Common settings for Announcements
- .. toggle_name: FEATURES['ENABLE_ANNOUNCEMENTS']
- .. toggle_implementation: SettingDictToggle
- .. toggle_default: False
- .. toggle_description: This feature can be enabled to show system wide announcements
- on the sidebar of the learner dashboard. Announcements can be created by Global Staff
- users on maintenance dashboard of studio. Maintenance dashboard can accessed at
- https://{studio.domain}/maintenance
- .. toggle_warning: TinyMCE is needed to show an editor in the studio.
- .. toggle_use_cases: open_edx
- .. toggle_creation_date: 2017-11-08
- .. toggle_tickets: https://github.com/openedx/edx-platform/pull/16496
- """
- settings.FEATURES['ENABLE_ANNOUNCEMENTS'] = False
- # Configure number of announcements to show per page
- settings.FEATURES['ANNOUNCEMENTS_PER_PAGE'] = 5
diff --git a/openedx/features/announcements/settings/test.py b/openedx/features/announcements/settings/test.py
deleted file mode 100644
index 47d57ca3dcbf..000000000000
--- a/openedx/features/announcements/settings/test.py
+++ /dev/null
@@ -1,8 +0,0 @@
-"""Test settings for Announcements"""
-
-
-def plugin_settings(settings):
- """
- Test settings for Announcements
- """
- settings.FEATURES['ENABLE_ANNOUNCEMENTS'] = True
diff --git a/openedx/features/announcements/static/announcements/jsx/Announcements.jsx b/openedx/features/announcements/static/announcements/jsx/Announcements.jsx
deleted file mode 100644
index 9d370883352c..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/Announcements.jsx
+++ /dev/null
@@ -1,141 +0,0 @@
-// eslint-disable-next-line max-classes-per-file
-import React from 'react';
-import ReactDOM from 'react-dom';
-import PropTypes from 'prop-types';
-import {Button} from '@edx/paragon';
-import $ from 'jquery';
-
-class AnnouncementSkipLink extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- count: 0
- };
- $.get('/announcements/page/1')
- .then(data => {
- this.setState({
- count: data.count
- });
- });
- }
-
- render() {
- return (
{'Skip to list of ' + this.state.count + ' announcements'}
);
- }
-}
-
-// eslint-disable-next-line react/prefer-stateless-function
-class Announcement extends React.Component {
- render() {
- return (
-
- );
- }
-}
-
-Announcement.propTypes = {
- content: PropTypes.string.isRequired,
-};
-
-class AnnouncementList extends React.Component {
- constructor(props) {
- super(props);
- this.state = {
- page: 1,
- announcements: [],
- // eslint-disable-next-line react/no-unused-state
- num_pages: 0,
- has_prev: false,
- has_next: false,
- start_index: 0,
- end_index: 0,
- };
- }
-
- retrievePage(page) {
- $.get('/announcements/page/' + page)
- .then(data => {
- this.setState({
- announcements: data.announcements,
- has_next: data.next,
- has_prev: data.prev,
- // eslint-disable-next-line react/no-unused-state
- num_pages: data.num_pages,
- count: data.count,
- start_index: data.start_index,
- end_index: data.end_index,
- page: page
- });
- });
- }
-
- renderPrevPage() {
- this.retrievePage(this.state.page - 1);
- }
-
- renderNextPage() {
- this.retrievePage(this.state.page + 1);
- }
-
- // eslint-disable-next-line react/no-deprecated, react/sort-comp
- componentWillMount() {
- this.retrievePage(this.state.page);
- }
-
- render() {
- var children = this.state.announcements.map(
- // eslint-disable-next-line react/no-array-index-key
- (announcement, index) =>
- );
- if (this.state.has_prev) {
- var prev_button = (
-
-
- );
- }
- if (this.state.has_next) {
- var next_button = (
-
-
- );
- }
- return (
-
- {children}
- {prev_button}
- {next_button}
-
- );
- }
-}
-
-export default class AnnouncementsView {
- constructor() {
- ReactDOM.render(
-
,
- document.getElementById('announcements'),
- );
- ReactDOM.render(
-
,
- document.getElementById('announcements-skip'),
- );
- }
-}
-
-export {AnnouncementsView, AnnouncementList, AnnouncementSkipLink};
diff --git a/openedx/features/announcements/static/announcements/jsx/Announcements.test.jsx b/openedx/features/announcements/static/announcements/jsx/Announcements.test.jsx
deleted file mode 100644
index 3ec55f392889..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/Announcements.test.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from 'react';
-import renderer from 'react-test-renderer';
-import testAnnouncements from './test-announcements.json';
-
-import {AnnouncementSkipLink, AnnouncementList} from './Announcements';
-
-describe('Announcements component', () => {
- test('render skip link', () => {
- const component = renderer.create(
-
,
- );
- component.root.instance.setState({count: 10});
- const tree = component.toJSON();
- expect(tree).toMatchSnapshot();
- });
-
- test('render test announcements', () => {
- const component = renderer.create(
-
,
- );
- component.root.instance.setState(testAnnouncements);
- const tree = component.toJSON();
- expect(tree).toMatchSnapshot();
- });
-});
diff --git a/openedx/features/announcements/static/announcements/jsx/__snapshots__/Announcements.test.jsx.snap b/openedx/features/announcements/static/announcements/jsx/__snapshots__/Announcements.test.jsx.snap
deleted file mode 100644
index bbf9bfaaaa69..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/__snapshots__/Announcements.test.jsx.snap
+++ /dev/null
@@ -1,78 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`Announcements component render skip link 1`] = `
-
- Skip to list of 10 announcements
-
-`;
-
-exports[`Announcements component render test announcements 1`] = `
-
-
-
Announcement 2",
- }
- }
- />
-
-
-
-
-
-
-
- 1 - 5) of 6
-
-
-
-`;
diff --git a/openedx/features/announcements/static/announcements/jsx/test-announcements.json b/openedx/features/announcements/static/announcements/jsx/test-announcements.json
deleted file mode 100644
index d23d39303020..000000000000
--- a/openedx/features/announcements/static/announcements/jsx/test-announcements.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "announcements": [
- {"content": "Test Announcement 1"},
- {"content": "Bold
Announcement 2"},
- {"content": "Test Announcement 3"},
- {"content": "Test Announcement 4"},
- {"content": "Test Announcement 5"},
- {"content": "Test Announcement 6"}
- ],
- "has_next": true,
- "has_prev": false,
- "num_pages": 2,
- "count": 6,
- "start_index": 1,
- "end_index": 5,
- "page": 1
-}
diff --git a/openedx/features/announcements/tests/__init__.py b/openedx/features/announcements/tests/__init__.py
deleted file mode 100644
index e69de29bb2d1..000000000000
diff --git a/openedx/features/announcements/tests/test_announcements.py b/openedx/features/announcements/tests/test_announcements.py
deleted file mode 100644
index 10c608b4a6cd..000000000000
--- a/openedx/features/announcements/tests/test_announcements.py
+++ /dev/null
@@ -1,95 +0,0 @@
-"""
-Unit tests for the announcements feature.
-"""
-
-import json
-from unittest.mock import patch
-
-from django.conf import settings
-from django.test import TestCase
-from django.test.client import Client
-from django.urls import reverse
-
-from common.djangoapps.student.tests.factories import AdminFactory
-from openedx.core.djangolib.testing.utils import skip_unless_lms
-from openedx.features.announcements.models import Announcement
-
-TEST_ANNOUNCEMENTS = [
- ("Active Announcement", True),
- ("Inactive Announcement", False),
- ("Another Test Announcement", True),
- ("
Formatted Announcement", True),
- ("
Other Formatted Announcement", True),
-]
-
-
-@skip_unless_lms
-class TestGlobalAnnouncements(TestCase):
- """
- Test Announcements in LMS
- """
-
- @classmethod
- def setUpTestData(cls):
- super().setUpTestData()
- Announcement.objects.bulk_create([
- Announcement(content=content, active=active)
- for content, active in TEST_ANNOUNCEMENTS
- ])
-
- def setUp(self):
- super().setUp()
- self.client = Client()
- self.admin = AdminFactory.create(
- email='staff@edx.org',
- username='admin',
- password='pass'
- )
- self.client.login(username=self.admin.username, password='pass')
-
- @patch.dict(settings.FEATURES, {'ENABLE_ANNOUNCEMENTS': False})
- def test_feature_flag_disabled(self):
- """Ensures that the default settings effectively disables the feature"""
- response = self.client.get('/dashboard')
- self.assertNotContains(response, 'AnnouncementsView')
- self.assertNotContains(response, '
Formatted Announcement")
diff --git a/openedx/features/announcements/urls.py b/openedx/features/announcements/urls.py
deleted file mode 100644
index 0f0ad3a33960..000000000000
--- a/openedx/features/announcements/urls.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""
-Defines URLs for announcements in the LMS.
-"""
-from django.contrib.auth.decorators import login_required
-from django.urls import path
-
-from .views import AnnouncementsJSONView
-
-urlpatterns = [
- path('page/', login_required(AnnouncementsJSONView.as_view()),
- name='page',
- ),
-]
diff --git a/openedx/features/announcements/views.py b/openedx/features/announcements/views.py
deleted file mode 100644
index b6657c29cc12..000000000000
--- a/openedx/features/announcements/views.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""
-Views to show announcements.
-"""
-
-
-from django.conf import settings
-from django.http import JsonResponse
-from django.views.generic.list import ListView
-
-from .models import Announcement
-
-
-class AnnouncementsJSONView(ListView):
- """
- View returning a page of announcements for the dashboard
- """
- model = Announcement
- object_list = Announcement.objects.filter(active=True)
- paginate_by = settings.FEATURES.get('ANNOUNCEMENTS_PER_PAGE', 5)
-
- def get(self, request, *args, **kwargs):
- """
- Return active announcements as json
- """
- context = self.get_context_data()
-
- announcements = [{"content": announcement.content} for announcement in context['object_list']]
- result = {
- "announcements": announcements,
- "next": context['page_obj'].has_next(),
- "prev": context['page_obj'].has_previous(),
- "start_index": context['page_obj'].start_index(),
- "end_index": context['page_obj'].end_index(),
- "count": context['paginator'].count,
- "num_pages": context['paginator'].num_pages,
- }
- return JsonResponse(result)
diff --git a/setup.py b/setup.py
index 3b8f8c59498d..3ccfe7734e33 100644
--- a/setup.py
+++ b/setup.py
@@ -138,7 +138,6 @@
],
"lms.djangoapp": [
"ace_common = openedx.core.djangoapps.ace_common.apps:AceCommonConfig",
- "announcements = openedx.features.announcements.apps:AnnouncementsConfig",
"content_libraries = openedx.core.djangoapps.content_libraries.apps:ContentLibrariesConfig",
"course_apps = openedx.core.djangoapps.course_apps.apps:CourseAppsConfig",
"course_live = openedx.core.djangoapps.course_live.apps:CourseLiveConfig",
@@ -157,7 +156,6 @@
"program_enrollments = lms.djangoapps.program_enrollments.apps:ProgramEnrollmentsConfig",
],
"cms.djangoapp": [
- "announcements = openedx.features.announcements.apps:AnnouncementsConfig",
"ace_common = openedx.core.djangoapps.ace_common.apps:AceCommonConfig",
"bookmarks = openedx.core.djangoapps.bookmarks.apps:BookmarksConfig",
"course_live = openedx.core.djangoapps.course_live.apps:CourseLiveConfig",
diff --git a/webpack.common.config.js b/webpack.common.config.js
index 322e252c6ae2..de8b545c978b 100644
--- a/webpack.common.config.js
+++ b/webpack.common.config.js
@@ -112,7 +112,6 @@ module.exports = Merge.smart({
CourseSock: './openedx/features/course_experience/static/course_experience/js/CourseSock.js',
Currency: './openedx/features/course_experience/static/course_experience/js/currency.js',
- AnnouncementsView: './openedx/features/announcements/static/announcements/jsx/Announcements.jsx',
CookiePolicyBanner: './common/static/js/src/CookiePolicyBanner.jsx',
// Common
@@ -172,19 +171,19 @@ module.exports = Merge.smart({
multiple: [
{ search: defineHeader, replace: '' },
{ search: defineFooter, replace: '' },
- {
+ {
search: /(\/\* RequireJS) \*\//g,
replace(match, p1, offset, string) {
return p1;
}
},
- {
+ {
search: /\/\* Webpack/g,
replace(match, p1, offset, string) {
return match + ' */';
}
},
- {
+ {
search: /text!(.*?\.underscore)/g,
replace(match, p1, offset, string) {
return p1;
@@ -635,13 +634,13 @@ module.exports = Merge.smart({
// We used to have node: { fs: 'empty' } in this file,
// that is no longer supported. Adding this based on the recommendation in
// https://stackoverflow.com/questions/64361940/webpack-error-configuration-node-has-an-unknown-property-fs
- //
+ //
// With this uncommented tests fail
// Tests failed in the following suites:
// * lms javascript
// * xmodule-webpack javascript
// Error: define cannot be used indirect
- //
+ //
// fallback: {
// fs: false
// }