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
80bd4dde
Commit
80bd4dde
authored
Oct 16, 2014
by
Clinton Blackburn
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #162 from edx/display-opaque-key
Updated Display of Opaque Keys
parents
afb15da7
2ed434da
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
48 additions
and
10 deletions
+48
-10
acceptance_tests/test_course_index.py
+1
-1
analytics_dashboard/analytics_dashboard/templatetags/dashboard_extras.py
+9
-0
analytics_dashboard/analytics_dashboard/tests/test_templatetags.py
+13
-0
analytics_dashboard/courses/middleware.py
+10
-1
analytics_dashboard/courses/templates/courses/base-course.html
+2
-1
analytics_dashboard/courses/templates/courses/index.html
+1
-1
analytics_dashboard/courses/tests/test_middleware.py
+5
-1
analytics_dashboard/courses/views.py
+7
-5
No files found.
acceptance_tests/test_course_index.py
View file @
80bd4dde
...
@@ -32,7 +32,7 @@ class CourseIndexTests(AssertMixin, PrimaryNavMixin, LoginMixin, WebAppTest):
...
@@ -32,7 +32,7 @@ class CourseIndexTests(AssertMixin, PrimaryNavMixin, LoginMixin, WebAppTest):
# The element should link to the course landing page.
# The element should link to the course landing page.
index
=
element
.
text
.
index
(
course_id
)
index
=
element
.
text
.
index
(
course_id
)
href
=
element
.
attrs
(
'href'
)[
index
]
href
=
element
.
attrs
(
'href'
)[
index
]
self
.
assertTrue
(
href
.
endswith
(
'/courses/{}/'
.
format
(
course_id
)))
self
.
assertTrue
(
href
.
endswith
(
u
'/courses/{}/'
.
format
(
course_id
)))
# check that we have an email
# check that we have an email
self
.
assertValidFeedbackLink
(
'div[class=help-msg] a[class=feedback-email]'
)
self
.
assertValidFeedbackLink
(
'div[class=help-msg] a[class=feedback-email]'
)
analytics_dashboard/analytics_dashboard/templatetags/dashboard_extras.py
View file @
80bd4dde
from
django
import
template
from
django
import
template
from
django.conf
import
settings
from
django.conf
import
settings
from
django.utils.safestring
import
mark_safe
from
django.utils.safestring
import
mark_safe
from
opaque_keys.edx.keys
import
CourseKey
register
=
template
.
Library
()
register
=
template
.
Library
()
...
@@ -78,3 +79,11 @@ def _get_base_error_context(content_type):
...
@@ -78,3 +79,11 @@ def _get_base_error_context(content_type):
'content_type'
:
content_type
,
'content_type'
:
content_type
,
'load_error_message'
:
settings
.
DOCUMENTATION_LOAD_ERROR_MESSAGE
'load_error_message'
:
settings
.
DOCUMENTATION_LOAD_ERROR_MESSAGE
}
}
@register.filter
def
format_course_key
(
course_key
):
if
isinstance
(
course_key
,
basestring
):
course_key
=
CourseKey
.
from_string
(
course_key
)
return
u'/'
.
join
([
course_key
.
org
,
course_key
.
course
,
course_key
.
run
])
analytics_dashboard/analytics_dashboard/tests/test_templatetags.py
View file @
80bd4dde
...
@@ -3,6 +3,8 @@
...
@@ -3,6 +3,8 @@
from
django.template
import
Template
,
Context
,
TemplateSyntaxError
from
django.template
import
Template
,
Context
,
TemplateSyntaxError
from
django.test
import
TestCase
from
django.test
import
TestCase
from
opaque_keys.edx.keys
import
CourseKey
from
analytics_dashboard.templatetags.dashboard_extras
import
format_course_key
class
DashboardExtraTests
(
TestCase
):
class
DashboardExtraTests
(
TestCase
):
...
@@ -37,3 +39,14 @@ class DashboardExtraTests(TestCase):
...
@@ -37,3 +39,14 @@ class DashboardExtraTests(TestCase):
def
test_captureas_unicode
(
self
):
def
test_captureas_unicode
(
self
):
self
.
assertTextCaptured
(
u'★❤'
)
self
.
assertTextCaptured
(
u'★❤'
)
def
test_format_course_key
(
self
):
values
=
[(
'edX/DemoX/Demo_Course'
,
'edX/DemoX/Demo_Course'
),
(
'course-v1:edX+DemoX+Demo_2014'
,
'edX/DemoX/Demo_2014'
)]
for
course_id
,
expected
in
values
:
# Test with CourseKey
course_key
=
CourseKey
.
from_string
(
course_id
)
self
.
assertEqual
(
format_course_key
(
course_key
),
expected
)
# Test with string
self
.
assertEqual
(
format_course_key
(
course_id
),
expected
)
analytics_dashboard/courses/middleware.py
View file @
80bd4dde
...
@@ -4,6 +4,7 @@ https://docs.djangoproject.com/en/dev/topics/http/middleware/.
...
@@ -4,6 +4,7 @@ https://docs.djangoproject.com/en/dev/topics/http/middleware/.
"""
"""
import
logging
import
logging
from
django.template.response
import
TemplateResponse
from
django.template.response
import
TemplateResponse
from
opaque_keys.edx.keys
import
CourseKey
from
courses.exceptions
import
PermissionsRetrievalFailedError
from
courses.exceptions
import
PermissionsRetrievalFailedError
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -15,7 +16,15 @@ class CourseMiddleware(object):
...
@@ -15,7 +16,15 @@ class CourseMiddleware(object):
"""
"""
def
process_view
(
self
,
request
,
_view_func
,
_view_args
,
view_kwargs
):
def
process_view
(
self
,
request
,
_view_func
,
_view_args
,
view_kwargs
):
request
.
course_id
=
view_kwargs
.
get
(
'course_id'
,
None
)
request
.
course_key
=
None
request
.
course_id
=
None
course_id
=
view_kwargs
.
get
(
'course_id'
,
None
)
if
course_id
:
request
.
course_key
=
CourseKey
.
from_string
(
course_id
)
request
.
course_id
=
unicode
(
request
.
course_key
)
return
None
return
None
...
...
analytics_dashboard/courses/templates/courses/base-course.html
View file @
80bd4dde
{% extends "base.html" %}
{% extends "base.html" %}
{% load dashboard_extras %}
{% block title %}{{ page_title }} - {{ course_
id
}} {{ block.super }}{% endblock title %}
{% block title %}{{ page_title }} - {{ course_
key|format_course_key
}} {{ block.super }}{% endblock title %}
{# This is intentionally left blank. Course pages do not need a title block. #}
{# This is intentionally left blank. Course pages do not need a title block. #}
{% block header-text %}{% endblock %}
{% block header-text %}{% endblock %}
...
...
analytics_dashboard/courses/templates/courses/index.html
View file @
80bd4dde
...
@@ -24,7 +24,7 @@
...
@@ -24,7 +24,7 @@
{% for course in courses %}
{% for course in courses %}
<a
href=
"{% url 'courses:home' course_id=course %}"
>
<a
href=
"{% url 'courses:home' course_id=course %}"
>
<div
class=
"course"
>
<div
class=
"course"
>
<span
class=
"course-title"
>
{{ course }}
</span>
<span
class=
"course-title"
>
{{ course
|format_course_key
}}
</span>
</div>
</div>
</a>
</a>
{% endfor %}
{% endfor %}
...
...
analytics_dashboard/courses/tests/test_middleware.py
View file @
80bd4dde
...
@@ -2,6 +2,7 @@ import logging
...
@@ -2,6 +2,7 @@ import logging
from
django.template.response
import
TemplateResponse
from
django.template.response
import
TemplateResponse
from
django.test
import
RequestFactory
from
django.test
import
RequestFactory
from
django.utils.unittest.case
import
TestCase
from
django.utils.unittest.case
import
TestCase
from
opaque_keys.edx.keys
import
CourseKey
from
testfixtures
import
LogCapture
from
testfixtures
import
LogCapture
from
courses.exceptions
import
PermissionsRetrievalFailedError
from
courses.exceptions
import
PermissionsRetrievalFailedError
from
courses.middleware
import
CourseMiddleware
,
CoursePermissionsExceptionMiddleware
from
courses.middleware
import
CourseMiddleware
,
CoursePermissionsExceptionMiddleware
...
@@ -36,12 +37,15 @@ class CourseMiddlewareTests(MiddlewareTestCase):
...
@@ -36,12 +37,15 @@ class CourseMiddlewareTests(MiddlewareTestCase):
request
=
self
.
factory
.
get
(
'/'
)
request
=
self
.
factory
.
get
(
'/'
)
self
.
middleware
.
process_view
(
request
,
''
,
None
,
{})
self
.
middleware
.
process_view
(
request
,
''
,
None
,
{})
self
.
assertIsNone
(
request
.
course_id
)
self
.
assertIsNone
(
request
.
course_id
)
self
.
assertIsNone
(
request
.
course_key
)
# Course-related URLs should set a course_id on the request
# Course-related URLs should set a course_id
and course_key
on the request
request
=
self
.
factory
.
get
(
'/'
)
request
=
self
.
factory
.
get
(
'/'
)
course_id
=
'edX/DemoX/Demo_Course'
course_id
=
'edX/DemoX/Demo_Course'
course_key
=
CourseKey
.
from_string
(
course_id
)
self
.
middleware
.
process_view
(
request
,
''
,
None
,
{
'course_id'
:
course_id
})
self
.
middleware
.
process_view
(
request
,
''
,
None
,
{
'course_id'
:
course_id
})
self
.
assertEqual
(
request
.
course_id
,
course_id
)
self
.
assertEqual
(
request
.
course_id
,
course_id
)
self
.
assertEqual
(
request
.
course_key
,
course_key
)
class
CoursePermissionsExceptionMiddlewareTests
(
MiddlewareAssertionMixin
,
MiddlewareTestCase
):
class
CoursePermissionsExceptionMiddlewareTests
(
MiddlewareAssertionMixin
,
MiddlewareTestCase
):
...
...
analytics_dashboard/courses/views.py
View file @
80bd4dde
...
@@ -3,9 +3,8 @@ import datetime
...
@@ -3,9 +3,8 @@ import datetime
import
json
import
json
import
logging
import
logging
import
urllib
import
urllib
from
opaque_keys.edx.keys
import
CourseKey
import
requests
import
requests
from
django.conf
import
settings
from
django.conf
import
settings
from
django.core.exceptions
import
PermissionDenied
from
django.core.exceptions
import
PermissionDenied
from
django.core.urlresolvers
import
reverse
from
django.core.urlresolvers
import
reverse
...
@@ -15,10 +14,10 @@ from django.views.generic import TemplateView
...
@@ -15,10 +14,10 @@ from django.views.generic import TemplateView
from
django.views.generic.base
import
RedirectView
from
django.views.generic.base
import
RedirectView
from
django.utils.translation
import
ugettext_lazy
as
_
from
django.utils.translation
import
ugettext_lazy
as
_
from
braces.views
import
LoginRequiredMixin
from
braces.views
import
LoginRequiredMixin
from
analyticsclient.constants
import
data_format
,
demographic
from
analyticsclient.constants
import
data_format
,
demographic
from
analyticsclient.client
import
Client
from
analyticsclient.client
import
Client
from
analyticsclient.exceptions
import
NotFoundError
from
analyticsclient.exceptions
import
NotFoundError
from
courses
import
permissions
from
courses
import
permissions
from
courses.presenters
import
CourseEngagementPresenter
,
CourseEnrollmentPresenter
from
courses.presenters
import
CourseEngagementPresenter
,
CourseEnrollmentPresenter
from
courses.utils
import
is_feature_enabled
from
courses.utils
import
is_feature_enabled
...
@@ -82,6 +81,7 @@ class CourseContextMixin(TrackedViewMixin):
...
@@ -82,6 +81,7 @@ class CourseContextMixin(TrackedViewMixin):
"""
"""
context
=
{
context
=
{
'course_id'
:
self
.
course_id
,
'course_id'
:
self
.
course_id
,
'course_key'
:
self
.
course_key
,
'page_title'
:
self
.
page_title
,
'page_title'
:
self
.
page_title
,
'page_subtitle'
:
self
.
page_subtitle
'page_subtitle'
:
self
.
page_subtitle
}
}
...
@@ -240,11 +240,13 @@ class CourseView(LoginRequiredMixin, CourseValidMixin, CoursePermissionMixin, Te
...
@@ -240,11 +240,13 @@ class CourseView(LoginRequiredMixin, CourseValidMixin, CoursePermissionMixin, Te
client
=
None
client
=
None
course
=
None
course
=
None
course_id
=
None
course_id
=
None
course_key
=
None
user
=
None
user
=
None
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
def
dispatch
(
self
,
request
,
*
args
,
**
kwargs
):
self
.
user
=
request
.
user
self
.
user
=
request
.
user
self
.
course_id
=
kwargs
[
'course_id'
]
self
.
course_id
=
request
.
course_id
self
.
course_key
=
request
.
course_key
# some views will catch the NotFoundError to set data to a state that
# some views will catch the NotFoundError to set data to a state that
# the template can rendering a loading error message for the section
# the template can rendering a loading error message for the section
...
@@ -310,7 +312,7 @@ class CSVResponseMixin(object):
...
@@ -310,7 +312,7 @@ class CSVResponseMixin(object):
raise
NotImplementedError
raise
NotImplementedError
def
_get_filename
(
self
):
def
_get_filename
(
self
):
course_key
=
CourseKey
.
from_string
(
self
.
course_id
)
course_key
=
self
.
course_key
course_id
=
'-'
.
join
([
course_key
.
org
,
course_key
.
course
,
course_key
.
run
])
course_id
=
'-'
.
join
([
course_key
.
org
,
course_key
.
course
,
course_key
.
run
])
filename
=
'{0}--{1}.csv'
.
format
(
course_id
,
self
.
csv_filename_suffix
)
filename
=
'{0}--{1}.csv'
.
format
(
course_id
,
self
.
csv_filename_suffix
)
return
urllib
.
quote
(
filename
)
return
urllib
.
quote
(
filename
)
...
...
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