Add switch to disable forum digest in prod.
This commit is contained in:
@@ -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)
|
||||
|
||||
39
lms/djangoapps/discussion/config/waffle.py
Normal file
39
lms/djangoapps/discussion/config/waffle.py
Normal file
@@ -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()
|
||||
@@ -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()
|
||||
|
||||
@@ -44,19 +44,21 @@
|
||||
<span class="row-description"><%- gettext("Follow or unfollow posts") %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="helpgrid-row helpgrid-row-notification">
|
||||
<th scope="row" class="row-title"><%- gettext('Receive updates') %></td>
|
||||
<td class="row-item-full" colspan="3">
|
||||
<label for="email-setting-checkbox">
|
||||
<span class="sr"><%- gettext("Toggle Notifications Setting") %></span>
|
||||
<span class="notification-checkbox">
|
||||
<input type="checkbox" id="email-setting-checkbox" class="email-setting" name="email-notification"/>
|
||||
<span class="icon fa fa-envelope" aria-hidden="true"></span>
|
||||
</span>
|
||||
</label>
|
||||
<span class="row-description"><%- gettext("Check this box to receive an email digest once a day notifying you about new, unread activity from posts you are following.") %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% if (window.ENABLE_FORUM_DAILY_DIGEST) {%>
|
||||
<tr class="helpgrid-row helpgrid-row-notification">
|
||||
<th scope="row" class="row-title"><%- gettext('Receive updates') %></td>
|
||||
<td class="row-item-full" colspan="3">
|
||||
<label for="email-setting-checkbox">
|
||||
<span class="sr"><%- gettext("Toggle Notifications Setting") %></span>
|
||||
<span class="notification-checkbox">
|
||||
<input type="checkbox" id="email-setting-checkbox" class="email-setting" name="email-notification"/>
|
||||
<span class="icon fa fa-envelope" aria-hidden="true"></span>
|
||||
</span>
|
||||
</label>
|
||||
<span class="row-description"><%- gettext("Check this box to receive an email digest once a day notifying you about new, unread activity from posts you are following.") %></span>
|
||||
</td>
|
||||
</tr>
|
||||
<% } %>
|
||||
</table>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
%>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.PLATFORM_NAME = "${settings.PLATFORM_NAME | n, js_escaped_string}";
|
||||
% if settings.FEATURES.get('ENABLE_DISCUSSION_HOME_PANEL', False):
|
||||
% if enable_discussion_home_panel:
|
||||
window.ENABLE_DISCUSSION_HOME_PANEL = true;
|
||||
% else:
|
||||
window.ENABLE_DISCUSSION_HOME_PANEL = false;
|
||||
% endif
|
||||
|
||||
% if enable_daily_digest:
|
||||
window.ENABLE_FORUM_DAILY_DIGEST = true;
|
||||
% else:
|
||||
window.ENABLE_FORUM_DAILY_DIGEST = false;
|
||||
% endif
|
||||
|
||||
</script>
|
||||
<%static:include path="common/templates/discussion/templates.underscore" />
|
||||
|
||||
79
lms/urls.py
79
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<token>[a-zA-Z0-9-_=]+)/',
|
||||
notification_prefs_views.set_subscription,
|
||||
{'subscribe': False},
|
||||
name='unsubscribe_forum_update',
|
||||
),
|
||||
url(
|
||||
r'^notification_prefs/resubscribe/(?P<token>[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<token>[a-zA-Z0-9-_=]+)/',
|
||||
notification_prefs_views.set_subscription,
|
||||
{
|
||||
'subscribe': False,
|
||||
},
|
||||
name='unsubscribe_forum_update',
|
||||
),
|
||||
url(
|
||||
r'^notification_prefs/resubscribe/(?P<token>[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)),
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user