From 71aaf6127e921901b0e80c059257ce752b855770 Mon Sep 17 00:00:00 2001 From: Eric Fischer Date: Thu, 16 Nov 2017 13:08:18 -0500 Subject: [PATCH 01/11] Follow up to #16473 This rule needs an !important in order to override the inline style --- lms/static/sass/discussion/_mixins.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/static/sass/discussion/_mixins.scss b/lms/static/sass/discussion/_mixins.scss index b0ff8ac283..26e938ca42 100644 --- a/lms/static/sass/discussion/_mixins.scss +++ b/lms/static/sass/discussion/_mixins.scss @@ -77,7 +77,7 @@ } svg { - max-width: 100%; + max-width: 100% !important; } } From 13ca6343ce4a241f4a5b1382b8f9ccb98e86c5e4 Mon Sep 17 00:00:00 2001 From: bmedx Date: Thu, 16 Nov 2017 15:38:18 -0500 Subject: [PATCH 02/11] Fix lang mapping for zh_HANS --- conf/locale/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/locale/config.yaml b/conf/locale/config.yaml index 93bb7a4c22..5d9374a1e4 100644 --- a/conf/locale/config.yaml +++ b/conf/locale/config.yaml @@ -2,7 +2,7 @@ # This will copy each source language to a new directory at the end of the i18n generate step # which allows us to migrate to a new locale code without re-creating the Transifex project. -edx-lang-map: +edx_lang_map: zh_CN: zh_HANS locales: From f93696ca85ccee77a52136690e6c4a4ca1b24ed4 Mon Sep 17 00:00:00 2001 From: bmedx Date: Thu, 16 Nov 2017 17:35:41 -0500 Subject: [PATCH 03/11] Move suggested_prices to CharField for Django 1.11 compat CommaSeparatedIntegerField is deprecated, this is the replacement. I have confirmed there is no SQL generated for this migration since it is already a CharField behind the scenes. --- .../0009_suggested_prices_to_charfield.py | 21 +++++++++++++++++++ common/djangoapps/course_modes/models.py | 5 +++-- 2 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py diff --git a/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py b/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py new file mode 100644 index 0000000000..60ed720cfd --- /dev/null +++ b/common/djangoapps/course_modes/migrations/0009_suggested_prices_to_charfield.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import re +import django.core.validators + + +class Migration(migrations.Migration): + + dependencies = [ + ('course_modes', '0008_course_key_field_to_foreign_key'), + ] + + operations = [ + migrations.AlterField( + model_name='coursemode', + name='suggested_prices', + field=models.CharField(default=b'', max_length=255, blank=True, validators=[django.core.validators.RegexValidator(re.compile('^[\\d,]+\\Z'), 'Enter only digits separated by commas.', 'invalid')]), + ), + ] diff --git a/common/djangoapps/course_modes/models.py b/common/djangoapps/course_modes/models.py index 8cdd9e9381..69a352ab62 100644 --- a/common/djangoapps/course_modes/models.py +++ b/common/djangoapps/course_modes/models.py @@ -8,11 +8,11 @@ import pytz from config_models.models import ConfigurationModel from django.conf import settings from django.core.exceptions import ValidationError +from django.core.validators import validate_comma_separated_integer_list from django.db import models from django.db.models import Q from django.dispatch import receiver from django.utils.translation import ugettext_lazy as _ -from django.utils.encoding import force_text from openedx.core.djangoapps.content.course_overviews.models import CourseOverview from opaque_keys.edx.keys import CourseKey @@ -103,7 +103,8 @@ class CourseMode(models.Model): # DEPRECATED: the suggested prices for this mode # We used to allow users to choose from a set of prices, but we now allow only # a single price. This field has been deprecated by `min_price` - suggested_prices = models.CommaSeparatedIntegerField(max_length=255, blank=True, default='') + suggested_prices = models.CharField(max_length=255, blank=True, default='', + validators=[validate_comma_separated_integer_list]) # optional description override # WARNING: will not be localized From bf2ca3adcd380fa8500c637eb6c00c344605b2b3 Mon Sep 17 00:00:00 2001 From: Hasnain Date: Fri, 17 Nov 2017 12:06:50 +0500 Subject: [PATCH 04/11] WL-1257 | Removed the hard-coded "edX" related strings from nudges emails. --- .../edx_ace/recurringnudge_day10/email/body.html | 4 ++-- .../schedules/edx_ace/recurringnudge_day10/email/body.txt | 4 ++-- .../schedules/edx_ace/recurringnudge_day3/email/body.html | 8 ++++---- .../schedules/edx_ace/recurringnudge_day3/email/body.txt | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html index a4a5eb1342..a50b8e11f8 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.html @@ -24,12 +24,12 @@

