Commit 0b184881 by cewing

MIT: CCX. Implement display of CCXs in user-facing templates such as dashboard

Show the display name for the POC in the menu for switching.

Remove the MOOC: prefix from the MOOC title to avoid truncation issues.

Incorporate the display name of the POC into the display of course org/number/name at the top of the page in the default theme.

Provide warning on the grading policy page in system warning style.

Provide a PocMembership model api that returns PocMemberships for a user.  Default to active memberships.

Build generator that yields triplets of poc, membership and course for each poc membership a user has.

This is an analog of the `get_course_enrollment_pairs` in common/djangoapps/students/views.py and is used in the student dashboard to provide pocs as options for a student to view.

refactor to use model api instead of inline code.

provide pocs as possible targets for a student to visit from their dashboard.

Unset the current active poc when visiting the dashboard so as to avoid needing to switch active pocs when viewing a plain course.  This ensures we can leave template code for the display of courses unchanged.

Update templates to show pocs in a course-like view on a student's dashboard.

Revert a portion of the template change so that the poc title will still render properly when a poc is being viewed.
parent bb7eed58
......@@ -660,6 +660,17 @@ def dashboard(request):
if course.pre_requisite_courses)
courses_requirements_not_met = get_pre_requisite_courses_not_completed(user, courses_having_prerequisites)
poc_membership_triplets = []
if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False):
from pocs import ACTIVE_POC_KEY
from pocs.utils import get_poc_membership_triplets
poc_membership_triplets = get_poc_membership_triplets(
user, course_org_filter, org_filter_out_set
)
# should we deselect any active POC at this time so that we don't have
# to change the URL for viewing a course? I think so.
request.session[ACTIVE_POC_KEY] = None
context = {
'enrollment_message': enrollment_message,
'course_enrollment_pairs': course_enrollment_pairs,
......@@ -691,6 +702,7 @@ def dashboard(request):
'provider_states': [],
'order_history_list': order_history_list,
'courses_requirements_not_met': courses_requirements_not_met,
'poc_membership_triplets': poc_membership_triplets,
}
if third_party_auth.is_enabled():
......
......@@ -43,6 +43,10 @@ class PocMembership(models.Model):
membership.save()
future_membership.delete()
@classmethod
def memberships_for_user(cls, user, active=True):
return cls.objects.filter(student=user, active__exact=active)
class PocFutureMembership(models.Model):
"""
......
......@@ -4,19 +4,18 @@ POC Enrollment operations for use by Coach APIs.
Does not include any access control, be sure to check access before calling.
"""
from courseware.courses import get_course_about_section
from courseware.courses import get_course_by_id
from django.contrib.auth.models import User
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.mail import send_mail
from courseware.courses import get_course_about_section
from courseware.courses import get_course_by_id
from edxmako.shortcuts import render_to_string
from microsite_configuration import microsite
from xmodule.modulestore.django import modulestore
from xmodule.error_module import ErrorDescriptor
from .models import (
PersonalOnlineCourse,
PocMembership,
PocFutureMembership,
)
......@@ -241,15 +240,12 @@ def get_all_pocs_for_user(user):
current_active_poc = get_current_poc(user)
if user.is_anonymous():
return []
active_poc_memberships = PocMembership.objects.filter(
student=user, active__exact=True
)
memberships = []
for membership in active_poc_memberships:
for membership in PocMembership.memberships_for_user(user):
course = get_course_by_id(membership.poc.course_id)
course_title = get_course_about_section(course, 'title')
poc_title = 'POC: {}'.format(course_title)
mooc_title = 'MOOC: {}'.format(course_title)
poc = membership.poc
poc_title = poc.display_name
mooc_title = get_course_about_section(course, 'title')
url = reverse(
'switch_active_poc',
args=[course.id.to_deprecated_string(), membership.poc.id]
......@@ -266,3 +262,30 @@ def get_all_pocs_for_user(user):
'mooc_url': mooc_url,
})
return memberships
def get_poc_membership_triplets(user, course_org_filter, org_filter_out_set):
"""
Get the relevant set of (PersonalOnlineCourse, PocMembership, Course)
triplets to be displayed on a student's dashboard.
"""
# only active memberships for now
for membership in PocMembership.memberships_for_user(user):
poc = membership.poc
store = modulestore()
with store.bulk_operations(poc.course_id):
course = store.get_course(poc.course_id)
if course and not isinstance(course, ErrorDescriptor):
# 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:
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:
continue
yield (poc, membership, course)
else:
log.error("User {0} enrolled in {2} course {1}".format(
user.username, poc.course_id, "broken" if course else "non-existent"
))
......@@ -222,6 +222,63 @@
</ul>
</section>
</section>
<section id="my-courses" class="my-courses" role="main" aria-label="Content">
<header>
<h2>${_("Current Courses")}</h2>
</header>
% if len(course_enrollment_pairs) > 0:
<ul class="listing-courses">
% for course, enrollment in course_enrollment_pairs:
<% show_courseware_link = (course.id in show_courseware_links_for) %>
<% cert_status = cert_statuses.get(course.id) %>
<% show_email_settings = (course.id in show_email_settings_for) %>
<% course_mode_info = all_course_modes.get(course.id) %>
<% show_refund_option = (course.id in show_refund_option_for) %>
<% is_paid_course = (course.id in enrolled_courses_either_paid) %>
<% is_course_blocked = (course.id in block_courses) %>
<% course_verification_status = verification_status_by_course.get(course.id, {}) %>
<% course_requirements = courses_requirements_not_met.get(course.id) %>
<%include file='dashboard/_dashboard_course_listing.html' args="course=course, enrollment=enrollment, show_courseware_link=show_courseware_link, cert_status=cert_status, show_email_settings=show_email_settings, course_mode_info=course_mode_info, show_refund_option = show_refund_option, is_paid_course = is_paid_course, is_course_blocked = is_course_blocked, verification_status=course_verification_status, course_requirements=course_requirements" />
% endfor
% if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False):
% for poc, membership, course in poc_membership_triplets:
<%include file='pocs/_dashboard_poc_listing.html' args="poc=poc, membership=membership, course=course" />
% endfor
% endif
</ul>
% else:
<section class="empty-dashboard-message">
% if settings.FEATURES.get('COURSES_ARE_BROWSABLE'):
<p>${_("Looks like you haven't enrolled in any courses yet.")}</p>
<a href="${marketing_link('COURSES')}">
${_("Find courses now!")}
</a>
% else:
<p>${_("Looks like you haven't enrolled in any courses yet.")}</p>
%endif
</section>
% endif
% if staff_access and len(errored_courses) > 0:
<div id="course-errors">
<h2>${_("Course-loading errors")}</h2>
% for course_dir, errors in errored_courses.items():
<h3>${course_dir | h}</h3>
<ul>
% for (msg, err) in errors:
<li>${msg}
<ul><li><pre>${err}</pre></li></ul>
</li>
% endfor
</ul>
% endfor
% endif
</section>
</section>
<section id="email-settings-modal" class="modal" aria-hidden="true">
......
......@@ -13,7 +13,7 @@ from status.status import get_site_status_msg
<%! from microsite_configuration import microsite %>
<%! from microsite_configuration.templatetags.microsite import platform_name %>
<%! from pocs.utils import get_all_pocs_for_user %>
<%! from pocs.overrides import get_current_poc %>
## Provide a hook for themes to inject branding on top.
<%block name="navigation_top" />
......@@ -48,7 +48,16 @@ site_status_msg = get_site_status_msg(course_id)
</h1>
% if course:
<h2><span class="provider">${course.display_org_with_default | h}:</span> ${course.display_number_with_default | h} ${course.display_name_with_default}</h2>
<h2><span class="provider">${course.display_org_with_default | h}:</span>
${course.display_number_with_default | h}
<%
display_name = course.display_name_with_default
if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False):
poc = get_current_poc(user)
if poc:
display_name = poc.display_name
%>
${display_name}</h2>
% endif
% if user.is_authenticated():
......@@ -83,15 +92,6 @@ site_status_msg = get_site_status_msg(course_id)
% if settings.MKTG_URL_LINK_MAP.get('FAQ'):
<li><a href="${marketing_link('FAQ')}">${_("Help")}</a></li>
% endif
% if settings.FEATURES.get('PERSONAL_ONLINE_COURSES', False):
%for poc in get_all_pocs_for_user(user):
% if poc['active']:
<li><a href="${poc['mooc_url']}" role="menuitem">${poc['mooc_name']}</a></li>
% else:
<li><a href="${poc['poc_url']}" role="menuitem">${poc['poc_name']}</a></li>
% endif
%endfor
% endif
</%block>
<li><a href="${reverse('logout')}" role="menuitem">${_("Sign out")}</a></li>
</ul>
......
<%page args="poc, membership, course" />
<%! from django.utils.translation import ugettext as _ %>
<%!
from django.core.urlresolvers import reverse
from courseware.courses import course_image_url, get_course_about_section
%>
<%
poc_switch_target = reverse('switch_active_poc', args=[course.id.to_deprecated_string(), poc.id])
%>
<li class="course-item">
<article class="course">
<a href="${poc_switch_target}" class="cover">
<img src="${course_image_url(course)}" alt="${_('{course_number} {poc_name} Cover Image').format(course_number=course.number, poc_name=poc.display_name) |h}" />
</a>
<section class="info">
<hgroup>
<p class="date-block">
Personal Online Course
</p>
<h2 class="university">${get_course_about_section(course, 'university')}</h2>
<h3>
<a href="${poc_switch_target}">${course.display_number_with_default | h} ${poc.display_name}</a>
</h3>
</hgroup>
<a href="${poc_switch_target}" class="enter-course">${_('View Course')}</a>
</section>
</article>
</li>
<%! from django.utils.translation import ugettext as _ %>
<div id="warn-coach" class="wrapper-msg urgency-high warning">
<div class="msg">
<i class="msg-icon icon-warning-sign"></i>
<div class="msg-content">
<h3 class="title">${_("WARNING")}</h3>
<div class="copy">
<p>${_("For advanced users only. Errors in the grading policy can lead to the course failing to display. This form does not check the validity of the policy before saving.")}</p>
<p>${_("Most coaches should not need to make changes to the grading policy.")}</p>
</div>
</div>
</div>
</div>
<h2>${_("Grading Policy")}</h2>
<form action="${grading_policy_url}" method="POST">
......
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