Skip to content
Snippets Groups Projects
Commit 70d8c5c2 authored by Anthony Mangano's avatar Anthony Mangano
Browse files

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

parent aa4eba33
No related branches found
Tags release-2018-12-12-12.20
No related merge requests found
......@@ -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>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment