Commit 147bdd34 by Dennis Jen

Merge pull request #181 from edx/dsjen/edu-demographics

Updated education levels to new API format.
parents b6449201 8e84455e
...@@ -2,6 +2,7 @@ import datetime ...@@ -2,6 +2,7 @@ import datetime
from unittest import skipUnless from unittest import skipUnless
from bok_choy.web_app_test import WebAppTest from bok_choy.web_app_test import WebAppTest
import analyticsclient.constants.education_level as EDUCATION_LEVEL
from analyticsclient.constants import demographic from analyticsclient.constants import demographic
from acceptance_tests import ENABLE_DEMOGRAPHICS_TESTS from acceptance_tests import ENABLE_DEMOGRAPHICS_TESTS
from acceptance_tests.mixins import CourseDemographicsPageTestsMixin from acceptance_tests.mixins import CourseDemographicsPageTestsMixin
...@@ -139,6 +140,20 @@ class CourseEnrollmentDemographicsGenderTests(CourseDemographicsPageTestsMixin, ...@@ -139,6 +140,20 @@ class CourseEnrollmentDemographicsGenderTests(CourseDemographicsPageTestsMixin,
@skipUnless(ENABLE_DEMOGRAPHICS_TESTS, 'Demographics tests are not enabled.') @skipUnless(ENABLE_DEMOGRAPHICS_TESTS, 'Demographics tests are not enabled.')
class CourseEnrollmentDemographicsEducationTests(CourseDemographicsPageTestsMixin, WebAppTest): class CourseEnrollmentDemographicsEducationTests(CourseDemographicsPageTestsMixin, WebAppTest):
EDUCATION_NAMES = {
EDUCATION_LEVEL.NONE: 'None',
EDUCATION_LEVEL.OTHER: 'Other',
EDUCATION_LEVEL.PRIMARY: 'Primary',
EDUCATION_LEVEL.JUNIOR_SECONDARY: 'Middle',
EDUCATION_LEVEL.SECONDARY: 'Secondary',
EDUCATION_LEVEL.ASSOCIATES: 'Associate',
EDUCATION_LEVEL.BACHELORS: "Bachelor's",
EDUCATION_LEVEL.MASTERS: "Master's",
EDUCATION_LEVEL.DOCTORATE: 'Doctorate',
None: 'Unknown'
}
help_path = 'enrollment/Demographics_Education.html' help_path = 'enrollment/Demographics_Education.html'
demographic_type = demographic.EDUCATION demographic_type = demographic.EDUCATION
...@@ -175,13 +190,13 @@ class CourseEnrollmentDemographicsEducationTests(CourseDemographicsPageTestsMixi ...@@ -175,13 +190,13 @@ class CourseEnrollmentDemographicsEducationTests(CourseDemographicsPageTestsMixi
for group in education_groups: for group in education_groups:
selector = 'data-stat-type={}'.format(group['stat_type']) selector = 'data-stat-type={}'.format(group['stat_type'])
filtered_group = ([education for education in self.demographic_data filtered_group = ([education for education in self.demographic_data
if education['education_level']['short_name'] in group['levels']]) if education['education_level'] in group['levels']])
group_total = float(sum([datum['count'] for datum in filtered_group])) group_total = float(sum([datum['count'] for datum in filtered_group]))
expected_percent_display = self.build_display_percentage(group_total, total) expected_percent_display = self.build_display_percentage(group_total, total)
self.assertSummaryPointValueEquals(selector, expected_percent_display) self.assertSummaryPointValueEquals(selector, expected_percent_display)
def _test_table_row(self, datum, column, sum_count): def _test_table_row(self, datum, column, sum_count):
expected = [datum['education_level']['name'], expected = [self.EDUCATION_NAMES[datum['education_level']],
unicode(datum['count'])] unicode(datum['count'])]
actual = [column[0].text, column[1].text] actual = [column[0].text, column[1].text]
self.assertListEqual(actual, expected) self.assertListEqual(actual, expected)
......
...@@ -2,7 +2,7 @@ import copy ...@@ -2,7 +2,7 @@ import copy
import datetime import datetime
import logging import logging
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy as _
from django.conf import settings from django.conf import settings
from django_countries import countries from django_countries import countries
from waffle import switch_is_active from waffle import switch_is_active
...@@ -34,19 +34,35 @@ GENDER_ORDER = { ...@@ -34,19 +34,35 @@ GENDER_ORDER = {
GENDER.OTHER: 2 GENDER.OTHER: 2
} }
KNOWN_EDUCATION_LEVELS = [EDUCATION_LEVEL.NONE, EDUCATION_LEVEL.OTHER, EDUCATION_LEVEL.PRIMARY,
EDUCATION_LEVEL.JUNIOR_SECONDARY, EDUCATION_LEVEL.SECONDARY, EDUCATION_LEVEL.ASSOCIATES,
EDUCATION_LEVEL.BACHELORS, EDUCATION_LEVEL.MASTERS, EDUCATION_LEVEL.DOCTORATE]
# for display # for display
EDUCATION_SHORT_NAMES = { EDUCATION_NAMES = {
EDUCATION_LEVEL.NONE: 'None', # Translators: This describes the learner's education level.
EDUCATION_LEVEL.OTHER: 'Other', EDUCATION_LEVEL.NONE: _('None'),
EDUCATION_LEVEL.PRIMARY: 'Elementary', # Translators: This describes the learner's education level.
EDUCATION_LEVEL.JUNIOR_SECONDARY: 'Middle', EDUCATION_LEVEL.OTHER: _('Other'),
EDUCATION_LEVEL.SECONDARY: 'High', # Translators: This describes the learner's education level (e.g. Elementary School Degree).
EDUCATION_LEVEL.ASSOCIATES: 'Associates', EDUCATION_LEVEL.PRIMARY: _('Primary'),
EDUCATION_LEVEL.BACHELORS: 'Bachelors', # Translators: This describes the learner's education level (e.g. Middle School Degree).
EDUCATION_LEVEL.MASTERS: 'Masters', EDUCATION_LEVEL.JUNIOR_SECONDARY: _('Middle'),
EDUCATION_LEVEL.DOCTORATE: 'Doctorate' # Translators: This describes the learner's education level.
EDUCATION_LEVEL.SECONDARY: _('Secondary'),
# Translators: This describes the learner's education level (e.g. Associate's Degree).
EDUCATION_LEVEL.ASSOCIATES: _("Associate"),
# Translators: This describes the learner's education level (e.g. Bachelor's Degree).
EDUCATION_LEVEL.BACHELORS: _("Bachelor's"),
# Translators: This describes the learner's education level (e.g. Master's Degree).
EDUCATION_LEVEL.MASTERS: _("Master's"),
# Translators: This describes the learner's education level (e.g. Doctorate Degree).
EDUCATION_LEVEL.DOCTORATE: _('Doctorate')
} }
# Translators: This describes the learner's education level.
UNKNOWN_EDUCATION_LEVEL_NAME = _('Unknown')
# order for displaying in the chart # order for displaying in the chart
EDUCATION_ORDER = { EDUCATION_ORDER = {
EDUCATION_LEVEL.NONE: 0, EDUCATION_LEVEL.NONE: 0,
...@@ -564,7 +580,7 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter): ...@@ -564,7 +580,7 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter):
def _calculate_education_percent(self, api_response, levels): def _calculate_education_percent(self, api_response, levels):
""" Aggregates levels of education and returns the percent of the total. """ """ Aggregates levels of education and returns the percent of the total. """
filtered_levels = ([education for education in api_response filtered_levels = ([education for education in api_response
if education['education_level']['short_name'] in levels]) if education['education_level'] in levels])
subset_enrollment = self._calculate_total_enrollment(filtered_levels) subset_enrollment = self._calculate_total_enrollment(filtered_levels)
return self._calculate_percent(subset_enrollment, self._calculate_total_enrollment(api_response)) return self._calculate_percent(subset_enrollment, self._calculate_total_enrollment(api_response))
...@@ -585,11 +601,10 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter): ...@@ -585,11 +601,10 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter):
def _build_education_levels(self, api_response): def _build_education_levels(self, api_response):
known_education = [i for i in api_response if i['education_level']] known_education = [i for i in api_response if i['education_level']]
known_enrollment_total = self._calculate_total_enrollment(known_education) known_enrollment_total = self._calculate_total_enrollment(known_education)
levels = [{'educationLevelShort': EDUCATION_SHORT_NAMES[datum['education_level']['short_name']], levels = [{'educationLevel': EDUCATION_NAMES[datum['education_level']],
'educationLevelLong': datum['education_level']['name'],
'count': datum['count'], 'count': datum['count'],
'percent': self._calculate_percent(datum['count'], known_enrollment_total), 'percent': self._calculate_percent(datum['count'], known_enrollment_total),
'order': EDUCATION_ORDER[datum['education_level']['short_name']]} 'order': EDUCATION_ORDER[datum['education_level']]}
for datum in known_education] for datum in known_education]
levels = sorted(levels, key=lambda i: i['order'], reverse=False) levels = sorted(levels, key=lambda i: i['order'], reverse=False)
...@@ -599,13 +614,25 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter): ...@@ -599,13 +614,25 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter):
if unknown: if unknown:
unknown_count = unknown[0]['count'] unknown_count = unknown[0]['count']
levels.append({ levels.append({
'educationLevelShort': 'Unknown', 'educationLevel': UNKNOWN_EDUCATION_LEVEL_NAME,
'educationLevelLong': 'Unknown',
'count': unknown_count 'count': unknown_count
}) })
return levels return levels
def _fill_empty_education_levels(self, api_response):
found_levels = [level['education_level'] for level in api_response]
# get the symmetric difference
missed_levels = list(set(found_levels) ^ set(KNOWN_EDUCATION_LEVELS))
for level in missed_levels:
api_response.append({
'education_level': level,
'count': 0
})
return api_response
def get_education(self): def get_education(self):
api_response = self.course.enrollment(demographic.EDUCATION) api_response = self.course.enrollment(demographic.EDUCATION)
education_levels = None education_levels = None
...@@ -615,6 +642,7 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter): ...@@ -615,6 +642,7 @@ class CourseEnrollmentDemographicsPresenter(BaseCourseEnrollmentPresenter):
if api_response: if api_response:
last_updated = self.parse_api_datetime(api_response[0]['created']) last_updated = self.parse_api_datetime(api_response[0]['created'])
api_response = self._fill_empty_education_levels(api_response)
education_levels = self._build_education_levels(api_response) education_levels = self._build_education_levels(api_response)
education_summary = self._build_education_summary(api_response) education_summary = self._build_education_summary(api_response)
known_enrollment_percent = self._calculate_known_total_percent(api_response, 'education_level') known_enrollment_percent = self._calculate_known_total_percent(api_response, 'education_level')
......
from django.core.serializers.json import DjangoJSONEncoder
from django.utils.encoding import force_text
from django.utils.functional import Promise
class LazyEncoder(DjangoJSONEncoder):
"""
Force the conversion of lazy translations so that they can be serialized to JSON.
via https://docs.djangoproject.com/en/dev/topics/serialization/
"""
# pylint: disable=method-hidden
def default(self, obj):
if isinstance(obj, Promise):
return force_text(obj)
return super(LazyEncoder, self).default(obj)
import json
from django.test import TestCase
from django.utils.translation import ugettext_lazy as _
from courses.serializers import LazyEncoder
class CourseEngagementPresenterTests(TestCase):
def test_lazy_encode(self):
primary = _('primary')
expected = '{{"education_level": "{0}"}}'.format(unicode(primary))
actual = json.dumps({'education_level': primary}, cls=LazyEncoder)
self.assertEqual(actual, expected)
...@@ -275,90 +275,63 @@ def get_mock_api_enrollment_education_data(course_id): ...@@ -275,90 +275,63 @@ def get_mock_api_enrollment_education_data(course_id):
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.NONE,
'name': 'None',
'short_name': EDUCATION_LEVEL.NONE
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.OTHER,
'name': 'Other',
'short_name': EDUCATION_LEVEL.OTHER
},
'count': 200, 'count': 200,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.PRIMARY,
'name': 'Elementary/Primary School',
'short_name': EDUCATION_LEVEL.PRIMARY
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.JUNIOR_SECONDARY,
'name': 'Junior Secondary/Junior High/Middle School',
'short_name': EDUCATION_LEVEL.JUNIOR_SECONDARY
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.SECONDARY,
'name': 'Secondary/High School',
'short_name': EDUCATION_LEVEL.SECONDARY
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.ASSOCIATES,
'name': "Associate's Degree",
'short_name': EDUCATION_LEVEL.ASSOCIATES
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.BACHELORS,
'name': "Bachelor's Degree",
'short_name': EDUCATION_LEVEL.BACHELORS
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.MASTERS,
'name': "Master's or Professional Degree",
'short_name': EDUCATION_LEVEL.MASTERS
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
{ {
'course_id': course_id, 'course_id': course_id,
'date': '2014-09-22', 'date': '2014-09-22',
'education_level': { 'education_level': EDUCATION_LEVEL.DOCTORATE,
'name': 'Doctorate',
'short_name': EDUCATION_LEVEL.DOCTORATE
},
'count': 100, 'count': 100,
'created': CREATED_DATETIME_STRING 'created': CREATED_DATETIME_STRING
}, },
...@@ -377,71 +350,61 @@ def get_mock_api_enrollment_education_data(course_id): ...@@ -377,71 +350,61 @@ def get_mock_api_enrollment_education_data(course_id):
def get_mock_presenter_enrollment_education_data(): def get_mock_presenter_enrollment_education_data():
data = [ data = [
{ {
'educationLevelShort': 'None', 'educationLevel': 'None',
'educationLevelLong': 'None',
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 0 'order': 0
}, },
{ {
'educationLevelShort': 'Elementary', 'educationLevel': 'Primary',
'educationLevelLong': 'Elementary/Primary School',
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 1 'order': 1
}, },
{ {
'educationLevelShort': 'Middle', 'educationLevel': 'Middle',
'educationLevelLong': 'Junior Secondary/Junior High/Middle School',
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 2 'order': 2
}, },
{ {
'educationLevelShort': 'High', 'educationLevel': 'Secondary',
'educationLevelLong': 'Secondary/High School',
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 3 'order': 3
}, },
{ {
'educationLevelShort': 'Associates', 'educationLevel': "Associate",
'educationLevelLong': "Associate's Degree",
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 4 'order': 4
}, },
{ {
'educationLevelShort': 'Bachelors', 'educationLevel': "Bachelor's",
'educationLevelLong': "Bachelor's Degree",
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 5 'order': 5
}, },
{ {
'educationLevelShort': 'Masters', 'educationLevel': "Master's",
'educationLevelLong': "Master's or Professional Degree",
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 6 'order': 6
}, },
{ {
'educationLevelShort': 'Doctorate', 'educationLevel': 'Doctorate',
'educationLevelLong': 'Doctorate',
'count': 100, 'count': 100,
'percent': 0.1, 'percent': 0.1,
'order': 7 'order': 7
}, },
{ {
'educationLevelShort': 'Other', 'educationLevel': 'Other',
'educationLevelLong': 'Other',
'count': 200, 'count': 200,
'percent': 0.2, 'percent': 0.2,
'order': 8 'order': 8
}, },
{ {
'educationLevelShort': 'Unknown', 'educationLevel': 'Unknown',
'educationLevelLong': 'Unknown',
'count': 1000 'count': 1000
} }
] ]
......
...@@ -22,6 +22,7 @@ from waffle import switch_is_active ...@@ -22,6 +22,7 @@ from waffle import switch_is_active
from courses import permissions from courses import permissions
from courses.presenters import CourseEngagementPresenter, CourseEnrollmentPresenter, \ from courses.presenters import CourseEngagementPresenter, CourseEnrollmentPresenter, \
CourseEnrollmentDemographicsPresenter CourseEnrollmentDemographicsPresenter
from courses.serializers import LazyEncoder
from courses.utils import is_feature_enabled from courses.utils import is_feature_enabled
from help.views import ContextSensitiveHelpMixin from help.views import ContextSensitiveHelpMixin
...@@ -49,7 +50,17 @@ class TrackedViewMixin(object): ...@@ -49,7 +50,17 @@ class TrackedViewMixin(object):
return context return context
class CourseContextMixin(TrackedViewMixin): class LazyEncoderMixin(object):
def get_page_data(self, context):
""" Returns JSON serialized data with lazy translations converted. """
if 'js_data' in context:
return json.dumps(context['js_data'], cls=LazyEncoder)
else:
return None
class CourseContextMixin(TrackedViewMixin, LazyEncoderMixin):
""" """
Adds default course context data. Adds default course context data.
...@@ -371,13 +382,6 @@ class CSVResponseMixin(object): ...@@ -371,13 +382,6 @@ class CSVResponseMixin(object):
return urllib.quote(filename) return urllib.quote(filename)
class JSONResponseMixin(object):
def render_to_response(self, context, **response_kwargs):
content = json.dumps(context['data'])
return HttpResponse(content, content_type='application/json',
**response_kwargs)
class EnrollmentActivityView(EnrollmentTemplateView): class EnrollmentActivityView(EnrollmentTemplateView):
template_name = 'courses/enrollment_activity.html' template_name = 'courses/enrollment_activity.html'
page_title = _('Enrollment Activity') page_title = _('Enrollment Activity')
...@@ -406,10 +410,10 @@ class EnrollmentActivityView(EnrollmentTemplateView): ...@@ -406,10 +410,10 @@ class EnrollmentActivityView(EnrollmentTemplateView):
context['js_data']['course']['enrollmentTrends'] = trend context['js_data']['course']['enrollmentTrends'] = trend
context.update({ context.update({
'page_data': json.dumps(context['js_data']),
'summary': summary, 'summary': summary,
'update_message': self.get_last_updated_message(last_updated) 'update_message': self.get_last_updated_message(last_updated)
}) })
context['page_data'] = self.get_page_data(context)
return context return context
...@@ -440,12 +444,12 @@ class EnrollmentDemographicsAgeView(EnrollmentDemographicsTemplateView): ...@@ -440,12 +444,12 @@ class EnrollmentDemographicsAgeView(EnrollmentDemographicsTemplateView):
context['js_data']['course']['ages'] = binned_ages context['js_data']['course']['ages'] = binned_ages
context.update({ context.update({
'page_data': json.dumps(context['js_data']),
'summary': summary, 'summary': summary,
'chart_tip': self._build_chart_tooltip(known_enrollment_percent), 'chart_tip': self._build_chart_tooltip(known_enrollment_percent),
'update_message': self.get_last_updated_message(last_updated), 'update_message': self.get_last_updated_message(last_updated),
'data_information_message': self.data_information_message 'data_information_message': self.data_information_message
}) })
context['page_data'] = self.get_page_data(context)
return context return context
...@@ -476,12 +480,12 @@ class EnrollmentDemographicsEducationView(EnrollmentDemographicsTemplateView): ...@@ -476,12 +480,12 @@ class EnrollmentDemographicsEducationView(EnrollmentDemographicsTemplateView):
context['js_data']['course']['education'] = binned_education context['js_data']['course']['education'] = binned_education
context.update({ context.update({
'page_data': json.dumps(context['js_data']),
'summary': summary, 'summary': summary,
'chart_tip': self._build_chart_tooltip(known_enrollment_percent), 'chart_tip': self._build_chart_tooltip(known_enrollment_percent),
'update_message': self.get_last_updated_message(last_updated), 'update_message': self.get_last_updated_message(last_updated),
'data_information_message': self.data_information_message 'data_information_message': self.data_information_message
}) })
context['page_data'] = self.get_page_data(context)
return context return context
...@@ -513,11 +517,11 @@ class EnrollmentDemographicsGenderView(EnrollmentDemographicsTemplateView): ...@@ -513,11 +517,11 @@ class EnrollmentDemographicsGenderView(EnrollmentDemographicsTemplateView):
context['js_data']['course']['genderTrend'] = trend context['js_data']['course']['genderTrend'] = trend
context.update({ context.update({
'page_data': json.dumps(context['js_data']),
'update_message': self.get_last_updated_message(last_updated), 'update_message': self.get_last_updated_message(last_updated),
'chart_tip': self._build_chart_tooltip(known_enrollment_percent), 'chart_tip': self._build_chart_tooltip(known_enrollment_percent),
'data_information_message': self.data_information_message 'data_information_message': self.data_information_message
}) })
context['page_data'] = self.get_page_data(context)
return context return context
...@@ -550,9 +554,9 @@ class EnrollmentGeographyView(EnrollmentTemplateView): ...@@ -550,9 +554,9 @@ class EnrollmentGeographyView(EnrollmentTemplateView):
context['js_data']['course']['enrollmentByCountry'] = data context['js_data']['course']['enrollmentByCountry'] = data
context.update({ context.update({
'page_data': json.dumps(context['js_data']),
'update_message': self.get_last_updated_message(last_updated) 'update_message': self.get_last_updated_message(last_updated)
}) })
context['page_data'] = self.get_page_data(context)
return context return context
...@@ -583,9 +587,9 @@ class EngagementContentView(EngagementTemplateView): ...@@ -583,9 +587,9 @@ class EngagementContentView(EngagementTemplateView):
context['js_data']['course']['engagementTrends'] = trends context['js_data']['course']['engagementTrends'] = trends
context.update({ context.update({
'summary': summary, 'summary': summary,
'page_data': json.dumps(context['js_data']),
'update_message': self.get_last_updated_message(last_updated) 'update_message': self.get_last_updated_message(last_updated)
}) })
context['page_data'] = self.get_page_data(context)
return context return context
...@@ -644,7 +648,7 @@ class CourseHome(LoginRequiredMixin, RedirectView): ...@@ -644,7 +648,7 @@ class CourseHome(LoginRequiredMixin, RedirectView):
return reverse('courses:enrollment_activity', kwargs={'course_id': course_id}) return reverse('courses:enrollment_activity', kwargs={'course_id': course_id})
class CourseIndex(LoginRequiredMixin, TrackedViewMixin, TemplateView): class CourseIndex(LoginRequiredMixin, TrackedViewMixin, LazyEncoderMixin, TemplateView):
template_name = 'courses/index.html' template_name = 'courses/index.html'
page_name = 'course_index' page_name = 'course_index'
...@@ -658,9 +662,6 @@ class CourseIndex(LoginRequiredMixin, TrackedViewMixin, TemplateView): ...@@ -658,9 +662,6 @@ class CourseIndex(LoginRequiredMixin, TrackedViewMixin, TemplateView):
raise PermissionDenied raise PermissionDenied
context['courses'] = sorted(courses) context['courses'] = sorted(courses)
context['page_data'] = self.get_page_data(context)
context.update({
'page_data': json.dumps(context['js_data']),
})
return context return context
...@@ -20,7 +20,7 @@ require(['vendor/domReady!', 'load/init-page'], function(doc, page) { ...@@ -20,7 +20,7 @@ require(['vendor/domReady!', 'load/init-page'], function(doc, page) {
title: gettext('Education'), title: gettext('Education'),
color: 'rgb(58, 162, 224)' color: 'rgb(58, 162, 224)'
}], }],
x: { key: 'educationLevelShort' }, x: { key: 'educationLevel' },
y: { key: 'percent' } y: { key: 'percent' }
}); });
...@@ -29,7 +29,7 @@ require(['vendor/domReady!', 'load/init-page'], function(doc, page) { ...@@ -29,7 +29,7 @@ require(['vendor/domReady!', 'load/init-page'], function(doc, page) {
model: page.models.courseModel, model: page.models.courseModel,
modelAttribute: 'education', modelAttribute: 'education',
columns: [ columns: [
{key: 'educationLevelLong', title: gettext('Educational Background')}, {key: 'educationLevel', title: gettext('Educational Background')},
{key: 'count', title: gettext('Number of Students'), className: 'text-right'} {key: 'count', title: gettext('Number of Students'), className: 'text-right'}
], ],
sorting: ['-count'] sorting: ['-count']
......
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