Commit a9cdf830 by Daniel Friedman

Add learner analytics UI scaffolding

AN-6199
parent f0459481
......@@ -301,6 +301,16 @@ class CoursePerformanceAnswerDistributionPage(CoursePage):
self.browser.title.startswith('Performance: Problem Submissions')
class CourseLearnersPage(CoursePage):
def __init__(self, browser, course_id=None):
super(CourseLearnersPage, self).__init__(browser, course_id)
self.page_url += '/learners/'
def is_browser_on_page(self):
return super(CourseLearnersPage, self).is_browser_on_page() \
and self.browser.title.startswith('Learners')
class ErrorPage(DashboardPage):
error_code = None
error_title = None
......
from bok_choy.web_app_test import WebAppTest
from acceptance_tests.mixins import CoursePageTestsMixin
from acceptance_tests.pages import CourseLearnersPage
class CourseLearnersTests(CoursePageTestsMixin, WebAppTest):
def setUp(self):
super(CourseLearnersTests, self).setUp()
self.page = CourseLearnersPage(self.browser)
def _test_data_update_message(self):
# Don't test the update message for now, since it won't exist
# until the SPA adds it to the page in AN-6205.
pass
def _get_data_update_message(self):
# Don't test the update message for now, since it won't exist
# until the SPA adds it to the page in AN-6205.
return ''
{% extends "courses/base-course.html" %}
{% load rjs %}
{% comment %}
View of individual learners within a course.
{% endcomment %}
{% block javascript %}
{{ block.super }}
<script src="{% static_rjs 'js/learners-main.js' %}"></script>
{% endblock javascript %}
{% block child_content %}
<div class="learners-app-container">
<p>TODO: put the app here!</p>
</div>
{% endblock %}
......@@ -4,7 +4,7 @@ from django.conf import settings
from django.conf.urls import url, patterns, include
from courses import views
from courses.views import enrollment, engagement, performance, csv
from courses.views import enrollment, engagement, performance, csv, learners
CONTENT_ID_PATTERN = r'(?P<content_id>(?:i4x://?[^/]+/[^/]+/[^/]+/[^@]+(?:@[^/]+)?)|(?:[^/]+))'
PROBLEM_PART_ID_PATTERN = CONTENT_ID_PATTERN.replace('content_id', 'problem_part_id')
......@@ -101,6 +101,11 @@ CSV_URLS = patterns(
name='performance_answer_distribution'),
)
LEARNER_URLS = patterns(
'',
url(r'^$', learners.LearnersView.as_view(), name='learners'),
)
COURSE_URLS = patterns(
'',
# Course homepage. This should be the entry point for other applications linking to the course.
......@@ -109,6 +114,7 @@ COURSE_URLS = patterns(
url(r'^engagement/', include(ENGAGEMENT_URLS, namespace='engagement')),
url(r'^performance/', include(PERFORMANCE_URLS, namespace='performance')),
url(r'^csv/', include(CSV_URLS, namespace='csv')),
url(r'^learners/', include(LEARNER_URLS, namespace='learners')),
)
urlpatterns = patterns(
......
......@@ -298,6 +298,12 @@ class CourseNavBarMixin(object):
'view': 'courses:performance:graded_content',
'icon': 'fa-check-square-o',
'switch': 'enable_course_api',
},
{
'name': 'learners',
'label': _('Learners'),
'view': 'courses:learners:learners',
'icon': 'fa-users',
}
]
......@@ -516,6 +522,32 @@ class CourseHome(CourseTemplateWithNavView):
]
})
items.append({
'name': _('Learners'),
'icon': 'fa-users',
'heading': _('What are individual learners doing?'),
'items': [
{
'title': _('Who has been active recently?'),
'view': 'courses:learners:learners', # TODO: map this to the actual action in AN-6205
# TODO: what would the breadcrumbs be?
'breadcrumbs': [_('TODO: what is this?')]
},
{
'title': _('Who is most engaged in the discussions?'),
'view': 'courses:learners:learners', # TODO: map this to the actual action in AN-6205
# TODO: what would the breadcrumbs be?
'breadcrumbs': [_('TODO: what is this?')]
},
{
'title': _("Who hasn't watched videos recently?"),
'view': 'courses:learners:learners', # TODO: map this to the actual action in AN-6205
# TODO: what would the breadcrumbs be?
'breadcrumbs': [_('TODO: what is this?')]
}
]
})
return items
# pylint: disable=redefined-variable-type
......
from django.utils.translation import ugettext_lazy as _
from courses.views import CourseTemplateWithNavView
class LearnersView(CourseTemplateWithNavView):
template_name = 'courses/learners.html'
active_primary_nav_item = 'learners'
page_title = _('Learners')
def get_context_data(self, **kwargs):
context = super(LearnersView, self).get_context_data(**kwargs)
context['page_data'] = self.get_page_data(context)
return context
......@@ -30,7 +30,8 @@ require.config({
'cldr-data': 'bower_components/cldr-data',
globalize: 'bower_components/globalize/dist/globalize',
globalization: 'js/utils/globalization',
collapsible: 'bower_components/edx-ui-toolkit/components/views/collapsible-view'
collapsible: 'bower_components/edx-ui-toolkit/components/views/collapsible-view',
marionette: 'bower_components/marionette/lib/backbone.marionette.min'
},
wrapShim: true,
shim: {
......
require([], function () {
'use strict';
});
......@@ -28,6 +28,7 @@
"font-awesome": "~4.2.0",
"natural-sort": "overset/javascript-natural-sort#dbf4ca259b327a488bd1d7897fd46d80c414a7e0",
"cldr-data": "26.0.3",
"edx-ui-toolkit": "edx/edx-ui-toolkit#1e025d169f28632cf903274f3ef8aaf6e2fd6825"
"edx-ui-toolkit": "edx/edx-ui-toolkit#1e025d169f28632cf903274f3ef8aaf6e2fd6825",
"marionette": "~2.4.4"
}
}
......@@ -67,6 +67,10 @@
{
name: 'js/performance-answer-distribution-main',
exclude: ['js/common']
},
{
name: 'js/learners-main',
exclude: ['js/common']
}
]
})
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