From 4a56fa5fb19c64e3788cdabd8bc5a5278bbe9d57 Mon Sep 17 00:00:00 2001
From: Nimisha Asthagiri <nasthagiri@edx.org>
Date: Mon, 29 Feb 2016 15:12:45 -0500
Subject: [PATCH] Adding infrastructure to support context-sensitive help links
 in the LMS.

---
 .../contentstore/context_processors.py        | 72 ++--------------
 .../djangoapps/util/help_context_processor.py | 85 +++++++++++++++++++
 docs/{config.ini => cms_config.ini}           |  0
 docs/lms_config.ini                           | 43 ++++++++++
 lms/djangoapps/context_processors.py          | 28 ++++++
 lms/envs/common.py                            |  3 +
 lms/templates/course.html                     |  1 +
 lms/templates/courseware/courseware.html      |  1 +
 lms/templates/courseware/info.html            |  1 +
 lms/templates/courseware/progress.html        |  1 +
 lms/templates/dashboard.html                  |  1 +
 lms/templates/header.html                     |  4 +-
 .../instructor_dashboard_2.html               |  1 +
 lms/templates/main.html                       |  4 +-
 lms/templates/main_django.html                |  2 +-
 lms/templates/navigation.html                 |  3 +-
 .../student_account/account_settings.html     |  1 +
 .../student_profile/learner_profile.html      |  1 +
 lms/templates/wiki/base.html                  |  2 +
 19 files changed, 185 insertions(+), 69 deletions(-)
 create mode 100644 common/djangoapps/util/help_context_processor.py
 rename docs/{config.ini => cms_config.ini} (100%)
 create mode 100644 docs/lms_config.ini
 create mode 100644 lms/djangoapps/context_processors.py

diff --git a/cms/djangoapps/contentstore/context_processors.py b/cms/djangoapps/contentstore/context_processors.py
index e9811c8be3e..082e52c6541 100644
--- a/cms/djangoapps/contentstore/context_processors.py
+++ b/cms/djangoapps/contentstore/context_processors.py
@@ -1,16 +1,16 @@
-
+"""
+Django Template Context Processor for CMS Online Contextual Help
+"""
 import ConfigParser
 from django.conf import settings
-import logging
-
 
-log = logging.getLogger(__name__)
+from util.help_context_processor import common_doc_url
 
 
 # Open and parse the configuration file when the module is initialized
-config_file = open(settings.REPO_ROOT / "docs" / "config.ini")
-config = ConfigParser.ConfigParser()
-config.readfp(config_file)
+CONFIG_FILE = open(settings.REPO_ROOT / "docs" / "cms_config.ini")
+CONFIG = ConfigParser.ConfigParser()
+CONFIG.readfp(CONFIG_FILE)
 
 
 def doc_url(request=None):  # pylint: disable=unused-argument
