diff --git a/lms/djangoapps/discussion/config/__init__.py b/lms/djangoapps/discussion/config/__init__.py
index 09a8c721f2..e69de29bb2 100644
--- a/lms/djangoapps/discussion/config/__init__.py
+++ b/lms/djangoapps/discussion/config/__init__.py
@@ -1,12 +0,0 @@
-"""
-Discussion settings and flags.
-"""
-
-
-from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
-
-# Namespace for course experience waffle flags.
-WAFFLE_FLAG_NAMESPACE = WaffleFlagNamespace(name='edx_discussions')
-
-# Waffle flag to enable the use of Bootstrap
-USE_BOOTSTRAP_FLAG = WaffleFlag(WAFFLE_FLAG_NAMESPACE, 'use_bootstrap', flag_undefined_default=True)
diff --git a/lms/djangoapps/discussion/config/waffle.py b/lms/djangoapps/discussion/config/waffle.py
new file mode 100644
index 0000000000..e672926703
--- /dev/null
+++ b/lms/djangoapps/discussion/config/waffle.py
@@ -0,0 +1,39 @@
+"""
+Discussion settings and flags.
+"""
+
+from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace
+
+USE_BOOTSTRAP = 'use_bootstrap'
+ENABLE_FORUM_DAILY_DIGEST = 'enable_forum_daily_digest'
+
+
+def waffle_flags():
+ """
+ Returns the namespaced, cached, audited Waffle flags dictionary for Grades.
+ """
+ namespace = WaffleFlagNamespace(name='edx_discussions')
+ return {
+ # Waffle flag to enable the use of Bootstrap
+ USE_BOOTSTRAP: WaffleFlag(
+ namespace,
+ USE_BOOTSTRAP,
+ flag_undefined_default=True
+ ),
+ # By default, enable forum notifications. Can be disabled platform wide.
+ ENABLE_FORUM_DAILY_DIGEST: WaffleFlag(
+ namespace,
+ ENABLE_FORUM_DAILY_DIGEST,
+ flag_undefined_default=True
+ ),
+ }
+
+
+def use_bootstrap_flag_enabled():
+ """Returns whether use of bootstrap is enabled."""
+ return waffle_flags()[USE_BOOTSTRAP].is_enabled()
+
+
+def is_forum_daily_digest_enabled():
+ """Returns whether forum notification features should be visible"""
+ return waffle_flags()[ENABLE_FORUM_DAILY_DIGEST].is_enabled()
diff --git a/lms/djangoapps/discussion/plugins.py b/lms/djangoapps/discussion/plugins.py
index b5ce9f1dde..c9ea2101eb 100644
--- a/lms/djangoapps/discussion/plugins.py
+++ b/lms/djangoapps/discussion/plugins.py
@@ -8,10 +8,9 @@ from django.utils.translation import ugettext_noop
import lms.djangoapps.discussion.django_comment_client.utils as utils
from lms.djangoapps.courseware.tabs import EnrolledTab
+from lms.djangoapps.discussion.config.waffle import use_bootstrap_flag_enabled
from xmodule.tabs import TabFragmentViewMixin
-from .config import USE_BOOTSTRAP_FLAG
-
class DiscussionTab(TabFragmentViewMixin, EnrolledTab):
"""
@@ -39,4 +38,4 @@ class DiscussionTab(TabFragmentViewMixin, EnrolledTab):
"""
Returns true if this tab is rendered with Bootstrap.
"""
- return USE_BOOTSTRAP_FLAG.is_enabled()
+ return use_bootstrap_flag_enabled()
diff --git a/lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore b/lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore
index 6a55a37706..f9ce1111f9 100644
--- a/lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore
+++ b/lms/djangoapps/discussion/static/discussion/templates/discussion-home.underscore
@@ -44,19 +44,21 @@
<%- gettext("Follow or unfollow posts") %>
-
- | <%- gettext('Receive updates') %>
- |
-
- <%- gettext("Check this box to receive an email digest once a day notifying you about new, unread activity from posts you are following.") %>
- |
-
+ <% if (window.ENABLE_FORUM_DAILY_DIGEST) {%>
+
+ | <%- gettext('Receive updates') %>
+ |
+
+ <%- gettext("Check this box to receive an email digest once a day notifying you about new, unread activity from posts you are following.") %>
+ |
+
+ <% } %>
<% } %>
diff --git a/lms/djangoapps/discussion/views.py b/lms/djangoapps/discussion/views.py
index a4bb67aab4..65ec5e92c8 100644
--- a/lms/djangoapps/discussion/views.py
+++ b/lms/djangoapps/discussion/views.py
@@ -30,6 +30,7 @@ import openedx.core.djangoapps.django_comment_common.comment_client as cc
from lms.djangoapps.courseware.access import has_access
from lms.djangoapps.courseware.courses import get_course_with_access
from lms.djangoapps.courseware.views.views import CourseTabView
+from lms.djangoapps.discussion.config.waffle import is_forum_daily_digest_enabled, use_bootstrap_flag_enabled
from lms.djangoapps.discussion.django_comment_client.base.views import track_thread_viewed_event
from lms.djangoapps.discussion.django_comment_client.constants import TYPE_ENTRY
from lms.djangoapps.discussion.django_comment_client.permissions import has_permission
@@ -59,8 +60,6 @@ from student.models import CourseEnrollment
from util.json_request import JsonResponse, expect_json
from xmodule.modulestore.django import modulestore
-from .config import USE_BOOTSTRAP_FLAG
-
log = logging.getLogger("edx.discussions")
@@ -433,7 +432,7 @@ def _create_base_discussion_view_context(request, course_key):
user_info = cc_user.to_dict()
course = get_course_with_access(user, 'load', course_key, check_if_enrolled=True)
course_settings = make_course_settings(course, user)
- uses_bootstrap = USE_BOOTSTRAP_FLAG.is_enabled()
+ uses_bootstrap = use_bootstrap_flag_enabled()
return {
'csrf': csrf(request)['csrf_token'],
'course': course,
@@ -519,6 +518,7 @@ def _create_discussion_board_context(request, base_context, thread=None):
'is_commentable_divided': is_commentable_divided(course_key, discussion_id, course_discussion_settings),
# If the default topic id is None the front-end code will look for a topic that contains "General"
'discussion_default_topic_id': _get_discussion_default_topic_id(course),
+ 'enable_daily_digest': is_forum_daily_digest_enabled()
})
context.update(
get_experiment_user_metadata_context(
@@ -818,7 +818,7 @@ class DiscussionBoardFragmentView(EdxFragmentView):
the files are loaded individually, but in production just the single bundle is loaded.
"""
is_right_to_left = get_language_bidi()
- if USE_BOOTSTRAP_FLAG.is_enabled():
+ if use_bootstrap_flag_enabled():
css_file = BOOTSTRAP_DISCUSSION_CSS_PATH
if is_right_to_left:
css_file = css_file.replace('.css', '-rtl.css')
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 071672918f..ff678e5acc 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -100,6 +100,11 @@ FEATURES = {
# this should remain off in production until digest notifications are online.
'ENABLE_DISCUSSION_HOME_PANEL': False,
+ # settings for forums/discussions to on/off daily digest feature. Set this to True if you want to
+ # enable the UI for the users to subscribe and unsubscribe for daily digest. This setting is the
+ # part of deprecation of daily digest in production.
+ 'ENABLE_FORUM_DAILY_DIGEST': True,
+
# Set this to True if you want the discussion digest emails enabled automatically for new users.
# This will be set on all new account registrations.
# It is not recommended to enable this feature if ENABLE_DISCUSSION_HOME_PANEL is not enabled, since
diff --git a/lms/templates/discussion/_underscore_templates.html b/lms/templates/discussion/_underscore_templates.html
index 1d43ba979b..fde2766bce 100644
--- a/lms/templates/discussion/_underscore_templates.html
+++ b/lms/templates/discussion/_underscore_templates.html
@@ -1,13 +1,23 @@
<%page expression_filter="h"/>
<%namespace name='static' file='../static_content.html'/>
-<%! from openedx.core.djangolib.js_utils import js_escaped_string %>
+<%
+from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_string
+enable_discussion_home_panel = settings.FEATURES.get('ENABLE_DISCUSSION_HOME_PANEL', False)
+%>
<%static:include path="common/templates/discussion/templates.underscore" />
diff --git a/lms/urls.py b/lms/urls.py
index d141946a33..3fd43db7a4 100644
--- a/lms/urls.py
+++ b/lms/urls.py
@@ -2,7 +2,6 @@
URLs for LMS
"""
-
from config_models.views import ConfigurationModelCurrentAPIView
from django.conf import settings
from django.conf.urls import include, url
@@ -10,26 +9,29 @@ from django.conf.urls.static import static
from django.contrib.admin import autodiscover as django_autodiscover
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import RedirectView
+from edx_api_doc_tools import make_docs_urls
from ratelimitbackend import admin
-from edx_api_doc_tools import make_docs_urls
-
from branding import views as branding_views
+from debug import views as debug_views
+from lms.djangoapps.certificates import views as certificates_views
from lms.djangoapps.courseware.masquerade import handle_ajax as courseware_masquerade_handle_ajax
from lms.djangoapps.courseware.module_render import (
- handle_xblock_callback, handle_xblock_callback_noauth, xblock_view, xqueue_callback,
+ handle_xblock_callback,
+ handle_xblock_callback_noauth,
+ xblock_view,
+ xqueue_callback
)
from lms.djangoapps.courseware.views import views as courseware_views
from lms.djangoapps.courseware.views.index import CoursewareIndex
from lms.djangoapps.courseware.views.views import CourseTabView, EnrollStaffView, StaticCourseTabView
-from debug import views as debug_views
-from lms.djangoapps.certificates import views as certificates_views
from lms.djangoapps.discussion import views as discussion_views
from lms.djangoapps.discussion.notification_prefs import views as notification_prefs_views
from lms.djangoapps.instructor.views import coupons as instructor_coupons_views
from lms.djangoapps.instructor.views import instructor_dashboard as instructor_dashboard_views
from lms.djangoapps.instructor.views import registration_codes as instructor_registration_codes_views
from lms.djangoapps.instructor_task import views as instructor_task_views
+from openedx.core.apidocs import api_info
from openedx.core.djangoapps.auth_exchange.views import LoginWithAccessTokenView
from openedx.core.djangoapps.catalog.models import CatalogIntegration
from openedx.core.djangoapps.common_views.xblock import xblock_resource
@@ -47,7 +49,6 @@ from openedx.core.djangoapps.self_paced.models import SelfPacedConfiguration
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
from openedx.core.djangoapps.user_authn.views.login import redirect_to_lms_login
from openedx.core.djangoapps.verified_track_content import views as verified_track_content_views
-from openedx.core.apidocs import api_info
from openedx.features.enterprise_support.api import enterprise_enabled
from static_template_view import views as static_template_view_views
from staticbook import views as staticbook_views
@@ -68,8 +69,28 @@ if settings.DEBUG or settings.FEATURES.get('ENABLE_DJANGO_ADMIN_SITE'):
handler404 = static_template_view_views.render_404
handler500 = static_template_view_views.render_500
+notification_prefs_urls = [
+ url(r'^notification_prefs/enable/', notification_prefs_views.ajax_enable),
+ url(r'^notification_prefs/disable/', notification_prefs_views.ajax_disable),
+ url(r'^notification_prefs/status/', notification_prefs_views.ajax_status),
+
+ url(
+ r'^notification_prefs/unsubscribe/(?P[a-zA-Z0-9-_=]+)/',
+ notification_prefs_views.set_subscription,
+ {'subscribe': False},
+ name='unsubscribe_forum_update',
+ ),
+ url(
+ r'^notification_prefs/resubscribe/(?P[a-zA-Z0-9-_=]+)/',
+ notification_prefs_views.set_subscription,
+ {'subscribe': True},
+ name='resubscribe_forum_update',
+ ),
+]
+
+
urlpatterns = [
- url(r'^$', branding_views.index, name='root'), # Main marketing page, or redirect to courseware
+ url(r'^$', branding_views.index, name='root'), # Main marketing page, or redirect to courseware
url(r'', include('student.urls')),
# TODO: Move lms specific student views out of common code
@@ -108,7 +129,6 @@ urlpatterns = [
# subsumed by api/user listed above.
url(r'', include('openedx.core.djangoapps.user_api.legacy_urls')),
-
# Profile Images API endpoints
url(r'^api/profile_images/', include('openedx.core.djangoapps.profile_images.urls')),
@@ -164,7 +184,6 @@ urlpatterns += [
url(r'^openassessment/fileupload/', include('openassessment.fileupload.urls')),
]
-
# sysadmin dashboard, to see what courses are loaded, to delete & load courses
if settings.FEATURES.get('ENABLE_SYSADMIN_DASHBOARD'):
urlpatterns += [
@@ -299,7 +318,7 @@ urlpatterns += [
url(r'^courses/?$', branding_views.courses, name='courses'),
- #About the course
+ # About the course
url(
r'^courses/{}/about$'.format(
settings.COURSE_ID_PATTERN,
@@ -320,7 +339,7 @@ urlpatterns += [
name='enroll_staff',
),
- #Inside the course
+ # Inside the course
url(
r'^courses/{}/$'.format(
settings.COURSE_ID_PATTERN,
@@ -486,7 +505,6 @@ urlpatterns += [
name='instructor_dashboard',
),
-
url(
r'^courses/{}/set_course_mode_price$'.format(
settings.COURSE_ID_PATTERN,
@@ -714,36 +732,11 @@ if settings.FEATURES.get('ENABLE_DISCUSSION_SERVICE'):
),
include('lms.djangoapps.discussion.django_comment_client.urls')
),
- url(
- r'^notification_prefs/enable/',
- notification_prefs_views.ajax_enable
- ),
- url(
- r'^notification_prefs/disable/',
- notification_prefs_views.ajax_disable
- ),
- url(
- r'^notification_prefs/status/',
- notification_prefs_views.ajax_status
- ),
- url(
- r'^notification_prefs/unsubscribe/(?P[a-zA-Z0-9-_=]+)/',
- notification_prefs_views.set_subscription,
- {
- 'subscribe': False,
- },
- name='unsubscribe_forum_update',
- ),
- url(
- r'^notification_prefs/resubscribe/(?P[a-zA-Z0-9-_=]+)/',
- notification_prefs_views.set_subscription,
- {
- 'subscribe': True,
- },
- name='resubscribe_forum_update',
- ),
]
+if settings.FEATURES.get('ENABLE_FORUM_DAILY_DIGEST'):
+ urlpatterns += notification_prefs_urls
+
urlpatterns += [
url(r'^bulk_email/', include('bulk_email.urls')),
]
@@ -804,7 +797,6 @@ if configuration_helpers.get_value('ENABLE_BULK_ENROLLMENT_VIEW', settings.FEATU
url(r'^api/bulk_enroll/v1/', include('bulk_enroll.urls')),
]
-
# Shopping cart
urlpatterns += [
url(r'^shoppingcart/', include('shoppingcart.urls')),
@@ -842,7 +834,6 @@ if settings.FEATURES.get('ENABLE_OAUTH2_PROVIDER'):
url(r'^_o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
]
-
if settings.FEATURES.get('ENABLE_SERVICE_STATUS'):
urlpatterns += [
url(r'^status/', include('openedx.core.djangoapps.service_status.urls')),
@@ -866,7 +857,6 @@ urlpatterns += [
url(r'^debug/show_parameters$', debug_views.show_parameters),
]
-
# Third-party auth.
if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
urlpatterns += [
@@ -948,6 +938,7 @@ urlpatterns += [
if 'debug_toolbar' in settings.INSTALLED_APPS:
import debug_toolbar
+
urlpatterns += [
url(r'^__debug__/', include(debug_toolbar.urls)),
]