Commit 16e63c9e by Matt Drayer

Added Certficates Web/HTML View

parent 766663ee
......@@ -670,6 +670,13 @@ class CourseFields(object):
scope=Scope.settings,
default=""
)
cert_html_view_overrides = Dict(
# Translators: This field is the container for course-specific certifcate configuration values
display_name=_("Certificate Web/HTML View Overrides"),
# Translators: These overrides allow for an alternative configuration of the certificate web view
help=_("Enter course-specific overrides for the Web/HTML template parameters here (JSON format)"),
scope=Scope.settings,
)
# An extra property is used rather than the wiki_slug/number because
# there are courses that change the number for different runs. This allows
......
......@@ -150,6 +150,7 @@ class AdvancedSettingsPage(CoursePage):
'allow_anonymous',
'allow_anonymous_to_peers',
'allow_public_wiki_access',
'cert_html_view_overrides',
'cert_name_long',
'cert_name_short',
'certificates_display_behavior',
......
......@@ -2,7 +2,9 @@
django admin pages for certificates models
"""
from django.contrib import admin
from certificates.models import CertificateGenerationConfiguration
from config_models.admin import ConfigurationModelAdmin
from certificates.models import CertificateGenerationConfiguration, CertificateHtmlViewConfiguration
admin.site.register(CertificateGenerationConfiguration)
admin.site.register(CertificateHtmlViewConfiguration, ConfigurationModelAdmin)
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding model 'CertificateHtmlViewConfiguration'
db.create_table('certificates_certificatehtmlviewconfiguration', (
('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
('change_date', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)),
('changed_by', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['auth.User'], null=True, on_delete=models.PROTECT)),
('enabled', self.gf('django.db.models.fields.BooleanField')(default=False)),
('configuration', self.gf('django.db.models.fields.TextField')()),
))
db.send_create_signal('certificates', ['CertificateHtmlViewConfiguration'])
def backwards(self, orm):
# Deleting model 'CertificateHtmlViewConfiguration'
db.delete_table('certificates_certificatehtmlviewconfiguration')
models = {
'auth.group': {
'Meta': {'object_name': 'Group'},
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}),
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'})
},
'auth.permission': {
'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'},
'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
},
'auth.user': {
'Meta': {'object_name': 'User'},
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}),
'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}),
'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'})
},
'certificates.certificategenerationconfiguration': {
'Meta': {'object_name': 'CertificateGenerationConfiguration'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'certificates.certificatehtmlviewconfiguration': {
'Meta': {'object_name': 'CertificateHtmlViewConfiguration'},
'change_date': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'changed_by': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']", 'null': 'True', 'on_delete': 'models.PROTECT'}),
'configuration': ('django.db.models.fields.TextField', [], {}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
'certificates.certificatewhitelist': {
'Meta': {'object_name': 'CertificateWhitelist'},
'course_id': ('xmodule_django.models.CourseKeyField', [], {'default': 'None', 'max_length': '255', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'whitelist': ('django.db.models.fields.BooleanField', [], {'default': 'False'})
},
'certificates.generatedcertificate': {
'Meta': {'unique_together': "(('user', 'course_id'),)", 'object_name': 'GeneratedCertificate'},
'course_id': ('xmodule_django.models.CourseKeyField', [], {'default': 'None', 'max_length': '255', 'blank': 'True'}),
'created_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now_add': 'True', 'blank': 'True'}),
'distinction': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'download_url': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '128', 'blank': 'True'}),
'download_uuid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
'error_reason': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '512', 'blank': 'True'}),
'grade': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '5', 'blank': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'key': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'}),
'mode': ('django.db.models.fields.CharField', [], {'default': "'honor'", 'max_length': '32'}),
'modified_date': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now', 'auto_now': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '255', 'blank': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'default': "'unavailable'", 'max_length': '32'}),
'user': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}),
'verify_uuid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '32', 'blank': 'True'})
},
'contenttypes.contenttype': {
'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"},
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
}
}
complete_apps = ['certificates']
......@@ -46,9 +46,12 @@ Eligibility:
unless he has allow_certificate set to False.
"""
from datetime import datetime
import json
import uuid
from django.conf import settings
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db import models, transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
......@@ -503,3 +506,44 @@ class CertificateGenerationConfiguration(ConfigurationModel):
"""
pass
class CertificateHtmlViewConfiguration(ConfigurationModel):
"""
Static values for certificate HTML view context parameters.
Default values will be applied across all certificate types (course modes)
Matching 'mode' overrides will be used instead of defaults, where applicable
Example configuration :
{
"default": {
"url": "http://www.edx.org",
"logo_src": "http://www.edx.org/static/images/logo.png",
"logo_alt": "Valid Certificate"
},
"honor": {
"logo_src": "http://www.edx.org/static/images/honor-logo.png",
"logo_alt": "Honor Certificate"
}
}
"""
configuration = models.TextField(
help_text="Certificate HTML View Parameters (JSON)"
)
def clean(self):
"""
Ensures configuration field contains valid JSON.
"""
try:
json.loads(self.configuration)
except ValueError:
raise ValidationError('Must be valid JSON string.')
@classmethod
def get_config(cls):
"""
Retrieves the configuration field value from the database
"""
instance = cls.current()
json_data = json.loads(instance.configuration) if instance.enabled else {}
return json_data
......@@ -2,7 +2,7 @@ from factory.django import DjangoModelFactory
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from certificates.models import GeneratedCertificate, CertificateStatuses
from certificates.models import GeneratedCertificate, CertificateStatuses, CertificateHtmlViewConfiguration
# Factories are self documenting
......@@ -15,3 +15,48 @@ class GeneratedCertificateFactory(DjangoModelFactory):
status = CertificateStatuses.unavailable
mode = GeneratedCertificate.MODES.honor
name = ''
class CertificateHtmlViewConfigurationFactory(DjangoModelFactory):
FACTORY_FOR = CertificateHtmlViewConfiguration
enabled = True
configuration = """{
"default": {
"accomplishment_class_append": "accomplishment--certificate--honorcode",
"certificate_verify_url_prefix": "https://verify-test.edx.org/cert/",
"certificate_verify_url_suffix": "/verify.html",
"company_about_url": "http://www.edx.org/about-us",
"company_courselist_url": "http://www.edx.org/course-list",
"company_careers_url": "http://www.edx.org/jobs",
"company_contact_url": "http://www.edx.org/contact-us",
"platform_name": "edX",
"company_privacy_url": "http://www.edx.org/edx-privacy-policy",
"company_tos_url": "http://www.edx.org/edx-terms-service",
"company_verified_certificate_url": "http://www.edx.org/verified-certificate",
"document_script_src_modernizr": "https://verify-test.edx.org/v2/static/js/vendor/modernizr-2.6.2.min.js",
"document_stylesheet_url_normalize": "https://verify-test.edx.org/v2/static/css/vendor/normalize.css",
"document_stylesheet_url_fontawesome": "https://verify-test.edx.org/v2/static/css/vendor/font-awesome.css",
"document_stylesheet_url_application": "https://verify-test.edx.org/v2/static/css/style-application.css",
"logo_src": "https://verify-test.edx.org/v2/static/images/logo-edx.svg",
"logo_url": "http://www.edx.org"
},
"honor": {
"certificate_type": "Honor Code",
"document_body_class_append": "is-honorcode"
},
"verified": {
"certificate_type": "Verified",
"document_body_class_append": "is-idverified"
},
"xseries": {
"certificate_type": "XSeries",
"document_body_class_append": "is-xseries",
"document_script_src_modernizr": "https://verify-test.edx.org/xseries/static/js/vendor/modernizr-2.6.2.min.js",
"document_stylesheet_url_normalize": "https://verify-test.edx.org/xseries/static/css/vendor/normalize.css",
"document_stylesheet_url_fontawesome": "https://verify-test.edx.org/xseries/static/css/vendor/font-awesome.css",
"document_stylesheet_url_application": "https://verify-test.edx.org/xseries/static/css/style-application.css",
"logo_src": "https://verify-test.edx.org/xseries/static/images/logo-edx.svg"
}
}"""
"""Tests for certificate Django models. """
from django.conf import settings
from django.core.exceptions import ValidationError
from django.test import TestCase
from django.test.utils import override_settings
from opaque_keys.edx.locator import CourseLocator
from certificates.models import (
ExampleCertificate,
ExampleCertificateSet
ExampleCertificateSet,
CertificateHtmlViewConfiguration
)
FEATURES_INVALID_FILE_PATH = settings.FEATURES.copy()
FEATURES_INVALID_FILE_PATH['CERTS_HTML_VIEW_CONFIG_PATH'] = 'invalid/path/to/config.json'
class ExampleCertificateTest(TestCase):
"""Tests for the ExampleCertificate model. """
......@@ -71,3 +78,73 @@ class ExampleCertificateTest(TestCase):
other_course = CourseLocator(org='other', course='other', run='other')
result = ExampleCertificateSet.latest_status(other_course)
self.assertIs(result, None)
class CertificateHtmlViewConfigurationTest(TestCase):
"""
Test the CertificateHtmlViewConfiguration model.
"""
def setUp(self):
super(CertificateHtmlViewConfigurationTest, self).setUp()
self.configuration_string = """{
"default": {
"url": "http://www.edx.org",
"logo_src": "http://www.edx.org/static/images/logo.png",
"logo_alt": "Valid Certificate"
},
"honor": {
"logo_src": "http://www.edx.org/static/images/honor-logo.png",
"logo_alt": "Honor Certificate"
}
}"""
self.config = CertificateHtmlViewConfiguration(configuration=self.configuration_string)
def test_create(self):
"""
Tests creation of configuration.
"""
self.config.save()
self.assertEquals(self.config.configuration, self.configuration_string)
def test_clean_bad_json(self):
"""
Tests if bad JSON string was given.
"""
self.config = CertificateHtmlViewConfiguration(configuration='{"bad":"test"')
self.assertRaises(ValidationError, self.config.clean)
def test_get(self):
"""
Tests get configuration from saved string.
"""
self.config.enabled = True
self.config.save()
expected_config = {
"default": {
"url": "http://www.edx.org",
"logo_src": "http://www.edx.org/static/images/logo.png",
"logo_alt": "Valid Certificate"
},
"honor": {
"logo_src": "http://www.edx.org/static/images/honor-logo.png",
"logo_alt": "Honor Certificate"
}
}
self.assertEquals(self.config.get_config(), expected_config)
def test_get_not_enabled_returns_blank(self):
"""
Tests get configuration that is not enabled.
"""
self.config.enabled = False
self.config.save()
self.assertEquals(len(self.config.get_config()), 0)
@override_settings(FEATURES=FEATURES_INVALID_FILE_PATH)
def test_get_no_database_no_file(self):
"""
Tests get configuration that is not enabled.
"""
self.config.configuration = ''
self.config.save()
self.assertEquals(self.config.get_config(), {})
......@@ -2,14 +2,28 @@
import json
import ddt
from uuid import uuid4
from django.test import TestCase
from django.core.urlresolvers import reverse
from django.conf import settings
from django.core.cache import cache
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.client import Client
from django.test.utils import override_settings
from opaque_keys.edx.locator import CourseLocator
from student.tests.factories import UserFactory
from xmodule.modulestore.tests.factories import CourseFactory
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
from certificates.models import ExampleCertificateSet, ExampleCertificate, GeneratedCertificate
from certificates.tests.factories import CertificateHtmlViewConfigurationFactory
FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True
from certificates.models import ExampleCertificateSet, ExampleCertificate
FEATURES_WITH_CERTS_DISABLED = settings.FEATURES.copy()
FEATURES_WITH_CERTS_DISABLED['CERTIFICATES_HTML_VIEW'] = False
@ddt.ddt
......@@ -151,3 +165,90 @@ class UpdateExampleCertificateViewTest(TestCase):
content = json.loads(response.content)
self.assertEqual(response.status_code, 200)
self.assertEqual(content['return_code'], 0)
class CertificatesViewsTests(ModuleStoreTestCase):
"""
Tests for the manual refund page
"""
def setUp(self):
super(CertificatesViewsTests, self).setUp()
self.client = Client()
self.course = CourseFactory.create(
org='testorg', number='run1', display_name='refundable course'
)
self.course_id = self.course.location.course_key
self.user = UserFactory.create(
email='joe_user@edx.org',
username='joeuser',
password='foo'
)
self.user.profile.name = "Joe User"
self.user.profile.save()
self.client.login(username=self.user.username, password='foo')
self.cert = GeneratedCertificate.objects.create(
user=self.user,
course_id=self.course_id,
verify_uuid=uuid4(),
download_uuid=uuid4(),
grade="0.95",
key='the_key',
distinction=True,
status='generated',
mode='honor',
name=self.user.profile.name,
)
CertificateHtmlViewConfigurationFactory.create()
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
def test_render_html_view_valid_certificate(self):
test_url = '/certificates/html?course={}'.format(unicode(self.course.id))
response = self.client.get(test_url)
self.assertIn(str(self.cert.verify_uuid), response.content)
# Hit any "verified" mode-specific branches
self.cert.mode = 'verified'
self.cert.save()
test_url = '/certificates/html?course={}'.format(unicode(self.course.id))
response = self.client.get(test_url)
self.assertIn(str(self.cert.verify_uuid), response.content)
# Hit any 'xseries' mode-specific branches
self.cert.mode = 'xseries'
self.cert.save()
test_url = '/certificates/html?course={}'.format(unicode(self.course.id))
response = self.client.get(test_url)
self.assertIn(str(self.cert.verify_uuid), response.content)
@override_settings(FEATURES=FEATURES_WITH_CERTS_DISABLED)
def test_render_html_view_invalid_feature_flag(self):
test_url = '/certificates/html?course={}'.format(unicode(self.course.id))
response = self.client.get(test_url)
self.assertIn('invalid', response.content)
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
def test_render_html_view_missing_course_id(self):
test_url = '/certificates/html'
response = self.client.get(test_url)
self.assertIn('invalid', response.content)
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
def test_render_html_view_invalid_course_id(self):
test_url = '/certificates/html?course=az-23423-4vs'
response = self.client.get(test_url)
self.assertIn('invalid', response.content)
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
def test_render_html_view_invalid_course(self):
test_url = '/certificates/html?course=missing/course/key'
response = self.client.get(test_url)
self.assertIn('invalid', response.content)
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
def test_render_html_view_invalid_certificate(self):
self.cert.delete()
self.assertEqual(len(GeneratedCertificate.objects.all()), 0)
test_url = '/certificates/html?course={}'.format(unicode(self.course.id))
response = self.client.get(test_url)
self.assertIn('invalid', response.content)
......@@ -65,6 +65,7 @@
"FEATURES": {
"AUTH_USE_OPENID_PROVIDER": true,
"CERTIFICATES_ENABLED": true,
"CERTIFICATES_HTML_VIEW": true,
"MULTIPLE_ENROLLMENT_ROLES": true,
"ENABLE_PAYMENT_FAKE": true,
"ENABLE_VERIFIED_CERTIFICATES": true,
......
......@@ -351,6 +351,9 @@ FEATURES = {
# enable beacons for video timing statistics
'ENABLE_VIDEO_BEACON': False,
# Certificates Web/HTML Views
'CERTIFICATES_HTML_VIEW': False,
}
# Ignore static asset files on import which match this pattern
......
......@@ -123,6 +123,10 @@ FEATURES['ENABLE_COURSEWARE_SEARCH'] = True
SEARCH_ENGINE = "search.elastic.ElasticSearchEngine"
########################## Certificates Web/HTML View #######################
FEATURES['CERTIFICATES_HTML_VIEW'] = True
#####################################################################
# See if the developer has any local overrides.
try:
......
......@@ -466,3 +466,6 @@ SEARCH_ENGINE = "search.tests.mock_search_engine.MockSearchEngine"
FACEBOOK_APP_SECRET = "Test"
FACEBOOK_APP_ID = "Test"
FACEBOOK_API_VERSION = "v2.2"
# Certificates Views
FEATURES['CERTIFICATES_HTML_VIEW'] = True
<%! from django.utils.translation import ugettext as _ %>
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/stylesheets/base.css">
</head>
<body>
<header>
<h1>edX and MITX</h1>
</header>
<section>
<header class="invalid">
<h1>${_("This is an invalid edX certificate number")}</h1>
<p>${_("Please check the number to make sure that it is the exact same as on the certificate.")}</p>
</header>
<section>
<p>${_("This is an unknown certificate number and therefore is a potential forgery.")}</p>
</section>
</section>
</body>
</html>
<%! from django.utils.translation import ugettext as _ %>
<%! import mako.runtime %>
<% mako.runtime.UNDEFINED = '' %>
<!DOCTYPE html>
<!--[if lt IE 7]><html class="no-js lt-ie9 lt-ie8 lt-ie7"><![endif]-->
<!--[if IE 7]><html class="no-js lt-ie10 lt-ie9 lt-ie8"><![endif]-->
<!--[if IE 8]><html class="no-js lt-ie10 lt-ie9"><![endif]-->
<!--[if IE 9]><html class="no-js lt-ie10"><![endif]-->
<!--[if gt IE 9]><!--><html class="no-js"><!--<![endif]-->
<head>
<title>${document_title}</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="${document_meta_description}">
<link rel="stylesheet" href="${document_stylesheet_url_normalize}" />
<link rel="stylesheet" href="${document_stylesheet_url_fontawesome}" />
<link rel="stylesheet" href="${document_stylesheet_url_application}" />
<script src="${document_script_src_modernizr}"></script>
</head>
<body class="view--valid-certificate ${document_body_class_append}" data-view="valid-certificate">
<!--[if lt IE 9]>
<p class="msg msg--browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<nav class="nav--skip sr">
<h2>${_("Skip to This Page's Content")}</h2>
<ol>
<li class="nav__item"><a class="action" href="#validation-status">${_("Validation Status")}</a></li>
<li class="nav__item"><a class="action" href="#validation-accomplishment">${_("Student Accomplishment")}</a></li>
<li class="nav__item"><a class="action" href="#validation-info">${_("More Information")}</a></li>
<li class="nav__item"><a class="action" href="#company-info">${_("About")} ${platform_name}</a></li>
</ol>
</nav>
<div class="wrapper--view">
<div class="wrapper--header">
<header class="header--app" role="banner">
<h1 class="title title--logo">
<span class="logo">
<a href="${logo_url}"><img class="img--logo" src="" alt="${logo_alt}" /></a>
</span>
<span class="title title--sub">${logo_subtitle}</span>
</h1>
</header>
</div>
<hr class="divider /">
<div class="wrapper--content">
<section class="content content--main" role="main">
<div class="status status--valid" id="validation-status">
<h2 class="title title--lvl2">${document_banner}<span class="sr">:</span></h2>
</div>
<article class="accomplishment ${accomplishment_class_append}" id="validation-accomplishment">
<div class="accomplishment__statement">
<p class="copy">
<span class="copy__name">${accomplishment_copy_name}</span>
<span class="copy__context">${accomplishment_copy_description_full}</span>
<span class="copy__course">
<span class="copy__course__org">${accomplishment_copy_course_org}</span>
<span class="copy__course__name">${accomplishment_copy_course_name}</span>
</span>
<span class="copy__context">${accomplishment_copy_course_description}</span>
</p>
</div>
<div class="accomplishment__details">
<h3 class="title title--lvl2 sr">${accomplishment_more_title}</h3>
<ul class="list list--metadata">
<li class="item certificate--type">
<span class="label">_(Certificate Type)</span>
<span class="value">
${certificate_type_title}
<span class="explanation">${certificate_type_description} </span>
</span>
</li>
<li class="item certificate--id">
<span class="label">${certificate_id_number_title}</span>
<span class="value">${certificate_id_number}</span>
</li>
<li class="item certificate--date">
<span class="label">${certificate_date_issued_title}</span>
<span class="value">${certificate_date_issued}</span>
</li>
</ul>
</div>
</article>
</section>
<hr class="divider /">
<aside class="content content--supplemental" role="complimentary" id="validation-info">
<div class="supplemental__about">
<h2 class="title">${company_about_title}</h2>
<div class="copy">
<p>${company_about_description}</p>
</div>
<ul class="list list--actions">
<li class="item item--action">
<a class="action action--primary action--moreinfo" href="${company_about_url}">${company_about_urltext}</a>
</li>
</ul>
</div>
<div class="supplemental__how">
<h2 class="title">${certificate_verify_title}</h2>
<div class="copy">
<p>${certificate_verify_description}</p>
</div>
<ul class="list list--actions">
<li class="item item--action">
<a class="action action--moreinfo" href="${certificate_verify_url}">${certificate_verify_urltext}</a>
</li>
</ul>
</div>
<div class="supplemental__certificates">
<h2 class="title">${certificate_info_title}</h2>
<div class="copy">
<p>${certificate_info_description}</p>
</div>
</div>
</aside>
</div>
<hr class="divider /">
<div class="wrapper--footer">
<footer class="footer--app" role="contentinfo" id="company-info">
<div class="copyright">
<p>${copyright_text}</p>
</div>
<nav class="nav--footer">
<ul class="list list--legal">
<li class="nav__item">
<a class="action" href="${company_tos_url}">${company_tos_urltext}</a>
</li>
<li class="nav__item">
<a class="action" href="${company_privacy_url}">${company_privacy_urltext}</a>
</li>
</ul>
<ul class="list list--actions">
<li class="nav__item">
<a class="action" href="${company_courselist_url}">${company_courselist_urltext}</a>
</li>
<li class="nav__item">
<a class="action" href="${company_careers_url}">${company_careers_urltext}</a>
</li>
<li class="nav__item">
<a class="action" href="${company_contact_url}">${company_contact_urltext}</a>
</li>
</ul>
</nav>
</footer>
</div>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="/v2/static/jsjs/vendor/jquery-1.10.2.min.js"><\/script>')</script>
</body>
</html>
......@@ -598,6 +598,11 @@ if settings.FEATURES.get('ENABLE_THIRD_PARTY_AUTH'):
url(r'^login_oauth_token/(?P<backend>[^/]+)/$', 'student.views.login_oauth_token'),
)
# Certificates Web/HTML View
if settings.FEATURES.get('CERTIFICATES_HTML_VIEW', False):
urlpatterns += (
url(r'^certificates/html', 'certificates.views.render_html_view', name='cert_html_view'),
)
urlpatterns = patterns(*urlpatterns)
......
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