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.
This commit is contained in:
@@ -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>
|
||||
|
||||
29
lms/templates/pocs/_dashboard_poc_listing.html
Normal file
29
lms/templates/pocs/_dashboard_poc_listing.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<%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>
|
||||
@@ -1,5 +1,18 @@
|
||||
<%! 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">
|
||||
|
||||
Reference in New Issue
Block a user