Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
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-platform
Commits
f1ccf1c0
Commit
f1ccf1c0
authored
Sep 09, 2013
by
Renzo Lucioni
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Integrate split testing and LMS tabs experiments
parent
fd06640d
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
184 additions
and
73 deletions
+184
-73
lms/djangoapps/courseware/tabs.py
+65
-34
lms/djangoapps/courseware/tests/test_tabs.py
+29
-28
lms/djangoapps/courseware/views.py
+1
-0
lms/envs/common.py
+15
-1
lms/envs/dev.py
+1
-1
lms/static/sass/course/layout/_courseware_header.scss
+11
-0
lms/templates/courseware/course_navigation.html
+8
-3
lms/templates/courseware/welcome-back.html
+33
-1
lms/templates/dashboard.html
+7
-1
lms/templates/widgets/segment-io.html
+12
-4
lms/urls.py
+1
-0
requirements/edx/github.txt
+1
-0
No files found.
lms/djangoapps/courseware/tabs.py
View file @
f1ccf1c0
...
@@ -25,6 +25,8 @@ from courseware.model_data import FieldDataCache
...
@@ -25,6 +25,8 @@ from courseware.model_data import FieldDataCache
from
open_ended_grading
import
open_ended_notifications
from
open_ended_grading
import
open_ended_notifications
import
waffle
log
=
logging
.
getLogger
(
__name__
)
log
=
logging
.
getLogger
(
__name__
)
...
@@ -55,32 +57,46 @@ TabImpl = namedtuple('TabImpl', 'validator generator')
...
@@ -55,32 +57,46 @@ TabImpl = namedtuple('TabImpl', 'validator generator')
##### Generators for various tabs.
##### Generators for various tabs.
def
_courseware
(
tab
,
user
,
course
,
active_page
,
request
):
def
_courseware
(
tab
,
user
,
course
,
active_page
):
"""
This returns a tab containing the course content.
"""
link
=
reverse
(
'courseware'
,
args
=
[
course
.
id
])
link
=
reverse
(
'courseware'
,
args
=
[
course
.
id
])
return
[
CourseTab
(
'Courseware'
,
link
,
active_page
==
"courseware"
)]
if
waffle
.
flag_is_active
(
request
,
'merge_course_tabs'
):
return
[
CourseTab
(
'Course Content'
,
link
,
active_page
==
"courseware"
)]
else
:
return
[
CourseTab
(
'Courseware'
,
link
,
active_page
==
"courseware"
)]
def
_course_info
(
tab
,
user
,
course
,
active_page
):
def
_course_info
(
tab
,
user
,
course
,
active_page
,
request
):
"""
This returns a tab containing information about the course.
"""
link
=
reverse
(
'info'
,
args
=
[
course
.
id
])
link
=
reverse
(
'info'
,
args
=
[
course
.
id
])
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
"info"
)]
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
"info"
)]
def
_progress
(
tab
,
user
,
course
,
active_page
):
def
_progress
(
tab
,
user
,
course
,
active_page
,
request
):
"""
This returns a tab containing information about the authenticated user's progress.
"""
if
user
.
is_authenticated
():
if
user
.
is_authenticated
():
link
=
reverse
(
'progress'
,
args
=
[
course
.
id
])
link
=
reverse
(
'progress'
,
args
=
[
course
.
id
])
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
"progress"
)]
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
"progress"
)]
return
[]
return
[]
def
_wiki
(
tab
,
user
,
course
,
active_page
):
def
_wiki
(
tab
,
user
,
course
,
active_page
,
request
):
"""
This returns a tab containing the course wiki.
"""
if
settings
.
WIKI_ENABLED
:
if
settings
.
WIKI_ENABLED
:
link
=
reverse
(
'course_wiki'
,
args
=
[
course
.
id
])
link
=
reverse
(
'course_wiki'
,
args
=
[
course
.
id
])
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
'wiki'
)]
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
'wiki'
)]
return
[]
return
[]
def
_discussion
(
tab
,
user
,
course
,
active_page
):
def
_discussion
(
tab
,
user
,
course
,
active_page
,
request
):
"""
"""
This tab format only supports the new Berkeley discussion forums.
This tab format only supports the new Berkeley discussion forums.
"""
"""
...
@@ -91,25 +107,25 @@ def _discussion(tab, user, course, active_page):
...
@@ -91,25 +107,25 @@ def _discussion(tab, user, course, active_page):
return
[]
return
[]
def
_external_discussion
(
tab
,
user
,
course
,
active_page
):
def
_external_discussion
(
tab
,
user
,
course
,
active_page
,
request
):
"""
"""
This returns a tab that links to an external discussion service
This returns a tab that links to an external discussion service
"""
"""
return
[
CourseTab
(
'Discussion'
,
tab
[
'link'
],
active_page
==
'discussion'
)]
return
[
CourseTab
(
'Discussion'
,
tab
[
'link'
],
active_page
==
'discussion'
)]
def
_external_link
(
tab
,
user
,
course
,
active_page
):
def
_external_link
(
tab
,
user
,
course
,
active_page
,
request
):
# external links are never active
# external links are never active
return
[
CourseTab
(
tab
[
'name'
],
tab
[
'link'
],
False
)]
return
[
CourseTab
(
tab
[
'name'
],
tab
[
'link'
],
False
)]
def
_static_tab
(
tab
,
user
,
course
,
active_page
):
def
_static_tab
(
tab
,
user
,
course
,
active_page
,
request
):
link
=
reverse
(
'static_tab'
,
args
=
[
course
.
id
,
tab
[
'url_slug'
]])
link
=
reverse
(
'static_tab'
,
args
=
[
course
.
id
,
tab
[
'url_slug'
]])
active_str
=
'static_tab_{0}'
.
format
(
tab
[
'url_slug'
])
active_str
=
'static_tab_{0}'
.
format
(
tab
[
'url_slug'
])
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
active_str
)]
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
active_str
)]
def
_textbooks
(
tab
,
user
,
course
,
active_page
):
def
_textbooks
(
tab
,
user
,
course
,
active_page
,
request
):
"""
"""
Generates one tab per textbook. Only displays if user is authenticated.
Generates one tab per textbook. Only displays if user is authenticated.
"""
"""
...
@@ -120,7 +136,8 @@ def _textbooks(tab, user, course, active_page):
...
@@ -120,7 +136,8 @@ def _textbooks(tab, user, course, active_page):
for
index
,
textbook
in
enumerate
(
course
.
textbooks
)]
for
index
,
textbook
in
enumerate
(
course
.
textbooks
)]
return
[]
return
[]
def
_pdf_textbooks
(
tab
,
user
,
course
,
active_page
):
def
_pdf_textbooks
(
tab
,
user
,
course
,
active_page
,
request
):
"""
"""
Generates one tab per textbook. Only displays if user is authenticated.
Generates one tab per textbook. Only displays if user is authenticated.
"""
"""
...
@@ -131,7 +148,8 @@ def _pdf_textbooks(tab, user, course, active_page):
...
@@ -131,7 +148,8 @@ def _pdf_textbooks(tab, user, course, active_page):
for
index
,
textbook
in
enumerate
(
course
.
pdf_textbooks
)]
for
index
,
textbook
in
enumerate
(
course
.
pdf_textbooks
)]
return
[]
return
[]
def
_html_textbooks
(
tab
,
user
,
course
,
active_page
):
def
_html_textbooks
(
tab
,
user
,
course
,
active_page
,
request
):
"""
"""
Generates one tab per textbook. Only displays if user is authenticated.
Generates one tab per textbook. Only displays if user is authenticated.
"""
"""
...
@@ -142,7 +160,8 @@ def _html_textbooks(tab, user, course, active_page):
...
@@ -142,7 +160,8 @@ def _html_textbooks(tab, user, course, active_page):
for
index
,
textbook
in
enumerate
(
course
.
html_textbooks
)]
for
index
,
textbook
in
enumerate
(
course
.
html_textbooks
)]
return
[]
return
[]
def
_staff_grading
(
tab
,
user
,
course
,
active_page
):
def
_staff_grading
(
tab
,
user
,
course
,
active_page
,
request
):
if
has_access
(
user
,
course
,
'staff'
):
if
has_access
(
user
,
course
,
'staff'
):
link
=
reverse
(
'staff_grading'
,
args
=
[
course
.
id
])
link
=
reverse
(
'staff_grading'
,
args
=
[
course
.
id
])
...
@@ -157,14 +176,13 @@ def _staff_grading(tab, user, course, active_page):
...
@@ -157,14 +176,13 @@ def _staff_grading(tab, user, course, active_page):
return
[]
return
[]
def
_syllabus
(
tab
,
user
,
course
,
active_page
):
def
_syllabus
(
tab
,
user
,
course
,
active_page
,
request
):
"""Display the syllabus tab"""
"""Display the syllabus tab"""
link
=
reverse
(
'syllabus'
,
args
=
[
course
.
id
])
link
=
reverse
(
'syllabus'
,
args
=
[
course
.
id
])
return
[
CourseTab
(
'Syllabus'
,
link
,
active_page
==
'syllabus'
)]
return
[
CourseTab
(
'Syllabus'
,
link
,
active_page
==
'syllabus'
)]
def
_peer_grading
(
tab
,
user
,
course
,
active_page
):
def
_peer_grading
(
tab
,
user
,
course
,
active_page
,
request
):
if
user
.
is_authenticated
():
if
user
.
is_authenticated
():
link
=
reverse
(
'peer_grading'
,
args
=
[
course
.
id
])
link
=
reverse
(
'peer_grading'
,
args
=
[
course
.
id
])
tab_name
=
"Peer grading"
tab_name
=
"Peer grading"
...
@@ -178,7 +196,7 @@ def _peer_grading(tab, user, course, active_page):
...
@@ -178,7 +196,7 @@ def _peer_grading(tab, user, course, active_page):
return
[]
return
[]
def
_combined_open_ended_grading
(
tab
,
user
,
course
,
active_page
):
def
_combined_open_ended_grading
(
tab
,
user
,
course
,
active_page
,
request
):
if
user
.
is_authenticated
():
if
user
.
is_authenticated
():
link
=
reverse
(
'open_ended_notifications'
,
args
=
[
course
.
id
])
link
=
reverse
(
'open_ended_notifications'
,
args
=
[
course
.
id
])
tab_name
=
"Open Ended Panel"
tab_name
=
"Open Ended Panel"
...
@@ -191,15 +209,15 @@ def _combined_open_ended_grading(tab, user, course, active_page):
...
@@ -191,15 +209,15 @@ def _combined_open_ended_grading(tab, user, course, active_page):
return
tab
return
tab
return
[]
return
[]
def
_notes_tab
(
tab
,
user
,
course
,
active_page
):
def
_notes_tab
(
tab
,
user
,
course
,
active_page
,
request
):
if
user
.
is_authenticated
()
and
settings
.
MITX_FEATURES
.
get
(
'ENABLE_STUDENT_NOTES'
):
if
user
.
is_authenticated
()
and
settings
.
MITX_FEATURES
.
get
(
'ENABLE_STUDENT_NOTES'
):
link
=
reverse
(
'notes'
,
args
=
[
course
.
id
])
link
=
reverse
(
'notes'
,
args
=
[
course
.
id
])
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
'notes'
)]
return
[
CourseTab
(
tab
[
'name'
],
link
,
active_page
==
'notes'
)]
return
[]
return
[]
#### Validators
#### Validators
def
key_checker
(
expected_keys
):
def
key_checker
(
expected_keys
):
"""
"""
Returns a function that checks that specified keys are present in a dict
Returns a function that checks that specified keys are present in a dict
...
@@ -263,12 +281,15 @@ def validate_tabs(course):
...
@@ -263,12 +281,15 @@ def validate_tabs(course):
if
len
(
tabs
)
<
2
:
if
len
(
tabs
)
<
2
:
raise
InvalidTabsException
(
"Expected at least two tabs. tabs: '{0}'"
.
format
(
tabs
))
raise
InvalidTabsException
(
"Expected at least two tabs. tabs: '{0}'"
.
format
(
tabs
))
if
tabs
[
0
][
'type'
]
!=
'courseware'
:
if
tabs
[
0
][
'type'
]
!=
'courseware'
:
raise
InvalidTabsException
(
raise
InvalidTabsException
(
"Expected first tab to have type 'courseware'. tabs: '{0}'"
.
format
(
tabs
))
"Expected first tab to have type 'courseware'. tabs: '{0}'"
.
format
(
tabs
))
if
tabs
[
1
][
'type'
]
!=
'course_info'
:
if
tabs
[
1
][
'type'
]
!=
'course_info'
:
raise
InvalidTabsException
(
raise
InvalidTabsException
(
"Expected second tab to have type 'course_info'. tabs: '{0}'"
.
format
(
tabs
))
"Expected second tab to have type 'course_info'. tabs: '{0}'"
.
format
(
tabs
))
for
t
in
tabs
:
for
t
in
tabs
:
if
t
[
'type'
]
not
in
VALID_TAB_TYPES
:
if
t
[
'type'
]
not
in
VALID_TAB_TYPES
:
raise
InvalidTabsException
(
"Unknown tab type {0}. Known types: {1}"
raise
InvalidTabsException
(
"Unknown tab type {0}. Known types: {1}"
...
@@ -280,12 +301,12 @@ def validate_tabs(course):
...
@@ -280,12 +301,12 @@ def validate_tabs(course):
# are actually unique (otherwise, will break active tag code)
# are actually unique (otherwise, will break active tag code)
def
get_course_tabs
(
user
,
course
,
active_page
):
def
get_course_tabs
(
user
,
course
,
active_page
,
request
):
"""
"""
Return the tabs to show a particular user, as a list of CourseTab items.
Return the tabs to show a particular user, as a list of CourseTab items.
"""
"""
if
not
hasattr
(
course
,
'tabs'
)
or
not
course
.
tabs
:
if
not
hasattr
(
course
,
'tabs'
)
or
not
course
.
tabs
:
return
get_default_tabs
(
user
,
course
,
active_page
)
return
get_default_tabs
(
user
,
course
,
active_page
,
request
)
# TODO (vshnayder): There needs to be a place to call this right after course
# TODO (vshnayder): There needs to be a place to call this right after course
# load, but not from inside xmodule, since that doesn't (and probably
# load, but not from inside xmodule, since that doesn't (and probably
...
@@ -293,12 +314,18 @@ def get_course_tabs(user, course, active_page):
...
@@ -293,12 +314,18 @@ def get_course_tabs(user, course, active_page):
validate_tabs
(
course
)
validate_tabs
(
course
)
tabs
=
[]
tabs
=
[]
for
tab
in
course
.
tabs
:
if
waffle
.
flag_is_active
(
request
,
'merge_course_tabs'
):
course_tabs
=
[
tab
for
tab
in
course
.
tabs
if
tab
[
'type'
]
!=
"course_info"
]
else
:
course_tabs
=
course
.
tabs
for
tab
in
course_tabs
:
# expect handlers to return lists--handles things that are turned off
# expect handlers to return lists--handles things that are turned off
# via feature flags, and things like 'textbook' which might generate
# via feature flags, and things like 'textbook' which might generate
# multiple tabs.
# multiple tabs.
gen
=
VALID_TAB_TYPES
[
tab
[
'type'
]]
.
generator
gen
=
VALID_TAB_TYPES
[
tab
[
'type'
]]
.
generator
tabs
.
extend
(
gen
(
tab
,
user
,
course
,
active_page
))
tabs
.
extend
(
gen
(
tab
,
user
,
course
,
active_page
,
request
))
# Instructor tab is special--automatically added if user is staff for the course
# Instructor tab is special--automatically added if user is staff for the course
if
has_access
(
user
,
course
,
'staff'
):
if
has_access
(
user
,
course
,
'staff'
):
...
@@ -314,7 +341,7 @@ def get_discussion_link(course):
...
@@ -314,7 +341,7 @@ def get_discussion_link(course):
Return the URL for the discussion tab for the given `course`.
Return the URL for the discussion tab for the given `course`.
If they have a discussion link specified, use that even if we disable
If they have a discussion link specified, use that even if we disable
discussions. Disabling disc
s
ussions is mostly a server safety feature at
discussions. Disabling discussions is mostly a server safety feature at
this point, and we don't need to worry about external sites. Otherwise,
this point, and we don't need to worry about external sites. Otherwise,
if the course has a discussion tab or uses the default tabs, return the
if the course has a discussion tab or uses the default tabs, return the
discussion view URL. Otherwise, return None to indicate the lack of a
discussion view URL. Otherwise, return None to indicate the lack of a
...
@@ -330,28 +357,33 @@ def get_discussion_link(course):
...
@@ -330,28 +357,33 @@ def get_discussion_link(course):
return
reverse
(
'django_comment_client.forum.views.forum_form_discussion'
,
args
=
[
course
.
id
])
return
reverse
(
'django_comment_client.forum.views.forum_form_discussion'
,
args
=
[
course
.
id
])
def
get_default_tabs
(
user
,
course
,
active_page
):
def
get_default_tabs
(
user
,
course
,
active_page
,
request
):
"""
Return the default set of tabs.
"""
# When calling the various _tab methods, can omit the 'type':'blah' from the
# When calling the various _tab methods, can omit the 'type':'blah' from the
# first arg, since that's only used for dispatch
# first arg, since that's only used for dispatch
tabs
=
[]
tabs
=
[]
tabs
.
extend
(
_courseware
({
''
},
user
,
course
,
active_page
))
tabs
.
extend
(
_course_info
({
'name'
:
'Course Info'
},
user
,
course
,
active_page
))
tabs
.
extend
(
_courseware
({
''
},
user
,
course
,
active_page
,
request
))
if
not
waffle
.
flag_is_active
(
request
,
'merge_course_tabs'
):
tabs
.
extend
(
_course_info
({
'name'
:
'Course Info'
},
user
,
course
,
active_page
,
request
))
if
hasattr
(
course
,
'syllabus_present'
)
and
course
.
syllabus_present
:
if
hasattr
(
course
,
'syllabus_present'
)
and
course
.
syllabus_present
:
link
=
reverse
(
'syllabus'
,
args
=
[
course
.
id
])
link
=
reverse
(
'syllabus'
,
args
=
[
course
.
id
])
tabs
.
append
(
CourseTab
(
'Syllabus'
,
link
,
active_page
==
'syllabus'
))
tabs
.
append
(
CourseTab
(
'Syllabus'
,
link
,
active_page
==
'syllabus'
))
tabs
.
extend
(
_textbooks
({},
user
,
course
,
active_page
))
tabs
.
extend
(
_textbooks
({},
user
,
course
,
active_page
,
request
))
discussion_link
=
get_discussion_link
(
course
)
discussion_link
=
get_discussion_link
(
course
)
if
discussion_link
:
if
discussion_link
:
tabs
.
append
(
CourseTab
(
'Discussion'
,
discussion_link
,
active_page
==
'discussion'
))
tabs
.
append
(
CourseTab
(
'Discussion'
,
discussion_link
,
active_page
==
'discussion'
))
tabs
.
extend
(
_wiki
({
'name'
:
'Wiki'
,
'type'
:
'wiki'
},
user
,
course
,
active_page
))
tabs
.
extend
(
_wiki
({
'name'
:
'Wiki'
,
'type'
:
'wiki'
},
user
,
course
,
active_page
,
request
))
if
user
.
is_authenticated
()
and
not
course
.
hide_progress_tab
:
if
user
.
is_authenticated
()
and
not
course
.
hide_progress_tab
:
tabs
.
extend
(
_progress
({
'name'
:
'Progress'
},
user
,
course
,
active_page
))
tabs
.
extend
(
_progress
({
'name'
:
'Progress'
},
user
,
course
,
active_page
,
request
))
if
has_access
(
user
,
course
,
'staff'
):
if
has_access
(
user
,
course
,
'staff'
):
link
=
reverse
(
'instructor_dashboard'
,
args
=
[
course
.
id
])
link
=
reverse
(
'instructor_dashboard'
,
args
=
[
course
.
id
])
...
@@ -376,7 +408,6 @@ def get_static_tab_by_slug(course, tab_slug):
...
@@ -376,7 +408,6 @@ def get_static_tab_by_slug(course, tab_slug):
def
get_static_tab_contents
(
request
,
course
,
tab
):
def
get_static_tab_contents
(
request
,
course
,
tab
):
loc
=
Location
(
course
.
location
.
tag
,
course
.
location
.
org
,
course
.
location
.
course
,
'static_tab'
,
tab
[
'url_slug'
])
loc
=
Location
(
course
.
location
.
tag
,
course
.
location
.
org
,
course
.
location
.
course
,
'static_tab'
,
tab
[
'url_slug'
])
field_data_cache
=
FieldDataCache
.
cache_for_descriptor_descendents
(
course
.
id
,
field_data_cache
=
FieldDataCache
.
cache_for_descriptor_descendents
(
course
.
id
,
request
.
user
,
modulestore
()
.
get_instance
(
course
.
id
,
loc
),
depth
=
0
)
request
.
user
,
modulestore
()
.
get_instance
(
course
.
id
,
loc
),
depth
=
0
)
...
...
lms/djangoapps/courseware/tests/test_tabs.py
View file @
f1ccf1c0
...
@@ -11,6 +11,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
...
@@ -11,6 +11,7 @@ from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
from
courseware.tests.modulestore_config
import
TEST_DATA_MIXED_MODULESTORE
FAKE_REQUEST
=
None
class
ProgressTestCase
(
TestCase
):
class
ProgressTestCase
(
TestCase
):
...
@@ -29,20 +30,20 @@ class ProgressTestCase(TestCase):
...
@@ -29,20 +30,20 @@ class ProgressTestCase(TestCase):
def
test_progress
(
self
):
def
test_progress
(
self
):
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser0
,
self
.
course
,
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser0
,
self
.
course
,
self
.
active_page0
),
[])
self
.
active_page0
,
FAKE_REQUEST
),
[])
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page1
)[
0
]
.
name
,
'same'
)
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
name
,
'same'
)
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page1
)[
0
]
.
link
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
link
,
reverse
(
'progress'
,
args
=
[
self
.
course
.
id
]))
reverse
(
'progress'
,
args
=
[
self
.
course
.
id
]))
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page0
)[
0
]
.
is_active
,
False
)
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
is_active
,
False
)
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
assertEqual
(
tabs
.
_progress
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page1
)[
0
]
.
is_active
,
True
)
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
is_active
,
True
)
class
WikiTestCase
(
TestCase
):
class
WikiTestCase
(
TestCase
):
...
@@ -60,26 +61,26 @@ class WikiTestCase(TestCase):
...
@@ -60,26 +61,26 @@ class WikiTestCase(TestCase):
def
test_wiki_enabled
(
self
):
def
test_wiki_enabled
(
self
):
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
course
,
self
.
active_page1
)[
0
]
.
name
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
name
,
'same'
)
'same'
)
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
course
,
self
.
active_page1
)[
0
]
.
link
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
link
,
reverse
(
'course_wiki'
,
args
=
[
self
.
course
.
id
]))
reverse
(
'course_wiki'
,
args
=
[
self
.
course
.
id
]))
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
course
,
self
.
active_page1
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
is_active
,
True
)
True
)
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
course
,
self
.
active_page0
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
is_active
,
False
)
False
)
@override_settings
(
WIKI_ENABLED
=
False
)
@override_settings
(
WIKI_ENABLED
=
False
)
def
test_wiki_enabled_false
(
self
):
def
test_wiki_enabled_false
(
self
):
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_wiki
(
self
.
tab
,
self
.
user
,
self
.
course
,
self
.
active_page1
),
[])
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
),
[])
class
ExternalLinkTestCase
(
TestCase
):
class
ExternalLinkTestCase
(
TestCase
):
...
@@ -95,19 +96,19 @@ class ExternalLinkTestCase(TestCase):
...
@@ -95,19 +96,19 @@ class ExternalLinkTestCase(TestCase):
def
test_external_link
(
self
):
def
test_external_link
(
self
):
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page0
)[
0
]
.
name
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
name
,
'same'
)
'same'
)
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page0
)[
0
]
.
link
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
link
,
'blink'
)
'blink'
)
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page0
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
is_active
,
False
)
False
)
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_external_link
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page00
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page00
,
FAKE_REQUEST
)[
0
]
.
is_active
,
False
)
False
)
...
@@ -125,20 +126,20 @@ class StaticTabTestCase(TestCase):
...
@@ -125,20 +126,20 @@ class StaticTabTestCase(TestCase):
def
test_static_tab
(
self
):
def
test_static_tab
(
self
):
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page1
)[
0
]
.
name
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
name
,
'same'
)
'same'
)
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page1
)[
0
]
.
link
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
link
,
reverse
(
'static_tab'
,
args
=
[
self
.
course
.
id
,
reverse
(
'static_tab'
,
args
=
[
self
.
course
.
id
,
self
.
tabby
[
'url_slug'
]]))
self
.
tabby
[
'url_slug'
]]))
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page1
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
0
]
.
is_active
,
True
)
True
)
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
assertEqual
(
tabs
.
_static_tab
(
self
.
tabby
,
self
.
user
,
self
.
course
,
self
.
active_page0
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
is_active
,
False
)
False
)
...
@@ -166,45 +167,45 @@ class TextbooksTestCase(TestCase):
...
@@ -166,45 +167,45 @@ class TextbooksTestCase(TestCase):
def
test_textbooks1
(
self
):
def
test_textbooks1
(
self
):
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page0
)[
0
]
.
name
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
name
,
'Algebra'
)
'Algebra'
)
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page0
)[
0
]
.
link
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
link
,
reverse
(
'book'
,
args
=
[
self
.
course
.
id
,
0
]))
reverse
(
'book'
,
args
=
[
self
.
course
.
id
,
0
]))
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page0
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_page0
,
FAKE_REQUEST
)[
0
]
.
is_active
,
True
)
True
)
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_pageX
)[
0
]
.
is_active
,
self
.
course
,
self
.
active_pageX
,
FAKE_REQUEST
)[
0
]
.
is_active
,
False
)
False
)
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page1
)[
1
]
.
name
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
1
]
.
name
,
'Topology'
)
'Topology'
)
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page1
)[
1
]
.
link
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
1
]
.
link
,
reverse
(
'book'
,
args
=
[
self
.
course
.
id
,
1
]))
reverse
(
'book'
,
args
=
[
self
.
course
.
id
,
1
]))
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_page1
)[
1
]
.
is_active
,
self
.
course
,
self
.
active_page1
,
FAKE_REQUEST
)[
1
]
.
is_active
,
True
)
True
)
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_pageX
)[
1
]
.
is_active
,
self
.
course
,
self
.
active_pageX
,
FAKE_REQUEST
)[
1
]
.
is_active
,
False
)
False
)
@override_settings
(
MITX_FEATURES
=
{
'ENABLE_TEXTBOOK'
:
False
})
@override_settings
(
MITX_FEATURES
=
{
'ENABLE_TEXTBOOK'
:
False
})
def
test_textbooks0
(
self
):
def
test_textbooks0
(
self
):
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser1
,
self
.
course
,
self
.
active_pageX
),
[])
self
.
course
,
self
.
active_pageX
,
FAKE_REQUEST
),
[])
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser0
,
self
.
assertEqual
(
tabs
.
_textbooks
(
self
.
tab
,
self
.
mockuser0
,
self
.
course
,
self
.
active_pageX
),
[])
self
.
course
,
self
.
active_pageX
,
FAKE_REQUEST
),
[])
class
KeyCheckerTestCase
(
TestCase
):
class
KeyCheckerTestCase
(
TestCase
):
...
...
lms/djangoapps/courseware/views.py
View file @
f1ccf1c0
...
@@ -728,6 +728,7 @@ def submission_history(request, course_id, student_username, location):
...
@@ -728,6 +728,7 @@ def submission_history(request, course_id, student_username, location):
Right now this only works for problems because that's all
Right now this only works for problems because that's all
StudentModuleHistory records.
StudentModuleHistory records.
"""
"""
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'load'
)
course
=
get_course_with_access
(
request
.
user
,
course_id
,
'load'
)
staff_access
=
has_access
(
request
.
user
,
course
,
'staff'
)
staff_access
=
has_access
(
request
.
user
,
course
,
'staff'
)
...
...
lms/envs/common.py
View file @
f1ccf1c0
...
@@ -80,7 +80,7 @@ MITX_FEATURES = {
...
@@ -80,7 +80,7 @@ MITX_FEATURES = {
'ENABLE_PSYCHOMETRICS'
:
False
,
# real-time psychometrics (eg item response theory analysis in instructor dashboard)
'ENABLE_PSYCHOMETRICS'
:
False
,
# real-time psychometrics (eg item response theory analysis in instructor dashboard)
'ENABLE_DJANGO_ADMIN_SITE'
:
Fals
e
,
# set true to enable django's admin site, even on prod (e.g. for course ops)
'ENABLE_DJANGO_ADMIN_SITE'
:
Tru
e
,
# set true to enable django's admin site, even on prod (e.g. for course ops)
'ENABLE_SQL_TRACKING_LOGS'
:
False
,
'ENABLE_SQL_TRACKING_LOGS'
:
False
,
'ENABLE_LMS_MIGRATION'
:
False
,
'ENABLE_LMS_MIGRATION'
:
False
,
'ENABLE_MANUAL_GIT_RELOAD'
:
False
,
'ENABLE_MANUAL_GIT_RELOAD'
:
False
,
...
@@ -523,6 +523,14 @@ MOCK_STAFF_GRADING = False
...
@@ -523,6 +523,14 @@ MOCK_STAFF_GRADING = False
################################# Jasmine ###################################
################################# Jasmine ###################################
JASMINE_TEST_DIRECTORY
=
PROJECT_ROOT
+
'/static/coffee'
JASMINE_TEST_DIRECTORY
=
PROJECT_ROOT
+
'/static/coffee'
################################# Waffle ###################################
# Name prepended to cookies set by Waffle
WAFFLE_COOKIE
=
"waffle_flag_
%
s"
# Two weeks (in sec)
WAFFLE_MAX_AGE
=
1209600
################################# Middleware ###################################
################################# Middleware ###################################
# List of finder classes that know how to find static files in
# List of finder classes that know how to find static files in
# various locations.
# various locations.
...
@@ -570,6 +578,9 @@ MIDDLEWARE_CLASSES = (
...
@@ -570,6 +578,9 @@ MIDDLEWARE_CLASSES = (
# catches any uncaught RateLimitExceptions and returns a 403 instead of a 500
# catches any uncaught RateLimitExceptions and returns a 403 instead of a 500
'ratelimitbackend.middleware.RateLimitMiddleware'
,
'ratelimitbackend.middleware.RateLimitMiddleware'
,
# For A/B testing
'waffle.middleware.WaffleMiddleware'
,
)
)
############################### Pipeline #######################################
############################### Pipeline #######################################
...
@@ -832,6 +843,9 @@ INSTALLED_APPS = (
...
@@ -832,6 +843,9 @@ INSTALLED_APPS = (
# Foldit integration
# Foldit integration
'foldit'
,
'foldit'
,
# For A/B testing
'waffle'
,
# For testing
# For testing
'django.contrib.admin'
,
# only used in DEBUG mode
'django.contrib.admin'
,
# only used in DEBUG mode
'django_nose'
,
'django_nose'
,
...
...
lms/envs/dev.py
View file @
f1ccf1c0
...
@@ -255,7 +255,7 @@ ANALYTICS_API_KEY = ""
...
@@ -255,7 +255,7 @@ ANALYTICS_API_KEY = ""
##### segment-io ######
##### segment-io ######
# If there's an environment variable set, grab it and turn on
segment
io
# If there's an environment variable set, grab it and turn on
Segment.
io
SEGMENT_IO_LMS_KEY
=
os
.
environ
.
get
(
'SEGMENT_IO_LMS_KEY'
)
SEGMENT_IO_LMS_KEY
=
os
.
environ
.
get
(
'SEGMENT_IO_LMS_KEY'
)
if
SEGMENT_IO_LMS_KEY
:
if
SEGMENT_IO_LMS_KEY
:
MITX_FEATURES
[
'SEGMENT_IO_LMS'
]
=
True
MITX_FEATURES
[
'SEGMENT_IO_LMS'
]
=
True
...
...
lms/static/sass/course/layout/_courseware_header.scss
View file @
f1ccf1c0
...
@@ -23,6 +23,17 @@ nav.course-material {
...
@@ -23,6 +23,17 @@ nav.course-material {
list-style
:
none
;
list-style
:
none
;
margin-right
:
6px
;
margin-right
:
6px
;
&
.prominent
{
margin-right
:
16px
;
background
:
rgba
(
255
,
255
,
255
,
.5
);
border-radius
:
3px
;
}
&
.prominent
+
li
{
padding-left
:
15px
;
border-left
:
1px
solid
#333
;
}
a
{
a
{
border-radius
:
3px
;
border-radius
:
3px
;
color
:
#555
;
color
:
#555
;
...
...
lms/templates/courseware/course_navigation.html
View file @
f1ccf1c0
...
@@ -13,19 +13,24 @@ def url_class(is_active):
...
@@ -13,19 +13,24 @@ def url_class(is_active):
%
>
%
>
<
%!
from
courseware
.
tabs
import
get_course_tabs
%
>
<
%!
from
courseware
.
tabs
import
get_course_tabs
%
>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%
import
waffle
%
>
<nav
class=
"${active_page} course-material"
>
<nav
class=
"${active_page} course-material"
>
<div
class=
"inner-wrapper"
>
<div
class=
"inner-wrapper"
>
<ol
class=
"course-tabs"
>
<ol
class=
"course-tabs"
>
% for tab in get_course_tabs(user, course, active_page):
% for tab in get_course_tabs(user, course, active_page, request):
% if waffle.flag_is_active(request, 'visual_treatment') or waffle.flag_is_active(request, 'merge_course_tabs'):
<li
class=
"${"
prominent
"
if
tab
.
name
in
("
Courseware
",
"
Course
Content
")
else
""}"
>
% else:
<li>
<li>
% endif
<a
href=
"${tab.link | h}"
class=
"${url_class(tab.is_active)}"
>
<a
href=
"${tab.link | h}"
class=
"${url_class(tab.is_active)}"
>
${tab.name | h}
${tab.name | h}
% if tab.is_active == True:
% if tab.is_active == True:
<span
class=
"sr"
>
, current location
</span>
<span
class=
"sr"
>
, current location
</span>
%endif
%endif
% if tab.has_img == True:
% if tab.has_img == True:
<img
src=
"${tab.img}"
/>
<img
src=
"${tab.img}"
/>
%endif
%endif
</a>
</a>
</li>
</li>
...
...
lms/templates/courseware/welcome-back.html
View file @
f1ccf1c0
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
%
>
<
%!
from
django
.
utils
.
translation
import
ugettext
as
_
import
waffle
%
>
<h2>
${chapter_module.display_name_with_default}
</h2>
<h2>
${chapter_module.display_name_with_default}
</h2>
<p>
${_("You were most recently in {section_link}. If you\'re done with that, choose another section on the left.").format(
<p>
${_("You were most recently in {section_link}. If you\'re done with that, choose another section on the left.").format(
...
@@ -7,3 +11,31 @@
...
@@ -7,3 +11,31 @@
section_name=prev_section.display_name_with_default,
section_name=prev_section.display_name_with_default,
)
)
)}
</p>
)}
</p>
% if waffle.flag_is_active(request, 'merge_course_tabs'):
<
%!
from
courseware
.
courses
import
get_course_info_section
%
>
<section
class=
"container"
>
<div
class=
"info-wrapper"
>
% if user.is_authenticated():
<section
class=
"updates"
>
<h1>
${_("Course Updates
&
News")}
</h1>
${get_course_info_section(request, course, 'updates')}
</section>
<section
aria-label=
"${_('Handout Navigation')}"
class=
"handouts"
>
<h1>
${course.info_sidebar_name}
</h1>
${get_course_info_section(request, course, 'handouts')}
</section>
% else:
<section
class=
"updates"
>
<h1>
${_("Course Updates
&
News")}
</h1>
${get_course_info_section(request, course, 'guest_updates')}
</section>
<section
aria-label=
"${_('Handout Navigation')}"
class=
"handouts"
>
<h1>
${_("Course Handouts")}
</h1>
${get_course_info_section(request, course, 'guest_handouts')}
</section>
% endif
</div>
</section>
% endif
lms/templates/dashboard.html
View file @
f1ccf1c0
...
@@ -5,8 +5,11 @@
...
@@ -5,8 +5,11 @@
from
courseware
.
courses
import
course_image_url
,
get_course_about_section
from
courseware
.
courses
import
course_image_url
,
get_course_about_section
from
courseware
.
access
import
has_access
from
courseware
.
access
import
has_access
from
certificates
.
models
import
CertificateStatuses
from
certificates
.
models
import
CertificateStatuses
from
xmodule
.
modulestore
import
MONGO_MODULESTORE_TYPE
from
xmodule
.
modulestore
import
MONGO_MODULESTORE_TYPE
from
xmodule
.
modulestore
.
django
import
modulestore
from
xmodule
.
modulestore
.
django
import
modulestore
import
waffle
%
>
%
>
<
%
inherit
file=
"main.html"
/>
<
%
inherit
file=
"main.html"
/>
...
@@ -163,7 +166,10 @@
...
@@ -163,7 +166,10 @@
<li
class=
"course-item"
>
<li
class=
"course-item"
>
<article
class=
"course ${enrollment.mode}"
>
<article
class=
"course ${enrollment.mode}"
>
<
%
<
%
course_target =
reverse('info',
args=
[course.id])
if
waffle
.
flag_is_active
(
request
,
'
merge_course_tabs
')
:
course_target =
reverse('courseware',
args=
[course.id])
else:
course_target =
reverse('info',
args=
[course.id])
%
>
%
>
% if course.id in show_courseware_links_for:
% if course.id in show_courseware_links_for:
...
...
lms/templates/widgets/segment-io.html
View file @
f1ccf1c0
% if settings.MITX_FEATURES.get('SEGMENT_IO_LMS'):
% if settings.MITX_FEATURES.get('SEGMENT_IO_LMS'):
<!-- begin Segment.io -->
<!-- begin Segment.io -->
<
%!
from
django
.
core
.
urlresolvers
import
reverse
%
>
<
%!
import
waffle
%
>
<
%
active_flags =
" + "
.
join
(
waffle
.
get_flags
(
request
))
%
>
<!-- <script src="${ reverse('wafflejs') }"></script> -->
<script
type=
"text/javascript"
>
<script
type=
"text/javascript"
>
var
analytics
=
analytics
||
[];
analytics
.
load
=
function
(
e
){
var
t
=
document
.
createElement
(
"script"
);
t
.
type
=
"text/javascript"
,
t
.
async
=!
0
,
t
.
src
=
(
"https:"
===
document
.
location
.
protocol
?
"https://"
:
"http://"
)
+
"d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/"
+
e
+
"/analytics.min.js"
;
var
n
=
document
.
getElementsByTagName
(
"script"
)[
0
];
n
.
parentNode
.
insertBefore
(
t
,
n
);
var
r
=
function
(
e
){
return
function
(){
analytics
.
push
([
e
].
concat
(
Array
.
prototype
.
slice
.
call
(
arguments
,
0
)))}},
i
=
[
"identify"
,
"track"
,
"trackLink"
,
"trackForm"
,
"trackClick"
,
"trackSubmit"
,
"pageview"
,
"ab"
,
"alias"
,
"ready"
];
for
(
var
s
=
0
;
s
<
i
.
length
;
s
++
)
analytics
[
i
[
s
]]
=
r
(
i
[
s
])};
var
analytics
=
analytics
||
[];
analytics
.
load
=
function
(
e
){
var
t
=
document
.
createElement
(
"script"
);
t
.
type
=
"text/javascript"
,
t
.
async
=!
0
,
t
.
src
=
(
"https:"
===
document
.
location
.
protocol
?
"https://"
:
"http://"
)
+
"d2dq2ahtl5zl1z.cloudfront.net/analytics.js/v1/"
+
e
+
"/analytics.min.js"
;
var
n
=
document
.
getElementsByTagName
(
"script"
)[
0
];
n
.
parentNode
.
insertBefore
(
t
,
n
);
var
r
=
function
(
e
){
return
function
(){
analytics
.
push
([
e
].
concat
(
Array
.
prototype
.
slice
.
call
(
arguments
,
0
)))}},
i
=
[
"identify"
,
"track"
,
"trackLink"
,
"trackForm"
,
"trackClick"
,
"trackSubmit"
,
"pageview"
,
"ab"
,
"alias"
,
"ready"
];
for
(
var
s
=
0
;
s
<
i
.
length
;
s
++
)
analytics
[
i
[
s
]]
=
r
(
i
[
s
])};
analytics
.
load
(
"${ settings.SEGMENT_IO_LMS_KEY }"
);
analytics
.
load
(
"${ settings.SEGMENT_IO_LMS_KEY }"
);
%
if
user
.
is_authenticated
():
%
if
user
.
is_authenticated
():
analytics
.
identify
(
"${ user.id }"
,
{
email
:
"${ user.email }"
,
analytics
.
identify
(
"${ user.id }"
,
{
username
:
"${ user.username }"
email
:
"${ user.email }"
,
});
username
:
"${ user.username }"
,
"Active Flags"
:
"${ active_flags }"
,
});
%
endif
%
endif
</script>
</script>
...
...
lms/urls.py
View file @
f1ccf1c0
...
@@ -59,6 +59,7 @@ urlpatterns = ('', # nopep8
...
@@ -59,6 +59,7 @@ urlpatterns = ('', # nopep8
url
(
r'^user_api/'
,
include
(
'user_api.urls'
)),
url
(
r'^user_api/'
,
include
(
'user_api.urls'
)),
url
(
r'^'
,
include
(
'waffle.urls'
)),
)
)
# if settings.MITX_FEATURES.get("MULTIPLE_ENROLLMENT_ROLES"):
# if settings.MITX_FEATURES.get("MULTIPLE_ENROLLMENT_ROLES"):
...
...
requirements/edx/github.txt
View file @
f1ccf1c0
...
@@ -18,3 +18,4 @@
...
@@ -18,3 +18,4 @@
-e git+https://github.com/edx/codejail.git@0a1b468#egg=codejail
-e git+https://github.com/edx/codejail.git@0a1b468#egg=codejail
-e git+https://github.com/edx/diff-cover.git@v0.2.3#egg=diff_cover
-e git+https://github.com/edx/diff-cover.git@v0.2.3#egg=diff_cover
-e git+https://github.com/edx/js-test-tool.git@v0.0.7#egg=js_test_tool
-e git+https://github.com/edx/js-test-tool.git@v0.0.7#egg=js_test_tool
-e git+https://github.com/edx/django-waffle.git@823a102e48#egg=django-waffle
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