{% if course_ids|length > 1 %} {% blocktrans trimmed %} - Many edX learners are completing more problems every week, and + Many {{ platform_name }} learners are completing more problems every week, and participating in the discussion forums. What do you want to do to keep learning? {% endblocktrans %} {% else %} {% blocktrans trimmed %} - Many edX learners in {{course_name}} are completing more problems every week, and + Many {{ platform_name }} learners in {{course_name}} are completing more problems every week, and participating in the discussion forums. What do you want to do to keep learning? {% endblocktrans %} {% endif %} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.txt b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.txt index 9a6e8cf8eb..66003da88f 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.txt +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day10/email/body.txt @@ -1,13 +1,13 @@ {% load i18n %} {% if course_ids|length > 1 %} {% blocktrans trimmed %} - Many edX learners are completing more problems every week, and + Many {{ platform_name }} learners are completing more problems every week, and participating in the discussion forums. What do you want to do to keep learning? {% endblocktrans %} {% trans "Keep learning" %} <{{dashboard_url}}> {% else %} {% blocktrans trimmed %} - Many edX learners in {{course_name}} are completing more problems every week, and + Many {{ platform_name }} learners in {{course_name}} are completing more problems every week, and participating in the discussion forums. What do you want to do to keep learning? {% endblocktrans %} {% trans "Keep learning" %} <{{course_url}}> diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html index 551ba7792b..d748594fc7 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.html @@ -4,12 +4,12 @@ {% block preview_text %} {% if course_ids|length > 1 %} {% blocktrans trimmed %} - Remember when you enrolled in {{ course_name }}, and other courses on edX.org? We do, and we’re glad + Remember when you enrolled in {{ course_name }}, and other courses on {{ platform_name }}? We do, and we’re glad to have you! Come see what everyone is learning. {% endblocktrans %} {% else %} {% blocktrans trimmed %} - Remember when you enrolled in {{ course_name }} on edX.org? We do, and we’re glad + Remember when you enrolled in {{ course_name }} on {{ platform_name }}? We do, and we’re glad to have you! Come see what everyone is learning. {% endblocktrans %} {% endif %} @@ -24,12 +24,12 @@

