Commit 1fcf32cf by Douglas Hall Committed by GitHub

Merge pull request #12822 from edx/patch/2016-06-22

Patch Release 2016-06-22
parents a5a235bd e2fd776a
...@@ -9,21 +9,22 @@ import ddt ...@@ -9,21 +9,22 @@ import ddt
import freezegun import freezegun
from mock import patch from mock import patch
from nose.plugins.attrib import attr from nose.plugins.attrib import attr
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from lms.djangoapps.commerce.tests import test_utils as ecomm_test_utils
from openedx.core.djangoapps.theming.tests import test_util as theming_test_utils
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from util.testing import UrlResetMixin
from embargo.test_utils import restrict_course
from xmodule.modulestore.django import modulestore from xmodule.modulestore.django import modulestore
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from course_modes.models import CourseMode, Mode
from course_modes.tests.factories import CourseModeFactory from course_modes.tests.factories import CourseModeFactory
from student.tests.factories import CourseEnrollmentFactory, UserFactory from embargo.test_utils import restrict_course
from student.models import CourseEnrollment from student.models import CourseEnrollment
import lms.djangoapps.commerce.tests.test_utils as ecomm_test_utils from student.tests.factories import CourseEnrollmentFactory, UserFactory
from course_modes.models import CourseMode, Mode from util.testing import UrlResetMixin
from openedx.core.djangoapps.theming.test_util import with_is_edx_domain
@attr('shard_3') @attr('shard_3')
...@@ -373,7 +374,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): ...@@ -373,7 +374,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase):
self.assertEquals(course_modes, expected_modes) self.assertEquals(course_modes, expected_modes)
@unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms') @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls', 'Test only valid in lms')
@with_is_edx_domain(True) @theming_test_utils.with_is_edx_domain(True)
def test_hide_nav(self): def test_hide_nav(self):
# Create the course modes # Create the course modes
for mode in ["honor", "verified"]: for mode in ["honor", "verified"]:
......
...@@ -58,7 +58,7 @@ class PasswordResetFormNoActive(PasswordResetForm): ...@@ -58,7 +58,7 @@ class PasswordResetFormNoActive(PasswordResetForm):
email_template_name='registration/password_reset_email.html', email_template_name='registration/password_reset_email.html',
use_https=False, use_https=False,
token_generator=default_token_generator, token_generator=default_token_generator,
from_email=theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL), from_email=theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
request=None request=None
): ):
""" """
......
...@@ -20,7 +20,7 @@ from django.conf import settings ...@@ -20,7 +20,7 @@ from django.conf import settings
from edxmako.shortcuts import render_to_string from edxmako.shortcuts import render_to_string
from util.request import safe_get_host from util.request import safe_get_host
from util.testing import EventTestMixin from util.testing import EventTestMixin
from openedx.core.djangoapps.theming.test_util import with_is_edx_domain from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
from openedx.core.djangoapps.theming import helpers as theming_helpers from openedx.core.djangoapps.theming import helpers as theming_helpers
...@@ -57,7 +57,7 @@ class EmailTestMixin(object): ...@@ -57,7 +57,7 @@ class EmailTestMixin(object):
email_user.assert_called_with( email_user.assert_called_with(
mock_render_to_string(subject_template, subject_context), mock_render_to_string(subject_template, subject_context),
mock_render_to_string(body_template, body_context), mock_render_to_string(body_template, body_context),
theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL) theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
) )
def append_allowed_hosts(self, hostname): def append_allowed_hosts(self, hostname):
...@@ -298,7 +298,7 @@ class EmailChangeRequestTests(EventTestMixin, TestCase): ...@@ -298,7 +298,7 @@ class EmailChangeRequestTests(EventTestMixin, TestCase):
send_mail.assert_called_with( send_mail.assert_called_with(
mock_render_to_string('emails/email_change_subject.txt', context), mock_render_to_string('emails/email_change_subject.txt', context),
mock_render_to_string('emails/email_change.txt', context), mock_render_to_string('emails/email_change.txt', context),
theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL), theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
[new_email] [new_email]
) )
self.assert_event_emitted( self.assert_event_emitted(
......
...@@ -125,7 +125,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase): ...@@ -125,7 +125,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase):
(subject, msg, from_addr, to_addrs) = send_email.call_args[0] (subject, msg, from_addr, to_addrs) = send_email.call_args[0]
self.assertIn("Password reset", subject) self.assertIn("Password reset", subject)
self.assertIn("You're receiving this e-mail because you requested a password reset", msg) self.assertIn("You're receiving this e-mail because you requested a password reset", msg)
self.assertEquals(from_addr, theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL)) self.assertEquals(from_addr, theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL))
self.assertEquals(len(to_addrs), 1) self.assertEquals(len(to_addrs), 1)
self.assertIn(self.user.email, to_addrs) self.assertIn(self.user.email, to_addrs)
......
...@@ -46,7 +46,7 @@ from certificates.tests.factories import GeneratedCertificateFactory # pylint: ...@@ -46,7 +46,7 @@ from certificates.tests.factories import GeneratedCertificateFactory # pylint:
from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification
import shoppingcart # pylint: disable=import-error import shoppingcart # pylint: disable=import-error
from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin from openedx.core.djangoapps.programs.tests.mixins import ProgramsApiConfigMixin
from openedx.core.djangoapps.theming.test_util import with_is_edx_domain from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
# Explicitly import the cache from ConfigurationModel so we can reset it after each test # Explicitly import the cache from ConfigurationModel so we can reset it after each test
from config_models.models import cache from config_models.models import cache
......
...@@ -2229,11 +2229,11 @@ def reactivation_email_for_user(user): ...@@ -2229,11 +2229,11 @@ def reactivation_email_for_user(user):
message = render_to_string('emails/activation_email.txt', context) message = render_to_string('emails/activation_email.txt', context)
try: try:
user.email_user(subject, message, theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL)) user.email_user(subject, message, theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL))
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
log.error( log.error(
u'Unable to send reactivation email from "%s"', u'Unable to send reactivation email from "%s"',
theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL), theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
exc_info=True exc_info=True
) )
return JsonResponse({ return JsonResponse({
...@@ -2357,7 +2357,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument ...@@ -2357,7 +2357,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument
user.email_user( user.email_user(
subject, subject,
message, message,
theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL) theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
) )
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
log.warning('Unable to send confirmation email to old address', exc_info=True) log.warning('Unable to send confirmation email to old address', exc_info=True)
...@@ -2373,7 +2373,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument ...@@ -2373,7 +2373,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument
user.email_user( user.email_user(
subject, subject,
message, message,
theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL) theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
) )
except Exception: # pylint: disable=broad-except except Exception: # pylint: disable=broad-except
log.warning('Unable to send confirmation email to new address', exc_info=True) log.warning('Unable to send confirmation email to new address', exc_info=True)
......
...@@ -535,8 +535,6 @@ ...@@ -535,8 +535,6 @@
.speed-option, .speed-option,
.control-lang { .control-lang {
@include border-left($baseline/10 solid rgb(14, 166, 236));
font-weight: $font-bold;
color: rgb(14, 166, 236); // UXPL primary accent color: rgb(14, 166, 236); // UXPL primary accent
} }
} }
......
...@@ -55,9 +55,8 @@ ...@@ -55,9 +55,8 @@
</div> </div>
</section> </section>
</article> </article>
<div class="subtitles">
<ol class="subtitles-menu"><li></li></ol> <ol class="subtitles"><li></li></ol>
</div>
</div> </div>
</div> </div>
</div> </div>
...@@ -109,9 +108,7 @@ ...@@ -109,9 +108,7 @@
</section> </section>
</article> </article>
<div class="subtitles"> <ol class="subtitles"><li></li></ol>
<ol class="subtitles-menu"><li></li></ol>
</div>
</div> </div>
</div> </div>
</div> </div>
......
...@@ -20,10 +20,12 @@ var options = { ...@@ -20,10 +20,12 @@ var options = {
libraryFilesToInclude: [ libraryFilesToInclude: [
{pattern: 'common_static/js/vendor/requirejs/require.js', included: true}, {pattern: 'common_static/js/vendor/requirejs/require.js', included: true},
{pattern: 'RequireJS-namespace-undefine.js', included: true}, {pattern: 'RequireJS-namespace-undefine.js', included: true},
{pattern: 'spec/main_requirejs.js', included: true},
{pattern: 'common_static/coffee/src/ajax_prefix.js', included: true}, {pattern: 'common_static/coffee/src/ajax_prefix.js', included: true},
{pattern: 'common_static/common/js/vendor/underscore.js', included: true}, {pattern: 'common_static/common/js/vendor/underscore.js', included: true},
{pattern: 'common_static/common/js/vendor/backbone.js', included: true}, {pattern: 'common_static/common/js/vendor/backbone.js', included: true},
{pattern: 'common_static/edx-ui-toolkit/js/utils/global-loader.js', included: true},
{pattern: 'common_static/js/vendor/CodeMirror/codemirror.js', included: true}, {pattern: 'common_static/js/vendor/CodeMirror/codemirror.js', included: true},
{pattern: 'common_static/js/vendor/draggabilly.js'}, {pattern: 'common_static/js/vendor/draggabilly.js'},
{pattern: 'common_static/common/js/vendor/jquery.js', included: true}, {pattern: 'common_static/common/js/vendor/jquery.js', included: true},
...@@ -48,14 +50,11 @@ var options = { ...@@ -48,14 +50,11 @@ var options = {
{pattern: 'common_static/js/vendor/jasmine-imagediff.js', included: true}, {pattern: 'common_static/js/vendor/jasmine-imagediff.js', included: true},
{pattern: 'common_static/common/js/spec_helpers/jasmine-waituntil.js', included: true}, {pattern: 'common_static/common/js/spec_helpers/jasmine-waituntil.js', included: true},
{pattern: 'common_static/common/js/spec_helpers/jasmine-extensions.js', included: true}, {pattern: 'common_static/common/js/spec_helpers/jasmine-extensions.js', included: true},
{pattern: 'common_static/js/vendor/sinon-1.17.0.js', included: true}, {pattern: 'common_static/js/vendor/sinon-1.17.0.js', included: true}
{pattern: 'spec/main_requirejs.js', included: true},
], ],
libraryFiles: [ libraryFiles: [
{pattern: 'common_static/edx-pattern-library/js/**/*.js'}, {pattern: 'common_static/edx-pattern-library/js/**/*.js'}
{pattern: 'common_static/edx-ui-toolkit/js/**/*.js'}
], ],
// Make sure the patterns in sourceFiles and specFiles do not match the same file. // Make sure the patterns in sourceFiles and specFiles do not match the same file.
......
(function(requirejs, define) { (function(requirejs) {
'use strict';
// We do not wish to bundle common libraries (that may also be used by non-RequireJS code on the page
// into the optimized files. Therefore load these libraries through script tags and explicitly define them.
// Note that when the optimizer executes this code, window will not be defined.
if (window) {
var defineDependency = function (globalName, name, noShim) {
var getGlobalValue = function(name) {
var globalNamePath = name.split('.'),
result = window,
i;
for (i = 0; i < globalNamePath.length; i++) {
result = result[globalNamePath[i]];
}
return result;
},
globalValue = getGlobalValue(globalName);
if (globalValue) {
if (noShim) {
define(name, {});
}
else {
define(name, [], function() { return globalValue; });
}
}
else {
console.error("Expected library to be included on page, but not found on window object: " + name);
}
};
defineDependency("jQuery", "jquery");
defineDependency("jQuery", "jquery-migrate");
defineDependency("_", "underscore");
}
requirejs.config({ requirejs.config({
baseUrl: '/base/', baseUrl: '/base/',
paths: { paths: {
...@@ -38,8 +6,7 @@ ...@@ -38,8 +6,7 @@
"modernizr": "common_static/edx-pattern-library/js/modernizr-custom", "modernizr": "common_static/edx-pattern-library/js/modernizr-custom",
"afontgarde": "common_static/edx-pattern-library/js/afontgarde", "afontgarde": "common_static/edx-pattern-library/js/afontgarde",
"edxicons": "common_static/edx-pattern-library/js/edx-icons", "edxicons": "common_static/edx-pattern-library/js/edx-icons",
"draggabilly": "common_static/js/vendor/draggabilly", "draggabilly": "common_static/js/vendor/draggabilly"
'edx-ui-toolkit': 'common_static/edx-ui-toolkit'
}, },
"moment": { "moment": {
exports: "moment" exports: "moment"
...@@ -51,4 +18,5 @@ ...@@ -51,4 +18,5 @@
exports: "AFontGarde" exports: "AFontGarde"
} }
}); });
}).call(this, RequireJS.requirejs, RequireJS.define);
}).call(this, RequireJS.requirejs);
...@@ -266,7 +266,6 @@ ...@@ -266,7 +266,6 @@
expect($('.closed-captions')).toHaveAttrs({ expect($('.closed-captions')).toHaveAttrs({
'lang': 'de' 'lang': 'de'
}); });
expect(link).toHaveAttr('aria-pressed', 'true');
}); });
it('when clicking on link with current language', function () { it('when clicking on link with current language', function () {
...@@ -285,7 +284,6 @@ ...@@ -285,7 +284,6 @@
expect(state.storage.setItem) expect(state.storage.setItem)
.not.toHaveBeenCalledWith('language', 'en'); .not.toHaveBeenCalledWith('language', 'en');
expect($('.langs-list li.is-active').length).toBe(1); expect($('.langs-list li.is-active').length).toBe(1);
expect(link).toHaveAttr('aria-pressed', 'true');
}); });
it('open the language toggle on hover', function () { it('open the language toggle on hover', function () {
...@@ -415,7 +413,7 @@ ...@@ -415,7 +413,7 @@
}); });
it('show explanation message', function () { it('show explanation message', function () {
expect($('.subtitles .subtitles-menu li')).toHaveText( expect($('.subtitles-menu li')).toHaveText(
'Transcript will be displayed when you start playing the video.' 'Transcript will be displayed when you start playing the video.'
); );
}); });
......
...@@ -203,18 +203,16 @@ ...@@ -203,18 +203,16 @@
describe('onSpeedChange', function () { describe('onSpeedChange', function () {
beforeEach(function () { beforeEach(function () {
state = jasmine.initializePlayer(); state = jasmine.initializePlayer();
$('li[data-speed="1.0"]').addClass('is-active').attr('aria-pressed', 'true'); $('li[data-speed="1.0"]').addClass('is-active');
state.videoSpeedControl.setSpeed(0.75); state.videoSpeedControl.setSpeed(0.75);
}); });
it('set the new speed as active', function () { it('set the new speed as active', function () {
expect($('li[data-speed="1.0"]')).not.toHaveClass('is-active'); expect($('.video-speeds li[data-speed="1.0"]'))
expect($('li[data-speed="1.0"] .speed-option').attr('aria-pressed')).not.toEqual('true'); .not.toHaveClass('is-active');
expect($('.video-speeds li[data-speed="0.75"]'))
expect($('li[data-speed="0.75"]')).toHaveClass('is-active'); .toHaveClass('is-active');
expect($('li[data-speed="0.75"] .speed-option').attr('aria-pressed')).toEqual('true'); expect($('.speeds .value')).toHaveHtml('0.75x');
expect($('.speeds .speed-button .value')).toHaveHtml('0.75x');
}); });
}); });
......
(function (requirejs, require, define) { (function (requirejs, require, define) {
"use strict"; "use strict";
define( define(
'video/08_video_speed_control.js', [ 'video/08_video_speed_control.js',
'video/00_iterator.js', ['video/00_iterator.js'],
'edx-ui-toolkit/js/utils/html-utils' function (Iterator) {
], function (Iterator, HtmlUtils) {
/** /**
* Video speed control module. * Video speed control module.
* @exports video/08_video_speed_control.js * @exports video/08_video_speed_control.js
...@@ -96,37 +95,23 @@ define( ...@@ -96,37 +95,23 @@ define(
* Creates any necessary DOM elements, attach them, and set their, * Creates any necessary DOM elements, attach them, and set their,
* initial configuration. * initial configuration.
* @param {array} speeds List of speeds available for the player. * @param {array} speeds List of speeds available for the player.
* @param {string} currentSpeed The current speed set to the player.
*/ */
render: function (speeds, currentSpeed) { render: function (speeds) {
var speedsContainer = this.speedsContainer, var speedsContainer = this.speedsContainer,
reversedSpeeds = speeds.concat().reverse(), reversedSpeeds = speeds.concat().reverse(),
speedsList = $.map(reversedSpeeds, function (speed) { speedsList = $.map(reversedSpeeds, function (speed) {
return HtmlUtils.interpolateHtml( return [
HtmlUtils.joinHtml( '<li data-speed="', speed, '">',
HtmlUtils.HTML('<li data-speed="{speed}">'), '<button class="control speed-option" tabindex="-1">',
HtmlUtils.HTML('<button class="control speed-option" tabindex="-1" aria-pressed="false">'), speed, 'x',
HtmlUtils.HTML(speed), '</button>',
HtmlUtils.HTML('x'), '</li>'
HtmlUtils.HTML('</button>'), ].join('');
HtmlUtils.HTML('</li>')
),
{
speed: speed
}
).toString();
}); });
HtmlUtils.setHtml( speedsContainer.html(speedsList.join(''));
speedsContainer,
HtmlUtils.HTML(speedsList)
);
this.speedLinks = new Iterator(speedsContainer.find('.speed-option')); this.speedLinks = new Iterator(speedsContainer.find('.speed-option'));
HtmlUtils.prepend( this.state.el.find('.secondary-controls').prepend(this.el);
this.state.el.find('.secondary-controls'),
HtmlUtils.HTML(this.el)
);
this.setActiveSpeed(currentSpeed);
}, },
/** /**
...@@ -231,38 +216,17 @@ define( ...@@ -231,38 +216,17 @@ define(
if (speed !== this.currentSpeed || forceUpdate) { if (speed !== this.currentSpeed || forceUpdate) {
this.speedsContainer this.speedsContainer
.find('li') .find('li')
.siblings("li[data-speed='" + speed + "']"); .removeClass('is-active')
.siblings("li[data-speed='" + speed + "']")
.addClass('is-active');
this.speedButton.find('.value').text(speed + 'x'); this.speedButton.find('.value').html(speed + 'x');
this.currentSpeed = speed; this.currentSpeed = speed;
if (!silent) { if (!silent) {
this.el.trigger('speedchange', [speed, this.state.speed]); this.el.trigger('speedchange', [speed, this.state.speed]);
} }
} }
this.resetActiveSpeed();
this.setActiveSpeed(speed);
},
resetActiveSpeed: function() {
var speedOptions = this.speedsContainer.find('li');
$(speedOptions).each(function(index, el) {
$(el).removeClass('is-active')
.find('.speed-option')
.attr('aria-pressed', 'false');
});
},
setActiveSpeed: function(speed) {
var speedOption = this.speedsContainer.find('li[data-speed="' + speed + '"]');
speedOption.addClass('is-active')
.find('.speed-option')
.attr('aria-pressed', 'true');
this.speedButton.attr('title', gettext('Video speed: ') + speed + 'x');
}, },
/** /**
...@@ -280,13 +244,10 @@ define( ...@@ -280,13 +244,10 @@ define(
* @param {jquery Event} event * @param {jquery Event} event
*/ */
clickLinkHandler: function (event) { clickLinkHandler: function (event) {
var el = $(event.currentTarget).parent(), var speed = $(event.currentTarget).parent().data('speed');
speed = $(el).data('speed');
this.resetActiveSpeed(); this.closeMenu();
this.setActiveSpeed(speed);
this.state.videoCommands.execute('speed', speed); this.state.videoCommands.execute('speed', speed);
this.closeMenu(true);
return false; return false;
}, },
......
...@@ -5,12 +5,11 @@ ...@@ -5,12 +5,11 @@
define('video/09_video_caption.js',[ define('video/09_video_caption.js',[
'video/00_sjson.js', 'video/00_sjson.js',
'video/00_async_process.js', 'video/00_async_process.js',
'edx-ui-toolkit/js/utils/html-utils',
'draggabilly', 'draggabilly',
'modernizr', 'modernizr',
'afontgarde', 'afontgarde',
'edxicons' 'edxicons'
], function (Sjson, AsyncProcess, HtmlUtils, Draggabilly) { ], function (Sjson, AsyncProcess, Draggabilly) {
/** /**
* @desc VideoCaption module exports a function. * @desc VideoCaption module exports a function.
...@@ -81,53 +80,47 @@ ...@@ -81,53 +80,47 @@
renderElements: function () { renderElements: function () {
var languages = this.state.config.transcriptLanguages; var languages = this.state.config.transcriptLanguages;
var langHtml = HtmlUtils.joinHtml( var langTemplate = [
HtmlUtils.HTML('<div class="grouped-controls">'), '<div class="grouped-controls">',
HtmlUtils.HTML('<button class="control toggle-captions" aria-disabled="false">'), '<button class="control toggle-captions" aria-disabled="false">',
HtmlUtils.HTML('<span class="icon-fallback-img">'), '<span class="icon-fallback-img">',
HtmlUtils.HTML('<span class="icon fa fa-cc" aria-hidden="true"></span>'), '<span class="icon fa fa-cc" aria-hidden="true"></span>',
HtmlUtils.HTML('<span class="sr control-text"></span>'), '<span class="sr control-text"></span>',
HtmlUtils.HTML('</span>'), '</span>',
HtmlUtils.HTML('</button>'), '</button>',
HtmlUtils.HTML('<button class="control toggle-transcript" aria-disabled="false">'), '<button class="control toggle-transcript" aria-disabled="false">',
HtmlUtils.HTML('<span class="icon-fallback-img">'), '<span class="icon-fallback-img">',
HtmlUtils.HTML('<span class="icon fa fa-quote-left" aria-hidden="true"></span>'), '<span class="icon fa fa-quote-left" aria-hidden="true"></span>',
HtmlUtils.HTML('<span class="sr control-text"></span>'), '<span class="sr control-text"></span>',
HtmlUtils.HTML('</span>'), '</span>',
HtmlUtils.HTML('</button>'), '</button>',
HtmlUtils.HTML('<div class="lang menu-container" role="application">'), '<div class="lang menu-container" role="application">',
HtmlUtils.HTML('<p class="sr instructions" id="lang-instructions"></p>'), '<p class="sr instructions" id="lang-instructions"></p>',
HtmlUtils.HTML('<button class="control language-menu" aria-disabled="false"'), '<button class="control language-menu" aria-disabled="false"',
HtmlUtils.HTML('aria-describedby="lang-instructions" '), 'aria-describedby="lang-instructions" ',
HtmlUtils.HTML('title="'), 'title="',
gettext('Open language menu'), gettext('Open language menu'),
HtmlUtils.HTML('">'), '">',
HtmlUtils.HTML('<span class="icon-fallback-img">'), '<span class="icon-fallback-img">',
HtmlUtils.HTML('<span class="icon fa fa-caret-left" aria-hidden="true"></span>'), '<span class="icon fa fa-caret-left" aria-hidden="true"></span>',
HtmlUtils.HTML('<span class="sr control-text"></span>'), '<span class="sr control-text"></span>',
HtmlUtils.HTML('</span>'), '</span>',
HtmlUtils.HTML('</button>'), '</button>',
HtmlUtils.HTML('</div>'), '</div>',
HtmlUtils.HTML('</div>)') '</div>'
); ].join('');
var subtitlesHtml = HtmlUtils.interpolateHtml( var template = [
HtmlUtils.joinHtml( '<div class="subtitles" role="region" id="transcript-' + this.state.id + '">',
HtmlUtils.HTML('<div class="subtitles" role="region" id="transcript-{courseId}">'), '<h3 id="transcript-label-' + this.state.id + '" class="transcript-title sr"></h3>',
HtmlUtils.HTML('<h3 id="transcript-label-{courseId}" class="transcript-title sr"></h3>'), '<ol id="transcript-captions" class="subtitles-menu" lang="' + this.state.lang + '"></ol>',
HtmlUtils.HTML('<ol id="transcript-captions" class="subtitles-menu" lang="{courseLang}"></ol>'), '</div>'
HtmlUtils.HTML('</div>') ].join('');
),
{
courseId: this.state.id,
courseLang: this.state.lang
}
);
this.loaded = false; this.loaded = false;
this.subtitlesEl = $(HtmlUtils.ensureHtml(subtitlesHtml).toString()); this.subtitlesEl = $(template);
this.subtitlesMenuEl = this.subtitlesEl.find('.subtitles-menu'); this.subtitlesMenuEl = this.subtitlesEl.find('.subtitles-menu');
this.container = $(HtmlUtils.ensureHtml(langHtml).toString()); this.container = $(langTemplate);
this.captionControlEl = this.container.find('.toggle-captions'); this.captionControlEl = this.container.find('.toggle-captions');
this.captionDisplayEl = this.state.el.find('.closed-captions'); this.captionDisplayEl = this.state.el.find('.closed-captions');
this.transcriptControlEl = this.container.find('.toggle-transcript'); this.transcriptControlEl = this.container.find('.toggle-transcript');
...@@ -549,26 +542,15 @@ ...@@ -549,26 +542,15 @@
} }
} else { } else {
if (state.isTouch) { if (state.isTouch) {
HtmlUtils.setHtml( self.subtitlesEl.find('.subtitles-menu')
self.subtitlesEl.find('.subtitles-menu'), .text(gettext('Transcript will be displayed when you start playing the video.')) // jshint ignore: line
HtmlUtils.joinHtml( .wrapInner('<li></li>');
HtmlUtils.HTML('<li>'),
gettext('Transcript will be displayed when you start playing the video.'),
HtmlUtils.HTML('</li>')
)
);
} else { } else {
self.renderCaption(start, captions); self.renderCaption(start, captions);
} }
self.hideCaptions(state.hide_captions, false); self.hideCaptions(state.hide_captions, false);
HtmlUtils.append( self.state.el.find('.video-wrapper').after(self.subtitlesEl);
self.state.el.find('.video-wrapper').parent(), self.state.el.find('.secondary-controls').append(self.container);
HtmlUtils.HTML(self.subtitlesEl)
);
HtmlUtils.append(
self.state.el.find('.secondary-controls'),
HtmlUtils.HTML(self.container)
);
self.bindHandlers(); self.bindHandlers();
} }
...@@ -648,9 +630,7 @@ ...@@ -648,9 +630,7 @@
onResize: function () { onResize: function () {
this.subtitlesEl this.subtitlesEl
.find('.spacing').first() .find('.spacing').first()
.height(this.topSpacingHeight()); .height(this.topSpacingHeight()).end()
this.subtitlesEl
.find('.spacing').last() .find('.spacing').last()
.height(this.bottomSpacingHeight()); .height(this.bottomSpacingHeight());
...@@ -669,9 +649,8 @@ ...@@ -669,9 +649,8 @@
renderLanguageMenu: function (languages) { renderLanguageMenu: function (languages) {
var self = this, var self = this,
state = this.state, state = this.state,
$menu = $('<ol class="langs-list menu">'), menu = $('<ol class="langs-list menu">'),
currentLang = state.getCurrentLanguage(), currentLang = state.getCurrentLanguage();
$li, $link, linkHtml;
if (_.keys(languages).length < 2) { if (_.keys(languages).length < 2) {
// Remove the menu toggle button // Remove the menu toggle button
...@@ -682,29 +661,20 @@ ...@@ -682,29 +661,20 @@
this.showLanguageMenu = true; this.showLanguageMenu = true;
$.each(languages, function(code, label) { $.each(languages, function(code, label) {
$li = $('<li />', { 'data-lang-code': code }); var li = $('<li data-lang-code="' + code + '" />'),
linkHtml = HtmlUtils.joinHtml( link = $('<button class="control control-lang">' + label + '</button>');
HtmlUtils.HTML('<button class="control control-lang">'),
label,
HtmlUtils.HTML('</button>')
);
$link = $(linkHtml.toString());
if (currentLang === code) { if (currentLang === code) {
$li.addClass('is-active'); li.addClass('is-active');
$link.attr('aria-pressed', 'true');
} }
$li.append($link); li.append(link);
$menu.append($li); menu.append(li);
}); });
HtmlUtils.append( this.languageChooserEl.append(menu);
this.languageChooserEl,
HtmlUtils.HTML($menu)
);
$menu.on('click', '.control-lang', function (e) { menu.on('click', '.control-lang', function (e) {
var el = $(e.currentTarget).parent(), var el = $(e.currentTarget).parent(),
state = self.state, state = self.state,
langCode = el.data('lang-code'); langCode = el.data('lang-code');
...@@ -713,11 +683,7 @@ ...@@ -713,11 +683,7 @@
state.lang = langCode; state.lang = langCode;
el .addClass('is-active') el .addClass('is-active')
.siblings('li') .siblings('li')
.removeClass('is-active') .removeClass('is-active');
.find('.control-lang')
.attr('aria-pressed', 'false');
$(e.currentTarget).attr('aria-pressed', 'true');
state.el.trigger('language_menu:change', [langCode]); state.el.trigger('language_menu:change', [langCode]);
self.fetchCaption(); self.fetchCaption();
...@@ -727,7 +693,6 @@ ...@@ -727,7 +693,6 @@
// update the transcript lang attribute // update the transcript lang attribute
self.subtitlesMenuEl.attr('lang', langCode); self.subtitlesMenuEl.attr('lang', langCode);
self.closeLanguageMenu(e);
} }
}); });
}, },
...@@ -750,18 +715,13 @@ ...@@ -750,18 +715,13 @@
'data-index': index, 'data-index': index,
'data-start': start[index], 'data-start': start[index],
'tabindex': 0 'tabindex': 0
}); }).html(text);
$(liEl).text(text);
return liEl[0]; return liEl[0];
}; };
return AsyncProcess.array(captions, process).done(function (list) { return AsyncProcess.array(captions, process).done(function (list) {
HtmlUtils.append( container.append(list);
container,
HtmlUtils.HTML(list)
);
}); });
}, },
...@@ -830,39 +790,16 @@ ...@@ -830,39 +790,16 @@
* out of the tabbing order. * out of the tabbing order.
* *
*/ */
addPaddings: function() { addPaddings: function () {
var topSpacer = HtmlUtils.interpolateHtml(
HtmlUtils.HTML([
'<li class="spacing" style="height: {height}px">',
'<a href="#transcript-end-{id}" id="transcript-start-{id}" class="transcript-start"></a>', // jshint ignore:line
'</li>'
].join('')),
{
id: this.state.id,
height: this.topSpacingHeight()
}
);
var bottomSpacer = HtmlUtils.interpolateHtml( this.subtitlesMenuEl
HtmlUtils.HTML([ .prepend(
'<li class="spacing" style="height: {height}px">', $('<li class="spacing"><a href="#transcript-end-' + this.state.id + '" id="transcript-start-' + this.state.id + '" class="transcript-start"></a>') // jshint ignore: line
'<a href="#transcript-start-{id}" id="transcript-end-{id}" class="transcript-end"></a>', // jshint ignore:line .height(this.topSpacingHeight())
'</li>' )
].join('')), .append(
{ $('<li class="spacing"><a href="#transcript-start-' + this.state.id + '" id="transcript-end-' + this.state.id + '" class="transcript-end"></a>') // jshint ignore: line
id: this.state.id, .height(this.bottomSpacingHeight())
height: this.bottomSpacingHeight()
}
);
HtmlUtils.prepend(
this.subtitlesMenuEl,
topSpacer
);
HtmlUtils.append(
this.subtitlesMenuEl,
bottomSpacer
); );
}, },
......
...@@ -10,7 +10,7 @@ import mock ...@@ -10,7 +10,7 @@ import mock
import ddt import ddt
from config_models.models import cache from config_models.models import cache
from branding.models import BrandingApiConfig from branding.models import BrandingApiConfig
from openedx.core.djangoapps.theming.test_util import with_edx_domain_context from openedx.core.djangoapps.theming.tests.test_util import with_edx_domain_context
@ddt.ddt @ddt.ddt
......
...@@ -389,7 +389,7 @@ def _get_source_address(course_id, course_title, truncate=True): ...@@ -389,7 +389,7 @@ def _get_source_address(course_id, course_title, truncate=True):
course_title=course_title_no_quotes, course_title=course_title_no_quotes,
course_name=course_name, course_name=course_name,
from_email=theming_helpers.get_value( from_email=theming_helpers.get_value(
'bulk_email_default_from_email', 'email_from_address',
settings.BULK_EMAIL_DEFAULT_FROM_EMAIL settings.BULK_EMAIL_DEFAULT_FROM_EMAIL
) )
) )
......
...@@ -8,7 +8,7 @@ from django.test import TestCase ...@@ -8,7 +8,7 @@ from django.test import TestCase
import mock import mock
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from openedx.core.djangoapps.theming.test_util import with_is_edx_domain from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
class UserMixin(object): class UserMixin(object):
......
...@@ -9,7 +9,7 @@ from wiki.models import URLPath ...@@ -9,7 +9,7 @@ from wiki.models import URLPath
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from xmodule.modulestore.tests.factories import CourseFactory from xmodule.modulestore.tests.factories import CourseFactory
from openedx.core.djangoapps.theming.test_util import with_comprehensive_theme from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
from courseware.tests.factories import InstructorFactory from courseware.tests.factories import InstructorFactory
from course_wiki.views import get_or_create_root from course_wiki.views import get_or_create_root
......
...@@ -6,7 +6,7 @@ from django.test import TestCase ...@@ -6,7 +6,7 @@ from django.test import TestCase
from path import path # pylint: disable=no-name-in-module from path import path # pylint: disable=no-name-in-module
from django.contrib import staticfiles from django.contrib import staticfiles
from openedx.core.djangoapps.theming.test_util import with_comprehensive_theme from openedx.core.djangoapps.theming.tests.test_util import with_comprehensive_theme
from openedx.core.lib.tempdir import mkdtemp_clean from openedx.core.lib.tempdir import mkdtemp_clean
......
...@@ -9,7 +9,7 @@ from django.conf import settings ...@@ -9,7 +9,7 @@ from django.conf import settings
from django.test import TestCase from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
from openedx.core.djangoapps.theming.test_util import with_is_edx_domain from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
@attr('shard_1') @attr('shard_1')
......
...@@ -33,7 +33,7 @@ from student_account.views import account_settings_context, get_user_orders ...@@ -33,7 +33,7 @@ from student_account.views import account_settings_context, get_user_orders
from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin from third_party_auth.tests.testutil import simulate_running_pipeline, ThirdPartyAuthTestMixin
from util.testing import UrlResetMixin from util.testing import UrlResetMixin
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from openedx.core.djangoapps.theming.test_util import with_edx_domain_context from openedx.core.djangoapps.theming.tests.test_util import with_edx_domain_context
@ddt.ddt @ddt.ddt
......
...@@ -39,7 +39,7 @@ from commerce.models import CommerceConfiguration ...@@ -39,7 +39,7 @@ from commerce.models import CommerceConfiguration
from commerce.tests import TEST_PAYMENT_DATA, TEST_API_URL, TEST_API_SIGNING_KEY, TEST_PUBLIC_URL_ROOT from commerce.tests import TEST_PAYMENT_DATA, TEST_API_URL, TEST_API_SIGNING_KEY, TEST_PUBLIC_URL_ROOT
from embargo.test_utils import restrict_course from embargo.test_utils import restrict_course
from openedx.core.djangoapps.user_api.accounts.api import get_account_settings from openedx.core.djangoapps.user_api.accounts.api import get_account_settings
from openedx.core.djangoapps.theming.test_util import with_is_edx_domain from openedx.core.djangoapps.theming.tests.test_util import with_is_edx_domain
from shoppingcart.models import Order, CertificateItem from shoppingcart.models import Order, CertificateItem
from student.tests.factories import UserFactory, CourseEnrollmentFactory from student.tests.factories import UserFactory, CourseEnrollmentFactory
from student.models import CourseEnrollment from student.models import CourseEnrollment
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
/* jshint node: true */ /* jshint node: true */
/*jshint -W079 */ /*jshint -W079 */
'use strict'; 'use strict';
var path = require('path'); var path = require('path');
var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js')); var configModule = require(path.join(__dirname, '../../common/static/common/js/karma.common.conf.js'));
...@@ -15,27 +16,23 @@ var options = { ...@@ -15,27 +16,23 @@ var options = {
// Avoid adding files to this list. Use RequireJS. // Avoid adding files to this list. Use RequireJS.
libraryFilesToInclude: [ libraryFilesToInclude: [
{pattern: 'xmodule_js/common_static/js/vendor/requirejs/require.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/requirejs/require.js', included: true},
{pattern: 'js/RequireJS-namespace-undefine.js', included: true}, {pattern: 'lms/js/spec/main_requirejs_coffee.js', included: true},
{pattern: 'common/js/vendor/jquery.js', included: true},
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/jquery.event.drag-2.2.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/slick.core.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/slick.grid.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/requirejs/require.js', included: true},
{pattern: 'js/RequireJS-namespace-undefine.js', included: true},
{pattern: 'xmodule_js/common_static/coffee/src/ajax_prefix.js', included: true}, {pattern: 'xmodule_js/common_static/coffee/src/ajax_prefix.js', included: true},
{pattern: 'common/js/vendor/jquery.js', included: true},
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
{pattern: 'common/js/vendor/underscore.js', included: true}, {pattern: 'common/js/vendor/underscore.js', included: true},
{pattern: 'edx-ui-toolkit/js/utils/global-loader.js', included: true},
{pattern: 'xmodule_js/common_static/js/src/logger.js', included: true}, {pattern: 'xmodule_js/common_static/js/src/logger.js', included: true},
{pattern: 'xmodule_js/common_static/js/test/i18n.js', included: true}, {pattern: 'xmodule_js/common_static/js/test/i18n.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/CodeMirror/codemirror.js', included: true},
{pattern: 'common/js/vendor/jquery.js', included: true},
{pattern: 'common/js/vendor/jquery-migrate.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/jquery.cookie.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/jquery.cookie.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/flot/jquery.flot.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/flot/jquery.flot.js', included: true},
{pattern: 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js', included: true}, {pattern: 'xmodule_js/common_static/coffee/src/jquery.immediateDescendents.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/jquery-ui.min.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/jquery-ui.min.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/moment.min.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/moment-with-locales.min.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/URI.min.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/URI.min.js', included: true},
{pattern: 'xmodule_js/common_static/js/xblock/*.js', included: true}, {pattern: 'xmodule_js/common_static/js/xblock/*.js', included: true},
...@@ -45,9 +42,7 @@ var options = { ...@@ -45,9 +42,7 @@ var options = {
{pattern: 'xmodule_js/src/xmodule.js', included: true}, {pattern: 'xmodule_js/src/xmodule.js', included: true},
{pattern: 'xmodule_js/common_static/js/vendor/jasmine-imagediff.js', included: true}, {pattern: 'xmodule_js/common_static/js/vendor/jasmine-imagediff.js', included: true},
{pattern: 'common/js/spec_helpers/jasmine-extensions.js', included: true}, {pattern: 'common/js/spec_helpers/jasmine-extensions.js', included: true}
{pattern: 'lms/js/spec/main_requirejs_coffee.js', included: true}
], ],
libraryFiles: [ libraryFiles: [
......
(function(requirejs, define) { (function(requirejs) {
'use strict'; 'use strict';
// We do not wish to bundle common libraries (that may also be used by non-RequireJS code on the page
// into the optimized files. Therefore load these libraries through script tags and explicitly define them.
// Note that when the optimizer executes this code, window will not be defined.
if (window) {
var defineDependency = function (globalName, name, noShim) {
var getGlobalValue = function(name) {
var globalNamePath = name.split('.'),
result = window,
i;
for (i = 0; i < globalNamePath.length; i++) {
result = result[globalNamePath[i]];
}
return result;
},
globalValue = getGlobalValue(globalName);
if (globalValue) {
if (noShim) {
define(name, {});
}
else {
define(name, [], function() { return globalValue; });
}
}
else {
console.error("Expected library to be included on page, but not found on window object: " + name);
}
};
defineDependency("jQuery", "jquery");
defineDependency("jQuery", "jquery-migrate");
defineDependency("_", "underscore");
}
requirejs.config({ requirejs.config({
baseUrl: '/base/', baseUrl: '/base/',
paths: { paths: {
...@@ -38,8 +7,7 @@ ...@@ -38,8 +7,7 @@
"modernizr": "edx-pattern-library/js/modernizr-custom", "modernizr": "edx-pattern-library/js/modernizr-custom",
"afontgarde": "edx-pattern-library/js/afontgarde", "afontgarde": "edx-pattern-library/js/afontgarde",
"edxicons": "edx-pattern-library/js/edx-icons", "edxicons": "edx-pattern-library/js/edx-icons",
"draggabilly": "xmodule_js/common_static/js/vendor/draggabilly", "draggabilly": "xmodule_js/common_static/js/vendor/draggabilly"
'edx-ui-toolkit': 'edx-ui-toolkit'
}, },
"moment": { "moment": {
exports: "moment" exports: "moment"
...@@ -52,4 +20,4 @@ ...@@ -52,4 +20,4 @@
} }
}); });
}).call(this, RequireJS.requirejs, RequireJS.define); }).call(this, requirejs, define); // jshint ignore:line
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
${_("Thank you for signing up for {platform_name}.").format(platform_name=settings.PLATFORM_NAME)} <%! from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value %>
${_("Thank you for signing up for {platform_name}.").format(
platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)
)}
${_("Change your life and start learning today by activating your " ${_("Change your life and start learning today by activating your "
"{platform_name} account. Click on the link below or copy and " "{platform_name} account. Click on the link below or copy and "
"paste it into your browser's address bar.").format( "paste it into your browser's address bar.").format(
platform_name=settings.PLATFORM_NAME platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)
)} )}
% if is_secure: % if is_secure:
...@@ -15,4 +18,4 @@ ${_("Change your life and start learning today by activating your " ...@@ -15,4 +18,4 @@ ${_("Change your life and start learning today by activating your "
${_("If you didn't request this, you don't need to do anything; you won't " ${_("If you didn't request this, you don't need to do anything; you won't "
"receive any more email from us. Please do not reply to this e-mail; " "receive any more email from us. Please do not reply to this e-mail; "
"if you require assistance, check the help section of the " "if you require assistance, check the help section of the "
"{platform_name} website.").format(platform_name=settings.PLATFORM_NAME)} "{platform_name} website.").format(platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME))}
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value %>
${_("Activate Your {platform_name} Account").format(platform_name=settings.PLATFORM_NAME)} ${_("Activate Your {platform_name} Account").format(
platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME
))}
<%! from django.core.urlresolvers import reverse %> <%! from django.core.urlresolvers import reverse %>
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value %>
${_("This is to confirm that you changed the e-mail associated with " ${_("This is to confirm that you changed the e-mail associated with "
"{platform_name} from {old_email} to {new_email}. If you " "{platform_name} from {old_email} to {new_email}. If you "
"did not make this request, please contact us immediately. Contact " "did not make this request, please contact us immediately. Contact "
"information is listed at:").format(platform_name=settings.PLATFORM_NAME, old_email=old_email, new_email=new_email)} "information is listed at:").format(
platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
old_email=old_email,
new_email=new_email
)
}
% if is_secure: % if is_secure:
https://${ site }${reverse('contact')} https://${ site }${reverse('contact')}
...@@ -11,5 +17,4 @@ ${_("This is to confirm that you changed the e-mail associated with " ...@@ -11,5 +17,4 @@ ${_("This is to confirm that you changed the e-mail associated with "
http://${ site }${reverse('contact')} http://${ site }${reverse('contact')}
% endif % endif
${_("We keep a log of old e-mails, so if this request was unintentional, we " ${_("We keep a log of old e-mails, so if this request was unintentional, we can investigate.")}
"can investigate.")}
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value %>
${_("We received a request to change the e-mail associated with your " ${_("We received a request to change the e-mail associated with your "
"{platform_name} account from {old_email} to {new_email}. " "{platform_name} account from {old_email} to {new_email}. "
"If this is correct, please confirm your new e-mail address by " "If this is correct, please confirm your new e-mail address by "
"visiting:").format(platform_name=settings.PLATFORM_NAME, old_email=old_email, new_email=new_email)} "visiting:").format(
platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME),
old_email=old_email,
new_email=new_email
)
}
% if is_secure: % if is_secure:
https://${ site }/email_confirm/${ key } https://${ site }/email_confirm/${ key }
...@@ -13,4 +19,4 @@ ${_("We received a request to change the e-mail associated with your " ...@@ -13,4 +19,4 @@ ${_("We received a request to change the e-mail associated with your "
${_("If you didn't request this, you don't need to do anything; you won't " ${_("If you didn't request this, you don't need to do anything; you won't "
"receive any more email from us. Please do not reply to this e-mail; " "receive any more email from us. Please do not reply to this e-mail; "
"if you require assistance, check the help section of the " "if you require assistance, check the help section of the "
"{platform_name} web site.").format(platform_name=settings.PLATFORM_NAME)} "{platform_name} web site.").format(platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME))}
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
${_("Request to change {platform_name} account e-mail").format(platform_name=settings.PLATFORM_NAME)} <%! from openedx.core.djangoapps.theming.helpers import get_value as get_themed_value %>
${_("Request to change {platform_name} account e-mail").format(
platform_name=get_themed_value('PLATFORM_NAME', settings.PLATFORM_NAME)
)}
...@@ -125,7 +125,7 @@ def send_credit_notifications(username, course_key): ...@@ -125,7 +125,7 @@ def send_credit_notifications(username, course_key):
notification_msg.attach(logo_image) notification_msg.attach(logo_image)
# add email addresses of sender and receiver # add email addresses of sender and receiver
from_address = theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL) from_address = theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL)
to_address = user.email to_address = user.email
# send the root email message # send the root email message
......
""" """
Helpers for accessing comprehensive theming related variables. Helpers for accessing comprehensive theming related variables.
""" """
from microsite_configuration import microsite
from microsite_configuration import page_title_breadcrumbs
from django.conf import settings from django.conf import settings
from microsite_configuration import microsite, page_title_breadcrumbs
def get_page_title_breadcrumbs(*args): def get_page_title_breadcrumbs(*args):
""" """
...@@ -17,7 +17,25 @@ def get_value(val_name, default=None, **kwargs): ...@@ -17,7 +17,25 @@ def get_value(val_name, default=None, **kwargs):
""" """
This is a proxy function to hide microsite_configuration behind comprehensive theming. This is a proxy function to hide microsite_configuration behind comprehensive theming.
""" """
return microsite.get_value(val_name, default=default, **kwargs)
# Retrieve the requested field/value from the microsite configuration
microsite_value = microsite.get_value(val_name, default=default, **kwargs)
# Attempt to perform a dictionary update using the provided default
# This will fail if either the default or the microsite value is not a dictionary
try:
value = dict(default)
value.update(microsite_value)
# If the dictionary update fails, just use the microsite value
# TypeError: default is not iterable (simple value or None)
# ValueError: default is iterable but not a dict (list, not dict)
# AttributeError: default does not have an 'update' method
except (TypeError, ValueError, AttributeError):
value = microsite_value
# Return the end result to the caller
return value
def get_template_path(relative_path, **kwargs): def get_template_path(relative_path, **kwargs):
......
"""
Test helpers for Comprehensive Theming.
"""
from django.test import TestCase
from mock import patch
from openedx.core.djangoapps.theming import helpers
class ThemingHelpersTests(TestCase):
"""
Make sure some of the theming helper functions work
"""
def test_get_value_returns_override(self):
"""
Tests to make sure the get_value() operation returns a combined dictionary consisting
of the base container with overridden keys from the microsite configuration
"""
with patch('microsite_configuration.microsite.get_value') as mock_get_value:
override_key = 'JWT_ISSUER'
override_value = 'testing'
mock_get_value.return_value = {override_key: override_value}
jwt_auth = helpers.get_value('JWT_AUTH')
self.assertEqual(jwt_auth[override_key], override_value)
...@@ -15,7 +15,7 @@ from django.test.utils import override_settings ...@@ -15,7 +15,7 @@ from django.test.utils import override_settings
import edxmako import edxmako
from .core import comprehensive_theme_changes from openedx.core.djangoapps.theming.core import comprehensive_theme_changes
EDX_THEME_DIR = settings.REPO_ROOT / "themes" / "edx.org" EDX_THEME_DIR = settings.REPO_ROOT / "themes" / "edx.org"
......
...@@ -398,7 +398,7 @@ def request_password_change(email, orig_host, is_secure): ...@@ -398,7 +398,7 @@ def request_password_change(email, orig_host, is_secure):
# Generate a single-use link for performing a password reset # Generate a single-use link for performing a password reset
# and email it to the user. # and email it to the user.
form.save( form.save(
from_email=theming_helpers.get_value('default_from_email', settings.DEFAULT_FROM_EMAIL), from_email=theming_helpers.get_value('email_from_address', settings.DEFAULT_FROM_EMAIL),
domain_override=orig_host, domain_override=orig_host,
use_https=is_secure use_https=is_secure
) )
......
...@@ -43,7 +43,7 @@ edx-drf-extensions==0.5.1 ...@@ -43,7 +43,7 @@ edx-drf-extensions==0.5.1
edx-lint==0.4.3 edx-lint==0.4.3
edx-django-oauth2-provider==1.1.1 edx-django-oauth2-provider==1.1.1
edx-django-sites-extensions==2.0.1 edx-django-sites-extensions==2.0.1
edx-oauth2-provider==1.1.1 edx-oauth2-provider==1.1.2
edx-opaque-keys==0.2.1 edx-opaque-keys==0.2.1
edx-organizations==0.4.1 edx-organizations==0.4.1
edx-rest-api-client==1.2.1 edx-rest-api-client==1.2.1
......
...@@ -90,7 +90,7 @@ git+https://github.com/edx/xblock-utils.git@v1.0.2#egg=xblock-utils==1.0.2 ...@@ -90,7 +90,7 @@ git+https://github.com/edx/xblock-utils.git@v1.0.2#egg=xblock-utils==1.0.2
-e git+https://github.com/edx/edx-reverification-block.git@0.0.5#egg=edx-reverification-block==0.0.5 -e git+https://github.com/edx/edx-reverification-block.git@0.0.5#egg=edx-reverification-block==0.0.5
git+https://github.com/edx/edx-user-state-client.git@1.0.1#egg=edx-user-state-client==1.0.1 git+https://github.com/edx/edx-user-state-client.git@1.0.1#egg=edx-user-state-client==1.0.1
git+https://github.com/edx/xblock-lti-consumer.git@v1.0.9#egg=xblock-lti-consumer==1.0.9 git+https://github.com/edx/xblock-lti-consumer.git@v1.0.9#egg=xblock-lti-consumer==1.0.9
git+https://github.com/edx/edx-proctoring.git@0.12.19#egg=edx-proctoring==0.12.19 git+https://github.com/edx/edx-proctoring.git@0.12.21#egg=edx-proctoring==0.12.21
# Third Party XBlocks # Third Party XBlocks
-e git+https://github.com/mitodl/edx-sga@172a90fd2738f8142c10478356b2d9ed3e55334a#egg=edx-sga -e git+https://github.com/mitodl/edx-sga@172a90fd2738f8142c10478356b2d9ed3e55334a#egg=edx-sga
......
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