@@ -25,60 +25,4 @@ def doc_url(request=None):  # pylint: disable=unused-argument
         request: Currently not used, but is passed by django to context processors.
             May be used in the future for determining the language of choice.
     """
-
-    def get_online_help_info(page_token=None):
-        """
-        Args:
-            page_token: A string that identifies the page for which the help information is requested.
-                It should correspond to an option in the docs/config.ini file.  If it doesn't, the "default"
-                option is used instead.
-
-        Returns:
-            A dict mapping the following items
-                * "doc_url" - a string with the url corresponding to the online help location for the given page_token.
-                * "pdf_url" - a string with the url corresponding to the location of the PDF help file.
-        """
-
-        def get_config_value_with_default(section_name, option, default_option="default"):
-            """
-            Args:
-                section_name: name of the section in the configuration from which the option should be found
-                option: name of the configuration option
-                default_option: name of the default configuration option whose value should be returned if the
-                    requested option is not found
-            """
-            try:
-                return config.get(section_name, option)
-            except (ConfigParser.NoOptionError, AttributeError):
-                log.debug("Didn't find a configuration option for '%s' section and '%s' option", section_name, option)
-                return config.get(section_name, default_option)
-
-        def get_doc_url():
-            """
-            Returns:
-                The URL for the documentation
-            """
-            return "{url_base}/{language}/{version}/{page_path}".format(
-                url_base=config.get("help_settings", "url_base"),
-                language=get_config_value_with_default("locales", settings.LANGUAGE_CODE),
-                version=config.get("help_settings", "version"),
-                page_path=get_config_value_with_default("pages", page_token),
-            )
-
-        def get_pdf_url():
-            """
-            Returns:
-                The URL for the PDF document using the pdf_settings and the help_settings (version) in the configuration
-            """
-            return "{pdf_base}/{version}/{pdf_file}".format(
-                pdf_base=config.get("pdf_settings", "pdf_base"),
-                version=config.get("help_settings", "version"),
-                pdf_file=config.get("pdf_settings", "pdf_file"),
-            )
-
-        return {
-            "doc_url": get_doc_url(),
-            "pdf_url": get_pdf_url(),
-        }
-
-    return {'get_online_help_info': get_online_help_info}
+    return common_doc_url(request, CONFIG)
diff --git a/common/djangoapps/util/help_context_processor.py b/common/djangoapps/util/help_context_processor.py
new file mode 100644
index 00000000000..5b037d8e131
--- /dev/null
+++ b/common/djangoapps/util/help_context_processor.py
@@ -0,0 +1,85 @@
+"""
+Common functionality for Django Template Context Processor for
+Online Contextual Help.
+"""
+
+import ConfigParser
+from django.conf import settings
+import logging
+
+
+log = logging.getLogger(__name__)
+
+
+def common_doc_url(request, config_file_object):  # pylint: disable=unused-argument
+    """
+    This function is added in the list of TEMPLATES 'context_processors' OPTION, which is a django setting for
+    a tuple of callables that take a request object as their argument and return a dictionary of items
+    to be merged into the RequestContext.
+
+    This function returns a dict with get_online_help_info, making it directly available to all mako templates.
+
+    Args:
+        request: Currently not used, but is passed by django to context processors.
+            May be used in the future for determining the language of choice.
+        config_file_object: Configuration file object.
+    """
+
+    def get_online_help_info(page_token=None):
+        """
+        Args:
+            page_token: A string that identifies the page for which the help information is requested.
+                It should correspond to an option in the docs/config_file_object.ini file.  If it doesn't, the "default"
+                option is used instead.
+
+        Returns:
+            A dict mapping the following items
+                * "doc_url" - a string with the url corresponding to the online help location for the given page_token.
+                * "pdf_url" - a string with the url corresponding to the location of the PDF help file.
+        """
+
+        def get_config_value_with_default(section_name, option, default_option="default"):
+            """
+            Args:
+                section_name: name of the section in the configuration from which the option should be found
+                option: name of the configuration option
+                default_option: name of the default configuration option whose value should be returned if the
+                    requested option is not found
+            """
+            if option:
+                try:
+                    return config_file_object.get(section_name, option)
+                except (ConfigParser.NoOptionError, AttributeError):
+                    log.debug("Didn't find a configuration option for '%s' section and '%s' option",
+                              section_name, option)
+            return config_file_object.get(section_name, default_option)
+
+        def get_doc_url():
+            """
+            Returns:
+                The URL for the documentation
+            """
+            return "{url_base}/{language}/{version}/{page_path}".format(
+                url_base=config_file_object.get("help_settings", "url_base"),
+                language=get_config_value_with_default("locales", settings.LANGUAGE_CODE),
+                version=config_file_object.get("help_settings", "version"),
+                page_path=get_config_value_with_default("pages", page_token),
+            )
+
+        def get_pdf_url():
+            """
+            Returns:
+                The URL for the PDF document using the pdf_settings and the help_settings (version) in the configuration
+            """
+            return "{pdf_base}/{version}/{pdf_file}".format(
+                pdf_base=config_file_object.get("pdf_settings", "pdf_base"),
+                version=config_file_object.get("help_settings", "version"),
+                pdf_file=config_file_object.get("pdf_settings", "pdf_file"),
+            )
+
+        return {
+            "doc_url": get_doc_url(),
+            "pdf_url": get_pdf_url(),
+        }
+
+    return {'get_online_help_info': get_online_help_info}
diff --git a/docs/config.ini b/docs/cms_config.ini
similarity index 100%
rename from docs/config.ini
rename to docs/cms_config.ini
diff --git a/docs/lms_config.ini b/docs/lms_config.ini
new file mode 100644
index 00000000000..c5ddfa305ef
--- /dev/null
+++ b/docs/lms_config.ini
@@ -0,0 +1,43 @@
+# below are the server-wide settings for documentation
+[help_settings]
+url_base = http://edx.readthedocs.io/projects/open-edx-learner-guide
+version = latest
+
+
+# below are the pdf settings for the pdf file
+[pdf_settings]
+pdf_base = https://media.readthedocs.io/pdf/open-edx-learner-guide
+pdf_file = open-edx-learner-guide.pdf
+
+
+# below are the sub-paths to the documentation for the various pages
+# NOTE: If any of these page settings change, then their corresponding test should be updated
+#       in edx-platform/cms/djangoapps/contentstore/features/help.feature
+[pages]
+default = index.html
+
+
+instructor = set_up_course/creating_course_certificates.html
+
+course = set_up_course/creating_course_certificates.html
+
+profile = sfd_dashboard_profile/index.html
+
+dashboard = sfd_dashboard_profile/index.html
+
+courseinfo = SFD_introduction.html
+
+progress = SFD_check_progress.html
+
+learneraccountsettings = sfd_dashboard_profile/SFD_dashboard_settings_profile.html#exploring-the-account-settings-page
+
+learnerdashboard = sfd_dashboard_profile/SFD_dashboard_settings_profile.html#exploring-the-learner-dashboard
+
+bookmarks = SFD_bookmarks.html
+
+
+# below are the language directory names for the different locales
+[locales]
+default = en
+en = en
+en_us = en
diff --git a/lms/djangoapps/context_processors.py b/lms/djangoapps/context_processors.py
new file mode 100644
index 00000000000..86e47a5b194
--- /dev/null
+++ b/lms/djangoapps/context_processors.py
@@ -0,0 +1,28 @@
+"""
+Django Template Context Processor for LMS Online Contextual Help
+"""
+import ConfigParser
+from django.conf import settings
+
+from util.help_context_processor import common_doc_url
+
+
+# Open and parse the configuration file when the module is initialized
+CONFIG_FILE = open(settings.REPO_ROOT / "docs" / "lms_config.ini")
+CONFIG = ConfigParser.ConfigParser()
+CONFIG.readfp(CONFIG_FILE)
+
+
+def doc_url(request=None):  # pylint: disable=unused-argument
+    """
+    This function is added in the list of TEMPLATES 'context_processors' OPTION, which is a django setting for
+    a tuple of callables that take a request object as their argument and return a dictionary of items
+    to be merged into the RequestContext.
+
+    This function returns a dict with get_online_help_info, making it directly available to all mako templates.
+
+    Args:
+        request: Currently not used, but is passed by django to context processors.
+            May be used in the future for determining the language of choice.
+    """
+    return common_doc_url(request, CONFIG)
diff --git a/lms/envs/common.py b/lms/envs/common.py
index c12fa134ddc..791834a369f 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -514,6 +514,9 @@ TEMPLATES = [
 
                 # Allows the open edX footer to be leveraged in Django Templates.
                 'edxmako.shortcuts.microsite_footer_context_processor',
+
+                # Online contextual help
+                'context_processors.doc_url',
             ],
             # Change 'debug' in your environment settings files - not here.
             'debug': False
diff --git a/lms/templates/course.html b/lms/templates/course.html
index a7f31ba4d34..25f739a8c68 100644
--- a/lms/templates/course.html
+++ b/lms/templates/course.html
@@ -1,3 +1,4 @@
+<%def name="online_help_token()"><% return "course" %></%def>
 <%namespace name='static' file='static_content.html'/>
 <%!
 from django.utils.translation import ugettext as _
diff --git a/lms/templates/courseware/courseware.html b/lms/templates/courseware/courseware.html
index f5a4e90c42b..8c4fd74ae36 100644
--- a/lms/templates/courseware/courseware.html
+++ b/lms/templates/courseware/courseware.html
@@ -1,6 +1,7 @@
 <%page expression_filter="h"/>
 <%inherit file="/main.html" />
 <%namespace name='static' file='/static_content.html'/>
+<%def name="online_help_token()"><% return "courseware" %></%def>
 <%!
 from django.utils.translation import ugettext as _
 from django.conf import settings
diff --git a/lms/templates/courseware/info.html b/lms/templates/courseware/info.html
index d57fbd9d70b..93e479bb744 100644
--- a/lms/templates/courseware/info.html
+++ b/lms/templates/courseware/info.html
@@ -1,5 +1,6 @@
 <%page expression_filter="h"/>
 <%inherit file="../main.html" />
+<%def name="online_help_token()"><% return "courseinfo" %></%def>
 <%namespace name='static' file='../static_content.html'/>
 <%!
 from django.utils.translation import ugettext as _
diff --git a/lms/templates/courseware/progress.html b/lms/templates/courseware/progress.html
index 43e462f3323..e930b1f5faa 100644
--- a/lms/templates/courseware/progress.html
+++ b/lms/templates/courseware/progress.html
@@ -1,5 +1,6 @@
 <%inherit file="/main.html" />
 <%namespace name='static' file='/static_content.html'/>
+<%def name="online_help_token()"><% return "progress" %></%def>
 <%!
 from django.utils.translation import ugettext as _
 from django.core.urlresolvers import reverse
diff --git a/lms/templates/dashboard.html b/lms/templates/dashboard.html
index ca299fb804d..7f0d7761442 100644
--- a/lms/templates/dashboard.html
+++ b/lms/templates/dashboard.html
@@ -1,5 +1,6 @@
 <%page expression_filter="h"/>
 <%inherit file="main.html" />
+<%def name="online_help_token()"><% return "learnerdashboard" %></%def>
 <%namespace name='static' file='static_content.html'/>
 <%!
 from django.core.urlresolvers import reverse
diff --git a/lms/templates/header.html b/lms/templates/header.html
index e62672d3733..5b07e9f1c76 100644
--- a/lms/templates/header.html
+++ b/lms/templates/header.html
@@ -1,4 +1,4 @@
 ## mako
-<%page expression_filter="h"/>
+<%page expression_filter="h" args="online_help_token"/>
 <%namespace name='static' file='static_content.html'/>
-<%include file="${static.get_themed_template_path(relative_path='theme-header.html', default_path='navigation.html')}" />
+<%include file="${static.get_themed_template_path(relative_path='theme-header.html', default_path='navigation.html')}"  args="online_help_token=online_help_token"  />
diff --git a/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html b/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html
index 8a60cc1a04c..62974d8d348 100644
--- a/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html
+++ b/lms/templates/instructor/instructor_dashboard_2/instructor_dashboard_2.html
@@ -1,5 +1,6 @@
 <%inherit file="/main.html" />
 <%namespace name='static' file='/static_content.html'/>
+<%def name="online_help_token()"><% return "instructor" %></%def>
 <%!
 from django.utils.translation import ugettext as _
 from django.core.urlresolvers import reverse
diff --git a/lms/templates/main.html b/lms/templates/main.html
index 9977348fcc8..61848b87f24 100644
--- a/lms/templates/main.html
+++ b/lms/templates/main.html
@@ -11,6 +11,7 @@
 
 
 <%namespace name='static' file='static_content.html'/>
+<% online_help_token = self.online_help_token() if hasattr(self, 'online_help_token') else None %>
 <%!
 from django.core.urlresolvers import reverse
 from django.utils.http import urlquote_plus
@@ -122,6 +123,7 @@ from pipeline_mako import render_require_js_path_overrides
 </head>
 
 <body class="${static.dir_rtl()} <%block name='bodyclass'/> lang_${LANGUAGE_CODE}">
+
 <%static:optional_include_mako file="body-initial.html" is_theming_enabled="True" />
 <div id="page-prompt"></div>
 % if not disable_window_wrap:
@@ -130,7 +132,7 @@ from pipeline_mako import render_require_js_path_overrides
     <a class="nav-skip" href="#main">${_("Skip to main content")}</a>
 
     % if not disable_header:
-        <%include file="${static.get_template_path('header.html')}" />
+        <%include file="${static.get_template_path('header.html')}" args="online_help_token=online_help_token" />
     % endif
 
     <div class="content-wrapper" id="content">
diff --git a/lms/templates/main_django.html b/lms/templates/main_django.html
index e2d5233ba94..932ecdf3aed 100644
--- a/lms/templates/main_django.html
+++ b/lms/templates/main_django.html
@@ -30,7 +30,7 @@
   <div class="window-wrap" dir="{{LANGUAGE_BIDI|yesno:'rtl,ltr'}}">
     <a class="nav-skip" href="#main">{% trans "Skip to main content" %}</a>
     {% with course=request.course %}
-      {% include "header.html"|microsite_template_path %}
+      {% include "header.html"|microsite_template_path with online_help_token=online_help_token  %}
     {% endwith %}
     <div class="content-wrapper" id="content">
       {% block body %}{% endblock %}
diff --git a/lms/templates/navigation.html b/lms/templates/navigation.html
index ebe92f1c3ff..785e16631d5 100644
--- a/lms/templates/navigation.html
+++ b/lms/templates/navigation.html
@@ -1,11 +1,12 @@
 ## mako
-<%page expression_filter="h"/>
+<%page expression_filter="h" args="online_help_token"/>
 <%namespace name='static' file='static_content.html'/>
 <%namespace file='main.html' import="login_query"/>
 <%!
 from django.core.urlresolvers import reverse
 from django.utils.translation import ugettext as _
 
+from context_processors import doc_url
 from lms.djangoapps.ccx.overrides import get_current_ccx
 from microsite_configuration import microsite
 from microsite_configuration.templatetags.microsite import platform_name
diff --git a/lms/templates/student_account/account_settings.html b/lms/templates/student_account/account_settings.html
index 723a6d4c928..5580a9b0ed1 100644
--- a/lms/templates/student_account/account_settings.html
+++ b/lms/templates/student_account/account_settings.html
@@ -13,6 +13,7 @@ from openedx.core.djangolib.js_utils import dump_js_escaped_json, js_escaped_str
 <!--<%namespace name='static' file='/static_content.html'/>-->
 
 <%inherit file="/main.html" />
+<%def name="online_help_token()"><% return "learneraccountsettings" %></%def>
 <%namespace name='static' file='/static_content.html'/>
 
 <%block name="pagetitle">${_("Account Settings")}</%block>
diff --git a/lms/templates/student_profile/learner_profile.html b/lms/templates/student_profile/learner_profile.html
index 8f974357004..1f5e5a2f580 100644
--- a/lms/templates/student_profile/learner_profile.html
+++ b/lms/templates/student_profile/learner_profile.html
@@ -1,5 +1,6 @@
 <%page expression_filter="h"/>
 <%inherit file="/main.html" />
+<%def name="online_help_token()"><% return "profile" %></%def>
 <%namespace name='static' file='/static_content.html'/>
 <%!
 import json
diff --git a/lms/templates/wiki/base.html b/lms/templates/wiki/base.html
index 2a9c69fed97..fe6112a369a 100644
--- a/lms/templates/wiki/base.html
+++ b/lms/templates/wiki/base.html
@@ -1,4 +1,5 @@
 {% extends "main_django.html" %}
+{% with online_help_token="wiki" %}
 {% load pipeline %}{% load sekizai_tags i18n microsite %}{% load url from future %}{% load staticfiles %}
 
 {% block title %}<title>{% block pagetitle %}{% endblock %} | {% trans "Wiki" %} | {% platform_name %}</title>{% endblock %}
@@ -78,3 +79,4 @@
 </main>
 
 {% endblock %}
+{% endwith %}
-- 
GitLab