Commit 70d8c5c2 by Anthony Mangano

update footer endpoint in branding api to support inclusion of language selector

parent aa4eba33
......@@ -3,6 +3,7 @@
import json
import urllib
from django.test import TestCase
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.conf import settings
......@@ -10,6 +11,8 @@ import mock
import ddt
from config_models.models import cache
from branding.models import BrandingApiConfig
from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
from openedx.core.djangoapps.lang_pref.api import released_languages
from openedx.core.djangoapps.site_configuration.tests.mixins import SiteMixin
from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme_context
from student.tests.factories import UserFactory
......@@ -208,6 +211,38 @@ class TestFooter(TestCase):
else:
self.assertNotIn("vendor", resp.content)
@ddt.data(
# OpenEdX
(None, None, '1'),
(None, 'eo', '1'),
(None, None, ''),
# EdX.org
('edx.org', None, '1'),
('edx.org', 'eo', '1'),
('edx.org', None, '')
)
@ddt.unpack
def test_include_language_selector(self, theme, language, include_language_selector):
self._set_feature_flag(True)
DarkLangConfig(released_languages='en,eo,es-419,fr', enabled=True, changed_by=User().save()).save()
with with_comprehensive_theme_context(theme):
params = {
key: val for key, val in [
('language', language), ('include-language-selector', include_language_selector)
] if val
}
resp = self._get_footer(accepts="text/html", params=params)
self.assertEqual(resp.status_code, 200)
if include_language_selector:
selected_language = language if language else 'en'
self._verify_language_selector(resp.content, selected_language)
else:
self.assertNotIn('footer-language-selector', resp.content)
def test_no_supported_accept_type(self):
self._set_feature_flag(True)
resp = self._get_footer(accepts="application/x-shockwave-flash")
......@@ -230,6 +265,20 @@ class TestFooter(TestCase):
return self.client.get(url, HTTP_ACCEPT=accepts)
def _verify_language_selector(self, content, selected_language):
""" Verify that the language selector is present and correctly configured."""
# Verify the selector is included
self.assertIn('footer-language-selector', content)
# Verify the correct language is selected
self.assertIn('<option value="{}" selected="selected">'.format(selected_language), content)
# Verify the language choices
for language in released_languages():
if language.code == selected_language:
continue
self.assertIn('<option value="{}">'.format(language.code), content)
class TestIndex(SiteMixin, TestCase):
""" Test the index view """
......
......@@ -20,6 +20,7 @@ from edxmako.shortcuts import marketing_link
from util.cache import cache_if_anonymous
from util.json_request import JsonResponse
import branding.api as branding_api
from openedx.core.djangoapps.lang_pref.api import released_languages
from openedx.core.djangoapps.site_configuration import helpers as configuration_helpers
log = logging.getLogger(__name__)
......@@ -122,12 +123,13 @@ def _footer_css_urls(request, package_name):
]
def _render_footer_html(request, show_openedx_logo, include_dependencies):
def _render_footer_html(request, show_openedx_logo, include_dependencies, include_language_selector):
"""Render the footer as HTML.
Arguments:
show_openedx_logo (bool): If True, include the OpenEdX logo in the rendered HTML.
include_dependencies (bool): If True, include JavaScript and CSS dependencies.
include_language_selector (bool): If True, include a language selector with all supported languages.
Returns: unicode
......@@ -141,6 +143,7 @@ def _render_footer_html(request, show_openedx_logo, include_dependencies):
'footer_css_urls': _footer_css_urls(request, css_name),
'bidi': bidi,
'include_dependencies': include_dependencies,
'include_language_selector': include_language_selector
}
return render_to_response("footer.html", context)
......@@ -235,6 +238,13 @@ def footer(request):
GET /api/branding/v1/footer?language=en
Accepts: text/html
Example: Retrieving the footer with a language selector
GET /api/branding/v1/footer?include-language-selector=1
Accepts: text/html
Example: Retrieving the footer with all JS and CSS dependencies (for testing)
GET /api/branding/v1/footer?include-dependencies=1
......@@ -261,19 +271,26 @@ def footer(request):
except LookupError:
language = settings.LANGUAGE_CODE
# Include a language selector
include_language_selector = request.GET.get('include-language-selector', '') == '1'
# Render the footer information based on the extension
if 'text/html' in accepts or '*/*' in accepts:
cache_key = u"branding.footer.{params}.html".format(
params=urllib.urlencode({
'language': language,
'show_openedx_logo': show_openedx_logo,
'include_dependencies': include_dependencies,
})
)
cache_params = {
'language': language,
'show_openedx_logo': show_openedx_logo,
'include_dependencies': include_dependencies
}
if include_language_selector:
cache_params['language_selector_options'] = ','.join(sorted([lang.code for lang in released_languages()]))
cache_key = u"branding.footer.{params}.html".format(params=urllib.urlencode(cache_params))
content = cache.get(cache_key)
if content is None:
with translation.override(language):
content = _render_footer_html(request, show_openedx_logo, include_dependencies)
content = _render_footer_html(
request, show_openedx_logo, include_dependencies, include_language_selector
)
cache.set(cache_key, content, settings.FOOTER_CACHE_TIMEOUT)
return HttpResponse(content, status=200, content_type="text/html; charset=utf-8")
......
......@@ -55,8 +55,8 @@ p {
}
span {
font: inherit;
color: inherit;
font: inherit;
}
/* Fix for CodeMirror: prevent top-level span from affecting deeply-embedded span in CodeMirror */
......
......@@ -33,6 +33,10 @@ footer#footer-edx-v3 {
font-family: $sans-serif;
}
.copyright {
margin-top: 30px;
}
.site-nav,
.legal-notices {
li {
......@@ -68,7 +72,7 @@ footer#footer-edx-v3 {
}
.legal-notices {
margin: 20px 0 30px;
margin: 20px 0;
}
.openedx-link {
......@@ -89,7 +93,7 @@ footer#footer-edx-v3 {
.social-media-links,
.mobile-app-links {
@extend %ui-no-list;
.list-item {
display: inline-block;
}
......@@ -107,6 +111,12 @@ footer#footer-edx-v3 {
margin-bottom: 30px;
}
.icon {
font-family: 'FontAwesome';
font-style: normal;
color: $edx-footer-link-color;
}
a.sm-link {
@include float(left);
@include margin(0, 0, 10px, 10px);
......@@ -129,11 +139,6 @@ footer#footer-edx-v3 {
opacity: 0.7;
border: none;
}
.icon {
font-family: 'FontAwesome';
color: $edx-footer-link-color;
}
}
.app-link {
......@@ -208,4 +213,13 @@ footer#footer-edx-v3 {
margin-bottom: 50px;
}
}
.footer-language-selector {
margin: 20px 0;
label[for=footer-language-select] {
display: inline-block;
cursor: initial;
}
}
}
......@@ -37,6 +37,11 @@
}
}
.icon {
font-family: 'FontAwesome';
font-style: normal;
}
// colophon
.colophon {
@include span-columns(8);
......@@ -186,6 +191,13 @@
}
}
}
.footer-language-selector {
label[for=footer-language-select] {
display: inline-block;
cursor: initial;
}
}
}
// edx theme overrides
......
......@@ -28,6 +28,10 @@
</ol>
</nav>
% if include_language_selector:
<%include file="widgets/footer-language-selector.html"/>
% endif
<div class="wrapper-logo">
<p>
<a href="/">
......
## Language-selection widget for the footer.
##
## Requires settings.LANGUAGE_COOKIE.
<%page expression_filter="h"/>
<%!
from babel import Locale
from django.conf import settings
from django.utils.translation import ugettext as _
from openedx.core.djangoapps.lang_pref import COOKIE_DURATION
from openedx.core.djangoapps.lang_pref.api import released_languages
from openedx.core.djangolib.js_utils import js_escaped_string
# Make sure LANGUAGE_COOKIE is present.
if not settings.LANGUAGE_COOKIE:
raise ValueError('settings.LANGUAGE_COOKIE is required to use footer-language-selector.')
%>
<div class="footer-language-selector">
<label for="footer-language-select">
<span class="icon fa fa-globe" aria-hidden="true"></span>
<span class="sr">${_("Choose Language")}</span>
</label>
<select id="footer-language-select" name="language" onchange="footerLanguageSelector.handleSelection(this)">
% for language in sorted(released_languages(), key=lambda x: x.code):
<% language_name = Locale.parse(language.code.replace('_', '-'), sep='-').language_name %>
% if language.code == LANGUAGE_CODE:
<option value="${language.code}" selected="selected">${language_name}</option>
% else:
<option value="${language.code}">${language_name}</option>
% endif
% endfor
</select>
</div>
<script type="text/javascript">
window.footerLanguageSelector = {
##
## Set the language cookie using the same settings as
## https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/lang_pref/views.py#L26
## and
## https://github.com/edx/edx-platform/blob/master/openedx/core/djangoapps/lang_pref/middleware.py#63
## Then refresh the page so that the language negotiation middleware can read it and re-render everything
## in the selected language.
##
## NOTE: For logged-in users, the LMS language negotiation middleware should persist the selected language
## preference to the user's profile. This effect may be delayed on pages that do not use the LMS language
## selection middleware.
##
handleSelection: function($select) {
this.setLanguageCookie($select.value, this.refreshPage);
},
setLanguageCookie: function(value, callback) {
var cookie = '${settings.LANGUAGE_COOKIE | n, js_escaped_string}=' + value + ';path=/';
% if settings.SESSION_COOKIE_DOMAIN:
cookie += ';domain=${settings.SESSION_COOKIE_DOMAIN | n, js_escaped_string}';
% endif
% if COOKIE_DURATION:
cookie += ';max-age=${COOKIE_DURATION | n, js_escaped_string}';
% endif
document.cookie = cookie;
callback();
},
refreshPage: function() {
window.location.reload();
}
};
</script>
......@@ -21,7 +21,7 @@
<div class="footer-content-wrapper">
<div class="footer-logo">
<a href="${marketing_link('ROOT')}">
<img alt="edX Home Page" src="${footer['logo_image']}">
<img alt="${_('edX Home Page')}" src="${footer['logo_image']}">
</a>
</div>
......@@ -44,6 +44,11 @@
% endfor
</ul>
</nav>
% if include_language_selector:
<%include file="widgets/footer-language-selector.html"/>
% endif
<p class="copyright">${_(
u"\u00A9 2012-{year} edX Inc. All rights reserved except where noted. "
u"EdX, Open edX and the edX and Open EdX logos are registered trademarks "
......
......@@ -43,6 +43,10 @@ from django.utils.translation import ugettext as _
</ol>
</nav>
% if include_language_selector:
<%include file='widgets/footer-language-selector.html'/>
% endif
<div class="wrapper-logo">
<p>
<a href="/">
......
......@@ -21,6 +21,11 @@
<li><a href="${reverse('tos')}#copyright">${_("Copyright")}</a></li>
</ol>
</nav>
% if include_language_selector:
<%include file='widgets/footer-language-selector.html'/>
% endif
</div>
<div class="references">
<span>Built on <a href="http://open.edx.org">OpenEdX</a>.</span>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment