Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-analytics-dashboard
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-analytics-dashboard
Commits
c9debee7
Commit
c9debee7
authored
Jul 07, 2016
by
Dennis Jen
Committed by
GitHub
Jul 07, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #496 from edx/dsjen/enrollment-tracks
Added audit and credit enrollment tracks.
parents
00c270b5
cfe1dc46
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
119 additions
and
144 deletions
+119
-144
Makefile
+0
-1
acceptance_tests/__init__.py
+0
-1
acceptance_tests/test_course_enrollment.py
+21
-23
analytics_dashboard/courses/presenters/enrollment.py
+16
-33
analytics_dashboard/courses/templates/courses/enrollment_activity.html
+9
-11
analytics_dashboard/courses/tests/test_presenters.py
+26
-6
analytics_dashboard/courses/tests/test_views/test_csv.py
+0
-4
analytics_dashboard/courses/tests/utils.py
+14
-39
analytics_dashboard/courses/views/csv.py
+1
-3
analytics_dashboard/static/js/enrollment-activity-main.js
+31
-22
requirements/base.txt
+1
-1
No files found.
Makefile
View file @
c9debee7
...
...
@@ -61,7 +61,6 @@ validate_js: requirements.js
validate
:
validate_python validate_js
demo
:
python manage.py switch display_verified_enrollment on
--create
python manage.py switch show_engagement_forum_activity off
--create
python manage.py switch enable_course_api off
--create
python manage.py switch display_names_for_course_index off
--create
...
...
acceptance_tests/__init__.py
View file @
c9debee7
...
...
@@ -62,7 +62,6 @@ TEST_VIDEO_ID = os.environ.get('TEST_VIDEO_ID',
DOC_BASE_URL
=
os
.
environ
.
get
(
'DOC_BASE_URL'
,
'http://edx-insights.readthedocs.org/en/latest'
)
ENABLE_ENROLLMENT_MODES
=
str2bool
(
os
.
environ
.
get
(
'ENABLE_ENROLLMENT_MODES'
,
False
))
ENABLE_FORUM_POSTS
=
str2bool
(
os
.
environ
.
get
(
'ENABLE_FORUM_POSTS'
,
False
))
# Course API settings
...
...
acceptance_tests/test_course_enrollment.py
View file @
c9debee7
from
collections
import
OrderedDict
import
datetime
from
analyticsclient.constants
import
demographic
,
UNKNOWN_COUNTRY_CODE
,
enrollment_modes
from
bok_choy.web_app_test
import
WebAppTest
from
acceptance_tests
import
ENABLE_ENROLLMENT_MODES
from
acceptance_tests.mixins
import
CoursePageTestsMixin
from
acceptance_tests.pages
import
CourseEnrollmentActivityPage
,
CourseEnrollmentGeographyPage
...
...
@@ -25,9 +25,7 @@ class CourseEnrollmentActivityTests(CoursePageTestsMixin, WebAppTest):
"""
end_date
=
datetime
.
datetime
.
utcnow
()
end_date_string
=
end_date
.
strftime
(
self
.
analytics_api_client
.
DATE_FORMAT
)
_demographic
=
'mode'
if
ENABLE_ENROLLMENT_MODES
else
None
return
self
.
course
.
enrollment
(
_demographic
,
start_date
=
None
,
end_date
=
end_date_string
)
return
self
.
course
.
enrollment
(
'mode'
,
start_date
=
None
,
end_date
=
end_date_string
)
def
test_page
(
self
):
super
(
CourseEnrollmentActivityTests
,
self
)
.
test_page
()
...
...
@@ -46,8 +44,8 @@ class CourseEnrollmentActivityTests(CoursePageTestsMixin, WebAppTest):
self
.
assertSummaryTooltipEquals
(
selector
,
tooltip
)
def
_get_valid_enrollment_modes
(
self
,
trends
):
valid_modes
=
{
enrollment_modes
.
AUDIT
,
enrollment_modes
.
HONOR
}
invalid_modes
=
set
(
enrollment_modes
.
ALL
)
-
valid_modes
valid_modes
=
set
()
invalid_modes
=
set
(
enrollment_modes
.
ALL
)
for
datum
in
trends
:
for
candidate
in
list
(
invalid_modes
):
...
...
@@ -76,14 +74,13 @@ class CourseEnrollmentActivityTests(CoursePageTestsMixin, WebAppTest):
tooltip
=
u'Net difference in current enrollment in the last week.'
self
.
assertMetricTileValid
(
'enrollment_change_last_
%
s_days'
%
i
,
enrollment
,
tooltip
)
if
ENABLE_ENROLLMENT_MODES
:
valid_modes
=
self
.
_get_valid_enrollment_modes
(
enrollment_data
)
valid_modes
=
self
.
_get_valid_enrollment_modes
(
enrollment_data
)
if
enrollment_modes
.
VERIFIED
in
valid_modes
:
# Verify the verified enrollment metric tile.
verified_enrollment
=
enrollment_data
[
-
1
][
enrollment_modes
.
VERIFIED
]
tooltip
=
u'Number of currently enrolled students pursuing a verified certificate of achievement.'
self
.
assertMetricTileValid
(
'verified_enrollment'
,
verified_enrollment
,
tooltip
)
if
enrollment_modes
.
VERIFIED
in
valid_modes
:
# Verify the verified enrollment metric tile.
verified_enrollment
=
enrollment_data
[
-
1
][
enrollment_modes
.
VERIFIED
]
tooltip
=
u'Number of currently enrolled students pursuing a verified certificate of achievement.'
self
.
assertMetricTileValid
(
'verified_enrollment'
,
verified_enrollment
,
tooltip
)
# Verify *something* rendered where the graph should be. We cannot easily verify what rendered
self
.
assertElementHasContent
(
"[data-section=enrollment-basics] #enrollment-trend-view"
)
...
...
@@ -96,16 +93,17 @@ class CourseEnrollmentActivityTests(CoursePageTestsMixin, WebAppTest):
table_selector
=
'div[data-role=enrollment-table] table'
headings
=
[
'Date'
,
'Current Enrollment'
]
if
ENABLE_ENROLLMENT_MODES
:
headings
.
append
(
'Honor Code'
)
valid_modes
=
self
.
_get_valid_enrollment_modes
(
enrollment_data
)
if
enrollment_modes
.
VERIFIED
in
valid_modes
:
headings
.
append
(
'Verified'
)
if
enrollment_modes
.
PROFESSIONAL
in
valid_modes
:
headings
.
append
(
'Professional'
)
valid_modes
=
self
.
_get_valid_enrollment_modes
(
enrollment_data
)
display_names
=
OrderedDict
([
(
enrollment_modes
.
HONOR
,
'Honor'
),
(
enrollment_modes
.
AUDIT
,
'Audit'
),
(
enrollment_modes
.
VERIFIED
,
'Verified'
),
(
enrollment_modes
.
PROFESSIONAL
,
'Professional'
),
(
enrollment_modes
.
CREDIT
,
'Verified with Credit'
)
])
for
mode
,
display_name
in
display_names
.
items
():
if
mode
in
valid_modes
:
headings
.
append
(
display_name
)
self
.
assertTableColumnHeadingsEqual
(
table_selector
,
headings
)
...
...
analytics_dashboard/courses/presenters/enrollment.py
View file @
c9debee7
...
...
@@ -4,7 +4,6 @@ import logging
from
django.utils.translation
import
ugettext_lazy
as
_
from
django_countries
import
countries
from
waffle
import
switch_is_active
from
analyticsclient.constants
import
demographic
,
UNKNOWN_COUNTRY_CODE
,
enrollment_modes
import
analyticsclient.constants.education_level
as
EDUCATION_LEVEL
import
analyticsclient.constants.gender
as
GENDER
...
...
@@ -82,16 +81,11 @@ class CourseEnrollmentPresenter(BasePresenter):
NUMBER_TOP_COUNTRIES
=
3
@property
def
display_verified_enrollment
(
self
):
return
switch_is_active
(
'display_verified_enrollment'
)
def
get_summary_and_trend_data
(
self
):
"""
Retrieve recent summary and all historical trend data.
"""
_demographic
=
'mode'
if
self
.
display_verified_enrollment
else
None
trends
=
self
.
course
.
enrollment
(
_demographic
,
start_date
=
None
,
end_date
=
self
.
get_current_date
())
trends
=
self
.
course
.
enrollment
(
'mode'
,
start_date
=
None
,
end_date
=
self
.
get_current_date
())
trends
=
self
.
_fill_trend
(
trends
)
summary
=
self
.
_build_summary
(
trends
)
...
...
@@ -101,19 +95,17 @@ class CourseEnrollmentPresenter(BasePresenter):
day_before
=
self
.
parse_api_date
(
trends
[
0
][
'date'
])
-
datetime
.
timedelta
(
days
=
1
)
trends
.
insert
(
0
,
self
.
_create_empty_enrollment_datapoint
(
day_before
))
if
self
.
display_verified_enrollment
:
trends
=
self
.
_merge_audit_and_honor
(
trends
)
summary
,
trends
=
self
.
_remove_empty_enrollment_modes
(
summary
,
trends
)
return
summary
,
trends
return
self
.
_remove_empty_enrollment_modes
(
summary
,
trends
)
def
_get_valid_enrollment_modes
(
self
,
trends
):
"""
Return enrollment modes for which there
is currently, or have been in the past,
at least one enrolled student.
Return enrollment modes for which there
was
at least one enrolled student.
"""
valid_modes
=
{
enrollment_modes
.
AUDIT
,
enrollment_modes
.
HONOR
}
invalid_modes
=
set
(
enrollment_modes
.
ALL
)
-
valid_modes
# default modes
valid_modes
=
set
()
invalid_modes
=
set
(
enrollment_modes
.
ALL
)
# go through each day of the trend and record any tracks with enrollment as valid
for
datum
in
trends
:
for
candidate
in
invalid_modes
.
copy
():
if
datum
.
get
(
candidate
,
0
)
>
0
:
...
...
@@ -136,22 +128,12 @@ class CourseEnrollmentPresenter(BasePresenter):
for
mode
in
invalid_modes
:
trend
.
pop
(
mode
,
None
)
# hides verified enrollment counts in the summary card if it doesn't exist
if
enrollment_modes
.
VERIFIED
not
in
valid_modes
:
summary
.
pop
(
'verified_enrollment'
)
return
summary
,
trends
def
_merge_audit_and_honor
(
self
,
data
):
"""
Merge the audit and honor tracks into a single "honor" track
Note: This can be removed once the API has been deployed, as it will be updated to handle this for us.
"""
for
datum
in
data
:
datum
[
enrollment_modes
.
HONOR
]
=
datum
.
get
(
enrollment_modes
.
HONOR
,
0
)
+
datum
.
pop
(
enrollment_modes
.
AUDIT
,
0
)
return
data
def
_fill_trend
(
self
,
api_response
):
""" Fills in enrollment counts for missing days in the trend data for display. """
if
api_response
:
...
...
@@ -180,12 +162,14 @@ class CourseEnrollmentPresenter(BasePresenter):
"""
Create an enrollment datapoint with all counts set to zero.
"""
trend
=
{
'date'
:
day
.
isoformat
(),
'count'
:
0
}
trend
=
{
'date'
:
day
.
isoformat
(),
'count'
:
0
,
'cumulative_count'
:
0
}
if
self
.
display_verified_enrollment
:
trend
[
'cumulative_count'
]
=
0
for
mode
in
enrollment_modes
.
ALL
:
trend
[
mode
]
=
0
for
mode
in
enrollment_modes
.
ALL
:
trend
[
mode
]
=
0
return
trend
...
...
@@ -273,8 +257,7 @@ class CourseEnrollmentPresenter(BasePresenter):
# Add the first values to the returned data dictionary using the most-recent enrollment data
current_enrollment
=
recent_enrollment
[
'count'
]
verified_enrollment
=
recent_enrollment
.
get
(
enrollment_modes
.
VERIFIED
,
0
)
if
self
.
display_verified_enrollment
else
None
verified_enrollment
=
recent_enrollment
.
get
(
enrollment_modes
.
VERIFIED
,
0
)
data
.
update
({
'last_updated'
:
last_enrollment_date
,
...
...
analytics_dashboard/courses/templates/courses/enrollment_activity.html
View file @
c9debee7
...
...
@@ -77,17 +77,15 @@ Individual course-centric enrollment activity view.
{% summary_point summary.enrollment_change_last_7_days label tooltip=tooltip %}
</div>
{% switch display_verified_enrollment %}
{% if not summary.verified_enrollment == None %}
<div
class=
"col-xs-12 col-sm-3"
data-stat-type=
"verified_enrollment"
>
{# Translators: This is a label to identify enrollment of students on the verified track. #}
{% trans "Verified Enrollment" as label %}
{# Translators: This is a label indicating the number of students enrolled in a course on the verified track. #}
{% trans "Number of currently enrolled students pursuing a verified certificate of achievement." as tooltip %}
{% summary_point summary.verified_enrollment label tooltip=tooltip %}
</div>
{% endif %}
{% endswitch %}
{% if not summary.verified_enrollment == None %}
<div
class=
"col-xs-12 col-sm-3"
data-stat-type=
"verified_enrollment"
>
{# Translators: This is a label to identify enrollment of students on the verified track. #}
{% trans "Verified Enrollment" as label %}
{# Translators: This is a label indicating the number of students enrolled in a course on the verified track. #}
{% trans "Number of currently enrolled students pursuing a verified certificate of achievement." as tooltip %}
{% summary_point summary.verified_enrollment label tooltip=tooltip %}
</div>
{% endif %}
</div>
</div>
{% else %}
...
...
analytics_dashboard/courses/tests/test_presenters.py
View file @
c9debee7
...
...
@@ -3,6 +3,7 @@ import copy
import
datetime
import
analyticsclient.constants.activity_type
as
AT
from
analyticsclient.constants
import
enrollment_modes
from
django.conf
import
settings
from
django.core.cache
import
cache
from
django.core.urlresolvers
import
reverse
...
...
@@ -579,9 +580,6 @@ class CourseEngagementVideoPresenterTests(SwitchMixin, TestCase):
class
CourseEnrollmentPresenterTests
(
SwitchMixin
,
TestCase
):
@classmethod
def
setUpClass
(
cls
):
cls
.
toggle_switch
(
'display_verified_enrollment'
,
True
)
def
setUp
(
self
):
self
.
course_id
=
'edX/DemoX/Demo_Course'
...
...
@@ -659,14 +657,36 @@ class CourseEnrollmentPresenterTests(SwitchMixin, TestCase):
@mock.patch
(
'analyticsclient.course.Course.enrollment'
)
def
test_hide_empty_enrollment_modes
(
self
,
mock_enrollment
):
""" Enrollment modes with no enrolled students should not be returned. """
mock_enrollment
.
return_value
=
utils
.
get_mock_api_enrollment_data
(
self
.
course_id
,
include_verified
=
False
)
# set trend for one mode to be all 0
mock_api_data
=
utils
.
get_mock_api_enrollment_data
(
self
.
course_id
)
for
day
in
mock_api_data
:
day
[
enrollment_modes
.
PROFESSIONAL
]
=
0
mock_enrollment
.
return_value
=
mock_api_data
actual_summary
,
actual_trend
=
self
.
presenter
.
get_summary_and_trend_data
()
self
.
assertDictEqual
(
actual_summary
,
utils
.
get_mock_enrollment_summary
(
include_verified
=
False
))
self
.
assertDictEqual
(
actual_summary
,
utils
.
get_mock_enrollment_summary
())
# trends without enrollment shouldn't be present in the returned trend
expected_trend
=
utils
.
get_mock_presenter_enrollment_trend
(
self
.
course_id
)
for
day
in
expected_trend
:
del
day
[
enrollment_modes
.
PROFESSIONAL
]
expected_trend
=
utils
.
get_mock_presenter_enrollment_trend
(
self
.
course_id
,
include_verified
=
False
)
self
.
assertListEqual
(
actual_trend
,
expected_trend
)
@mock.patch
(
'analyticsclient.course.Course.enrollment'
)
def
test_remove_verified_summary
(
self
,
mock_enrollment
):
""" Verified summary should be removed none are enrolled. """
mock_api_data
=
utils
.
get_mock_api_enrollment_data
(
self
.
course_id
)
for
day
in
mock_api_data
:
day
[
enrollment_modes
.
VERIFIED
]
=
0
mock_enrollment
.
return_value
=
mock_api_data
actual_summary
,
_actual_trend
=
self
.
presenter
.
get_summary_and_trend_data
()
expected_summary
=
utils
.
get_mock_enrollment_summary
()
del
expected_summary
[
'verified_enrollment'
]
self
.
assertDictEqual
(
actual_summary
,
expected_summary
)
class
CourseEnrollmentDemographicsPresenterTests
(
TestCase
):
def
setUp
(
self
):
...
...
analytics_dashboard/courses/tests/test_views/test_csv.py
View file @
c9debee7
...
...
@@ -90,10 +90,6 @@ class CourseEnrollmentModeCSVViewTests(SwitchMixin, CourseCSVTestMixin, TestCase
base_file_name
=
'enrollment'
api_method
=
'analyticsclient.course.Course.enrollment'
@classmethod
def
setUpClass
(
cls
):
cls
.
toggle_switch
(
'display_verified_enrollment'
,
True
)
def
get_mock_data
(
self
,
course_id
):
return
get_mock_api_enrollment_data
(
course_id
)
...
...
analytics_dashboard/courses/tests/utils.py
View file @
c9debee7
...
...
@@ -20,10 +20,10 @@ GAP_START = 2
GAP_END
=
4
def
get_mock_api_enrollment_data
(
course_id
,
include_verified
=
True
):
def
get_mock_api_enrollment_data
(
course_id
):
data
=
[]
start_date
=
datetime
.
date
(
year
=
2014
,
month
=
1
,
day
=
1
)
modes
=
enrollment_modes
.
ALL
if
include_verified
else
[
enrollment_modes
.
AUDIT
,
enrollment_modes
.
HONOR
]
modes
=
enrollment_modes
.
ALL
for
index
in
range
(
31
):
date
=
start_date
+
datetime
.
timedelta
(
days
=
index
)
...
...
@@ -32,12 +32,10 @@ def get_mock_api_enrollment_data(course_id, include_verified=True):
'date'
:
date
.
strftime
(
Client
.
DATE_FORMAT
),
'course_id'
:
unicode
(
course_id
),
'count'
:
index
*
len
(
modes
),
'created'
:
CREATED_DATETIME_STRING
'created'
:
CREATED_DATETIME_STRING
,
'cumulative_count'
:
index
*
len
(
modes
)
*
2
}
if
include_verified
:
datum
[
'cumulative_count'
]
=
datum
[
'count'
]
*
2
for
mode
in
modes
:
datum
[
mode
]
=
index
...
...
@@ -52,22 +50,14 @@ def get_mock_api_enrollment_data_with_gaps(course_id):
return
data
def
get_mock_enrollment_summary
(
include_verified
=
True
):
def
get_mock_enrollment_summary
():
summary
=
{
'last_updated'
:
CREATED_DATETIME
,
'current_enrollment'
:
60
,
'total_enrollment'
:
None
,
'enrollment_change_last_7_days'
:
14
,
'current_enrollment'
:
150
,
'total_enrollment'
:
300
,
'enrollment_change_last_7_days'
:
35
,
'verified_enrollment'
:
30
,
}
if
include_verified
:
summary
.
update
({
'current_enrollment'
:
120
,
'total_enrollment'
:
240
,
'enrollment_change_last_7_days'
:
28
,
'verified_enrollment'
:
30
,
})
return
summary
...
...
@@ -84,17 +74,8 @@ def _get_empty_enrollment(date):
return
enrollment
def
_clean_modes
(
data
):
for
datum
in
data
:
datum
[
enrollment_modes
.
HONOR
]
=
datum
[
enrollment_modes
.
AUDIT
]
+
datum
[
enrollment_modes
.
HONOR
]
datum
.
pop
(
enrollment_modes
.
AUDIT
)
return
data
def
get_mock_presenter_enrollment_trend
(
course_id
,
include_verified
=
True
):
trend
=
get_mock_api_enrollment_data
(
course_id
,
include_verified
=
include_verified
)
trend
=
_clean_modes
(
trend
)
def
get_mock_presenter_enrollment_trend
(
course_id
):
trend
=
get_mock_api_enrollment_data
(
course_id
)
return
trend
...
...
@@ -119,19 +100,13 @@ def get_mock_presenter_enrollment_trend_with_gaps_filled(course_id):
def
get_mock_presenter_enrollment_data_small
(
course_id
):
data
=
[
_get_empty_enrollment
(
'2014-01-30'
),
get_mock_api_enrollment_data
(
course_id
)[
-
1
]]
data
=
_clean_modes
(
data
)
return
data
def
get_mock_presenter_enrollment_summary_small
():
return
{
'last_updated'
:
CREATED_DATETIME
,
'current_enrollment'
:
120
,
'total_enrollment'
:
240
,
'enrollment_change_last_7_days'
:
None
,
'verified_enrollment'
:
30
,
}
summary
=
get_mock_enrollment_summary
()
summary
[
'enrollment_change_last_7_days'
]
=
None
return
summary
def
get_mock_api_enrollment_geography_data
(
course_id
):
...
...
analytics_dashboard/courses/views/csv.py
View file @
c9debee7
...
...
@@ -4,7 +4,6 @@ import urllib
from
django.http
import
HttpResponse
from
waffle
import
switch_is_active
from
analyticsclient.constants
import
data_format
,
demographic
from
analyticsclient.client
import
Client
...
...
@@ -66,9 +65,8 @@ class CourseEnrollmentCSV(CSVResponseMixin, CourseView):
csv_filename_suffix
=
u'enrollment'
def
get_data
(
self
):
_demographic
=
'mode'
if
switch_is_active
(
'display_verified_enrollment'
)
else
None
end_date
=
datetime
.
datetime
.
utcnow
()
.
strftime
(
Client
.
DATE_FORMAT
)
return
self
.
course
.
enrollment
(
_demographic
,
data_format
=
data_format
.
CSV
,
end_date
=
end_date
)
return
self
.
course
.
enrollment
(
'mode'
,
data_format
=
data_format
.
CSV
,
end_date
=
end_date
)
class
CourseEngagementActivityTrendCSV
(
CSVResponseMixin
,
CourseView
):
...
...
analytics_dashboard/static/js/enrollment-activity-main.js
View file @
c9debee7
...
...
@@ -11,40 +11,49 @@ require(['vendor/domReady!', 'load/init-page'], function (doc, page) {
'views/stacked-trends-view'
],
function
(
DataTableView
,
StackedTrendsView
)
{
var
settings
=
[
var
colors
=
[
'#4BB4FB'
,
'#CA0061'
,
'#CCCCCC'
],
numericColumn
=
{
className
:
'text-right'
,
type
:
'number'
},
settings
=
[
{
key
:
'date'
,
title
:
gettext
(
'Date'
),
type
:
'date'
},
{
_
.
defaults
({},
numericColumn
,
{
key
:
'count'
,
title
:
gettext
(
'Current Enrollment'
),
className
:
'text-right'
,
type
:
'number'
,
color
:
'#4BB4FB'
},
{
color
:
colors
[
0
]
}),
_
.
defaults
({},
numericColumn
,
{
key
:
'honor'
,
title
:
gettext
(
'Honor Code'
),
className
:
'text-right'
,
type
:
'number'
,
color
:
'#4BB4FB'
},
{
// Translators: this describe the learner's enrollment track (e.g. Honor certificate)
title
:
gettext
(
'Honor'
),
color
:
colors
[
0
]
}),
_
.
defaults
({},
numericColumn
,
{
key
:
'audit'
,
title
:
gettext
(
'Audit'
),
color
:
colors
[
0
]
}),
_
.
defaults
({},
numericColumn
,
{
key
:
'verified'
,
title
:
gettext
(
'Verified'
),
className
:
'text-right'
,
type
:
'number'
,
color
:
'#CA0061'
},
{
color
:
colors
[
1
]
}),
_
.
defaults
({},
numericColumn
,
{
key
:
'professional'
,
title
:
gettext
(
'Professional'
),
className
:
'text-right'
,
type
:
'number'
,
color
:
'#CCCCCC'
}
color
:
colors
[
2
]
}),
_
.
defaults
({},
numericColumn
,
{
key
:
'credit'
,
// Translators: this label indicates the learner has registered for academic credit
title
:
gettext
(
'Verified with Credit'
),
color
:
colors
[
2
]
})
],
trendSettings
,
enrollmentTrackTrendSettings
;
...
...
requirements/base.txt
View file @
c9debee7
...
...
@@ -26,7 +26,7 @@ requests==2.10.0 # Apache 2.0
git+https://github.com/pinax/django-announcements.git@f85e690705e038a62407abe54ac195f60760934b#egg=django-announcements # MIT
git+https://github.com/edx/django-lang-pref-middleware.git@0.1.0#egg=django-lang-pref-middleware
git+https://github.com/edx/edx-analytics-data-api-client.git@0.
6.1#egg=edx-analytics-data-api-client==0.6.1
# edX
git+https://github.com/edx/edx-analytics-data-api-client.git@0.
8.0#egg=edx-analytics-data-api-client==0.8.0
# edX
git+https://github.com/edx/i18n-tools.git@0d7847f9dfa2281640527b4dc51f5854f950f9b7#egg=i18n_tools
git+https://github.com/edx/opaque-keys.git@d45d0bd8d64c69531be69178b9505b5d38806ce0#egg=opaque-keys
# custom opaque-key implementations for ccx
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment