Commit a9c4774f by Kyle McCormick

PLA-749 Fix student dashboard for users enrolled in CCX courses

parent 72ab1fbc
......@@ -557,9 +557,9 @@ class TestGetMembershipTriplets(ModuleStoreTestCase):
self.make_ccx_membership()
triplets = self.call_fut()
self.assertEqual(len(triplets), 1)
ccx, membership, course = triplets[0]
ccx, membership, course_overview = triplets[0]
self.assertEqual(ccx.id, self.ccx.id)
self.assertEqual(unicode(course.id), unicode(self.course.id))
self.assertEqual(unicode(course_overview.id), unicode(self.course.id))
self.assertEqual(membership.student, self.user)
def test_has_membership_org_filtered(self):
......
......@@ -16,9 +16,11 @@ from courseware.tests.factories import StudentModuleFactory # pylint: disable=i
from courseware.tests.helpers import LoginEnrollmentTestCase # pylint: disable=import-error
from courseware.tabs import get_course_tab_list
from django.core.urlresolvers import reverse
from django.utils.timezone import UTC
from django.test.utils import override_settings
from django.test import RequestFactory
from edxmako.shortcuts import render_to_response # pylint: disable=import-error
from student.models import CourseEnrollment
from student.roles import CourseCcxCoachRole # pylint: disable=import-error
from student.tests.factories import ( # pylint: disable=import-error
AdminFactory,
......@@ -27,6 +29,7 @@ from student.tests.factories import ( # pylint: disable=import-error
)
from xmodule.x_module import XModuleMixin
from xmodule.modulestore import ModuleStoreEnum
from xmodule.modulestore.tests.django_utils import (
ModuleStoreTestCase,
TEST_DATA_SPLIT_MODULESTORE)
......@@ -655,6 +658,43 @@ class CCXCoachTabTestCase(ModuleStoreTestCase):
)
class TestStudentDashboardWithCCX(ModuleStoreTestCase):
"""
Test to ensure that the student dashboard works for users enrolled in CCX
courses.
"""
def setUp(self):
"""
Set up courses and enrollments.
"""
super(TestStudentDashboardWithCCX, self).setUp()
# Create a Draft Mongo and a Split Mongo course and enroll a student user in them.
self.student_password = "foobar"
self.student = UserFactory.create(username="test", password=self.student_password, is_staff=False)
self.draft_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.mongo)
self.split_course = CourseFactory.create(default_store=ModuleStoreEnum.Type.split)
CourseEnrollment.enroll(self.student, self.draft_course.id)
CourseEnrollment.enroll(self.student, self.split_course.id)
# Create a CCX coach.
self.coach = AdminFactory.create()
role = CourseCcxCoachRole(self.split_course.id)
role.add_users(self.coach)
# Create a CCX course and enroll the user in it.
self.ccx = CcxFactory(course_id=self.split_course.id, coach=self.coach)
last_week = datetime.datetime.now(UTC()) - datetime.timedelta(days=7)
override_field_for_ccx(self.ccx, self.split_course, 'start', last_week) # Required by self.ccx.has_started().
CcxMembershipFactory(ccx=self.ccx, student=self.student, active=True)
def test_load_student_dashboard(self):
self.client.login(username=self.student.username, password=self.student_password)
response = self.client.get(reverse('dashboard'))
self.assertEqual(response.status_code, 200)
def flatten(seq):
"""
For [[1, 2], [3, 4]] returns [1, 2, 3, 4]. Does not recurse.
......
......@@ -10,6 +10,7 @@ from django.core.urlresolvers import reverse
from django.core.mail import send_mail
from edxmako.shortcuts import render_to_string # pylint: disable=import-error
from microsite_configuration import microsite # pylint: disable=import-error
from openedx.core.djangoapps.content.course_overviews.models import CourseOverview
from xmodule.modulestore.django import modulestore
from xmodule.error_module import ErrorDescriptor
from ccx_keys.locator import CCXLocator
......@@ -240,29 +241,41 @@ def send_mail_to_student(student, param_dict):
def get_ccx_membership_triplets(user, course_org_filter, org_filter_out_set):
"""
Get the relevant set of (CustomCourseForEdX, CcxMembership, Course)
Get the relevant set of (CustomCourseForEdX, CcxMembership, CourseOverview)
triplets to be displayed on a student's dashboard.
"""
error_message_format = "User {0} enrolled in {2} course {1}"
# only active memberships for now
for membership in CcxMembership.memberships_for_user(user):
ccx = membership.ccx
store = modulestore()
with store.bulk_operations(ccx.course_id):
course = store.get_course(ccx.course_id)
if course and not isinstance(course, ErrorDescriptor):
try:
course_overview = CourseOverview.get_from_id(ccx.course_id)
except CourseOverview.DoesNotExist:
log.error(error_message_format.format( # pylint: disable=logging-format-interpolation
user.username, ccx.course_id, "non-existent"
))
continue
except IOError:
log.error(error_message_format.format( # pylint: disable=logging-format-interpolation
user.username, ccx.course_id, "broken"
))
continue
# if we are in a Microsite, then filter out anything that is not
# attributed (by ORG) to that Microsite
if course_org_filter and course_org_filter != course.location.org:
if course_org_filter and course_org_filter != course_overview.location.org:
continue
# Conversely, if we are not in a Microsite, then let's filter out any enrollments
# with courses attributed (by ORG) to Microsites
elif course.location.org in org_filter_out_set:
elif course_overview.location.org in org_filter_out_set:
continue
# If, somehow, we've got a ccx that has been created for a
# course with a deprecated ID, we must filter it out. Emit a
# warning to the log so we can clean up.
if course.location.deprecated:
if course_overview.location.deprecated:
log.warning(
"CCX %s exists for course %s with deprecated id",
ccx,
......@@ -270,8 +283,4 @@ def get_ccx_membership_triplets(user, course_org_filter, org_filter_out_set):
)
continue
yield (ccx, membership, course)
else:
log.error("User {0} enrolled in {2} course {1}".format( # pylint: disable=logging-format-interpolation
user.username, ccx.course_id, "broken" if course else "non-existent"
))
yield (ccx, membership, course_overview)
......@@ -42,7 +42,7 @@ from ccx_keys.locator import CCXLocator
% endif
</h3>
<div class="course-info">
<span class="info-university">${get_course_about_section(course, 'university')} - </span>
<span class="info-university">${get_course_about_section(course_overview, 'university')} - </span>
<span class="info-course-id">${course_overview.display_number_with_default | h}</span>
<span class="info-date-block" data-tooltip="Hi">
% if ccx.has_ended():
......
......@@ -88,10 +88,10 @@ from django.core.urlresolvers import reverse
% endfor
% if settings.FEATURES.get('CUSTOM_COURSES_EDX', False):
% for ccx, membership, course in ccx_membership_triplets:
% for ccx, membership, course_overview in ccx_membership_triplets:
<% show_courseware_link = ccx.has_started() %>
<% is_course_blocked = False %>
<%include file='ccx/_dashboard_ccx_listing.html' args="ccx=ccx, membership=membership, course_overview=enrollment.course_overview, show_courseware_link=show_courseware_link, is_course_blocked=is_course_blocked" />
<%include file='ccx/_dashboard_ccx_listing.html' args="ccx=ccx, membership=membership, course_overview=course_overview, show_courseware_link=show_courseware_link, is_course_blocked=is_course_blocked" />
% endfor
% endif
......
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