Commit 92c94b53 by Diana Huang

Merge pull request #1483 from edx/diana/certs-upgrade-path

Verified Certificate Upsell
parents de7bba51 a9da48ac
...@@ -9,7 +9,7 @@ from collections import namedtuple ...@@ -9,7 +9,7 @@ from collections import namedtuple
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.db.models import Q from django.db.models import Q
Mode = namedtuple('Mode', ['slug', 'name', 'min_price', 'suggested_prices', 'currency']) Mode = namedtuple('Mode', ['slug', 'name', 'min_price', 'suggested_prices', 'currency', 'expiration_date'])
class CourseMode(models.Model): class CourseMode(models.Model):
...@@ -39,7 +39,7 @@ class CourseMode(models.Model): ...@@ -39,7 +39,7 @@ class CourseMode(models.Model):
# turn this mode off after the given expiration date # turn this mode off after the given expiration date
expiration_date = models.DateField(default=None, null=True, blank=True) expiration_date = models.DateField(default=None, null=True, blank=True)
DEFAULT_MODE = Mode('honor', _('Honor Code Certificate'), 0, '', 'usd') DEFAULT_MODE = Mode('honor', _('Honor Code Certificate'), 0, '', 'usd', None)
DEFAULT_MODE_SLUG = 'honor' DEFAULT_MODE_SLUG = 'honor'
class Meta: class Meta:
...@@ -57,8 +57,14 @@ class CourseMode(models.Model): ...@@ -57,8 +57,14 @@ class CourseMode(models.Model):
found_course_modes = cls.objects.filter(Q(course_id=course_id) & found_course_modes = cls.objects.filter(Q(course_id=course_id) &
(Q(expiration_date__isnull=True) | (Q(expiration_date__isnull=True) |
Q(expiration_date__gte=now))) Q(expiration_date__gte=now)))
modes = ([Mode(mode.mode_slug, mode.mode_display_name, mode.min_price, mode.suggested_prices, mode.currency) modes = ([Mode(
for mode in found_course_modes]) mode.mode_slug,
mode.mode_display_name,
mode.min_price,
mode.suggested_prices,
mode.currency,
mode.expiration_date
) for mode in found_course_modes])
if not modes: if not modes:
modes = [cls.DEFAULT_MODE] modes = [cls.DEFAULT_MODE]
return modes return modes
......
...@@ -49,7 +49,7 @@ class CourseModeModelTest(TestCase): ...@@ -49,7 +49,7 @@ class CourseModeModelTest(TestCase):
self.create_mode('verified', 'Verified Certificate') self.create_mode('verified', 'Verified Certificate')
modes = CourseMode.modes_for_course(self.course_id) modes = CourseMode.modes_for_course(self.course_id)
mode = Mode(u'verified', u'Verified Certificate', 0, '', 'usd') mode = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None)
self.assertEqual([mode], modes) self.assertEqual([mode], modes)
modes_dict = CourseMode.modes_for_course_dict(self.course_id) modes_dict = CourseMode.modes_for_course_dict(self.course_id)
...@@ -61,8 +61,8 @@ class CourseModeModelTest(TestCase): ...@@ -61,8 +61,8 @@ class CourseModeModelTest(TestCase):
""" """
Finding the modes when there's multiple modes Finding the modes when there's multiple modes
""" """
mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd') mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None)
mode2 = Mode(u'verified', u'Verified Certificate', 0, '', 'usd') mode2 = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', None)
set_modes = [mode1, mode2] set_modes = [mode1, mode2]
for mode in set_modes: for mode in set_modes:
self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices) self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices)
...@@ -81,9 +81,9 @@ class CourseModeModelTest(TestCase): ...@@ -81,9 +81,9 @@ class CourseModeModelTest(TestCase):
self.assertEqual(0, CourseMode.min_course_price_for_currency(self.course_id, 'usd')) self.assertEqual(0, CourseMode.min_course_price_for_currency(self.course_id, 'usd'))
# create some modes # create some modes
mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd') mode1 = Mode(u'honor', u'Honor Code Certificate', 10, '', 'usd', None)
mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd') mode2 = Mode(u'verified', u'Verified Certificate', 20, '', 'usd', None)
mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny') mode3 = Mode(u'honor', u'Honor Code Certificate', 80, '', 'cny', None)
set_modes = [mode1, mode2, mode3] set_modes = [mode1, mode2, mode3]
for mode in set_modes: for mode in set_modes:
self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices, mode.currency) self.create_mode(mode.slug, mode.name, mode.min_price, mode.suggested_prices, mode.currency)
...@@ -98,14 +98,15 @@ class CourseModeModelTest(TestCase): ...@@ -98,14 +98,15 @@ class CourseModeModelTest(TestCase):
modes = CourseMode.modes_for_course(self.course_id) modes = CourseMode.modes_for_course(self.course_id)
self.assertEqual([CourseMode.DEFAULT_MODE], modes) self.assertEqual([CourseMode.DEFAULT_MODE], modes)
mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd') mode1 = Mode(u'honor', u'Honor Code Certificate', 0, '', 'usd', None)
self.create_mode(mode1.slug, mode1.name, mode1.min_price, mode1.suggested_prices) self.create_mode(mode1.slug, mode1.name, mode1.min_price, mode1.suggested_prices)
modes = CourseMode.modes_for_course(self.course_id) modes = CourseMode.modes_for_course(self.course_id)
self.assertEqual([mode1], modes) self.assertEqual([mode1], modes)
expired_mode.expiration_date = datetime.now(pytz.UTC) + timedelta(days=1) expiration_date = datetime.now(pytz.UTC) + timedelta(days=1)
expired_mode.expiration_date = expiration_date
expired_mode.save() expired_mode.save()
expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd') expired_mode_value = Mode(u'verified', u'Verified Certificate', 0, '', 'usd', expiration_date.date())
modes = CourseMode.modes_for_course(self.course_id) modes = CourseMode.modes_for_course(self.course_id)
self.assertEqual([expired_mode_value, mode1], modes) self.assertEqual([expired_mode_value, mode1], modes)
......
...@@ -34,10 +34,19 @@ class ChooseModeView(View): ...@@ -34,10 +34,19 @@ class ChooseModeView(View):
@method_decorator(login_required) @method_decorator(login_required)
def get(self, request, course_id, error=None): def get(self, request, course_id, error=None):
""" Displays the course mode choice page """ """ Displays the course mode choice page """
if CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified':
enrollment_mode = CourseEnrollment.enrollment_mode_for_user(request.user, course_id)
upgrade = request.GET.get('upgrade', False)
# verified users do not need to register or upgrade
if enrollment_mode == 'verified':
return redirect(reverse('dashboard')) return redirect(reverse('dashboard'))
modes = CourseMode.modes_for_course_dict(course_id)
# registered users who are not trying to upgrade do not need to re-register
if enrollment_mode is not None and upgrade is False:
return redirect(reverse('dashboard'))
modes = CourseMode.modes_for_course_dict(course_id)
donation_for_course = request.session.get("donation_for_course", {}) donation_for_course = request.session.get("donation_for_course", {})
chosen_price = donation_for_course.get(course_id, None) chosen_price = donation_for_course.get(course_id, None)
...@@ -50,6 +59,7 @@ class ChooseModeView(View): ...@@ -50,6 +59,7 @@ class ChooseModeView(View):
"course_num": course.display_number_with_default, "course_num": course.display_number_with_default,
"chosen_price": chosen_price, "chosen_price": chosen_price,
"error": error, "error": error,
"upgrade": upgrade,
} }
if "verified" in modes: if "verified" in modes:
context["suggested_prices"] = [decimal.Decimal(x) for x in modes["verified"].suggested_prices.split(",")] context["suggested_prices"] = [decimal.Decimal(x) for x in modes["verified"].suggested_prices.split(",")]
...@@ -70,6 +80,8 @@ class ChooseModeView(View): ...@@ -70,6 +80,8 @@ class ChooseModeView(View):
error_msg = _("Enrollment is closed") error_msg = _("Enrollment is closed")
return self.get(request, course_id, error=error_msg) return self.get(request, course_id, error=error_msg)
upgrade = request.GET.get('upgrade', False)
requested_mode = self.get_requested_mode(request.POST.get("mode")) requested_mode = self.get_requested_mode(request.POST.get("mode"))
if requested_mode == "verified" and request.POST.get("honor-code"): if requested_mode == "verified" and request.POST.get("honor-code"):
requested_mode = "honor" requested_mode = "honor"
...@@ -106,13 +118,12 @@ class ChooseModeView(View): ...@@ -106,13 +118,12 @@ class ChooseModeView(View):
if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user): if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user):
return redirect( return redirect(
reverse('verify_student_verified', reverse('verify_student_verified',
kwargs={'course_id': course_id}) kwargs={'course_id': course_id}) + "?upgrade={}".format(upgrade)
) )
return redirect( return redirect(
reverse('verify_student_show_requirements', reverse('verify_student_show_requirements',
kwargs={'course_id': course_id}), kwargs={'course_id': course_id}) + "?upgrade={}".format(upgrade))
)
def get_requested_mode(self, user_choice): def get_requested_mode(self, user_choice):
""" """
...@@ -121,6 +132,7 @@ class ChooseModeView(View): ...@@ -121,6 +132,7 @@ class ChooseModeView(View):
""" """
choices = { choices = {
"Select Audit": "audit", "Select Audit": "audit",
"Select Certificate": "verified" "Select Certificate": "verified",
"Upgrade Your Registration": "verified"
} }
return choices.get(user_choice) return choices.get(user_choice)
...@@ -2,6 +2,7 @@ from student.models import (User, UserProfile, Registration, ...@@ -2,6 +2,7 @@ from student.models import (User, UserProfile, Registration,
CourseEnrollmentAllowed, CourseEnrollment, CourseEnrollmentAllowed, CourseEnrollment,
PendingEmailChange, UserStanding, PendingEmailChange, UserStanding,
) )
from course_modes.models import CourseMode
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from datetime import datetime from datetime import datetime
from factory import DjangoModelFactory, SubFactory, PostGenerationMethodCall, post_generation, Sequence from factory import DjangoModelFactory, SubFactory, PostGenerationMethodCall, post_generation, Sequence
...@@ -36,6 +37,16 @@ class UserProfileFactory(DjangoModelFactory): ...@@ -36,6 +37,16 @@ class UserProfileFactory(DjangoModelFactory):
goals = u'World domination' goals = u'World domination'
class CourseModeFactory(DjangoModelFactory):
FACTORY_FOR = CourseMode
course_id = None
mode_display_name = u'Honor Code',
mode_slug = 'honor'
min_price = 0
suggested_prices = ''
currency = 'usd'
class RegistrationFactory(DjangoModelFactory): class RegistrationFactory(DjangoModelFactory):
FACTORY_FOR = Registration FACTORY_FOR = Registration
......
...@@ -8,6 +8,8 @@ import logging ...@@ -8,6 +8,8 @@ import logging
import json import json
import re import re
import unittest import unittest
from datetime import datetime, timedelta
import pytz
from django.conf import settings from django.conf import settings
from django.test import TestCase from django.test import TestCase
...@@ -28,8 +30,8 @@ from textwrap import dedent ...@@ -28,8 +30,8 @@ from textwrap import dedent
from student.models import unique_id_for_user, CourseEnrollment from student.models import unique_id_for_user, CourseEnrollment
from student.views import (process_survey_link, _cert_info, password_reset, password_reset_confirm_wrapper, from student.views import (process_survey_link, _cert_info, password_reset, password_reset_confirm_wrapper,
change_enrollment) change_enrollment, complete_course_mode_info)
from student.tests.factories import UserFactory from student.tests.factories import UserFactory, CourseModeFactory
from student.tests.test_email import mock_render_to_string from student.tests.test_email import mock_render_to_string
import shoppingcart import shoppingcart
...@@ -216,6 +218,45 @@ class CourseEndingTest(TestCase): ...@@ -216,6 +218,45 @@ class CourseEndingTest(TestCase):
}) })
@override_settings(MODULESTORE=TEST_DATA_MIXED_MODULESTORE)
class DashboardTest(TestCase):
"""
Tests for dashboard utility functions
"""
# arbitrary constant
COURSE_SLUG = "100"
COURSE_NAME = "test_course"
COURSE_ORG = "EDX"
def setUp(self):
self.course = CourseFactory.create(org=self.COURSE_ORG, display_name=self.COURSE_NAME, number=self.COURSE_SLUG)
self.assertIsNotNone(self.course)
self.user = UserFactory.create(username="jack", email="jack@fake.edx.org")
CourseModeFactory.create(
course_id=self.course.id,
mode_slug='honor',
mode_display_name='Honor Code',
)
def test_course_mode_info(self):
verified_mode = CourseModeFactory.create(
course_id=self.course.id,
mode_slug='verified',
mode_display_name='Verified',
expiration_date=(datetime.now(pytz.UTC) + timedelta(days=1)).date()
)
enrollment = CourseEnrollment.enroll(self.user, self.course.id)
course_mode_info = complete_course_mode_info(self.course.id, enrollment)
self.assertTrue(course_mode_info['show_upsell'])
self.assertEquals(course_mode_info['days_for_upsell'], 1)
verified_mode.expiration_date = datetime.now(pytz.UTC) + timedelta(days=-1)
verified_mode.save()
course_mode_info = complete_course_mode_info(self.course.id, enrollment)
self.assertFalse(course_mode_info['show_upsell'])
self.assertIsNone(course_mode_info['days_for_upsell'])
class EnrollInCourseTest(TestCase): class EnrollInCourseTest(TestCase):
"""Tests enrolling and unenrolling in courses.""" """Tests enrolling and unenrolling in courses."""
......
...@@ -267,6 +267,29 @@ def register_user(request, extra_context=None): ...@@ -267,6 +267,29 @@ def register_user(request, extra_context=None):
return render_to_response('register.html', context) return render_to_response('register.html', context)
def complete_course_mode_info(course_id, enrollment):
"""
We would like to compute some more information from the given course modes
and the user's current enrollment
Returns the given information:
- whether to show the course upsell information
- numbers of days until they can't upsell anymore
"""
modes = CourseMode.modes_for_course_dict(course_id)
mode_info = {'show_upsell': False, 'days_for_upsell': None}
# we want to know if the user is already verified and if verified is an
# option
if 'verified' in modes and enrollment.mode != 'verified':
mode_info['show_upsell'] = True
# if there is an expiration date, find out how long from now it is
if modes['verified'].expiration_date:
today = datetime.datetime.now(UTC).date()
mode_info['days_for_upsell'] = (modes['verified'].expiration_date - today).days
return mode_info
@login_required @login_required
@ensure_csrf_cookie @ensure_csrf_cookie
def dashboard(request): def dashboard(request):
...@@ -300,6 +323,7 @@ def dashboard(request): ...@@ -300,6 +323,7 @@ def dashboard(request):
show_courseware_links_for = frozenset(course.id for course, _enrollment in courses show_courseware_links_for = frozenset(course.id for course, _enrollment in courses
if has_access(request.user, course, 'load')) if has_access(request.user, course, 'load'))
course_modes = {course.id: complete_course_mode_info(course.id, enrollment) for course, enrollment in courses}
cert_statuses = {course.id: cert_info(request.user, course) for course, _enrollment in courses} cert_statuses = {course.id: cert_info(request.user, course) for course, _enrollment in courses}
# only show email settings for Mongo course and when bulk email is turned on # only show email settings for Mongo course and when bulk email is turned on
...@@ -324,6 +348,7 @@ def dashboard(request): ...@@ -324,6 +348,7 @@ def dashboard(request):
'staff_access': staff_access, 'staff_access': staff_access,
'errored_courses': errored_courses, 'errored_courses': errored_courses,
'show_courseware_links_for': show_courseware_links_for, 'show_courseware_links_for': show_courseware_links_for,
'all_course_modes': course_modes,
'cert_statuses': cert_statuses, 'cert_statuses': cert_statuses,
'show_email_settings_for': show_email_settings_for, 'show_email_settings_for': show_email_settings_for,
} }
......
...@@ -2,8 +2,16 @@ ...@@ -2,8 +2,16 @@
<%! from django.core.urlresolvers import reverse %> <%! from django.core.urlresolvers import reverse %>
<%inherit file="../main.html" /> <%inherit file="../main.html" />
<%block name="bodyclass">register verification-process step-select-track</%block> <%block name="bodyclass">register verification-process step-select-track ${'is-upgrading' if upgrade else ''}</%block>
<%block name="title"><title>${_("Register for {} | Choose Your Track").format(course_name)}</title></%block> <%block name="title">
<title>
%if upgrade:
${_("Upgrade Your Registration for {} | Choose Your Track").format(course_name)}
%else:
${_("Register for {} | Choose Your Track").format(course_name)}
%endif
</title>
</%block>
<%block name="js_extra"> <%block name="js_extra">
<script type="text/javascript"> <script type="text/javascript">
...@@ -48,7 +56,10 @@ $(document).ready(function() { ...@@ -48,7 +56,10 @@ $(document).ready(function() {
<div class="wrapper-register-choose wrapper-content-main"> <div class="wrapper-register-choose wrapper-content-main">
<article class="register-choose content-main"> <article class="register-choose content-main">
%if not upgrade:
<h3 class="title">${_("Select your track:")}</h3> <h3 class="title">${_("Select your track:")}</h3>
%endif
<form class="form-register-choose" method="post" name="enrollment_mode_form" id="enrollment_mode_form"> <form class="form-register-choose" method="post" name="enrollment_mode_form" id="enrollment_mode_form">
...@@ -57,9 +68,16 @@ $(document).ready(function() { ...@@ -57,9 +68,16 @@ $(document).ready(function() {
<div class="wrapper-copy"> <div class="wrapper-copy">
<span class="deco-ribbon"></span> <span class="deco-ribbon"></span>
<h4 class="title">${_("Certificate of Achievement (ID Verified)")}</h4> <h4 class="title">${_("Certificate of Achievement (ID Verified)")}</h4>
<div class="copy">
<p>${_("Sign up and work toward a verified Certificate of Achievement.")}</p> %if upgrade:
</div> <div class="copy">
<p>${_("Upgrade and work toward a verified Certificate of Achievement.")}</p>
</div>
%else:
<div class="copy">
<p>${_("Sign up and work toward a verified Certificate of Achievement.")}</p>
</div>
%endif
</div> </div>
<div class="field field-certificate-contribution"> <div class="field field-certificate-contribution">
...@@ -115,16 +133,28 @@ $(document).ready(function() { ...@@ -115,16 +133,28 @@ $(document).ready(function() {
<ul class="list-actions"> <ul class="list-actions">
<li class="action action-select"> <li class="action action-select">
<input type="submit" name="mode" value="Select Certificate" /> %if upgrade:
<input type="submit" name="mode" value="Upgrade Your Registration" />
%else:
<input type="submit" name="mode" value="Select Certificate" />
%endif
</li> </li>
</ul> </ul>
</div> </div>
<div class="help help-register"> <div class="help help-register">
<h3 class="title">${_("Verified Registration Requirements")}</h3> <h3 class="title">${_("Verified Registration Requirements")}</h3>
<div class="copy">
<p>${_("To register for a Verified Certificate of Achievement option, you will need a webcam, a credit or debit card, and an ID.")}</p> %if upgrade:
</div> <div class="copy">
<p>${_("To upgrade your registration and work towards a Verified Certificate of Achievement, you will need a webcam, a credit or debit card, and an ID.")}</p>
</div>
%else:
<div class="copy">
<p>${_("To register for a Verified Certificate of Achievement option, you will need a webcam, a credit or debit card, and an ID.")}</p>
</div>
%endif
<h3 class="title">${_("What is an ID Verified Certificate?")}</h3> <h3 class="title">${_("What is an ID Verified Certificate?")}</h3>
<div class="copy"> <div class="copy">
...@@ -133,25 +163,29 @@ $(document).ready(function() { ...@@ -133,25 +163,29 @@ $(document).ready(function() {
</div> </div>
% endif % endif
% if "audit" in modes: %if not upgrade:
<span class="deco-divider">
<span class="copy">${_("or")}</span> % if "audit" in modes:
</span> <span class="deco-divider">
<div class="register-choice register-choice-audit"> <span class="copy">${_("or")}</span>
<div class="wrapper-copy"> </span>
<h4 class="title">${_("Audit This Course")}</h4> <div class="register-choice register-choice-audit">
<div class="copy"> <div class="wrapper-copy">
<p>${_("Sign up to audit this course for free and track your own progress.")}</p> <h4 class="title">${_("Audit This Course")}</h4>
<div class="copy">
<p>${_("Sign up to audit this course for free and track your own progress.")}</p>
</div>
</div> </div>
<ul class="list-actions">
<li class="action action-select">
<input type="submit" name="mode" value="Select Audit" />
</li>
</ul>
</div> </div>
% endif
<ul class="list-actions"> %endif
<li class="action action-select">
<input type="submit" name="mode" value="Select Audit" />
</li>
</ul>
</div>
% endif
<input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }"> <input type="hidden" name="csrfmiddlewaretoken" value="${ csrf_token }">
</form> </form>
......
...@@ -35,6 +35,7 @@ Feature: LMS.Verified certificates ...@@ -35,6 +35,7 @@ Feature: LMS.Verified certificates
And I navigate to my dashboard And I navigate to my dashboard
Then I see the course on my dashboard Then I see the course on my dashboard
And I see that I am on the verified track And I see that I am on the verified track
And I do not see the upsell link on my dashboard
# Not easily automated # Not easily automated
# Scenario: I can re-take photos # Scenario: I can re-take photos
...@@ -70,3 +71,24 @@ Feature: LMS.Verified certificates ...@@ -70,3 +71,24 @@ Feature: LMS.Verified certificates
And the course has an honor mode And the course has an honor mode
When I give a reason why I cannot pay When I give a reason why I cannot pay
Then I should see the course on my dashboard Then I should see the course on my dashboard
Scenario: The upsell offer is on the dashboard if I am auditing.
Given I am logged in
When I select the audit track
And I navigate to my dashboard
Then I see the upsell link on my dashboard
Scenario: I can take the upsell offer and pay for it
Given I am logged in
And I select the audit track
And I navigate to my dashboard
When I see the upsell link on my dashboard
And I select the upsell link on my dashboard
And I select the verified track for upgrade
And I submit my photos and confirm
And I am at the payment page
And I submit valid payment information
And I navigate to my dashboard
Then I see the course on my dashboard
And I see that I am on the verified track
...@@ -6,6 +6,8 @@ from lettuce.django import django_url ...@@ -6,6 +6,8 @@ from lettuce.django import django_url
from course_modes.models import CourseMode from course_modes.models import CourseMode
from nose.tools import assert_equal from nose.tools import assert_equal
UPSELL_LINK_CSS = '.message-upsell a.action-upgrade[href*="edx/999/Certificates"]'
def create_cert_course(): def create_cert_course():
world.clear_courses() world.clear_courses()
org = 'edx' org = 'edx'
...@@ -53,7 +55,7 @@ def the_course_has_an_honor_mode(step): ...@@ -53,7 +55,7 @@ def the_course_has_an_honor_mode(step):
mode_slug='honor', mode_slug='honor',
mode_display_name='honor mode', mode_display_name='honor mode',
min_price=0, min_price=0,
) )
assert isinstance(honor_mode, CourseMode) assert isinstance(honor_mode, CourseMode)
...@@ -73,14 +75,28 @@ def select_contribution(amount=32): ...@@ -73,14 +75,28 @@ def select_contribution(amount=32):
assert world.css_find(radio_css).selected assert world.css_find(radio_css).selected
def click_verified_track_button():
world.wait_for_ajax_complete()
btn_css = 'input[value="Select Certificate"]'
world.css_click(btn_css)
@step(u'I select the verified track for upgrade')
def select_verified_track_upgrade(step):
select_contribution(32)
world.wait_for_ajax_complete()
btn_css = 'input[value="Upgrade Your Registration"]'
world.css_click(btn_css)
# TODO: might want to change this depending on the changes for upgrade
assert world.is_css_present('section.progress')
@step(u'I select the verified track$') @step(u'I select the verified track$')
def select_the_verified_track(step): def select_the_verified_track(step):
create_cert_course() create_cert_course()
register() register()
select_contribution(32) select_contribution(32)
world.wait_for_ajax_complete() click_verified_track_button()
btn_css = 'input[value="Select Certificate"]'
world.css_click(btn_css)
assert world.is_css_present('section.progress') assert world.is_css_present('section.progress')
...@@ -203,6 +219,20 @@ def submitted_photos_to_verify_my_identity(step): ...@@ -203,6 +219,20 @@ def submitted_photos_to_verify_my_identity(step):
step.given('I go to step "4"') step.given('I go to step "4"')
@step(u'I submit my photos and confirm')
def submit_photos_and_confirm(step):
step.given('I go to step "1"')
step.given('I capture my "face" photo')
step.given('I approve my "face" photo')
step.given('I go to step "2"')
step.given('I capture my "photo_id" photo')
step.given('I approve my "photo_id" photo')
step.given('I go to step "3"')
step.given('I select a contribution amount')
step.given('I confirm that the details match')
step.given('I go to step "4"')
@step(u'I see that my payment was successful') @step(u'I see that my payment was successful')
def see_that_my_payment_was_successful(step): def see_that_my_payment_was_successful(step):
title = world.css_find('div.wrapper-content-main h3.title') title = world.css_find('div.wrapper-content-main h3.title')
...@@ -221,6 +251,27 @@ def see_the_course_on_my_dashboard(step): ...@@ -221,6 +251,27 @@ def see_the_course_on_my_dashboard(step):
assert world.is_css_present(course_link_css) assert world.is_css_present(course_link_css)
@step(u'I see the upsell link on my dashboard')
def see_upsell_link_on_my_dashboard(step):
course_link_css = UPSELL_LINK_CSS
assert world.is_css_present(course_link_css)
@step(u'I do not see the upsell link on my dashboard')
def see_upsell_link_on_my_dashboard(step):
course_link_css = UPSELL_LINK_CSS
assert not world.is_css_present(course_link_css)
@step(u'I select the upsell link on my dashboard')
def see_upsell_link_on_my_dashboard(step):
# expand the upsell section
world.css_click('.message-upsell')
course_link_css = UPSELL_LINK_CSS
# click the actual link
world.css_click(course_link_css)
@step(u'I see that I am on the verified track') @step(u'I see that I am on the verified track')
def see_that_i_am_on_the_verified_track(step): def see_that_i_am_on_the_verified_track(step):
id_verified_css = 'li.course-item article.course.verified' id_verified_css = 'li.course-item article.course.verified'
......
...@@ -44,12 +44,15 @@ class VerifyView(View): ...@@ -44,12 +44,15 @@ class VerifyView(View):
before proceeding to payment before proceeding to payment
""" """
upgrade = request.GET.get('upgrade', False)
# If the user has already been verified within the given time period, # If the user has already been verified within the given time period,
# redirect straight to the payment -- no need to verify again. # redirect straight to the payment -- no need to verify again.
if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user): if SoftwareSecurePhotoVerification.user_has_valid_or_pending(request.user):
return redirect( return redirect(
reverse('verify_student_verified', reverse('verify_student_verified',
kwargs={'course_id': course_id})) kwargs={'course_id': course_id}) + "?upgrade={}".format(upgrade)
)
elif CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified': elif CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified':
return redirect(reverse('dashboard')) return redirect(reverse('dashboard'))
else: else:
...@@ -85,6 +88,7 @@ class VerifyView(View): ...@@ -85,6 +88,7 @@ class VerifyView(View):
"currency": verify_mode.currency.upper(), "currency": verify_mode.currency.upper(),
"chosen_price": chosen_price, "chosen_price": chosen_price,
"min_price": verify_mode.min_price, "min_price": verify_mode.min_price,
"upgrade": upgrade,
} }
return render_to_response('verify_student/photo_verification.html', context) return render_to_response('verify_student/photo_verification.html', context)
...@@ -100,6 +104,7 @@ class VerifiedView(View): ...@@ -100,6 +104,7 @@ class VerifiedView(View):
""" """
Handle the case where we have a get request Handle the case where we have a get request
""" """
upgrade = request.GET.get('upgrade', False)
if CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified': if CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified':
return redirect(reverse('dashboard')) return redirect(reverse('dashboard'))
verify_mode = CourseMode.mode_for_course(course_id, "verified") verify_mode = CourseMode.mode_for_course(course_id, "verified")
...@@ -117,6 +122,7 @@ class VerifiedView(View): ...@@ -117,6 +122,7 @@ class VerifiedView(View):
"purchase_endpoint": get_purchase_endpoint(), "purchase_endpoint": get_purchase_endpoint(),
"currency": verify_mode.currency.upper(), "currency": verify_mode.currency.upper(),
"chosen_price": chosen_price, "chosen_price": chosen_price,
"upgrade": upgrade,
} }
return render_to_response('verify_student/verified.html', context) return render_to_response('verify_student/verified.html', context)
...@@ -250,6 +256,7 @@ def show_requirements(request, course_id): ...@@ -250,6 +256,7 @@ def show_requirements(request, course_id):
if CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified': if CourseEnrollment.enrollment_mode_for_user(request.user, course_id) == 'verified':
return redirect(reverse('dashboard')) return redirect(reverse('dashboard'))
upgrade = request.GET.get('upgrade', False)
course = course_from_id(course_id) course = course_from_id(course_id)
context = { context = {
"course_id": course_id, "course_id": course_id,
...@@ -257,5 +264,6 @@ def show_requirements(request, course_id): ...@@ -257,5 +264,6 @@ def show_requirements(request, course_id):
"course_org": course.display_org_with_default, "course_org": course.display_org_with_default,
"course_num": course.display_number_with_default, "course_num": course.display_number_with_default,
"is_not_active": not request.user.is_active, "is_not_active": not request.user.is_active,
"upgrade": upgrade,
} }
return render_to_response("verify_student/show_requirements.html", context) return render_to_response("verify_student/show_requirements.html", context)
...@@ -100,3 +100,16 @@ ...@@ -100,3 +100,16 @@
// outline: thin dotted !important; // outline: thin dotted !important;
} }
} }
// removes list styling/spacing when using uls, ols for navigation and less content-centric cases
%ui-no-list {
list-style: none;
margin: 0;
padding: 0;
text-indent: 0;
li {
margin: 0;
padding: 0;
}
}
...@@ -282,4 +282,5 @@ ...@@ -282,4 +282,5 @@
border-radius: ($baseline/5); border-radius: ($baseline/5);
padding: ($baseline/2) $baseline; padding: ($baseline/2) $baseline;
text-transform: uppercase; text-transform: uppercase;
letter-spacing: 0.1rem;
} }
...@@ -227,6 +227,8 @@ ...@@ -227,6 +227,8 @@
} }
} }
// ====================
// course listings // course listings
.my-courses { .my-courses {
float: left; float: left;
...@@ -272,6 +274,8 @@ ...@@ -272,6 +274,8 @@
} }
} }
// ====================
// UI: course list // UI: course list
.listing-courses { .listing-courses {
@extend %ui-no-list; @extend %ui-no-list;
...@@ -289,6 +293,8 @@ ...@@ -289,6 +293,8 @@
} }
} }
// ====================
// UI: individual course item // UI: individual course item
.course { .course {
@include box-sizing(box); @include box-sizing(box);
...@@ -416,25 +422,27 @@ ...@@ -416,25 +422,27 @@
} }
} }
// ====================
// STATE: course mode - verified // STATE: course mode - verified
&.verified { &.verified {
@extend %ui-depth2; @extend %ui-depth2;
margin-top: ($baseline*2.5); position: relative;
border-top: 1px solid $verified-color-lvl3;
padding-top: ($baseline*1.25);
background: $white;
// FIXME: bad, but needed selector! .cover {
.info > hgroup .date-block { border-radius: ($baseline/10);
top: ($baseline*1.25); border: 1px solid $verified-color-lvl3;
border-bottom: 4px solid $verified-color-lvl3;
padding: ($baseline/10);
} }
// course enrollment status message // course enrollment status message
.sts-enrollment { .sts-enrollment {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
top: -28px; top: 105px;
right: ($baseline/2); left: 55px;
bottom: ($baseline/2);
text-align: center; text-align: center;
.label { .label {
...@@ -454,53 +462,176 @@ ...@@ -454,53 +462,176 @@
@extend %copy-badge; @extend %copy-badge;
border-radius: 0; border-radius: 0;
padding: ($baseline/4) ($baseline/2) ($baseline/4) $baseline; padding: ($baseline/4) ($baseline/2) ($baseline/4) $baseline;
color: $white;
background: $verified-color-lvl3; background: $verified-color-lvl3;
color: $white;
} }
} }
} }
} }
.message-status { // ====================
// UI: message
.message {
@include clearfix; @include clearfix;
border-radius: 3px; border-radius: 3px;
display: none; display: none;
z-index: 10; z-index: 10;
margin: 20px 0 10px; margin: $baseline 0 ($baseline/2) 0;
padding: 15px 20px; padding: ($baseline*0.75) $baseline;
font-family: $sans-serif; font-family: $sans-serif;
background: tint($yellow,70%); background: tint($yellow,70%);
border: 1px solid #ccc; border: 1px solid #ccc;
.message-copy { // STATE: shown
&.is-shown {
display: block;
}
a {
font-family: $sans-serif; font-family: $sans-serif;
font-size: 13px; }
margin: 0;
strong {
font-weight: 700;
a { a {
font-family: $sans-serif; font-weight: 700;
} }
}
.grade-value { .actions {
font-size: 1.2rem; @include clearfix;
font-weight: bold; list-style: none;
margin: 0;
padding: 0;
}
.message-title,
.message-copy .title {
@extend %t-title5;
@extend %t-weight4;
margin-bottom: ($baseline/4);
}
.message-copy,
.message-copy .copy {
@extend %t-copy-sub1;
margin: 0;
}
// CASE: expandable
&.is-expandable {
.wrapper-tip {
.message-title, .message-copy {
@include transition(color 0.25s ease-in-out 0);
margin-bottom: 0;
}
// STATE: hover
&:hover {
cursor: pointer;
.message-title, .message-copy {
color: $link-color;
}
}
} }
strong { .wrapper-extended {
font-weight: 700; @include transition(opacity 0.25s ease-in-out 0);
display: none;
opacity: 0.0;
}
a { // STATE: is expanded
font-weight: 700; &.is-expanded {
.wrapper-extended {
display: block;
opacity: 1.0;
} }
} }
} }
}
.actions { // TYPE: upsell
@include clearfix; .message-upsell {
list-style: none;
.wrapper-tip {
@include clearfix();
.message-title {
float: left;
}
.message-copy {
float: right;
}
}
.wrapper-extended {
padding: ($baseline/2) 0;
.message-copy {
margin-bottom: $baseline;
}
}
.action-upgrade {
@extend %btn-primary-green;
@include clearfix();
position: relative;
left: ($baseline/2);
padding: 8px $baseline 8px ($baseline*2);
.deco-graphic {
position: absolute;
top: -($baseline/4);
left: -($baseline*0.75);
width: ($baseline*2);
}
span {
color: $white; // nasty but needed override for poor <span> styling
}
.copy, .copy-sub {
display: inline-block;
vertical-align: middle;
}
.copy {
@extend %t-action3;
@extend %t-weight4;
margin-right: $baseline;
}
.copy-sub {
@extend %t-action4;
opacity: 0.875;
}
}
}
// TYPE: status
.message-status {
background: tint($yellow,70%);
border-color: #ccc;
.message-copy {
@extend %t-copy-sub1;
margin: 0; margin: 0;
padding: 0;
.grade-value {
font-size: 1.2rem;
font-weight: bold;
}
}
.actions {
.action { .action {
float: left; float: left;
...@@ -589,10 +720,6 @@ ...@@ -589,10 +720,6 @@
} }
} }
&.is-shown {
display: block;
}
&.course-status-processing { &.course-status-processing {
} }
...@@ -614,7 +741,6 @@ ...@@ -614,7 +741,6 @@
} }
} }
a.unenroll { a.unenroll {
float: right; float: right;
display: block; display: block;
......
// lms - views - verification flow // lms - views - verification flow
// ==================== // ====================
// MISC: extends - type
// application: canned headings
%hd-lv1 {
@extend %t-title1;
@extend %t-weight1;
color: $m-gray-d4;
margin: 0 0 ($baseline*2) 0;
}
%hd-lv2 {
@extend %t-title4;
@extend %t-weight1;
margin: 0 0 ($baseline*0.75) 0;
border-bottom: 1px solid $m-gray-l4;
padding-bottom: ($baseline/2);
color: $m-gray-d4;
}
%hd-lv3 {
@extend %t-title6;
@extend %t-weight4;
margin: 0 0 ($baseline/4) 0;
color: $m-gray-d4;
}
%hd-lv4 {
@extend %t-title6;
@extend %t-weight2;
margin: 0 0 $baseline 0;
color: $m-gray-d4;
}
%hd-lv5 {
@extend %t-title7;
@extend %t-weight4;
margin: 0 0 ($baseline/4) 0;
color: $m-gray-d4;
}
// application: canned copy
%copy-base {
@extend %t-copy-base;
color: $m-gray-d2;
}
%copy-lead1 {
@extend %t-copy-lead2;
color: $m-gray;
}
%copy-detail {
@extend %t-copy-sub1;
@extend %t-weight3;
color: $m-gray-d1;
}
%copy-metadata {
@extend %t-copy-sub2;
color: $m-gray-d1;
%copy-metadata-value {
@extend %t-weight2;
}
%copy-metadata-value {
@extend %t-weight4;
}
}
// application: canned links
%copy-link {
border-bottom: 1px dotted transparent;
&:hover, &:active {
border-color: $link-color-d1;
}
}
// ====================
// MISC: extends - button // MISC: extends - button
%btn-verify-primary { %btn-verify-primary {
@extend %btn-primary-green; @extend %btn-primary-green;
...@@ -72,7 +153,7 @@ ...@@ -72,7 +153,7 @@
// ==================== // ====================
// VIEW: all verification steps // VIEW: all verification steps
.register.verification-process { .verification-process {
// reset: box-sizing (making things so right its scary) // reset: box-sizing (making things so right its scary)
* { * {
...@@ -179,12 +260,16 @@ ...@@ -179,12 +260,16 @@
// elements - controls // elements - controls
.action-primary { .action-primary {
@extend %btn-primary-blue; @extend %btn-primary-blue;
border: none; // needed for override due to .register a:link styling
border: 0 !important;
color: $white !important;
} }
.action-confirm { .action-confirm {
@extend %btn-verify-primary; @extend %btn-verify-primary;
border: none; // needed for override due to .register a:link styling
border: 0 !important;
color: $white !important;
} }
// ==================== // ====================
...@@ -382,17 +467,19 @@ ...@@ -382,17 +467,19 @@
margin-right: ($baseline/4); margin-right: ($baseline/4);
opacity: 0.80; opacity: 0.80;
color: $white; color: $white;
letter-spacing: 0.1rem;
} }
} }
} }
.sts-label { .sts-label {
@extend %t-title7; @extend %t-title7;
@extend %t-weight4;
display: block; display: block;
margin-bottom: ($baseline/2); margin-bottom: ($baseline/2);
border-bottom: ($baseline/10) solid $m-gray-l4; border-bottom: ($baseline/10) solid $m-gray-l4;
padding-bottom: ($baseline/2); padding-bottom: ($baseline/2);
color: $m-gray; color: $m-gray-d1;
} }
.sts-course { .sts-course {
...@@ -1816,3 +1903,11 @@ ...@@ -1816,3 +1903,11 @@
width: 32% !important; width: 32% !important;
} }
} }
// STATE: upgrading registration type
.register.is-upgrading {
.form-register-choose {
margin-top: ($baseline*2) !important;
}
}
...@@ -14,6 +14,14 @@ ...@@ -14,6 +14,14 @@
<script type="text/javascript"> <script type="text/javascript">
(function() { (function() {
$('.message.is-expandable .wrapper-tip').bind('click', toggleExpandMessage);
function toggleExpandMessage(e) {
(e).preventDefault();
$(this).closest('.message.is-expandable').toggleClass('is-expanded');
}
$(".email-settings").click(function(event) { $(".email-settings").click(function(event) {
$("#email_settings_course_id").val( $(event.target).data("course-id") ); $("#email_settings_course_id").val( $(event.target).data("course-id") );
$("#email_settings_course_number").text( $(event.target).data("course-number") ); $("#email_settings_course_number").text( $(event.target).data("course-number") );
...@@ -179,7 +187,8 @@ ...@@ -179,7 +187,8 @@
<% show_courseware_link = (course.id in show_courseware_links_for) %> <% show_courseware_link = (course.id in show_courseware_links_for) %>
<% cert_status = cert_statuses.get(course.id) %> <% cert_status = cert_statuses.get(course.id) %>
<% show_email_settings = (course.id in show_email_settings_for) %> <% show_email_settings = (course.id in show_email_settings_for) %>
<%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 = all_course_modes.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" />
% endfor % endfor
</ul> </ul>
......
<%page args="course, enrollment, show_courseware_link, cert_status, show_email_settings" /> <%page args="course, enrollment, show_courseware_link, cert_status, show_email_settings, course_mode_info" />
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! <%!
...@@ -29,11 +29,11 @@ ...@@ -29,11 +29,11 @@
% endif % endif
% if enrollment.mode == "verified": % if enrollment.mode == "verified":
<span class="sts-enrollment"> <span class="sts-enrollment">
<span class="label">${_("Enrolled as: ")}</span> <span class="label">${_("Enrolled as: ")}</span>
<img class="deco-graphic" src="${static.url('images/vcert-ribbon-s.png')}" alt="ID Verified Ribbon/Badge"> <img class="deco-graphic" src="${static.url('images/vcert-ribbon-s.png')}" alt="ID Verified Ribbon/Badge" />
<span class="sts-enrollment-value">${_("ID Verified")}</span> <span class="sts-enrollment-value">${_("ID Verified")}</span>
</span> </span>
% endif % endif
<section class="info"> <section class="info">
...@@ -95,12 +95,12 @@ ...@@ -95,12 +95,12 @@
<li class="action"> <li class="action">
<a class="btn" href="${cert_status['download_url']}" <a class="btn" href="${cert_status['download_url']}"
title="${_('This link will open/download a PDF document')}"> title="${_('This link will open/download a PDF document')}">
Download Your PDF Certificate</a></li> ${_("Download Your PDF Certificate")}</a></li>
% endif % endif
% if cert_status['show_survey_button']: % if cert_status['show_survey_button']:
<li class="action"><a class="cta" href="${cert_status['survey_url']}"> <li class="action"><a class="cta" href="${cert_status['survey_url']}">
${_('Complete our course feedback survey')}</a></li> ${_("Complete our course feedback survey")}</a></li>
% endif % endif
</ul> </ul>
% endif % endif
...@@ -108,6 +108,31 @@ ...@@ -108,6 +108,31 @@
% endif % endif
%if course_mode_info['show_upsell']:
<div class="message message-upsell has-actions is-expandable is-shown">
<div class="wrapper-tip">
<h4 class="message-title">${_("Challenge Yourself!")}</h4>
<p class="message-copy">${_("Take this course as an ID-verified student.")}</p>
</div>
<div class="wrapper-extended">
<p class="message-copy">${_("You can still sign up for an ID verified certificate for this course. If you plan to complete the whole course, it is a great way to recognize your achievement. {a_start}Learn more about verified certificates{a_end}.").format(a_start='<a href="{}">'.format(marketing_link('WHAT_IS_VERIFIED_CERT')), a_end="</a>")}</p>
<ul class="actions message-actions">
<li class="action-item">
<a class="action action-upgrade" href="${reverse('course_modes_choose', kwargs={'course_id': course.id})}?upgrade=True">
<img class="deco-graphic" src="${static.url('images/vcert-ribbon-s.png')}" alt="ID Verified Ribbon/Badge">
<span class="wrapper-copy">
<span class="copy">${_("Upgrade to Verified Track")}</span>
</span>
</a>
</li>
</ul>
</div>
</div>
%endif
% if show_courseware_link: % if show_courseware_link:
% if course.has_ended(): % if course.has_ended():
<a href="${course_target}" class="enter-course archived">${_('View Archived Course')}</a> <a href="${course_target}" class="enter-course archived">${_('View Archived Course')}</a>
...@@ -116,8 +141,6 @@ ...@@ -116,8 +141,6 @@
% endif % endif
% endif % endif
<a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id}" data-course-number="${course.number}">${_('Unregister')}</a> <a href="#unenroll-modal" class="unenroll" rel="leanModal" data-course-id="${course.id}" data-course-number="${course.number}">${_('Unregister')}</a>
% if show_email_settings: % if show_email_settings:
......
...@@ -2,7 +2,11 @@ ...@@ -2,7 +2,11 @@
<header class="page-header"> <header class="page-header">
<h2 class="title"> <h2 class="title">
<span class="sts-label">${_("You are registering for")}</span> %if upgrade:
<span class="sts-label">${_("You are upgrading your registration for")}</span>
%else:
<span class="sts-label">${_("You are registering for")}</span>
%endif
<span class="wrapper-sts"> <span class="wrapper-sts">
<span class="sts-course"> <span class="sts-course">
...@@ -13,7 +17,11 @@ ...@@ -13,7 +17,11 @@
<span class="sts-track"> <span class="sts-track">
<span class="sts-track-value"> <span class="sts-track-value">
<span class="context">${_("Registering as: ")}</span> ${_("ID Verified")} %if upgrade:
<span class="context">${_("Upgrading to:")}</span> ${_("ID Verified")}
%else:
<span class="context">${_("Registering as: ")}</span> ${_("ID Verified")}
%endif
</span> </span>
</span> </span>
</span> </span>
......
...@@ -11,14 +11,21 @@ ...@@ -11,14 +11,21 @@
</li> </li>
<li class="help-item help-item-coldfeet"> <li class="help-item help-item-coldfeet">
<h3 class="title">${_("Change your mind?")}</h3> %if upgrade:
<div class="copy"> <h3 class="title">${_("Change your mind?")}</h3>
<p>${_("You can always {a_start} audit the course for free {a_end} without verifying.").format(a_start='<a rel="external" href="/course_modes/choose/' + course_id + '">', a_end="</a>")}</p> <div class="copy">
</div> <p>${_("You can always continue to audit the course without verifying.")}</p>
</div>
%else:
<h3 class="title">${_("Change your mind?")}</h3>
<div class="copy">
<p>${_("You can always {a_start} audit the course for free {a_end} without verifying.").format(a_start='<a rel="external" href="/course_modes/choose/' + course_id + '">', a_end="</a>")}</p>
</div>
%endif
</li> </li>
<li class="help-item help-item-technical"> <li class="help-item help-item-technical">
<h3 class="title">${_("Having Technical Trouble?")}</h3> <h3 class="title">${_("Technical Requirements")}</h3>
<div class="copy"> <div class="copy">
<p>${_("Please make sure your browser is updated to the {strong_start}{a_start}most recent version possible{a_end}{strong_end}. Also, please make sure your {strong_start}web cam is plugged in, turned on, and allowed to function in your web browser (commonly adjustable in your browser settings).{strong_end}").format(a_start='<a rel="external" href="http://browsehappy.com/">', a_end="</a>", strong_start="<strong>", strong_end="</strong>")}</p> <p>${_("Please make sure your browser is updated to the {strong_start}{a_start}most recent version possible{a_end}{strong_end}. Also, please make sure your {strong_start}web cam is plugged in, turned on, and allowed to function in your web browser (commonly adjustable in your browser settings).{strong_end}").format(a_start='<a rel="external" href="http://browsehappy.com/">', a_end="</a>", strong_start="<strong>", strong_end="</strong>")}</p>
</div> </div>
......
...@@ -3,8 +3,16 @@ ...@@ -3,8 +3,16 @@
<%inherit file="../main.html" /> <%inherit file="../main.html" />
<%namespace name='static' file='/static_content.html'/> <%namespace name='static' file='/static_content.html'/>
<%block name="bodyclass">register verification-process step-photos</%block> <%block name="bodyclass">register verification-process step-photos ${'is-upgrading' if upgrade else ''}</%block>
<%block name="title"><title>${_("Register for {} | Verification").format(course_name)}</title></%block> <%block name="title">
<title>
%if upgrade:
${_("Upgrade Your Registration for {} | Verification").format(course_name)}
%else:
${_("Register for {} | Verification").format(course_name)}
%endif
</title>
</%block>
<%block name="js_extra"> <%block name="js_extra">
<script src="${static.url('js/vendor/responsive-carousel/responsive-carousel.js')}"></script> <script src="${static.url('js/vendor/responsive-carousel/responsive-carousel.js')}"></script>
...@@ -172,7 +180,12 @@ ...@@ -172,7 +180,12 @@
<dt class="faq-question">${_("What do you do with this picture?")}</dt> <dt class="faq-question">${_("What do you do with this picture?")}</dt>
<dd class="faq-answer">${_("We only use it to verify your identity. It is not displayed anywhere.")}</dd> <dd class="faq-answer">${_("We only use it to verify your identity. It is not displayed anywhere.")}</dd>
<dt class="faq-question">${_("What if my camera isn't working?")}</dt> <dt class="faq-question">${_("What if my camera isn't working?")}</dt>
<dd class="faq-answer">${_("You can always {a_start} audit the course for free {a_end} without verifying.").format(a_start='<a rel="external" href="/course_modes/choose/' + course_id + '">', a_end="</a>")}</dd>
%if upgrade:
<dd class="faq-answer">${_("You can always continue to audit the course without verifying.")}</dd>
%else:
<dd class="faq-answer">${_("You can always {a_start} audit the course for free {a_end} without verifying.").format(a_start='<a rel="external" href="/course_modes/choose/' + course_id + '">', a_end="</a>")}</dd>
%endif
</dl> </dl>
</div> </div>
</div> </div>
......
<%! from django.utils.translation import ugettext as _ %> <%! from django.utils.translation import ugettext as _ %>
<%! from django.core.urlresolvers import reverse %> <%! from django.core.urlresolvers import reverse %>
<%inherit file="../main.html" /> <%inherit file="../main.html" />
<%block name="bodyclass">register verification-process step-requirements</%block> <%block name="bodyclass">register verification-process step-requirements ${'is-upgrading' if upgrade else ''}</%block>
<%block name="title"><title>${_("Register for {}").format(course_name)}</title></%block> <%block name="title">
<title>
%if upgrade:
${_("Upgrade Your Registration for {}").format(course_name)}
%else:
${_("Register for {}").format(course_name)}
%endif
</title>
</%block>
<%block name="content"> <%block name="content">
%if is_not_active: %if is_not_active:
...@@ -71,11 +79,19 @@ ...@@ -71,11 +79,19 @@
<div class="wrapper-content-main"> <div class="wrapper-content-main">
<article class="content-main"> <article class="content-main">
<h3 class="title">${_("What You Will Need to Register")}</h3> %if upgrade:
<h3 class="title">${_("What You Will Need to Upgrade")}</h3>
<div class="instruction">
<p>${_("There are three things you will need to upgrade to being an ID verified student:")}</p>
</div>
%else:
<h3 class="title">${_("What You Will Need to Register")}</h3>
<div class="instruction"> <div class="instruction">
<p>${_("There are three things you will need to register as an ID verified student:")}</p> <p>${_("There are three things you will need to register as an ID verified student:")}</p>
</div> </div>
%endif
<ul class="list-reqs ${"account-not-activated" if is_not_active else ""}"> <ul class="list-reqs ${"account-not-activated" if is_not_active else ""}">
%if is_not_active: %if is_not_active:
...@@ -149,11 +165,16 @@ ...@@ -149,11 +165,16 @@
</ul> </ul>
<nav class="nav-wizard ${"is-not-ready" if is_not_active else "is-ready"}"> <nav class="nav-wizard ${"is-not-ready" if is_not_active else "is-ready"}">
<span class="help help-inline">${_("Missing something? You can always {a_start} audit this course instead {a_end}").format(a_start='<a href="/course_modes/choose/' + course_id + '">', a_end="</a>")}</span>
%if upgrade:
<span class="help help-inline">${_("Missing something? You can always continue to audit this course instead.")}</span>
%else:
<span class="help help-inline">${_("Missing something? You can always {a_start} audit this course instead {a_end}").format(a_start='<a href="/course_modes/choose/' + course_id + '">', a_end="</a>")}</span>
%endif
<ol class="wizard-steps"> <ol class="wizard-steps">
<li class="wizard-step"> <li class="wizard-step">
<a class="next action-primary ${"disabled" if is_not_active else ""}" id="face_next_button" href="${reverse('verify_student_verify', kwargs={'course_id': course_id})}">${_("Go to Step 1: Take my Photo")}</a> <a class="next action-primary ${"disabled" if is_not_active else ""}" id="face_next_button" href="${reverse('verify_student_verify', kwargs={'course_id': course_id})}?upgrade=${upgrade}">${_("Go to Step 1: Take my Photo")}</a>
</li> </li>
</ol> </ol>
</nav> </nav>
......
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