From 40543ca0dec398aceab2d71794d271b47dd89b6e Mon Sep 17 00:00:00 2001 From: Douglas Hall Date: Tue, 21 Jun 2016 10:47:46 -0400 Subject: [PATCH 1/7] Upgrade edx-proctoring to 0.12.20 --- requirements/edx/github.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/edx/github.txt b/requirements/edx/github.txt index 3ef76c490c..856f1c6e9a 100644 --- a/requirements/edx/github.txt +++ b/requirements/edx/github.txt @@ -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 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/edx-proctoring.git@0.12.19#egg=edx-proctoring==0.12.19 +git+https://github.com/edx/edx-proctoring.git@0.12.20#egg=edx-proctoring==0.12.20 # Third Party XBlocks -e git+https://github.com/mitodl/edx-sga@172a90fd2738f8142c10478356b2d9ed3e55334a#egg=edx-sga From ad45681a530d098e3e82a0f393b76d9531843698 Mon Sep 17 00:00:00 2001 From: Michael Frey Date: Mon, 20 Jun 2016 16:54:13 -0400 Subject: [PATCH 2/7] mjfrey/micro-settings-merge: Override base dictionary keys with microsite configuration keys * mattdrayer: Add helpers.get_value test * mattdrayer: Change to simpler implementation, per @douglashall * mattdrayer: Address quality violations and test failures --- .../course_modes/tests/test_views.py | 19 +++++++------- common/djangoapps/student/tests/test_email.py | 2 +- common/djangoapps/student/tests/tests.py | 2 +- lms/djangoapps/branding/tests/test_views.py | 2 +- lms/djangoapps/commerce/tests/test_views.py | 2 +- .../tests/test_comprehensive_theming.py | 2 +- .../tests/test_comprehensive_theming.py | 2 +- .../courseware/tests/test_footer.py | 2 +- .../student_account/test/test_views.py | 2 +- .../verify_student/tests/test_views.py | 2 +- openedx/core/djangoapps/theming/helpers.py | 26 ++++++++++++++++--- .../core/djangoapps/theming/tests/__init__.py | 0 .../djangoapps/theming/tests/test_helpers.py | 25 ++++++++++++++++++ .../theming/{ => tests}/test_util.py | 2 +- 14 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 openedx/core/djangoapps/theming/tests/__init__.py create mode 100644 openedx/core/djangoapps/theming/tests/test_helpers.py rename openedx/core/djangoapps/theming/{ => tests}/test_util.py (97%) diff --git a/common/djangoapps/course_modes/tests/test_views.py b/common/djangoapps/course_modes/tests/test_views.py index b8c5161ddf..8fa21e0fde 100644 --- a/common/djangoapps/course_modes/tests/test_views.py +++ b/common/djangoapps/course_modes/tests/test_views.py @@ -9,21 +9,22 @@ import ddt import freezegun from mock import patch from nose.plugins.attrib import attr + from django.conf import settings 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 util.testing import UrlResetMixin -from embargo.test_utils import restrict_course from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.factories import CourseFactory -from course_modes.tests.factories import CourseModeFactory -from student.tests.factories import CourseEnrollmentFactory, UserFactory -from student.models import CourseEnrollment -import lms.djangoapps.commerce.tests.test_utils as ecomm_test_utils + from course_modes.models import CourseMode, Mode -from openedx.core.djangoapps.theming.test_util import with_is_edx_domain +from course_modes.tests.factories import CourseModeFactory +from embargo.test_utils import restrict_course +from student.models import CourseEnrollment +from student.tests.factories import CourseEnrollmentFactory, UserFactory +from util.testing import UrlResetMixin @attr('shard_3') @@ -373,7 +374,7 @@ class CourseModeViewTest(UrlResetMixin, ModuleStoreTestCase): self.assertEquals(course_modes, expected_modes) @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): # Create the course modes for mode in ["honor", "verified"]: diff --git a/common/djangoapps/student/tests/test_email.py b/common/djangoapps/student/tests/test_email.py index 3c44111608..2bd303c91d 100644 --- a/common/djangoapps/student/tests/test_email.py +++ b/common/djangoapps/student/tests/test_email.py @@ -20,7 +20,7 @@ from django.conf import settings from edxmako.shortcuts import render_to_string from util.request import safe_get_host 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 diff --git a/common/djangoapps/student/tests/tests.py b/common/djangoapps/student/tests/tests.py index a16101e928..26a3df4117 100644 --- a/common/djangoapps/student/tests/tests.py +++ b/common/djangoapps/student/tests/tests.py @@ -46,7 +46,7 @@ from certificates.tests.factories import GeneratedCertificateFactory # pylint: from lms.djangoapps.verify_student.models import SoftwareSecurePhotoVerification import shoppingcart # pylint: disable=import-error 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 from config_models.models import cache diff --git a/lms/djangoapps/branding/tests/test_views.py b/lms/djangoapps/branding/tests/test_views.py index a6cb5d7249..eb62bf2282 100644 --- a/lms/djangoapps/branding/tests/test_views.py +++ b/lms/djangoapps/branding/tests/test_views.py @@ -10,7 +10,7 @@ import mock import ddt from config_models.models import cache 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 diff --git a/lms/djangoapps/commerce/tests/test_views.py b/lms/djangoapps/commerce/tests/test_views.py index 703a518c12..b28fd7a84b 100644 --- a/lms/djangoapps/commerce/tests/test_views.py +++ b/lms/djangoapps/commerce/tests/test_views.py @@ -8,7 +8,7 @@ from django.test import TestCase import mock 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): diff --git a/lms/djangoapps/course_wiki/tests/test_comprehensive_theming.py b/lms/djangoapps/course_wiki/tests/test_comprehensive_theming.py index 536ccc7f54..e32af4991f 100644 --- a/lms/djangoapps/course_wiki/tests/test_comprehensive_theming.py +++ b/lms/djangoapps/course_wiki/tests/test_comprehensive_theming.py @@ -9,7 +9,7 @@ from wiki.models import URLPath from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase 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 course_wiki.views import get_or_create_root diff --git a/lms/djangoapps/courseware/tests/test_comprehensive_theming.py b/lms/djangoapps/courseware/tests/test_comprehensive_theming.py index 752eb81030..ee28177a15 100644 --- a/lms/djangoapps/courseware/tests/test_comprehensive_theming.py +++ b/lms/djangoapps/courseware/tests/test_comprehensive_theming.py @@ -6,7 +6,7 @@ from django.test import TestCase from path import path # pylint: disable=no-name-in-module 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 diff --git a/lms/djangoapps/courseware/tests/test_footer.py b/lms/djangoapps/courseware/tests/test_footer.py index 0a14ee1860..44cc93cbdd 100644 --- a/lms/djangoapps/courseware/tests/test_footer.py +++ b/lms/djangoapps/courseware/tests/test_footer.py @@ -9,7 +9,7 @@ from django.conf import settings from django.test import TestCase 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') diff --git a/lms/djangoapps/student_account/test/test_views.py b/lms/djangoapps/student_account/test/test_views.py index c5f2c7fe66..7815d24fa5 100644 --- a/lms/djangoapps/student_account/test/test_views.py +++ b/lms/djangoapps/student_account/test/test_views.py @@ -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 util.testing import UrlResetMixin 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 diff --git a/lms/djangoapps/verify_student/tests/test_views.py b/lms/djangoapps/verify_student/tests/test_views.py index b937699999..d5231e2d48 100644 --- a/lms/djangoapps/verify_student/tests/test_views.py +++ b/lms/djangoapps/verify_student/tests/test_views.py @@ -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 embargo.test_utils import restrict_course 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 student.tests.factories import UserFactory, CourseEnrollmentFactory from student.models import CourseEnrollment diff --git a/openedx/core/djangoapps/theming/helpers.py b/openedx/core/djangoapps/theming/helpers.py index 28ce710ebe..82434934cb 100644 --- a/openedx/core/djangoapps/theming/helpers.py +++ b/openedx/core/djangoapps/theming/helpers.py @@ -1,10 +1,10 @@ """ - 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 microsite_configuration import microsite, page_title_breadcrumbs + def get_page_title_breadcrumbs(*args): """ @@ -17,7 +17,25 @@ def get_value(val_name, default=None, **kwargs): """ 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): diff --git a/openedx/core/djangoapps/theming/tests/__init__.py b/openedx/core/djangoapps/theming/tests/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openedx/core/djangoapps/theming/tests/test_helpers.py b/openedx/core/djangoapps/theming/tests/test_helpers.py new file mode 100644 index 0000000000..536e9cc657 --- /dev/null +++ b/openedx/core/djangoapps/theming/tests/test_helpers.py @@ -0,0 +1,25 @@ +""" +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) diff --git a/openedx/core/djangoapps/theming/test_util.py b/openedx/core/djangoapps/theming/tests/test_util.py similarity index 97% rename from openedx/core/djangoapps/theming/test_util.py rename to openedx/core/djangoapps/theming/tests/test_util.py index fbd871c213..6f13b9c187 100644 --- a/openedx/core/djangoapps/theming/test_util.py +++ b/openedx/core/djangoapps/theming/tests/test_util.py @@ -15,7 +15,7 @@ from django.test.utils import override_settings 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" From 7b86da02f792e8f7b499e1fd955d8c57300fbefb Mon Sep 17 00:00:00 2001 From: Douglas Hall Date: Wed, 22 Jun 2016 11:49:49 -0400 Subject: [PATCH 3/7] Check theme overrides when retrieving platform name from settings --- lms/templates/emails/activation_email.txt | 9 ++++++--- lms/templates/emails/activation_email_subject.txt | 5 ++++- lms/templates/emails/email_change.txt | 10 ++++++++-- lms/templates/emails/email_change_subject.txt | 5 ++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lms/templates/emails/activation_email.txt b/lms/templates/emails/activation_email.txt index 56a49702b6..a697fada1a 100644 --- a/lms/templates/emails/activation_email.txt +++ b/lms/templates/emails/activation_email.txt @@ -1,10 +1,13 @@ <%! 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 " "{platform_name} account. Click on the link below or copy and " "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: @@ -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 " "receive any more email from us. Please do not reply to this e-mail; " "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))} diff --git a/lms/templates/emails/activation_email_subject.txt b/lms/templates/emails/activation_email_subject.txt index 01514b5f4f..8fb64f9abc 100644 --- a/lms/templates/emails/activation_email_subject.txt +++ b/lms/templates/emails/activation_email_subject.txt @@ -1,3 +1,6 @@ <%! 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 +))} diff --git a/lms/templates/emails/email_change.txt b/lms/templates/emails/email_change.txt index 79f8929f99..618320fb49 100644 --- a/lms/templates/emails/email_change.txt +++ b/lms/templates/emails/email_change.txt @@ -1,8 +1,14 @@ <%! 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 " "{platform_name} account from {old_email} to {new_email}. " "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: https://${ site }/email_confirm/${ key } @@ -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 " "receive any more email from us. Please do not reply to this e-mail; " "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))} diff --git a/lms/templates/emails/email_change_subject.txt b/lms/templates/emails/email_change_subject.txt index 7c9e3fb400..acc114bb98 100644 --- a/lms/templates/emails/email_change_subject.txt +++ b/lms/templates/emails/email_change_subject.txt @@ -1,2 +1,5 @@ <%! 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) +)} From 51d85809822a4720c8d883c362dd68c37185160b Mon Sep 17 00:00:00 2001 From: Douglas Hall Date: Wed, 22 Jun 2016 12:33:58 -0400 Subject: [PATCH 4/7] Fix default from email lookups --- common/djangoapps/student/forms.py | 2 +- common/djangoapps/student/tests/test_email.py | 4 ++-- .../djangoapps/student/tests/test_reset_password.py | 2 +- common/djangoapps/student/views.py | 8 ++++---- lms/djangoapps/bulk_email/tasks.py | 2 +- lms/templates/emails/confirm_email_change.txt | 11 ++++++++--- openedx/core/djangoapps/credit/email_utils.py | 2 +- openedx/core/djangoapps/user_api/accounts/api.py | 2 +- 8 files changed, 19 insertions(+), 14 deletions(-) diff --git a/common/djangoapps/student/forms.py b/common/djangoapps/student/forms.py index 095b7cc21c..84bdb17e0c 100644 --- a/common/djangoapps/student/forms.py +++ b/common/djangoapps/student/forms.py @@ -58,7 +58,7 @@ class PasswordResetFormNoActive(PasswordResetForm): email_template_name='registration/password_reset_email.html', use_https=False, 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 ): """ diff --git a/common/djangoapps/student/tests/test_email.py b/common/djangoapps/student/tests/test_email.py index 2bd303c91d..e97311b9cd 100644 --- a/common/djangoapps/student/tests/test_email.py +++ b/common/djangoapps/student/tests/test_email.py @@ -57,7 +57,7 @@ class EmailTestMixin(object): email_user.assert_called_with( mock_render_to_string(subject_template, subject_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): @@ -298,7 +298,7 @@ class EmailChangeRequestTests(EventTestMixin, TestCase): send_mail.assert_called_with( mock_render_to_string('emails/email_change_subject.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] ) self.assert_event_emitted( diff --git a/common/djangoapps/student/tests/test_reset_password.py b/common/djangoapps/student/tests/test_reset_password.py index 96cca17e7a..6ca006765b 100644 --- a/common/djangoapps/student/tests/test_reset_password.py +++ b/common/djangoapps/student/tests/test_reset_password.py @@ -125,7 +125,7 @@ class ResetPasswordTests(EventTestMixin, CacheIsolationTestCase): (subject, msg, from_addr, to_addrs) = send_email.call_args[0] self.assertIn("Password reset", subject) 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.assertIn(self.user.email, to_addrs) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 6db07a4bac..b502dc6bea 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -2229,11 +2229,11 @@ def reactivation_email_for_user(user): message = render_to_string('emails/activation_email.txt', context) 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 log.error( 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 ) return JsonResponse({ @@ -2357,7 +2357,7 @@ def confirm_email_change(request, key): # pylint: disable=unused-argument user.email_user( subject, 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 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 user.email_user( subject, 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 log.warning('Unable to send confirmation email to new address', exc_info=True) diff --git a/lms/djangoapps/bulk_email/tasks.py b/lms/djangoapps/bulk_email/tasks.py index 3fd044fd94..021fce34a8 100644 --- a/lms/djangoapps/bulk_email/tasks.py +++ b/lms/djangoapps/bulk_email/tasks.py @@ -389,7 +389,7 @@ def _get_source_address(course_id, course_title, truncate=True): course_title=course_title_no_quotes, course_name=course_name, from_email=theming_helpers.get_value( - 'bulk_email_default_from_email', + 'email_from_address', settings.BULK_EMAIL_DEFAULT_FROM_EMAIL ) ) diff --git a/lms/templates/emails/confirm_email_change.txt b/lms/templates/emails/confirm_email_change.txt index ae33c82609..b462d78e37 100644 --- a/lms/templates/emails/confirm_email_change.txt +++ b/lms/templates/emails/confirm_email_change.txt @@ -1,9 +1,15 @@ <%! from django.core.urlresolvers import reverse %> <%! 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 " "{platform_name} from {old_email} to {new_email}. If you " "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: https://${ site }${reverse('contact')} @@ -11,5 +17,4 @@ ${_("This is to confirm that you changed the e-mail associated with " http://${ site }${reverse('contact')} % endif -${_("We keep a log of old e-mails, so if this request was unintentional, we " - "can investigate.")} +${_("We keep a log of old e-mails, so if this request was unintentional, we can investigate.")} diff --git a/openedx/core/djangoapps/credit/email_utils.py b/openedx/core/djangoapps/credit/email_utils.py index 263cee2fce..2993020e89 100644 --- a/openedx/core/djangoapps/credit/email_utils.py +++ b/openedx/core/djangoapps/credit/email_utils.py @@ -125,7 +125,7 @@ def send_credit_notifications(username, course_key): notification_msg.attach(logo_image) # 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 # send the root email message diff --git a/openedx/core/djangoapps/user_api/accounts/api.py b/openedx/core/djangoapps/user_api/accounts/api.py index 48d4e10433..0361e3a761 100644 --- a/openedx/core/djangoapps/user_api/accounts/api.py +++ b/openedx/core/djangoapps/user_api/accounts/api.py @@ -398,7 +398,7 @@ def request_password_change(email, orig_host, is_secure): # Generate a single-use link for performing a password reset # and email it to the user. 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, use_https=is_secure ) From 07f5bacce29b434f0e1574df431ed3ed942f8104 Mon Sep 17 00:00:00 2001 From: Adam Palay Date: Thu, 23 Jun 2016 13:07:15 -0500 Subject: [PATCH 5/7] Revert "AC-454 adding visual clarify for selected menu options" This reverts commit 55d84d34b854a00a15f04a98920c2e64d201c96c. --- .../xmodule/xmodule/css/video/display.scss | 2 - .../js/fixtures/video_yt_multiple.html | 9 +- .../xmodule/xmodule/js/karma_xmodule.conf.js | 9 +- .../xmodule/xmodule/js/spec/main_requirejs.js | 40 +--- .../js/spec/video/video_caption_spec.js | 4 +- .../js/spec/video/video_speed_control_spec.js | 14 +- .../js/src/video/08_video_speed_control.js | 79 ++----- .../xmodule/js/src/video/09_video_caption.js | 195 ++++++------------ lms/static/karma_lms_coffee.conf.js | 23 +-- .../lms/js/spec/main_requirejs_coffee.js | 38 +--- 10 files changed, 116 insertions(+), 297 deletions(-) diff --git a/common/lib/xmodule/xmodule/css/video/display.scss b/common/lib/xmodule/xmodule/css/video/display.scss index 060842d788..bd478ab0a2 100644 --- a/common/lib/xmodule/xmodule/css/video/display.scss +++ b/common/lib/xmodule/xmodule/css/video/display.scss @@ -535,8 +535,6 @@ .speed-option, .control-lang { - @include border-left($baseline/10 solid rgb(14, 166, 236)); - font-weight: $font-bold; color: rgb(14, 166, 236); // UXPL primary accent } } diff --git a/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html b/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html index c941c535a6..d4f5401785 100644 --- a/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html +++ b/common/lib/xmodule/xmodule/js/fixtures/video_yt_multiple.html @@ -55,9 +55,8 @@ -
-
-
+ +
@@ -109,9 +108,7 @@ -
-
-
+
diff --git a/common/lib/xmodule/xmodule/js/karma_xmodule.conf.js b/common/lib/xmodule/xmodule/js/karma_xmodule.conf.js index 3f72dcb7b0..5ee38962a7 100644 --- a/common/lib/xmodule/xmodule/js/karma_xmodule.conf.js +++ b/common/lib/xmodule/xmodule/js/karma_xmodule.conf.js @@ -20,10 +20,12 @@ var options = { libraryFilesToInclude: [ {pattern: 'common_static/js/vendor/requirejs/require.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/common/js/vendor/underscore.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/draggabilly.js'}, {pattern: 'common_static/common/js/vendor/jquery.js', included: true}, @@ -48,14 +50,11 @@ var options = { {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-extensions.js', included: true}, - {pattern: 'common_static/js/vendor/sinon-1.17.0.js', included: true}, - - {pattern: 'spec/main_requirejs.js', included: true}, + {pattern: 'common_static/js/vendor/sinon-1.17.0.js', included: true} ], libraryFiles: [ - {pattern: 'common_static/edx-pattern-library/js/**/*.js'}, - {pattern: 'common_static/edx-ui-toolkit/js/**/*.js'} + {pattern: 'common_static/edx-pattern-library/js/**/*.js'} ], // Make sure the patterns in sourceFiles and specFiles do not match the same file. diff --git a/common/lib/xmodule/xmodule/js/spec/main_requirejs.js b/common/lib/xmodule/xmodule/js/spec/main_requirejs.js index d4692469e5..a57497f8c8 100644 --- a/common/lib/xmodule/xmodule/js/spec/main_requirejs.js +++ b/common/lib/xmodule/xmodule/js/spec/main_requirejs.js @@ -1,36 +1,4 @@ -(function(requirejs, define) { - '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"); - } +(function(requirejs) { requirejs.config({ baseUrl: '/base/', paths: { @@ -38,8 +6,7 @@ "modernizr": "common_static/edx-pattern-library/js/modernizr-custom", "afontgarde": "common_static/edx-pattern-library/js/afontgarde", "edxicons": "common_static/edx-pattern-library/js/edx-icons", - "draggabilly": "common_static/js/vendor/draggabilly", - 'edx-ui-toolkit': 'common_static/edx-ui-toolkit' + "draggabilly": "common_static/js/vendor/draggabilly" }, "moment": { exports: "moment" @@ -51,4 +18,5 @@ exports: "AFontGarde" } }); -}).call(this, RequireJS.requirejs, RequireJS.define); + +}).call(this, RequireJS.requirejs); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js index 5d85be2551..b8cf3065b1 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_caption_spec.js @@ -266,7 +266,6 @@ expect($('.closed-captions')).toHaveAttrs({ 'lang': 'de' }); - expect(link).toHaveAttr('aria-pressed', 'true'); }); it('when clicking on link with current language', function () { @@ -285,7 +284,6 @@ expect(state.storage.setItem) .not.toHaveBeenCalledWith('language', 'en'); expect($('.langs-list li.is-active').length).toBe(1); - expect(link).toHaveAttr('aria-pressed', 'true'); }); it('open the language toggle on hover', function () { @@ -415,7 +413,7 @@ }); 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.' ); }); diff --git a/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js b/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js index f73b1f3c59..2a8b5e8b67 100644 --- a/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js +++ b/common/lib/xmodule/xmodule/js/spec/video/video_speed_control_spec.js @@ -203,18 +203,16 @@ describe('onSpeedChange', function () { beforeEach(function () { 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); }); it('set the new speed as active', function () { - expect($('li[data-speed="1.0"]')).not.toHaveClass('is-active'); - expect($('li[data-speed="1.0"] .speed-option').attr('aria-pressed')).not.toEqual('true'); - - expect($('li[data-speed="0.75"]')).toHaveClass('is-active'); - expect($('li[data-speed="0.75"] .speed-option').attr('aria-pressed')).toEqual('true'); - - expect($('.speeds .speed-button .value')).toHaveHtml('0.75x'); + expect($('.video-speeds li[data-speed="1.0"]')) + .not.toHaveClass('is-active'); + expect($('.video-speeds li[data-speed="0.75"]')) + .toHaveClass('is-active'); + expect($('.speeds .value')).toHaveHtml('0.75x'); }); }); diff --git a/common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js b/common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js index b54de6a24a..986d9ea7ff 100644 --- a/common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js +++ b/common/lib/xmodule/xmodule/js/src/video/08_video_speed_control.js @@ -1,10 +1,9 @@ (function (requirejs, require, define) { "use strict"; define( -'video/08_video_speed_control.js', [ - 'video/00_iterator.js', - 'edx-ui-toolkit/js/utils/html-utils' -], function (Iterator, HtmlUtils) { +'video/08_video_speed_control.js', +['video/00_iterator.js'], +function (Iterator) { /** * Video speed control module. * @exports video/08_video_speed_control.js @@ -96,37 +95,23 @@ define( * Creates any necessary DOM elements, attach them, and set their, * initial configuration. * @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, reversedSpeeds = speeds.concat().reverse(), speedsList = $.map(reversedSpeeds, function (speed) { - return HtmlUtils.interpolateHtml( - HtmlUtils.joinHtml( - HtmlUtils.HTML('
  • '), - HtmlUtils.HTML(''), - HtmlUtils.HTML('
  • ') - ), - { - speed: speed - } - ).toString(); + return [ + '
  • ', + '', + '
  • ' + ].join(''); }); - HtmlUtils.setHtml( - speedsContainer, - HtmlUtils.HTML(speedsList) - ); + speedsContainer.html(speedsList.join('')); this.speedLinks = new Iterator(speedsContainer.find('.speed-option')); - HtmlUtils.prepend( - this.state.el.find('.secondary-controls'), - HtmlUtils.HTML(this.el) - ); - this.setActiveSpeed(currentSpeed); + this.state.el.find('.secondary-controls').prepend(this.el); }, /** @@ -231,38 +216,17 @@ define( if (speed !== this.currentSpeed || forceUpdate) { this.speedsContainer .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; if (!silent) { 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( * @param {jquery Event} event */ clickLinkHandler: function (event) { - var el = $(event.currentTarget).parent(), - speed = $(el).data('speed'); - - this.resetActiveSpeed(); - this.setActiveSpeed(speed); + var speed = $(event.currentTarget).parent().data('speed'); + + this.closeMenu(); this.state.videoCommands.execute('speed', speed); - this.closeMenu(true); return false; }, diff --git a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js index dd409e7a91..b99a1b1128 100644 --- a/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js +++ b/common/lib/xmodule/xmodule/js/src/video/09_video_caption.js @@ -5,12 +5,11 @@ define('video/09_video_caption.js',[ 'video/00_sjson.js', 'video/00_async_process.js', - 'edx-ui-toolkit/js/utils/html-utils', 'draggabilly', 'modernizr', 'afontgarde', 'edxicons' - ], function (Sjson, AsyncProcess, HtmlUtils, Draggabilly) { + ], function (Sjson, AsyncProcess, Draggabilly) { /** * @desc VideoCaption module exports a function. @@ -81,53 +80,47 @@ renderElements: function () { var languages = this.state.config.transcriptLanguages; - var langHtml = HtmlUtils.joinHtml( - HtmlUtils.HTML('
    '), - HtmlUtils.HTML(''), - HtmlUtils.HTML(''), - HtmlUtils.HTML(')') - ); + '">', + '', + '', + '', + '', + '', + '
    ', + '' + ].join(''); - var subtitlesHtml = HtmlUtils.interpolateHtml( - HtmlUtils.joinHtml( - HtmlUtils.HTML('
    '), - HtmlUtils.HTML('

    '), - HtmlUtils.HTML('
      '), - HtmlUtils.HTML('
      ') - ), - { - courseId: this.state.id, - courseLang: this.state.lang - } - ); + var template = [ + '
      ', + '

      ', + '
        ', + '
        ' + ].join(''); this.loaded = false; - this.subtitlesEl = $(HtmlUtils.ensureHtml(subtitlesHtml).toString()); + this.subtitlesEl = $(template); this.subtitlesMenuEl = this.subtitlesEl.find('.subtitles-menu'); - this.container = $(HtmlUtils.ensureHtml(langHtml).toString()); + this.container = $(langTemplate); this.captionControlEl = this.container.find('.toggle-captions'); this.captionDisplayEl = this.state.el.find('.closed-captions'); this.transcriptControlEl = this.container.find('.toggle-transcript'); @@ -549,26 +542,15 @@ } } else { if (state.isTouch) { - HtmlUtils.setHtml( - self.subtitlesEl.find('.subtitles-menu'), - HtmlUtils.joinHtml( - HtmlUtils.HTML('
      1. '), - gettext('Transcript will be displayed when you start playing the video.'), - HtmlUtils.HTML('
      2. ') - ) - ); + self.subtitlesEl.find('.subtitles-menu') + .text(gettext('Transcript will be displayed when you start playing the video.')) // jshint ignore: line + .wrapInner('
      3. '); } else { self.renderCaption(start, captions); } self.hideCaptions(state.hide_captions, false); - HtmlUtils.append( - self.state.el.find('.video-wrapper').parent(), - HtmlUtils.HTML(self.subtitlesEl) - ); - HtmlUtils.append( - self.state.el.find('.secondary-controls'), - HtmlUtils.HTML(self.container) - ); + self.state.el.find('.video-wrapper').after(self.subtitlesEl); + self.state.el.find('.secondary-controls').append(self.container); self.bindHandlers(); } @@ -648,11 +630,9 @@ onResize: function () { this.subtitlesEl .find('.spacing').first() - .height(this.topSpacingHeight()); - - this.subtitlesEl + .height(this.topSpacingHeight()).end() .find('.spacing').last() - .height(this.bottomSpacingHeight()); + .height(this.bottomSpacingHeight()); this.scrollCaption(); this.setSubtitlesHeight(); @@ -669,9 +649,8 @@ renderLanguageMenu: function (languages) { var self = this, state = this.state, - $menu = $('