Commit cf33d85e by Victor Shnayder Committed by Carlos Andrés Rocha

Wire up cert status

parent 01dcf291
......@@ -29,6 +29,9 @@ from django_future.csrf import ensure_csrf_cookie, csrf_exempt
from student.models import (Registration, UserProfile,
PendingNameChange, PendingEmailChange,
CourseEnrollment)
from certificates.models import CertificateStatuses, certificate_status_for_student
from xmodule.course_module import CourseDescriptor
from xmodule.modulestore.exceptions import ItemNotFoundError
from xmodule.modulestore.django import modulestore
......@@ -143,11 +146,15 @@ def dashboard(request):
show_courseware_links_for = frozenset(course.id for course in courses
if has_access(request.user, course, 'load'))
cert_statuses = [certificate_status_for_student(request.user, course.id) for course in courses]
context = {'courses': courses,
'message': message,
'staff_access': staff_access,
'errored_courses': errored_courses,
'show_courseware_links_for' : show_courseware_links_for}
'show_courseware_links_for' : show_courseware_links_for,
'cert_statuses': cert_statuses,
}
return render_to_response('dashboard.html', context)
......@@ -206,13 +213,13 @@ def change_enrollment(request):
return {'success': False,
'error': 'enrollment in {} not allowed at this time'
.format(course.display_name)}
org, course_num, run=course_id.split("/")
org, course_num, run=course_id.split("/")
statsd.increment("common.student.enrollment",
tags=["org:{0}".format(org),
"course:{0}".format(course_num),
"run:{0}".format(run)])
enrollment, created = CourseEnrollment.objects.get_or_create(user=user, course_id=course.id)
return {'success': True}
......@@ -220,13 +227,13 @@ def change_enrollment(request):
try:
enrollment = CourseEnrollment.objects.get(user=user, course_id=course_id)
enrollment.delete()
org, course_num, run=course_id.split("/")
org, course_num, run=course_id.split("/")
statsd.increment("common.student.unenrollment",
tags=["org:{0}".format(org),
"course:{0}".format(course_num),
"run:{0}".format(run)])
return {'success': True}
except CourseEnrollment.DoesNotExist:
return {'success': False, 'error': 'You are not enrolled for this course.'}
......@@ -275,13 +282,13 @@ def login_user(request, error=""):
log.info("Login success - {0} ({1})".format(username, email))
try_change_enrollment(request)
statsd.increment("common.student.successful_login")
return HttpResponse(json.dumps({'success': True}))
log.warning("Login failed - Account not active for user {0}, resending activation".format(username))
reactivation_email_for_user(user)
not_activated_msg = "This account has not been activated. We have " + \
"sent another activation message. Please check your " + \
......@@ -483,9 +490,9 @@ def create_account(request, post_override=None):
log.debug('bypassing activation email')
login_user.is_active = True
login_user.save()
statsd.increment("common.student.account_created")
js = {'success': True}
return HttpResponse(json.dumps(js), mimetype="application/json")
......@@ -541,9 +548,9 @@ def password_reset(request):
''' Attempts to send a password reset e-mail. '''
if request.method != "POST":
raise Http404
# By default, Django doesn't allow Users with is_active = False to reset their passwords,
# but this bites people who signed up a long time ago, never activated, and forgot their
# but this bites people who signed up a long time ago, never activated, and forgot their
# password. So for their sake, we'll auto-activate a user for whome password_reset is called.
try:
user = User.objects.get(email=request.POST['email'])
......@@ -551,7 +558,7 @@ def password_reset(request):
user.save()
except:
log.exception("Tried to auto-activate user to enable password reset, but failed.")
form = PasswordResetForm(request.POST)
if form.is_valid():
form.save(use_https = request.is_secure(),
......@@ -589,7 +596,7 @@ def reactivation_email_for_user(user):
res = user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)
return HttpResponse(json.dumps({'success': True}))
@ensure_csrf_cookie
def change_email_request(request):
......@@ -764,8 +771,8 @@ def accept_name_change_by_id(id):
@ensure_csrf_cookie
def accept_name_change(request):
''' JSON: Name change process. Course staff clicks 'accept' on a given name change
''' JSON: Name change process. Course staff clicks 'accept' on a given name change
We used this during the prototype but now we simply record name changes instead
of manually approving them. Still keeping this around in case we want to go
back to this approval method.
......
......@@ -299,6 +299,16 @@ class CourseDescriptor(SequenceDescriptor):
return self.metadata.get('hide_progress_tab') == True
@property
def end_of_course_survey_url(self):
"""
Pull from policy. Once we have our own survey module set up, can change this to point to an automatically
created survey for each class.
Returns None if no url specified.
"""
return self.metadata.get('end_of_course_survey_url')
@property
def title(self):
return self.display_name
......
......@@ -2,7 +2,7 @@ from django.contrib.auth.models import User
from django.db import models
from datetime import datetime
'''
"""
Certificates are created for a student and an offering of a course.
When a certificate is generated, a unique ID is generated so that
......@@ -35,8 +35,7 @@ State diagram:
v v v
[downloadable] [downloadable] [deleted]
'''
"""
class CertificateStatuses(object):
unavailable = 'unavailable'
......@@ -88,6 +87,7 @@ def certificate_status_for_student(student, course_id):
If the status is "downloadable", the dictionary also contains
"download_url".
If the student has been graded, the dictionary also contains their grade for the course.
'''
try:
......@@ -97,6 +97,7 @@ def certificate_status_for_student(student, course_id):
return {
'status': CertificateStatuses.downloadable,
'download_url': generated_certificate.download_url,
'grade': generated_certificate.grade,
}
else:
return {'status': generated_certificate.status}
......
......@@ -2,6 +2,7 @@
from django.core.urlresolvers import reverse
from courseware.courses import course_image_url, get_course_about_section
from courseware.access import has_access
from certificates.models import CertificateStatuses
%>
<%inherit file="main.html" />
......@@ -114,7 +115,7 @@
</header>
% if len(courses) > 0:
% for course in courses:
% for course, cert_status in zip(courses, cert_statuses):
<article class="my-course">
<%
......@@ -145,35 +146,65 @@
</a>
</article>
<div class="message message-status course-status-processing is-shown">
<p class="message-copy">Final course details are being wrapped up at this time. Your final standing will be available shortly.</p>
</div>
<div class="message message-status course-status-certrendering is-shown">
<p class="message-copy">You have received a grade of <span class="grade-value">B</span> in this course.</p>
<ul class="actions">
<li class="action"><span class="btn disabled" href="">Your Certificate is Generating</span></li>
<li class="action"><a class="cta" href="">Complete our course feedback survey</a></li>
</ul>
</div>
<div class="message message-status course-status-certavailable is-shown">
<p class="message-copy">You have received a grade of <span class="grade-value">B</span> in this course.</p>
<ul class="actions">
<li class="action"><a class="btn" href="" title="This link will open/download a PDF document">Download Your PDF Certificate</a></li>
<li class="action"><a class="cta" href="">Complete our course feedback survey</a></li>
</ul>
</div>
<div class="message message-status course-status-certnotavailable is-shown">
<p class="message-copy">You did not complete the necessary requirements for completion of this course.</p>
<ul class="actions">
<li class="action"><a class="cta" href="">Complete our course feedback survey</a></li>
</ul>
</div>
% if course.has_ended:
<%
passing_grade = False
cert_button = False
survey_button = False
if cert_status['status'] in [CertificateStatuses.generating, CertificateStatuses.regenerating]:
status_css_class = 'course-status-certrendering'
cert_button = True
survey_button = True
passing_grade = True
elif cert_status['status'] == CertificateStatuses.downloadable:
status_css_class = 'course-status-certavailable'
cert_button = True
survey_button = True
passing_grade = True
elif cert_status['status'] == CertificateStatuses.notpassing:
status_css_class = 'course-status-certnotavailable'
survey_button = True
else cert_status['status']:
# This is primarily the 'unavailable' state, but also 'error', 'deleted', etc.
status_css_class = 'course-status-processing'
if survey_button and not course.end_of_course_survey_url:
survey_button = False
%>
<div class="message message-status ${status_css_class} is-shown">
% if cert_status == CertificateStatuses.unavailable:
<p class="message-copy">Final course details are being wrapped up at this time.
Your final standing will be available shortly.</p>
% elif passing_grade:
<p class="message-copy">You have received a grade of
<span class="grade-value">${cert_status['grade']}</span>
in this course.</p>
% elif cert_status == CertificateStatuses.notpassing:
<p class="message-copy">You did not complete the necessary requirements for
completion of this course. Your grade was <span class="grade-value">${cert_status['grade']}</span>
</p>
% endif
% if cert_button or survey_button:
<ul class="actions">
% if cert_button and cert_status['status'] == CertificateStatuses.generating:
<li class="action"><span class="btn disabled" href="">Your Certificate is Generating</span></li>
% elif cert_button and cert_status['status'] == CertificateStatuses.downloadable:
<li class="action">
<a class="btn" href="${cert_status['download_url']}"
title="This link will open/download a PDF document">
Download Your PDF Certificate</a></li>
% endif
% if survey_button:
<li class="action"><a class="cta" href="${course.end_of_course_survey_url}">
Complete our course feedback survey</a></li>
% endif
</ul>
% endif
</div>
% endif
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id}" data-course-number="${course.number}">Unregister</a>
......
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