Merge pull request #24566 from edx/private_to_public_03835a5
Mergeback PR from private to public.
This commit is contained in:
@@ -51,9 +51,8 @@ class LMSLinksTestCase(TestCase):
|
||||
mode = 'professional'
|
||||
|
||||
self.assertEqual(
|
||||
utils.get_lms_link_for_certificate_web_view(dummy_user, course_key, mode),
|
||||
"//localhost:8000/certificates/user/{user_id}/course/{course_key}?preview={mode}".format(
|
||||
user_id=dummy_user,
|
||||
utils.get_lms_link_for_certificate_web_view(course_key, mode),
|
||||
"//localhost:8000/certificates/course/{course_key}?preview={mode}".format(
|
||||
course_key=course_key,
|
||||
mode=mode
|
||||
)
|
||||
@@ -61,9 +60,8 @@ class LMSLinksTestCase(TestCase):
|
||||
|
||||
with with_site_configuration_context(configuration={"course_org_filter": "mitX", "LMS_BASE": "dummyhost:8000"}):
|
||||
self.assertEqual(
|
||||
utils.get_lms_link_for_certificate_web_view(dummy_user, course_key, mode),
|
||||
"//dummyhost:8000/certificates/user/{user_id}/course/{course_key}?preview={mode}".format(
|
||||
user_id=dummy_user,
|
||||
utils.get_lms_link_for_certificate_web_view(course_key, mode),
|
||||
"//dummyhost:8000/certificates/course/{course_key}?preview={mode}".format(
|
||||
course_key=course_key,
|
||||
mode=mode
|
||||
)
|
||||
|
||||
@@ -139,7 +139,7 @@ def get_lms_link_for_item(location, preview=False):
|
||||
)
|
||||
|
||||
|
||||
def get_lms_link_for_certificate_web_view(user_id, course_key, mode):
|
||||
def get_lms_link_for_certificate_web_view(course_key, mode):
|
||||
"""
|
||||
Returns the url to the certificate web view.
|
||||
"""
|
||||
@@ -151,9 +151,8 @@ def get_lms_link_for_certificate_web_view(user_id, course_key, mode):
|
||||
if lms_base is None:
|
||||
return None
|
||||
|
||||
return u"//{certificate_web_base}/certificates/user/{user_id}/course/{course_id}?preview={mode}".format(
|
||||
return u"//{certificate_web_base}/certificates/course/{course_id}?preview={mode}".format(
|
||||
certificate_web_base=lms_base,
|
||||
user_id=user_id,
|
||||
course_id=six.text_type(course_key),
|
||||
mode=mode
|
||||
)
|
||||
|
||||
@@ -411,7 +411,6 @@ def certificates_list_handler(request, course_key_string):
|
||||
|
||||
if has_certificate_modes:
|
||||
certificate_web_view_url = get_lms_link_for_certificate_web_view(
|
||||
user_id=request.user.id,
|
||||
course_key=course_key,
|
||||
mode=course_modes[0] # CourseMode.modes_for_course returns default mode if doesn't find anyone.
|
||||
)
|
||||
|
||||
@@ -263,7 +263,6 @@ class CertificatesListHandlerTestCase(
|
||||
@override_settings(LMS_BASE=None)
|
||||
def test_no_lms_base_for_certificate_web_view_link(self):
|
||||
test_link = get_lms_link_for_certificate_web_view(
|
||||
user_id=self.user.id,
|
||||
course_key=self.course.id,
|
||||
mode='honor'
|
||||
)
|
||||
@@ -271,10 +270,9 @@ class CertificatesListHandlerTestCase(
|
||||
|
||||
@override_settings(LMS_BASE="lms_base_url")
|
||||
def test_lms_link_for_certificate_web_view(self):
|
||||
test_url = "//lms_base_url/certificates/user/" \
|
||||
+ str(self.user.id) + "/course/" + six.text_type(self.course.id) + '?preview=honor'
|
||||
test_url = "//lms_base_url/certificates/" \
|
||||
"course/" + six.text_type(self.course.id) + '?preview=honor'
|
||||
link = get_lms_link_for_certificate_web_view(
|
||||
user_id=self.user.id,
|
||||
course_key=self.course.id,
|
||||
mode='honor'
|
||||
)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
define(
|
||||
[
|
||||
'jquery', 'backbone', 'underscore',
|
||||
'js/views/video/transcripts/utils'
|
||||
'js/views/video/transcripts/utils',
|
||||
'edx-ui-toolkit/js/utils/html-utils'
|
||||
],
|
||||
function($, Backbone, _, TranscriptUtils) {
|
||||
function($, Backbone, _, TranscriptUtils, HtmlUtils) {
|
||||
'use strict';
|
||||
var FileUploader = Backbone.View.extend({
|
||||
invisibleClass: 'is-invisible',
|
||||
|
||||
@@ -37,9 +39,8 @@ function($, Backbone, _, TranscriptUtils) {
|
||||
|
||||
return;
|
||||
}
|
||||
this.template = _.template(tpl);
|
||||
|
||||
tplContainer.html(this.template({
|
||||
this.template = HtmlUtils.template(tpl);
|
||||
HtmlUtils.setHtml(tplContainer, this.template({
|
||||
ext: this.validFileExtensions,
|
||||
component_locator: this.options.component_locator
|
||||
}));
|
||||
@@ -126,11 +127,12 @@ function($, Backbone, _, TranscriptUtils) {
|
||||
*
|
||||
*/
|
||||
checkExtValidity: function(file) {
|
||||
var fileExtension;
|
||||
if (!file.name) {
|
||||
return void(0);
|
||||
}
|
||||
|
||||
var fileExtension = file.name
|
||||
fileExtension = file.name
|
||||
.split('.')
|
||||
.pop()
|
||||
.toLowerCase();
|
||||
@@ -153,7 +155,7 @@ function($, Backbone, _, TranscriptUtils) {
|
||||
|
||||
this.$progress
|
||||
.width(percentVal)
|
||||
.html(percentVal)
|
||||
.text(percentVal)
|
||||
.removeClass(this.invisibleClass);
|
||||
},
|
||||
|
||||
@@ -177,7 +179,7 @@ function($, Backbone, _, TranscriptUtils) {
|
||||
|
||||
this.$progress
|
||||
.width(percentVal)
|
||||
.html(percentVal);
|
||||
.text(percentVal);
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<%block name="page_bundle">
|
||||
<%static:webpack entry="js/factories/edit_tabs">
|
||||
EditTabsFactory("${context_course.location | n, js_escaped_string}", "${reverse('tabs_handler', kwargs={'course_key_string': context_course.id})}");
|
||||
EditTabsFactory("${context_course.location | n, js_escaped_string}", "${reverse('tabs_handler', kwargs={'course_key_string': context_course.id}) | n, js_escaped_string}");
|
||||
</%static:webpack>
|
||||
</%block>
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<%page expression_filter="h"/>
|
||||
|
||||
<%inherit file="base.html" />
|
||||
<%!
|
||||
from django.utils.translation import ugettext as _
|
||||
@@ -110,7 +112,7 @@ from openedx.core.djangolib.js_utils import (
|
||||
<%block name="requirejs">
|
||||
require(["js/factories/manage_users_lib"], function(ManageLibraryUsersFactory) {
|
||||
ManageLibraryUsersFactory(
|
||||
"${context_library.display_name_with_default | h}",
|
||||
"${context_library.display_name_with_default | n, js_escaped_string}",
|
||||
${users | n, dump_js_escaped_json},
|
||||
"${reverse('course_team_handler', kwargs={'course_key_string': library_key, 'email': '@@EMAIL@@'}) | n, js_escaped_string}",
|
||||
${request.user.id | n, dump_js_escaped_json},
|
||||
|
||||
@@ -7,6 +7,7 @@ import hashlib
|
||||
import logging
|
||||
|
||||
import six
|
||||
|
||||
from django.urls import reverse
|
||||
from django.utils.text import slugify
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
@@ -15,6 +16,7 @@ from badges.models import BadgeAssertion, BadgeClass, CourseCompleteImageConfigu
|
||||
from badges.utils import requires_badges_enabled, site_prefix
|
||||
from xmodule.modulestore.django import modulestore
|
||||
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -63,8 +65,11 @@ def evidence_url(user_id, course_key):
|
||||
event.
|
||||
"""
|
||||
course_id = six.text_type(course_key)
|
||||
# avoid circular import problems
|
||||
from lms.djangoapps.certificates.models import GeneratedCertificate
|
||||
cert = GeneratedCertificate.eligible_certificates.get(user__id=int(user_id), course_id=course_id)
|
||||
return site_prefix() + reverse(
|
||||
'certificates:html_view', kwargs={'user_id': user_id, 'course_id': course_id}) + '?evidence_visit=1'
|
||||
'certificates:render_cert_by_uuid', kwargs={'certificate_uuid': cert.verify_uuid}) + '?evidence_visit=1'
|
||||
|
||||
|
||||
def criteria(course_key):
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"""
|
||||
Tests for the course completion helper functions.
|
||||
"""
|
||||
|
||||
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
from badges.events import course_complete
|
||||
from lms.djangoapps.certificates.models import GeneratedCertificate
|
||||
from student.tests.factories import UserFactory
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
@@ -64,9 +64,19 @@ class CourseCompleteTestCase(ModuleStoreTestCase):
|
||||
Make sure the evidence URL points to the right place.
|
||||
"""
|
||||
user = UserFactory.create()
|
||||
cert = GeneratedCertificate.eligible_certificates.create(
|
||||
user=user,
|
||||
course_id=self.course_key,
|
||||
download_uuid=uuid4(),
|
||||
grade="0.95",
|
||||
key='the_key',
|
||||
distinction=True,
|
||||
status='downloadable',
|
||||
mode='honor',
|
||||
name=user.profile.name,
|
||||
verify_uuid=uuid4().hex
|
||||
)
|
||||
self.assertEqual(
|
||||
'https://edx.org/certificates/user/{user_id}/course/{course_key}?evidence_visit=1'.format(
|
||||
user_id=user.id, course_key=self.course_key
|
||||
),
|
||||
'https://edx.org/certificates/{}?evidence_visit=1'.format(cert.verify_uuid),
|
||||
course_complete.evidence_url(user.id, self.course_key)
|
||||
)
|
||||
|
||||
@@ -312,7 +312,9 @@ def certificate_downloadable_status(student, course_key):
|
||||
|
||||
if current_status['status'] == CertificateStatuses.downloadable and may_view_certificate:
|
||||
response_data['is_downloadable'] = True
|
||||
response_data['download_url'] = current_status['download_url'] or get_certificate_url(student.id, course_key)
|
||||
response_data['download_url'] = current_status['download_url'] or get_certificate_url(
|
||||
student.id, course_key, current_status['uuid']
|
||||
)
|
||||
response_data['is_pdf_certificate'] = bool(current_status['download_url'])
|
||||
response_data['uuid'] = current_status['uuid']
|
||||
|
||||
@@ -472,13 +474,13 @@ def _course_from_key(course_key):
|
||||
return CourseOverview.get_from_id(_safe_course_key(course_key))
|
||||
|
||||
|
||||
def _certificate_html_url(user_id, course_id, uuid):
|
||||
if uuid:
|
||||
return reverse('certificates:render_cert_by_uuid', kwargs={'certificate_uuid': uuid})
|
||||
elif user_id and course_id:
|
||||
kwargs = {"user_id": str(user_id), "course_id": six.text_type(course_id)}
|
||||
return reverse('certificates:html_view', kwargs=kwargs)
|
||||
return ''
|
||||
def _certificate_html_url(uuid):
|
||||
"""
|
||||
Returns uuid based certificate URL.
|
||||
"""
|
||||
return reverse(
|
||||
'certificates:render_cert_by_uuid', kwargs={'certificate_uuid': uuid}
|
||||
) if uuid else ''
|
||||
|
||||
|
||||
def _certificate_download_url(user_id, course_id, user_certificate=None):
|
||||
@@ -515,7 +517,7 @@ def get_certificate_url(user_id=None, course_id=None, uuid=None, user_certificat
|
||||
return url
|
||||
|
||||
if has_html_certificates_enabled(course):
|
||||
url = _certificate_html_url(user_id, course_id, uuid)
|
||||
url = _certificate_html_url(uuid)
|
||||
else:
|
||||
url = _certificate_download_url(user_id, course_id, user_certificate=user_certificate)
|
||||
return url
|
||||
@@ -631,10 +633,11 @@ def emit_certificate_event(event_name, user, course_id, course=None, event_data=
|
||||
'org_id': course.org,
|
||||
'course_id': six.text_type(course_id)
|
||||
}
|
||||
|
||||
data = {
|
||||
'user_id': user.id,
|
||||
'course_id': six.text_type(course_id),
|
||||
'certificate_url': get_certificate_url(user.id, course_id)
|
||||
'certificate_url': get_certificate_url(user.id, course_id, uuid=event_data['certificate_id'])
|
||||
}
|
||||
event_data = event_data or {}
|
||||
event_data.update(data)
|
||||
|
||||
@@ -199,10 +199,7 @@ class CertificateDownloadableStatusTests(WebCertificateTestMixin, ModuleStoreTes
|
||||
'is_downloadable': True,
|
||||
'is_generating': False,
|
||||
'is_unverified': False,
|
||||
'download_url': '/certificates/user/{user_id}/course/{course_id}'.format(
|
||||
user_id=self.student.id,
|
||||
course_id=self.course.id,
|
||||
),
|
||||
'download_url': '/certificates/{uuid}'.format(uuid=cert_status['uuid']),
|
||||
'is_pdf_certificate': False,
|
||||
'uuid': cert_status['uuid']
|
||||
}
|
||||
@@ -496,16 +493,14 @@ class CertificateGetTests(SharedModuleStoreTestCase):
|
||||
self.assertEqual(expected_url, cert_url)
|
||||
|
||||
expected_url = reverse(
|
||||
'certificates:html_view',
|
||||
kwargs={
|
||||
"user_id": str(self.student.id),
|
||||
"course_id": six.text_type(self.web_cert_course.id),
|
||||
}
|
||||
'certificates:render_cert_by_uuid',
|
||||
kwargs=dict(certificate_uuid=self.uuid)
|
||||
)
|
||||
|
||||
cert_url = certs_api.get_certificate_url(
|
||||
user_id=self.student.id,
|
||||
course_id=self.web_cert_course.id
|
||||
course_id=self.web_cert_course.id,
|
||||
uuid=self.uuid
|
||||
)
|
||||
self.assertEqual(expected_url, cert_url)
|
||||
|
||||
|
||||
@@ -4,9 +4,11 @@ Tests for certificate app views used by the support team.
|
||||
|
||||
|
||||
import json
|
||||
from uuid import uuid4
|
||||
|
||||
import ddt
|
||||
import six
|
||||
|
||||
from django.conf import settings
|
||||
from django.test.utils import override_settings
|
||||
from django.urls import reverse
|
||||
@@ -85,6 +87,7 @@ class CertificateSupportTestCase(ModuleStoreTestCase):
|
||||
status=self.CERT_STATUS,
|
||||
mode=self.CERT_MODE,
|
||||
download_url=self.CERT_DOWNLOAD_URL,
|
||||
verify_uuid=uuid4().hex
|
||||
)
|
||||
|
||||
# Login as support staff
|
||||
@@ -226,8 +229,8 @@ class CertificateSearchTests(CertificateSupportTestCase):
|
||||
self.assertEqual(
|
||||
retrieved_cert["download_url"],
|
||||
reverse(
|
||||
'certificates:html_view',
|
||||
kwargs={"user_id": self.student.id, "course_id": self.course.id}
|
||||
'certificates:render_cert_by_uuid',
|
||||
kwargs={"certificate_uuid": self.cert.verify_uuid}
|
||||
)
|
||||
)
|
||||
self.assertTrue(retrieved_cert["regenerate"])
|
||||
|
||||
@@ -229,13 +229,14 @@ class CertificatesViewsSiteTests(ModuleStoreTestCase):
|
||||
self.cert = GeneratedCertificate.eligible_certificates.create(
|
||||
user=self.user,
|
||||
course_id=self.course_id,
|
||||
download_uuid=uuid4(),
|
||||
download_uuid=uuid4().hex,
|
||||
grade="0.95",
|
||||
key='the_key',
|
||||
distinction=True,
|
||||
status='downloadable',
|
||||
mode='honor',
|
||||
name=self.user.profile.name,
|
||||
verify_uuid=uuid4().hex
|
||||
)
|
||||
self._setup_configuration()
|
||||
|
||||
@@ -284,7 +285,8 @@ class CertificatesViewsSiteTests(ModuleStoreTestCase):
|
||||
def test_html_view_for_site(self):
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
response = self.client.get(test_url)
|
||||
@@ -302,7 +304,8 @@ class CertificatesViewsSiteTests(ModuleStoreTestCase):
|
||||
def test_html_view_site_configuration_missing(self):
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
response = self.client.get(test_url)
|
||||
|
||||
@@ -102,7 +102,7 @@ class CommonCertificatesTestCase(ModuleStoreTestCase):
|
||||
self.cert = GeneratedCertificateFactory.create(
|
||||
user=self.user,
|
||||
course_id=self.course_id,
|
||||
download_uuid=uuid4(),
|
||||
download_uuid=uuid4().hex,
|
||||
download_url="http://www.example.com/certificates/download",
|
||||
grade="0.95",
|
||||
key='the_key',
|
||||
@@ -409,7 +409,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=1, is_active=True)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(
|
||||
@@ -489,7 +490,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url, HTTP_HOST='test.localhost')
|
||||
|
||||
@@ -527,7 +529,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, str(self.cert.verify_uuid))
|
||||
@@ -553,7 +556,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
# Validate certificate
|
||||
@@ -564,9 +568,7 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self.cert.status = CertificateStatuses.generating
|
||||
self.cert.save()
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, "Invalid Certificate")
|
||||
self.assertContains(response, "Cannot Find Certificate")
|
||||
self.assertContains(response, "We cannot find a certificate with this URL or ID number.")
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@ddt.data(
|
||||
(CertificateStatuses.downloadable, True),
|
||||
@@ -588,27 +590,26 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
|
||||
if eligible_for_certificate:
|
||||
self.assertContains(response, str(self.cert.verify_uuid))
|
||||
else:
|
||||
self.assertContains(response, "Invalid Certificate")
|
||||
self.assertContains(response, "Cannot Find Certificate")
|
||||
self.assertContains(response, "We cannot find a certificate with this URL or ID number.")
|
||||
self.assertNotContains(response, str(self.cert.verify_uuid))
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_html_view_for_invalid_certificate(self):
|
||||
def test_html_view_returns_404_for_invalid_certificate(self):
|
||||
"""
|
||||
Tests that Certificate HTML Web View returns "Cannot Find Certificate" if certificate has been invalidated.
|
||||
Tests that Certificate HTML Web View successfully retrieves certificate only
|
||||
if the certificate is not invalidated otherwise returns 404
|
||||
"""
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
# Validate certificate
|
||||
@@ -618,32 +619,7 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
# invalidate certificate and verify that "Cannot Find Certificate" is returned
|
||||
self.cert.invalidate()
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, "Invalid Certificate")
|
||||
self.assertContains(response, "Cannot Find Certificate")
|
||||
self.assertContains(response, "We cannot find a certificate with this URL or ID number.")
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_html_lang_attribute_is_dynamic_for_invalid_certificate_html_view(self):
|
||||
"""
|
||||
Tests that Certificate HTML Web View's lang attribute is based on user language.
|
||||
"""
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
)
|
||||
|
||||
self.cert.invalidate()
|
||||
|
||||
user_language = 'fr'
|
||||
self.client.cookies[settings.LANGUAGE_COOKIE] = user_language
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, '<html class="no-js" lang="fr">')
|
||||
|
||||
user_language = 'ar'
|
||||
self.client.cookies[settings.LANGUAGE_COOKIE] = user_language
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, '<html class="no-js" lang="ar">')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_html_lang_attribute_is_dynamic_for_certificate_html_view(self):
|
||||
@@ -653,7 +629,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
user_language = 'fr'
|
||||
@@ -688,7 +665,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, "Invalid Certificate")
|
||||
@@ -700,7 +678,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
response = self.client.get(test_url)
|
||||
@@ -729,7 +708,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
response = self.client.get(test_url)
|
||||
@@ -747,7 +727,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
self.course.display_coursenumber = "overridden_number"
|
||||
@@ -776,7 +757,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
# make sure response html has only one organization logo container for edX
|
||||
@@ -787,7 +769,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=0)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertNotContains(response, 'Signatory_Name 0')
|
||||
@@ -815,7 +798,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertNotContains(response, '<script>')
|
||||
@@ -825,7 +809,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
def test_render_html_view_disabled_feature_flag_returns_static_url(self):
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
self.assertIn(str(self.cert.download_url), test_url)
|
||||
|
||||
@@ -838,38 +823,19 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, 'invalid')
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_render_html_view_invalid_user(self):
|
||||
self._add_course_certificates(count=1, signatory_count=0)
|
||||
test_url = get_certificate_url(
|
||||
user_id=111,
|
||||
course_id=six.text_type(self.course.id)
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, 'invalid')
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_render_html_view_non_int_user(self):
|
||||
self._add_course_certificates(count=1, signatory_count=0)
|
||||
test_url = get_certificate_url(
|
||||
user_id="Good tests make good neighbors",
|
||||
course_id=six.text_type(self.course.id)
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_render_html_view_invalid_user_certificate(self):
|
||||
self._add_course_certificates(count=1, signatory_count=0)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
self.cert.delete()
|
||||
self.assertListEqual(list(GeneratedCertificate.eligible_certificates.all()), [])
|
||||
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, 'invalid')
|
||||
self.assertEqual(response.status_code, 404)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED, PLATFORM_NAME=u'Űńíćődé Űńívéŕśítӳ')
|
||||
def test_render_html_view_with_unicode_platform_name(self):
|
||||
@@ -877,32 +843,37 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_render_html_view_with_preview_mode(self):
|
||||
def test_user_id_cert_url_not_supported(self):
|
||||
"""
|
||||
test certificate web view should render properly along with its signatories information when accessing it in
|
||||
preview mode. Either the certificate is marked active or not.
|
||||
tests the user id based certificate url is no longer supported
|
||||
"""
|
||||
self.cert.delete()
|
||||
self.assertListEqual(list(GeneratedCertificate.eligible_certificates.all()), [])
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
test_url = reverse(
|
||||
'certificates:unsupported_url', kwargs={'user_id': self.user.id, 'course_id': self.course_id}
|
||||
)
|
||||
response = self.client.get(test_url + '?preview=honor')
|
||||
# accessing certificate web view in preview mode without
|
||||
# staff or instructor access should show invalid certificate
|
||||
self.assertContains(response, 'Cannot Find Certificate')
|
||||
|
||||
CourseStaffRole(self.course.id).add_users(self.user)
|
||||
self.assertContains(response, 'URL Not Supported')
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_render_html_view_with_preview_mode(self):
|
||||
"""
|
||||
test certificate web view should render properly along with its signatories information when accessing it in
|
||||
preview mode only for the staff users. Either the certificate is marked active or not.
|
||||
"""
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
self.user.is_staff = True
|
||||
self.user.save()
|
||||
test_url = reverse('certificates:preview_cert', kwargs={'course_id': self.course_id})
|
||||
response = self.client.get(test_url + '?preview=honor')
|
||||
|
||||
self.assertNotContains(response, self.course.display_name.encode('utf-8'))
|
||||
self.assertContains(response, 'course_title_0')
|
||||
self.assertContains(response, 'Signatory_Title 0')
|
||||
@@ -926,7 +897,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
# user has already has certificate generated for 'honor' mode
|
||||
# so let's try to preview in 'verified' mode.
|
||||
@@ -953,7 +925,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=1, is_active=True)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
if self_paced or self.course.certificate_available_date > today:
|
||||
@@ -977,7 +950,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertContains(response, "Invalid Certificate")
|
||||
@@ -989,7 +963,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url + "?preview=honor")
|
||||
self.assertContains(response, "Invalid Certificate Configuration")
|
||||
@@ -1042,7 +1017,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._create_custom_named_template('test_template_3_course', org_id=2, mode='honor')
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
with patch('lms.djangoapps.certificates.api.get_course_organization_id') as mock_get_org_id:
|
||||
@@ -1082,7 +1058,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._create_custom_named_template('test_template_4_course', org_id=2, mode='honor') # wrong org
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
with patch('lms.djangoapps.certificates.api.get_course_organization_id') as mock_get_org_id:
|
||||
@@ -1105,7 +1082,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._create_custom_named_template('test_template_3_course', org_id=2, mode=None) # wrong org
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
with patch('lms.djangoapps.certificates.api.get_course_organization_id') as mock_get_org_id:
|
||||
@@ -1129,7 +1107,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._create_custom_named_template('test_template_3_course', org_id=2, mode=mode) # wrong org
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
with patch('lms.djangoapps.certificates.api.get_course_organization_id') as mock_get_org_id:
|
||||
@@ -1174,7 +1153,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
#create a org_mode_and_coursekey template language=null
|
||||
self._create_custom_named_template(
|
||||
@@ -1253,7 +1233,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
#create a org and mode template language=null
|
||||
self._create_custom_named_template('test_null_lang_template', org_id=1, mode='honor', language=None)
|
||||
@@ -1310,7 +1291,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
#create a org template language=null
|
||||
self._create_custom_named_template('test_null_lang_template', org_id=1, language=None)
|
||||
@@ -1368,7 +1350,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
#create a mode template language=null
|
||||
self._create_custom_named_template('test_null_lang_template', mode='honor', language=None)
|
||||
@@ -1429,7 +1412,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
#create a mode template language=null
|
||||
self._create_custom_named_template('test_null_lang_template', org_id=1, mode='honor', language=None)
|
||||
@@ -1485,7 +1469,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._create_custom_template_with_hours_of_effort(org_id=1, language=None)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -1510,7 +1495,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
}):
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
with patch.dict("django.conf.settings.SOCIAL_SHARING_SETTINGS", {
|
||||
"CERTIFICATE_TWITTER": True,
|
||||
@@ -1539,7 +1525,8 @@ class CertificatesViewsTests(CommonCertificatesTestCase, CacheIsolationTestCase)
|
||||
self._create_custom_template(mode='honor')
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
|
||||
# render certificate without template asset
|
||||
@@ -1578,7 +1565,8 @@ class CertificateEventTests(CommonCertificatesTestCase, EventTrackingTestCase):
|
||||
self.recreate_tracker()
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=six.text_type(self.course.id)
|
||||
course_id=six.text_type(self.course.id),
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
@@ -1608,7 +1596,8 @@ class CertificateEventTests(CommonCertificatesTestCase, EventTrackingTestCase):
|
||||
|
||||
cert_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=self.course_id
|
||||
course_id=self.course_id,
|
||||
uuid=self.cert.verify_uuid
|
||||
)
|
||||
test_url = '{}?evidence_visit=1'.format(cert_url)
|
||||
self.recreate_tracker()
|
||||
|
||||
@@ -13,8 +13,14 @@ urlpatterns = [
|
||||
# Certificates HTML view end point to render web certs by user and course
|
||||
url(
|
||||
r'^user/(?P<user_id>[^/]*)/course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
|
||||
views.render_html_view,
|
||||
name='html_view'
|
||||
views.unsupported_url,
|
||||
name='unsupported_url'
|
||||
),
|
||||
|
||||
url(
|
||||
r'^course/{course_id}'.format(course_id=settings.COURSE_ID_PATTERN),
|
||||
views.render_preview_certificate,
|
||||
name='preview_cert'
|
||||
),
|
||||
|
||||
# Certificates HTML view end point to render web certs by certificate_uuid
|
||||
|
||||
@@ -8,10 +8,11 @@ import logging
|
||||
from datetime import datetime
|
||||
from uuid import uuid4
|
||||
|
||||
import pytz
|
||||
import six
|
||||
import pytz
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.template import RequestContext
|
||||
from django.utils import translation
|
||||
@@ -444,6 +445,26 @@ def _update_organization_context(context, course):
|
||||
context['organization_logo'] = organization_logo
|
||||
|
||||
|
||||
def unsupported_url(request, user_id, course_id):
|
||||
"""
|
||||
This view returns the un-supported url page aimed to let the user aware that
|
||||
url is no longer supported
|
||||
"""
|
||||
platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME)
|
||||
configuration = CertificateHtmlViewConfiguration.get_config()
|
||||
return _render_invalid_certificate(
|
||||
request, course_id, platform_name, configuration, cert_path='certificates/url_unsupported.html'
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
def render_preview_certificate(request, course_id):
|
||||
"""
|
||||
This view renders the course certificate in preview mode
|
||||
"""
|
||||
return render_html_view(request, six.text_type(course_id))
|
||||
|
||||
|
||||
def render_cert_by_uuid(request, certificate_uuid):
|
||||
"""
|
||||
This public view generates an HTML representation of the specified certificate
|
||||
@@ -453,7 +474,7 @@ def render_cert_by_uuid(request, certificate_uuid):
|
||||
verify_uuid=certificate_uuid,
|
||||
status=CertificateStatuses.downloadable
|
||||
)
|
||||
return render_html_view(request, certificate.user.id, six.text_type(certificate.course_id))
|
||||
return render_html_view(request, six.text_type(certificate.course_id), certificate)
|
||||
except GeneratedCertificate.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
@@ -462,16 +483,13 @@ def render_cert_by_uuid(request, certificate_uuid):
|
||||
template_path="certificates/server-error.html",
|
||||
test_func=lambda request: request.GET.get('preview', None)
|
||||
)
|
||||
def render_html_view(request, user_id, course_id):
|
||||
def render_html_view(request, course_id, certificate=None):
|
||||
"""
|
||||
This public view generates an HTML representation of the specified user and course
|
||||
If a certificate is not available, we display a "Sorry!" screen instead
|
||||
"""
|
||||
try:
|
||||
user_id = int(user_id)
|
||||
except ValueError:
|
||||
raise Http404
|
||||
|
||||
user = certificate.user if certificate else request.user
|
||||
user_id = user.id
|
||||
preview_mode = request.GET.get('preview', None)
|
||||
platform_name = configuration_helpers.get_value("platform_name", settings.PLATFORM_NAME)
|
||||
configuration = CertificateHtmlViewConfiguration.get_config()
|
||||
@@ -483,16 +501,15 @@ def render_html_view(request, user_id, course_id):
|
||||
# Load the course and user objects
|
||||
try:
|
||||
course_key = CourseKey.from_string(course_id)
|
||||
user = User.objects.get(id=user_id)
|
||||
course = get_course_by_id(course_key)
|
||||
|
||||
# For any course or user exceptions, kick the user back to the "Invalid" screen
|
||||
except (InvalidKeyError, User.DoesNotExist, Http404) as exception:
|
||||
except (InvalidKeyError, Http404) as exception:
|
||||
error_str = (
|
||||
u"Invalid cert: error finding course %s or user with id "
|
||||
u"%d. Specific error: %s"
|
||||
u"Invalid cert: error finding course %s "
|
||||
u"Specific error: %s"
|
||||
)
|
||||
log.info(error_str, course_id, user_id, str(exception))
|
||||
log.info(error_str, course_id, str(exception))
|
||||
return _render_invalid_certificate(request, course_id, platform_name, configuration)
|
||||
|
||||
# Kick the user back to the "Invalid" screen if the feature is disabled for the course
|
||||
@@ -654,7 +671,8 @@ def _get_custom_template_and_language(course_id, course_mode, course_language):
|
||||
return (None, None)
|
||||
|
||||
|
||||
def _render_invalid_certificate(request, course_id, platform_name, configuration):
|
||||
def _render_invalid_certificate(request, course_id, platform_name, configuration,
|
||||
cert_path=INVALID_CERTIFICATE_TEMPLATE_PATH):
|
||||
"""
|
||||
Renders the invalid certificate view with default header and footer.
|
||||
"""
|
||||
@@ -663,7 +681,7 @@ def _render_invalid_certificate(request, course_id, platform_name, configuration
|
||||
# Add certificate header/footer data to current context
|
||||
context.update(get_certificate_header_context(is_secure=request.is_secure()))
|
||||
context.update(get_certificate_footer_context())
|
||||
return render_to_response(INVALID_CERTIFICATE_TEMPLATE_PATH, context)
|
||||
return render_to_response(cert_path, context)
|
||||
|
||||
|
||||
def _render_valid_certificate(request, context, custom_template=None):
|
||||
|
||||
@@ -410,10 +410,7 @@ class TestUserEnrollmentCertificates(UrlResetMixin, MobileAPITestCase, Milestone
|
||||
certificate_data = response.data[0]['certificate']
|
||||
self.assertRegex(
|
||||
certificate_data['url'],
|
||||
r'http.*/certificates/user/{user_id}/course/{course_id}'.format(
|
||||
user_id=self.user.id,
|
||||
course_id=self.course.id,
|
||||
)
|
||||
r'http.*/certificates/[0-9a-f]{32}'
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -126,7 +126,10 @@ var edx = edx || {};
|
||||
// Get or create the step container
|
||||
$stepEl = $('#current-step-container');
|
||||
if (!$stepEl.length) {
|
||||
$stepEl = $('<div id="current-step-container"></div>').appendTo(this.el);
|
||||
$stepEl = edx.HtmlUtils.append(
|
||||
$(this.el),
|
||||
edx.HtmlUtils.HTML('<div id="current-step-container"></div>').toString()
|
||||
);
|
||||
}
|
||||
|
||||
// Render the subview
|
||||
|
||||
@@ -83,7 +83,10 @@
|
||||
// Get or create the step container
|
||||
$stepEl = $('#current-step-container');
|
||||
if (!$stepEl.length) {
|
||||
$stepEl = $('<div id="current-step-container"></div>').appendTo(this.el);
|
||||
$stepEl = edx.HtmlUtils.append(
|
||||
$(this.el),
|
||||
edx.HtmlUtils.HTML('<div id="current-step-container"></div>').toString()
|
||||
);
|
||||
}
|
||||
|
||||
// Render the step subview
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
(function(define) {
|
||||
'use strict';
|
||||
define([
|
||||
'gettext', 'jquery', 'underscore', 'backbone', 'js/views/fields',
|
||||
'gettext', 'jquery', 'underscore', 'backbone',
|
||||
'edx-ui-toolkit/js/utils/html-utils', 'js/views/fields',
|
||||
'text!templates/fields/field_image.underscore',
|
||||
'backbone-super', 'jquery.fileupload'
|
||||
], function(gettext, $, _, Backbone, FieldViews, field_image_template) {
|
||||
], function(gettext, $, _, Backbone, HtmlUtils, FieldViews, FieldImageTemplate) {
|
||||
var ImageFieldView = FieldViews.FieldView.extend({
|
||||
|
||||
fieldType: 'image',
|
||||
|
||||
fieldTemplate: field_image_template,
|
||||
fieldTemplate: FieldImageTemplate,
|
||||
uploadButtonSelector: '.upload-button-input',
|
||||
|
||||
titleAdd: gettext('Upload an image'),
|
||||
@@ -44,7 +45,7 @@
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template({
|
||||
var attributes = {
|
||||
id: this.options.valueAttribute,
|
||||
inputName: (this.options.inputName || 'file'),
|
||||
imageUrl: _.result(this, 'imageUrl'),
|
||||
@@ -54,7 +55,8 @@
|
||||
removeButtonIcon: _.result(this, 'iconRemove'),
|
||||
removeButtonTitle: _.result(this, 'removeButtonTitle'),
|
||||
screenReaderTitle: _.result(this, 'screenReaderTitle')
|
||||
}));
|
||||
};
|
||||
this.$el.html(HtmlUtils.HTML(this.template(attributes)).toString());
|
||||
this.delegateEvents();
|
||||
this.updateButtonsVisibility();
|
||||
this.watchForPageUnload();
|
||||
@@ -184,14 +186,14 @@
|
||||
|
||||
showUploadInProgressMessage: function() {
|
||||
this.$('.u-field-upload-button').addClass('in-progress');
|
||||
this.$('.upload-button-icon').html(this.iconProgress);
|
||||
this.$('.upload-button-title').html(this.titleUploading);
|
||||
HtmlUtils.setHtml(this.$('.upload-button-icon'), HtmlUtils.HTML(this.iconProgress));
|
||||
HtmlUtils.setHtml(this.$('.upload-button-title'), HtmlUtils.HTML(this.titleUploading));
|
||||
},
|
||||
|
||||
showRemovalInProgressMessage: function() {
|
||||
this.$('.u-field-remove-button').css('opacity', 1);
|
||||
this.$('.remove-button-icon').html(this.iconProgress);
|
||||
this.$('.remove-button-title').html(this.titleRemoving);
|
||||
HtmlUtils.setHtml(this.$('.remove-button-icon'), HtmlUtils.HTML(this.iconProgress));
|
||||
HtmlUtils.setHtml(this.$('.remove-button-title'), HtmlUtils.HTML(this.titleRemoving));
|
||||
},
|
||||
|
||||
setCurrentStatus: function(status) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.html(this.template({
|
||||
this.$el.html(this.template({ // xss-lint: disable=javascript-jquery-html
|
||||
type: this.model.get('type'),
|
||||
title: this.model.get('title'),
|
||||
message: this.model.get('message'),
|
||||
|
||||
18
lms/templates/certificates/url_unsupported.html
Normal file
18
lms/templates/certificates/url_unsupported.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<%page expression_filter="h"/>
|
||||
<%inherit file="accomplishment-base.html" />
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
|
||||
<div class="wrapper-content status status-invalid">
|
||||
<div class="wrapper-content-grid">
|
||||
<main class="content content-main">
|
||||
<section class="">
|
||||
<h2 class="title">${_("URL Not Supported")}</h2>
|
||||
<div class="copy">
|
||||
<p>${_("This link is no longer valid. But don’t worry—this Verified Certificate is still valid and available to share. If this is your certificate, please visit your dashboard to get a new shareable link. If you're viewing someone else's certificate, please contact them to get an updated link.")}</p>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
<aside role="complementary" class="content-secondary about" aria-label="${_('About {platform_name} Certificates').format(platform_name=platform_name)}">
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,4 +1,9 @@
|
||||
<%! from django.utils.translation import ugettext as _ %>
|
||||
<%page expression_filter="h"/>
|
||||
|
||||
<%!
|
||||
from django.utils.translation import ugettext as _
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
%>
|
||||
|
||||
<%
|
||||
split_test = context.get('split_test')
|
||||
@@ -11,8 +16,8 @@ show_link = group_configuration_url is not None
|
||||
<div class="xblock-message information">
|
||||
<p>
|
||||
<span class="message-text">
|
||||
${_("This content experiment uses group configuration '{group_configuration_name}'.").format(
|
||||
group_configuration_name="<a href='{}'>{}</a>".format(group_configuration_url, user_partition.name) if show_link else user_partition.name
|
||||
${Text(_("This content experiment uses group configuration '{group_configuration_name}'.")).format(
|
||||
group_configuration_name=Text(HTML("<a href='{}'>{}</a>")).format(group_configuration_url, user_partition.name) if show_link else user_partition.name
|
||||
)}
|
||||
</span>
|
||||
</p>
|
||||
@@ -23,13 +28,13 @@ show_link = group_configuration_url is not None
|
||||
% if is_root:
|
||||
<div class="wrapper-groups is-active">
|
||||
<h3 class="sr">${_("Active Groups")}</h3>
|
||||
${active_groups_preview}
|
||||
${HTML(active_groups_preview)}
|
||||
</div>
|
||||
|
||||
% if inactive_groups_preview:
|
||||
<div class="wrapper-groups is-inactive">
|
||||
<h3 class="title">${_("Inactive Groups")}</h3>
|
||||
${inactive_groups_preview}
|
||||
${HTML(inactive_groups_preview)}
|
||||
</div>
|
||||
% endif
|
||||
% endif
|
||||
|
||||
Reference in New Issue
Block a user