From 1773107db40812d72b8287ddeb8e33f3b108c323 Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Tue, 20 Mar 2018 15:56:57 -0400 Subject: [PATCH 1/2] Maintenance banner functionality, including a new waffle switch and setting This adds the following new waffle switch (and namespace): open_edx_util.display_maintenance_warning and a new setting: settings.MAINTENANCE_BANNER_TEXT The provided view decorator allows developers to select which views receive the static banner, and the banner can be globally toggled via the waffle switch. The text of the banner is determined by the setting, which is currently not translated. --- .../djangoapps/util/maintenance_banner.py | 43 +++++++++++++++++++ openedx/core/djangoapps/util/waffle.py | 18 ++++++++ 2 files changed, 61 insertions(+) create mode 100644 openedx/core/djangoapps/util/maintenance_banner.py create mode 100644 openedx/core/djangoapps/util/waffle.py diff --git a/openedx/core/djangoapps/util/maintenance_banner.py b/openedx/core/djangoapps/util/maintenance_banner.py new file mode 100644 index 0000000000..cab008e0ec --- /dev/null +++ b/openedx/core/djangoapps/util/maintenance_banner.py @@ -0,0 +1,43 @@ +""" +View decorator to add a maintenance banner configured in settings. +""" +from __future__ import absolute_import + +from functools import wraps + +from django.conf import settings + +from openedx.core.djangoapps.util.user_messages import PageLevelMessages +from openedx.core.djangoapps.util.waffle import DISPLAY_MAINTENANCE_WARNING, waffle + + +def add_maintenance_banner(func): + """ + View decorator to select where exactly the banner will appear + + Add to function-based views like this: + + from openedx.core.djangoapps.util.maintenance_banner import add_maintenance_banner + + @add_maintenance_banner + def my_view(request): + ... + + Add to class-based views using method_decorator: + + from openedx.core.djangoapps.util.maintenance_banner import add_maintenance_banner + from django.utils.decorators import method_decorator + + @method_decorator(add_maintenance_banner, name='dispatch') + class MyView(View): + ... + """ + @wraps(func) + def _decorated(request, *args, **kwargs): # pylint: disable=missing-docstring + if waffle().is_enabled(DISPLAY_MAINTENANCE_WARNING): + if hasattr(settings, 'EDXAPP_MAINTENANCE_BANNER_TEXT') and settings.EDXAPP_MAINTENANCE_BANNER_TEXT: + # The waffle switch is enabled and the banner text is defined + # and non-empty. We can now register the message: + PageLevelMessages.register_warning_message(request, settings.EDXAPP_MAINTENANCE_BANNER_TEXT) + return func(request, *args, **kwargs) + return _decorated diff --git a/openedx/core/djangoapps/util/waffle.py b/openedx/core/djangoapps/util/waffle.py new file mode 100644 index 0000000000..1823041fdc --- /dev/null +++ b/openedx/core/djangoapps/util/waffle.py @@ -0,0 +1,18 @@ +""" +Waffle flags and switches +""" +from __future__ import absolute_import + +from openedx.core.djangoapps.waffle_utils import WaffleSwitchNamespace + +WAFFLE_NAMESPACE = u'open_edx_util' + +# Switches +DISPLAY_MAINTENANCE_WARNING = u'display_maintenance_warning' + + +def waffle(): + """ + Returns the namespaced, cached, audited Waffle class for open_edx_util. + """ + return WaffleSwitchNamespace(name=WAFFLE_NAMESPACE, log_prefix=u'OpenEdX Util: ') From 9afe485f448a022d39bd8a393759db34a95efbae Mon Sep 17 00:00:00 2001 From: Troy Sankey Date: Tue, 20 Mar 2018 16:01:27 -0400 Subject: [PATCH 2/2] add the maintenance banner to the student dashboard and course homepage --- common/djangoapps/student/views/dashboard.py | 2 ++ openedx/features/course_experience/views/course_home.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/common/djangoapps/student/views/dashboard.py b/common/djangoapps/student/views/dashboard.py index d16b598224..4b81553c6f 100644 --- a/common/djangoapps/student/views/dashboard.py +++ b/common/djangoapps/student/views/dashboard.py @@ -38,6 +38,7 @@ from openedx.core.djangoapps.credit.email_utils import get_credit_provider_displ from openedx.core.djangoapps.programs.models import ProgramsApiConfig from openedx.core.djangoapps.programs.utils import ProgramDataExtender, ProgramProgressMeter from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers +from openedx.core.djangoapps.util.maintenance_banner import add_maintenance_banner from openedx.core.djangoapps.waffle_utils import WaffleFlag, WaffleFlagNamespace from openedx.features.enterprise_support.api import get_dashboard_consent_notification from shoppingcart.api import order_history @@ -527,6 +528,7 @@ def _get_urls_for_resume_buttons(user, enrollments): @login_required @ensure_csrf_cookie +@add_maintenance_banner def student_dashboard(request): """ Provides the LMS dashboard view diff --git a/openedx/features/course_experience/views/course_home.py b/openedx/features/course_experience/views/course_home.py index 48abb63e68..8d1d45b0ff 100644 --- a/openedx/features/course_experience/views/course_home.py +++ b/openedx/features/course_experience/views/course_home.py @@ -24,6 +24,7 @@ from lms.djangoapps.course_goals.api import ( from lms.djangoapps.courseware.exceptions import CourseAccessRedirect from lms.djangoapps.courseware.views.views import CourseTabView from openedx.core.djangoapps.plugin_api.views import EdxFragmentView +from openedx.core.djangoapps.util.maintenance_banner import add_maintenance_banner from openedx.features.course_experience.course_tools import CourseToolsPluginManager from student.models import CourseEnrollment from util.views import ensure_valid_course_key @@ -48,6 +49,7 @@ class CourseHomeView(CourseTabView): @method_decorator(ensure_csrf_cookie) @method_decorator(cache_control(no_cache=True, no_store=True, must_revalidate=True)) @method_decorator(ensure_valid_course_key) + @method_decorator(add_maintenance_banner) def get(self, request, course_id, **kwargs): """ Displays the home page for the specified course.