{% if course_ids|length > 1 %} {% blocktrans trimmed %} - Remember when you enrolled in {{ course_name }}, and other courses on edX.org? We do, and we’re glad + Remember when you enrolled in {{ course_name }}, and other courses on {{ platform_name }}? We do, and we’re glad to have you! Come see what everyone is learning. {% endblocktrans %} {% else %} {% blocktrans trimmed %} - Remember when you enrolled in {{ course_name }} on edX.org? We do, and we’re glad + Remember when you enrolled in {{ course_name }} on {{ platform_name }}? We do, and we’re glad to have you! Come see what everyone is learning. {% endblocktrans %} {% endif %} diff --git a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.txt b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.txt index efcfeba1bf..bd1b74f140 100644 --- a/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.txt +++ b/openedx/core/djangoapps/schedules/templates/schedules/edx_ace/recurringnudge_day3/email/body.txt @@ -2,14 +2,14 @@ {% if course_ids|length > 1 %} {% blocktrans trimmed %} - Remember when you enrolled in {{ course_name }}, and other courses on edX.org? We do, and we’re glad + Remember when you enrolled in {{ course_name }}, and other courses on {{ platform_name }}? We do, and we’re glad to have you! Come see what everyone is learning. {% endblocktrans %} {% trans "Start learning now" %} <{{ dashboard_url }}> {% else %} {% blocktrans trimmed %} - Remember when you enrolled in {{ course_name }} on edX.org? We do, and we’re glad + Remember when you enrolled in {{ course_name }} on {{ platform_name }}? We do, and we’re glad to have you! Come see what everyone is learning. {% endblocktrans %} From e77137c2f96fda04b904dd3b07d3b78d43ef6051 Mon Sep 17 00:00:00 2001 From: Sofiya Semenova Date: Fri, 17 Nov 2017 15:32:56 -0500 Subject: [PATCH 05/11] Don't get the site object unless the message is going to be sent --- lms/djangoapps/discussion/tasks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lms/djangoapps/discussion/tasks.py b/lms/djangoapps/discussion/tasks.py index 5c5fe4fcfa..ed360dc3e7 100644 --- a/lms/djangoapps/discussion/tasks.py +++ b/lms/djangoapps/discussion/tasks.py @@ -3,7 +3,6 @@ Defines asynchronous celery task for sending email notification (through edx-ace pertaining to new discussion forum comments. """ import logging -from urllib import urlencode from urlparse import urljoin from celery import task @@ -41,8 +40,9 @@ class ResponseNotification(MessageType): @task(base=LoggedTask, routing_key=ROUTING_KEY) def send_ace_message(context): context['course_id'] = CourseKey.from_string(context['course_id']) - context['site'] = Site.objects.get(id=context['site_id']) + if _should_send_message(context): + context['site'] = Site.objects.get(id=context['site_id']) thread_author = User.objects.get(id=context['thread_author_id']) middleware_classes = [ CurrentRequestUserMiddleware, From c78ccf8fc1e506b87dffdb47f37937bfc2d4e13a Mon Sep 17 00:00:00 2001 From: John Eskew Date: Wed, 15 Nov 2017 20:36:10 -0500 Subject: [PATCH 06/11] Fix the systems parsing code for pylint. Add lower pylint error threshold to guard against unsuccessful runs. Increase upper pylint threshold. Add tests for pylint option parsing. --- pavelib/paver_tests/test_paver_quality.py | 30 ++++++++++- pavelib/quality.py | 64 ++++++++++++++++------- scripts/all-tests.sh | 3 +- scripts/circle-ci-tests.sh | 2 +- scripts/generic-ci-tests.sh | 2 +- 5 files changed, 78 insertions(+), 23 deletions(-) diff --git a/pavelib/paver_tests/test_paver_quality.py b/pavelib/paver_tests/test_paver_quality.py index 2ced4b8cfe..8e35861ac5 100644 --- a/pavelib/paver_tests/test_paver_quality.py +++ b/pavelib/paver_tests/test_paver_quality.py @@ -8,7 +8,7 @@ import unittest import paver.easy import paver.tasks -from ddt import ddt, file_data +from ddt import ddt, file_data, data, unpack from mock import MagicMock, mock_open, patch from path import Path as path from paver.easy import BuildFailure @@ -60,6 +60,34 @@ class TestPaverQualityViolations(unittest.TestCase): self.assertEqual(num, 2) +@ddt +class TestPaverQualityOptions(unittest.TestCase): + """ + Tests the paver pylint command-line options parsing. + """ + @data( + ({'limit': '5500'}, (-1, 5500, False, pavelib.quality.ALL_SYSTEMS.split(','))), + ({'limit': '1000:5500'}, (1000, 5500, False, pavelib.quality.ALL_SYSTEMS.split(','))), + ({'limit': '1:2:3:4:5'}, (1, 2, False, pavelib.quality.ALL_SYSTEMS.split(','))), + ({'system': 'lms,cms'}, (-1, -1, False, ['lms', 'cms'])), + ( + {'limit': '2000:5000', 'errors': True, 'system': 'lms,cms,openedx'}, + (2000, 5000, True, ['lms', 'cms', 'openedx']) + ), + ) + @unpack + def test_pylint_parser_other_string(self, options, expected_values): + class PaverOptions(object): + """ + Simple options class to mimick paver's Namespace object. + """ + def __init__(self, d): + self.__dict__ = d + paver_options = PaverOptions(options) + returned_values = pavelib.quality._parse_pylint_options(paver_options) # pylint: disable=protected-access + self.assertEqual(returned_values, expected_values) + + class TestPaverReportViolationsCounts(unittest.TestCase): """ For testing utility functions for getting counts from reports for diff --git a/pavelib/quality.py b/pavelib/quality.py index 7a954831fc..f533221518 100644 --- a/pavelib/quality.py +++ b/pavelib/quality.py @@ -6,7 +6,6 @@ Check code quality using pep8, pylint, and diff_quality. import json import os import re -from string import join from paver.easy import BuildFailure, call_task, cmdopts, needs, sh, task @@ -15,13 +14,7 @@ from openedx.core.djangolib.markup import HTML from .utils.envs import Env from .utils.timer import timed -ALL_SYSTEMS = [ - 'cms', - 'common', - 'lms', - 'openedx', - 'pavelib', -] +ALL_SYSTEMS = 'lms,cms,common,openedx,pavelib' def top_python_dirs(dirname): @@ -55,7 +48,7 @@ def find_fixme(options): Run pylint on system code, only looking for fixme items. """ num_fixme = 0 - systems = getattr(options, 'system', '').split(',') or ALL_SYSTEMS + systems = getattr(options, 'system', ALL_SYSTEMS).split(',') for system in systems: # Directory to put the pylint report in. @@ -92,7 +85,7 @@ def find_fixme(options): @cmdopts([ ("system=", "s", "System to act on"), ("errors", "e", "Check for errors only"), - ("limit=", "l", "limit for number of acceptable violations"), + ("limit=", "l", "Limits for number of acceptable violations - either or :"), ]) @timed def run_pylint(options): @@ -100,14 +93,12 @@ def run_pylint(options): Run pylint on system code. When violations limit is passed in, fail the task if too many violations are found. """ - num_violations = 0 - violations_limit = int(getattr(options, 'limit', -1)) - errors = getattr(options, 'errors', False) - systems = getattr(options, 'system', '').split(',') or ALL_SYSTEMS + lower_violations_limit, upper_violations_limit, errors, systems = _parse_pylint_options(options) # Make sure the metrics subdirectory exists Env.METRICS_DIR.makedirs_p() + num_violations = 0 for system in systems: # Directory to put the pylint report in. # This makes the folder if it doesn't already exist. @@ -147,10 +138,45 @@ def run_pylint(options): with open(Env.METRICS_DIR / "pylint", "w") as f: f.write(violations_count_str) - # Fail number of violations is greater than the limit - if num_violations > violations_limit > -1: - raise BuildFailure("Failed. Too many pylint violations. " - "The limit is {violations_limit}.".format(violations_limit=violations_limit)) + # Fail when number of violations is less than the lower limit, + # which likely means that pylint did not run successfully. + # If pylint *did* run successfully, then great! Modify the lower limit. + if num_violations < lower_violations_limit > -1: + raise BuildFailure( + "Failed. Too few pylint violations. " + "Expected to see at least {lower_limit} pylint violations. " + "Either pylint is not running correctly -or- " + "the limits should be lowered and/or the lower limit should be removed.".format( + lower_limit=lower_violations_limit + ) + ) + + # Fail when number of violations is greater than the upper limit. + if num_violations > upper_violations_limit > -1: + raise BuildFailure( + "Failed. Too many pylint violations. " + "The limit is {upper_limit}.".format(upper_limit=upper_violations_limit) + ) + + +def _parse_pylint_options(options): + """ + Parse the options passed to run_pylint. + """ + lower_violations_limit = upper_violations_limit = -1 + violations_limit = getattr(options, 'limit', '').split(':') + if violations_limit[0]: + # Limit was specified. + if len(violations_limit) == 1: + # Only upper limit was specified. + upper_violations_limit = int(violations_limit[0]) + else: + # Upper and lower limits were both specified. + lower_violations_limit = int(violations_limit[0]) + upper_violations_limit = int(violations_limit[1]) + errors = getattr(options, 'errors', False) + systems = getattr(options, 'system', ALL_SYSTEMS).split(',') + return lower_violations_limit, upper_violations_limit, errors, systems def _count_pylint_violations(report_file): @@ -244,7 +270,7 @@ def run_complexity(): Uses radon to examine cyclomatic complexity. For additional details on radon, see http://radon.readthedocs.org/ """ - system_string = join(ALL_SYSTEMS, '/ ') + '/' + system_string = '/ '.join(ALL_SYSTEMS.split(',')) + '/' complexity_report_dir = (Env.REPORT_DIR / "complexity") complexity_report = complexity_report_dir / "python_complexity.log" diff --git a/scripts/all-tests.sh b/scripts/all-tests.sh index b435d97a04..8de5bdf801 100755 --- a/scripts/all-tests.sh +++ b/scripts/all-tests.sh @@ -11,7 +11,8 @@ set -e ############################################################################### # Violations thresholds for failing the build -export PYLINT_THRESHOLD=3600 +export LOWER_PYLINT_THRESHOLD=1000 +export UPPER_PYLINT_THRESHOLD=5335 export ESLINT_THRESHOLD=9134 export STYLELINT_THRESHOLD=973 diff --git a/scripts/circle-ci-tests.sh b/scripts/circle-ci-tests.sh index bcc201ff63..391ad2b981 100755 --- a/scripts/circle-ci-tests.sh +++ b/scripts/circle-ci-tests.sh @@ -57,7 +57,7 @@ else echo "Finding pylint violations and storing in report..." # HACK: we need to print something to the console, otherwise circleci # fails and aborts the job because nothing is displayed for > 10 minutes. - paver run_pylint -l $PYLINT_THRESHOLD | tee pylint.log || EXIT=1 + paver run_pylint -l $LOWER_PYLINT_THRESHOLD:$UPPER_PYLINT_THRESHOLD | tee pylint.log || EXIT=1 mkdir -p reports PATH=$PATH:node_modules/.bin diff --git a/scripts/generic-ci-tests.sh b/scripts/generic-ci-tests.sh index abda8cec80..d835b0344f 100755 --- a/scripts/generic-ci-tests.sh +++ b/scripts/generic-ci-tests.sh @@ -84,7 +84,7 @@ case "$TEST_SUITE" in echo "Finding pep8 violations and storing report..." paver run_pep8 > pep8.log || { cat pep8.log; EXIT=1; } echo "Finding pylint violations and storing in report..." - paver run_pylint -l $PYLINT_THRESHOLD > pylint.log || { echo 'Too many pylint violations. You can view them in pylint.log'; EXIT=1; } + paver run_pylint -l $LOWER_PYLINT_THRESHOLD:$UPPER_PYLINT_THRESHOLD > pylint.log || { echo 'Too many pylint violations. You can view them in pylint.log'; EXIT=1; } mkdir -p reports From 7dbe2cd89d8224092998c215c5b7e8a42d01c957 Mon Sep 17 00:00:00 2001 From: Gabe Mulley Date: Fri, 17 Nov 2017 08:46:01 -0500 Subject: [PATCH 07/11] ensure landing page for scheduled emails is not a redirect --- .../commands/tests/send_email_base.py | 7 +++-- .../core/djangoapps/schedules/resolvers.py | 30 ++++++++++++++----- openedx/core/djangoapps/schedules/tasks.py | 23 ++++++++------ 3 files changed, 41 insertions(+), 19 deletions(-) diff --git a/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py b/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py index 6194bfe3d3..7d35df374e 100644 --- a/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py +++ b/openedx/core/djangoapps/schedules/management/commands/tests/send_email_base.py @@ -39,14 +39,15 @@ ORG_DEADLINE_QUERY = 1 # courseware_orgdynamicupgradedeadlineconfiguration COURSE_DEADLINE_QUERY = 1 # courseware_coursedynamicupgradedeadlineconfiguration COMMERCE_CONFIG_QUERY = 1 # commerce_commerceconfiguration -USER_QUERY = 1 +USER_QUERY = 1 # auth_user THEME_PREVIEW_QUERY = 1 -THEME_QUERY = 1 -SCHEDULE_CONFIG_QUERY = 1 +THEME_QUERY = 1 # theming_sitetheme +SCHEDULE_CONFIG_QUERY = 1 # schedules_scheduleconfig NUM_QUERIES_SITE_SCHEDULES = ( SITE_QUERY + SITE_CONFIG_QUERY + + THEME_QUERY + SCHEDULES_QUERY ) diff --git a/openedx/core/djangoapps/schedules/resolvers.py b/openedx/core/djangoapps/schedules/resolvers.py index 61f6a7b911..e5b94dbc5a 100644 --- a/openedx/core/djangoapps/schedules/resolvers.py +++ b/openedx/core/djangoapps/schedules/resolvers.py @@ -10,7 +10,6 @@ from django.core.urlresolvers import reverse from django.db.models import F, Q from django.utils.formats import dateformat, get_format - from edx_ace.recipient_resolver import RecipientResolver from edx_ace.recipient import Recipient @@ -22,7 +21,7 @@ from openedx.core.djangoapps.schedules.models import Schedule, ScheduleExperienc from openedx.core.djangoapps.schedules.utils import PrefixedDebugLoggerMixin from openedx.core.djangoapps.schedules.template_context import get_base_template_context from openedx.core.djangoapps.site_configuration.models import SiteConfiguration - +from openedx.features.course_experience import course_home_url_name LOG = logging.getLogger(__name__) @@ -244,7 +243,7 @@ class RecurringNudgeResolver(BinnedSchedulesBaseResolver): first_schedule = user_schedules[0] context = { 'course_name': first_schedule.enrollment.course.display_name, - 'course_url': reverse('course_root', args=[str(first_schedule.enrollment.course_id)]), + 'course_url': _get_trackable_course_home_url(first_schedule.enrollment.course_id), } # Information for including upsell messaging in template. @@ -284,7 +283,7 @@ class UpgradeReminderResolver(BinnedSchedulesBaseResolver): course_id_str = str(schedule.enrollment.course_id) course_id_strs.append(course_id_str) course_links.append({ - 'url': reverse('course_root', args=[course_id_str]), + 'url': _get_trackable_course_home_url(schedule.enrollment.course_id), 'name': schedule.enrollment.course.display_name }) @@ -357,16 +356,33 @@ class CourseUpdateResolver(BinnedSchedulesBaseResolver): except CourseUpdateDoesNotExist: continue - course_id_str = str(enrollment.course_id) template_context.update({ 'course_name': schedule.enrollment.course.display_name, - 'course_url': reverse('course_root', args=[course_id_str]), + 'course_url': _get_trackable_course_home_url(enrollment.course_id), + 'week_num': week_num, 'week_highlights': week_highlights, # This is used by the bulk email optout policy - 'course_ids': [course_id_str], + 'course_ids': [str(enrollment.course_id)], }) template_context.update(_get_upsell_information_for_schedule(user, schedule)) yield (user, schedule.enrollment.course.language, template_context) + + +def _get_trackable_course_home_url(course_id): + """ + Get the home page URL for the course. + + NOTE: For us to be able to track clicks in the email, this URL needs to point to a landing page that does not result + in a redirect so that the GA snippet can register the UTM parameters. + + Args: + course_id (CourseKey): The course to get the home page URL for. + + Returns: + A relative path to the course home page. + """ + course_url_name = course_home_url_name(course_id) + return reverse(course_url_name, args=[str(course_id)]) diff --git a/openedx/core/djangoapps/schedules/tasks.py b/openedx/core/djangoapps/schedules/tasks.py index 89b2dc9b53..12166eae84 100644 --- a/openedx/core/djangoapps/schedules/tasks.py +++ b/openedx/core/djangoapps/schedules/tasks.py @@ -103,15 +103,20 @@ class ScheduleMessageBaseTask(Task): ): msg_type = self.make_message_type(day_offset) site = Site.objects.select_related('configuration').get(id=site_id) - _annotate_for_monitoring(msg_type, site, bin_num, target_day_str, day_offset) - return self.resolver( - self.async_send_task, - site, - deserialize(target_day_str), - day_offset, - bin_num, - override_recipient_email=override_recipient_email, - ).send(msg_type) + middleware_classes = [ + CurrentRequestUserMiddleware, + CurrentSiteThemeMiddleware, + ] + with emulate_http_request(site=site, middleware_classes=middleware_classes): + _annotate_for_monitoring(msg_type, site, bin_num, target_day_str, day_offset) + return self.resolver( + self.async_send_task, + site, + deserialize(target_day_str), + day_offset, + bin_num, + override_recipient_email=override_recipient_email, + ).send(msg_type) def make_message_type(self, day_offset): raise NotImplementedError From 1fdba18502e50134539ec8f9aa70a1169f76a2cc Mon Sep 17 00:00:00 2001 From: Robert Raposa Date: Mon, 20 Nov 2017 10:27:51 -0500 Subject: [PATCH 08/11] Lower thresholds. --- scripts/xsslint_thresholds.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/xsslint_thresholds.json b/scripts/xsslint_thresholds.json index 3d00a8a836..e536d90079 100644 --- a/scripts/xsslint_thresholds.json +++ b/scripts/xsslint_thresholds.json @@ -19,14 +19,14 @@ "mako-unparseable-expression": 0, "mako-unwanted-html-filter": 0, "python-close-before-format": 0, - "python-concat-html": 25, + "python-concat-html": 24, "python-custom-escape": 13, "python-deprecated-display-name": 41, - "python-interpolate-html": 66, + "python-interpolate-html": 64, "python-parse-error": 0, "python-requires-html-or-text": 0, - "python-wrap-html": 235, + "python-wrap-html": 226, "underscore-not-escaped": 507 }, - "total": 1782 + "total": 1770 } From c8c3b553907d51ae713c3faa60574e3cc776c713 Mon Sep 17 00:00:00 2001 From: Farhanah Sheets Date: Mon, 20 Nov 2017 10:53:15 -0500 Subject: [PATCH 09/11] Update sr label to match visual label --- lms/static/coffee/src/customwmd.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lms/static/coffee/src/customwmd.coffee b/lms/static/coffee/src/customwmd.coffee index c0240b4617..f6339eabf4 100644 --- a/lms/static/coffee/src/customwmd.coffee +++ b/lms/static/coffee/src/customwmd.coffee @@ -133,7 +133,7 @@ if Markdown? .append($("

").attr("id", "wmd-preview#{_append}").addClass("wmd-panel wmd-preview")) $wmdPanel = $("
").addClass("wmd-panel") .append($("
").attr("id", "wmd-button-bar#{_append}")) - .append($("