mattdrayer/SOL-981: Integrate edx-organizations application
* asadiqbal08/SOL-1058: Add edx-organizations to certificate web view * Support organization logo asset management * Remove organization fields from Studio certificate configuration model * SOL-981 pull request feedback fixes
This commit is contained in:
@@ -1033,7 +1033,6 @@ class CourseMetadataEditingTest(CourseTestCase):
|
||||
'id': 1,
|
||||
'name': 'Certificate Config Name',
|
||||
'course_title': 'Title override',
|
||||
'org_logo_path': '/c4x/test/CSS101/asset/org_logo.png',
|
||||
'signatories': [],
|
||||
'is_active': True
|
||||
}
|
||||
|
||||
@@ -177,8 +177,6 @@ class CertificateManager(object):
|
||||
"name": certificate_data['name'],
|
||||
"description": certificate_data['description'],
|
||||
"version": CERTIFICATE_SCHEMA_VERSION,
|
||||
"org_logo_path": certificate_data.get('org_logo_path', ''),
|
||||
"is_active": certificate_data.get('is_active', False),
|
||||
"signatories": certificate_data['signatories']
|
||||
}
|
||||
|
||||
@@ -231,7 +229,6 @@ class CertificateManager(object):
|
||||
if int(cert['id']) == int(certificate_id):
|
||||
certificate = course.certificates['certificates'][index]
|
||||
# Remove any signatory assets prior to dropping the entire cert record from the course
|
||||
_delete_asset(course.id, certificate['org_logo_path'])
|
||||
for sig_index, signatory in enumerate(certificate.get('signatories')): # pylint: disable=unused-variable
|
||||
_delete_asset(course.id, signatory['signature_image_path'])
|
||||
# Now drop the certificate record
|
||||
|
||||
@@ -93,13 +93,11 @@ class HelperMethods(object):
|
||||
'id': i,
|
||||
'name': 'Name ' + str(i),
|
||||
'description': 'Description ' + str(i),
|
||||
'org_logo_path': '/c4x/test/CSS101/asset/org_logo{}.png'.format(i),
|
||||
'signatories': signatories,
|
||||
'version': CERTIFICATE_SCHEMA_VERSION,
|
||||
'is_active': is_active
|
||||
} for i in xrange(0, count)
|
||||
]
|
||||
self._create_fake_images([certificate['org_logo_path'] for certificate in certificates])
|
||||
self.course.certificates = {'certificates': certificates}
|
||||
self.save_course()
|
||||
|
||||
@@ -219,8 +217,6 @@ class CertificatesListHandlerTestCase(EventTestMixin, CourseTestCase, Certificat
|
||||
u'version': CERTIFICATE_SCHEMA_VERSION,
|
||||
u'name': u'Test certificate',
|
||||
u'description': u'Test description',
|
||||
u'org_logo_path': '',
|
||||
u'is_active': False,
|
||||
u'signatories': []
|
||||
}
|
||||
response = self.client.ajax_post(
|
||||
@@ -388,8 +384,6 @@ class CertificatesDetailHandlerTestCase(EventTestMixin, CourseTestCase, Certific
|
||||
u'name': u'Test certificate',
|
||||
u'description': u'Test description',
|
||||
u'course_title': u'Course Title Override',
|
||||
u'org_logo_path': '',
|
||||
u'is_active': False,
|
||||
u'signatories': []
|
||||
}
|
||||
|
||||
@@ -420,8 +414,6 @@ class CertificatesDetailHandlerTestCase(EventTestMixin, CourseTestCase, Certific
|
||||
u'name': u'New test certificate',
|
||||
u'description': u'New test description',
|
||||
u'course_title': u'Course Title Override',
|
||||
u'org_logo_path': '',
|
||||
u'is_active': False,
|
||||
u'signatories': []
|
||||
|
||||
}
|
||||
@@ -453,11 +445,6 @@ class CertificatesDetailHandlerTestCase(EventTestMixin, CourseTestCase, Certific
|
||||
Delete certificate
|
||||
"""
|
||||
self._add_course_certificates(count=2, signatory_count=1)
|
||||
certificates = self.course.certificates['certificates']
|
||||
org_logo_url = certificates[1]['org_logo_path']
|
||||
image_asset_location = AssetLocation.from_deprecated_string(org_logo_url)
|
||||
content = contentstore().find(image_asset_location)
|
||||
self.assertIsNotNone(content)
|
||||
response = self.client.delete(
|
||||
self._url(cid=1),
|
||||
content_type="application/json",
|
||||
@@ -474,8 +461,6 @@ class CertificatesDetailHandlerTestCase(EventTestMixin, CourseTestCase, Certific
|
||||
# Verify that certificates are properly updated in the course.
|
||||
certificates = self.course.certificates['certificates']
|
||||
self.assertEqual(len(certificates), 1)
|
||||
# make sure certificate org logo is deleted too
|
||||
self.assertRaises(NotFoundError, contentstore().find, image_asset_location)
|
||||
self.assertEqual(certificates[0].get('name'), 'Name 0')
|
||||
self.assertEqual(certificates[0].get('description'), 'Description 0')
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ function (_, str, Backbone, BackboneRelational, BackboneAssociations, gettext, C
|
||||
defaults: {
|
||||
// Metadata fields currently displayed in web forms
|
||||
course_title: '',
|
||||
org_logo_path: '',
|
||||
|
||||
// Metadata fields not currently displayed in web forms
|
||||
name: 'Name of the certificate',
|
||||
|
||||
@@ -41,7 +41,6 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
|
||||
uploadDialog: 'form.upload-dialog',
|
||||
uploadDialogButton: '.action-upload',
|
||||
uploadDialogFileInput: 'form.upload-dialog input[type=file]',
|
||||
uploadOrgLogoButton: '.action-upload-org-logo',
|
||||
saveCertificateButton: 'button.action-primary'
|
||||
};
|
||||
|
||||
@@ -311,9 +310,6 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
|
||||
setValuesToInputs(this.view, {
|
||||
inputCertificateDescription: 'New Test Description'
|
||||
});
|
||||
this.view.$(SELECTORS.uploadOrgLogoButton).click();
|
||||
var org_logo_path = '/c4x/edX/DemoX/asset/org-logo.png';
|
||||
uploadFile(org_logo_path, requests);
|
||||
|
||||
setValuesToInputs(this.view, {
|
||||
inputSignatoryName: 'New Signatory Name'
|
||||
@@ -334,8 +330,7 @@ function(_, Course, CertificateModel, SignatoryModel, CertificatesCollection, Ce
|
||||
ViewHelpers.submitAndVerifyFormSuccess(this.view, requests, notificationSpy);
|
||||
expect(this.model).toBeCorrectValuesInModel({
|
||||
name: 'New Test Name',
|
||||
description: 'New Test Description',
|
||||
org_logo_path: org_logo_path
|
||||
description: 'New Test Description'
|
||||
});
|
||||
|
||||
// get the first signatory from the signatories collection.
|
||||
|
||||
@@ -7,12 +7,10 @@ define([ // jshint ignore:line
|
||||
'gettext',
|
||||
'js/views/list_item_editor',
|
||||
'js/certificates/models/signatory',
|
||||
'js/certificates/views/signatory_editor',
|
||||
'js/models/uploads',
|
||||
'js/views/uploads'
|
||||
'js/certificates/views/signatory_editor'
|
||||
],
|
||||
function($, _, Backbone, gettext,
|
||||
ListItemEditorView, SignatoryModel, SignatoryEditorView, FileUploadModel, FileUploadDialog) {
|
||||
ListItemEditorView, SignatoryModel, SignatoryEditorView) {
|
||||
'use strict';
|
||||
var MAX_SIGNATORIES_LIMIT = 4;
|
||||
var CertificateEditorView = ListItemEditorView.extend({
|
||||
@@ -21,13 +19,11 @@ function($, _, Backbone, gettext,
|
||||
'change .collection-name-input': 'setName',
|
||||
'change .certificate-description-input': 'setDescription',
|
||||
'change .certificate-course-title-input': 'setCourseTitle',
|
||||
'change .org-logo-input': 'setOrgLogoPath',
|
||||
'focus .input-text': 'onFocus',
|
||||
'blur .input-text': 'onBlur',
|
||||
'submit': 'setAndClose',
|
||||
'click .action-cancel': 'cancel',
|
||||
'click .action-add-signatory': 'addSignatory',
|
||||
'click .action-upload-org-logo': 'uploadLogoImage'
|
||||
'click .action-add-signatory': 'addSignatory'
|
||||
},
|
||||
|
||||
className: function () {
|
||||
@@ -141,45 +137,12 @@ function($, _, Backbone, gettext,
|
||||
);
|
||||
},
|
||||
|
||||
setOrgLogoPath: function(event) {
|
||||
// Updates the indicated model field (still requires persistence on server)
|
||||
if (event && event.preventDefault) { event.preventDefault(); }
|
||||
var org_logo_path = this.$('.org-logo-input').val();
|
||||
this.model.set(
|
||||
'org_logo_path', org_logo_path,
|
||||
{ silent: true }
|
||||
);
|
||||
this.$('.current-org-logo img.org-logo').attr('src', org_logo_path);
|
||||
},
|
||||
|
||||
setValues: function() {
|
||||
// Update the specified values in the local model instance
|
||||
this.setName();
|
||||
this.setDescription();
|
||||
this.setCourseTitle();
|
||||
this.setOrgLogoPath();
|
||||
return this;
|
||||
},
|
||||
|
||||
uploadLogoImage: function(event) {
|
||||
event.preventDefault();
|
||||
var upload = new FileUploadModel({
|
||||
title: gettext("Upload organization logo."),
|
||||
message: gettext("Maximum logo height should be 125px."),
|
||||
mimeTypes: ['image/png', 'image/jpeg']
|
||||
});
|
||||
var self = this;
|
||||
var modal = new FileUploadDialog({
|
||||
model: upload,
|
||||
onSuccess: function(response) {
|
||||
var org_logo_path = response.asset.url;
|
||||
self.model.set('org_logo_path', org_logo_path);
|
||||
self.$('.current-org-logo img.org-logo').attr('src', org_logo_path);
|
||||
self.$('.current-org-logo').show();
|
||||
self.$('input.org-logo-input').attr('value', org_logo_path);
|
||||
}
|
||||
});
|
||||
modal.show();
|
||||
}
|
||||
});
|
||||
return CertificateEditorView;
|
||||
|
||||
@@ -313,49 +313,6 @@
|
||||
border-color: $red;
|
||||
}
|
||||
}
|
||||
.org-logo-upload-wrapper {
|
||||
@include clearfix();
|
||||
width: flex-grid(12,12);
|
||||
|
||||
.org-logo-upload-input-wrapper {
|
||||
float: left;
|
||||
width: flex-grid(7,12);
|
||||
margin-right: flex-gutter();
|
||||
}
|
||||
|
||||
.action-upload-org-logo {
|
||||
@extend %ui-btn-flat-outline;
|
||||
float: right;
|
||||
width: flex-grid(4,12);
|
||||
margin-top: ($baseline/4);
|
||||
padding: ($baseline/2) $baseline;
|
||||
}
|
||||
}
|
||||
|
||||
.current-org-logo {
|
||||
margin-bottom: ($baseline/2);
|
||||
padding: ($baseline/2) $baseline;
|
||||
background: $gray-l5;
|
||||
text-align: center;
|
||||
|
||||
.wrapper-org-logo {
|
||||
display: block;
|
||||
width: 375px;
|
||||
height: 200px;
|
||||
overflow: hidden;
|
||||
margin: 0 auto;
|
||||
border: 1px solid $gray-l4;
|
||||
box-shadow: 0 1px 1px $shadow-l1;
|
||||
padding: ($baseline/2);
|
||||
background: $white;
|
||||
}
|
||||
|
||||
.org-logo {
|
||||
display: block;
|
||||
width: 100%;
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label.required {
|
||||
|
||||
@@ -24,17 +24,6 @@
|
||||
<input id="certificate-course-title-<%= uniqueId %>" class="certificate-course-title-input input-text" name="certificate-course-title" type="text" placeholder="<%= gettext("Course title") %>" value="<%= course_title %>" aria-describedby="certificate-course-title-<%=uniqueId %>-tip" />
|
||||
<span id="certificate-course-title-<%= uniqueId %>-tip" class="tip tip-stacked"><%= gettext("Specify an alternative to the official course title to display on certificates. Leave blank to use the official course title.") %></span>
|
||||
</div>
|
||||
<div class="input-wrap field text add-org-logo">
|
||||
<label for="certificate-org-logo-<%= uniqueId %>"><%= gettext("Organization Logo") %></label>
|
||||
<div class="current-org-logo" <% if (org_logo_path == "") { print('style="display:none"'); } %>><span class="wrapper-org-logo"><img class="org-logo" src="<%= org_logo_path %>" alt="Organization Logo"></span></div>
|
||||
<div class="org-logo-upload-wrapper">
|
||||
<div class="org-logo-upload-input-wrapper">
|
||||
<input id="certificate-org-logo-<%= uniqueId %>" class="collection-name-input input-text org-logo-input" name="org-logo-path" type="text" placeholder="<%= gettext("Path to organization logo") %>" value="<%= org_logo_path %>" aria-describedby="certificate-org-logo-<%=uniqueId %>-tip" readonly />
|
||||
<span id="certificate-org-logo-<%=uniqueId %>-tip" class="tip tip-stacked"><%= gettext("Maximum logo height 125px, width variable") %></span>
|
||||
</div>
|
||||
<button type="button" class="action action-upload-org-logo">Upload Organization Logo</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<header>
|
||||
<span class="title"><%= gettext("Certificate Signatories") %></legend>
|
||||
|
||||
66
common/djangoapps/util/organizations_helpers.py
Normal file
66
common/djangoapps/util/organizations_helpers.py
Normal file
@@ -0,0 +1,66 @@
|
||||
# pylint: disable=invalid-name
|
||||
"""
|
||||
Utility library for working with the edx-organizations app
|
||||
"""
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def add_organization(organization_data):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('ORGANIZATIONS_APP', False):
|
||||
return None
|
||||
from organizations import api as organizations_api
|
||||
return organizations_api.add_organization(organization_data=organization_data)
|
||||
|
||||
|
||||
def add_organization_course(organization_data, course_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('ORGANIZATIONS_APP', False):
|
||||
return None
|
||||
from organizations import api as organizations_api
|
||||
return organizations_api.add_organization_course(organization_data=organization_data, course_key=course_id)
|
||||
|
||||
|
||||
def get_organization(organization_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('ORGANIZATIONS_APP', False):
|
||||
return []
|
||||
from organizations import api as organizations_api
|
||||
return organizations_api.get_organization(organization_id)
|
||||
|
||||
|
||||
def get_organizations():
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('ORGANIZATIONS_APP', False):
|
||||
return []
|
||||
from organizations import api as organizations_api
|
||||
return organizations_api.get_organizations()
|
||||
|
||||
|
||||
def get_organization_courses(organization_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('ORGANIZATIONS_APP', False):
|
||||
return []
|
||||
from organizations import api as organizations_api
|
||||
return organizations_api.get_organization_courses(organization_id)
|
||||
|
||||
|
||||
def get_course_organizations(course_id):
|
||||
"""
|
||||
Client API operation adapter/wrapper
|
||||
"""
|
||||
if not settings.FEATURES.get('ORGANIZATIONS_APP', False):
|
||||
return []
|
||||
from organizations import api as organizations_api
|
||||
return organizations_api.get_course_organizations(course_id)
|
||||
51
common/djangoapps/util/tests/test_organizations_helpers.py
Normal file
51
common/djangoapps/util/tests/test_organizations_helpers.py
Normal file
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
Tests for the organizations helpers library, which is the integration point for the edx-organizations API
|
||||
"""
|
||||
from mock import patch
|
||||
|
||||
from util import organizations_helpers
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory
|
||||
|
||||
|
||||
@patch.dict('django.conf.settings.FEATURES', {'ORGANIZATIONS_APP': False})
|
||||
class OrganizationsHelpersTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Main test suite for Organizations API client library
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Test case scaffolding
|
||||
"""
|
||||
super(OrganizationsHelpersTestCase, self).setUp(create_user=False)
|
||||
self.course = CourseFactory.create()
|
||||
|
||||
self.organization = {
|
||||
'name': 'Test Organization',
|
||||
'description': 'Testing Organization Helpers Library',
|
||||
}
|
||||
|
||||
def test_get_organization_returns_none_when_app_disabled(self):
|
||||
response = organizations_helpers.get_organization(1)
|
||||
self.assertEqual(len(response), 0)
|
||||
|
||||
def test_get_organizations_returns_none_when_app_disabled(self):
|
||||
response = organizations_helpers.get_organizations()
|
||||
self.assertEqual(len(response), 0)
|
||||
|
||||
def test_get_organization_courses_returns_none_when_app_disabled(self):
|
||||
response = organizations_helpers.get_organization_courses(1)
|
||||
self.assertEqual(len(response), 0)
|
||||
|
||||
def test_get_course_organizations_returns_none_when_app_disabled(self):
|
||||
response = organizations_helpers.get_course_organizations(unicode(self.course.id))
|
||||
self.assertEqual(len(response), 0)
|
||||
|
||||
def test_add_organization_returns_none_when_app_disabled(self):
|
||||
response = organizations_helpers.add_organization(organization_data=self.organization)
|
||||
self.assertIsNone(response)
|
||||
|
||||
def test_add_organization_course_returns_none_when_app_disabled(self):
|
||||
response = organizations_helpers.add_organization_course(self.organization, self.course.id)
|
||||
self.assertIsNone(response)
|
||||
@@ -215,7 +215,6 @@ class GenerateUserCertificatesTest(EventTestMixin, ModuleStoreTestCase):
|
||||
'name': 'Test Certificate Name',
|
||||
'description': 'Test Certificate Description',
|
||||
'course_title': 'tes_course_title',
|
||||
'org_logo_path': '/t4x/orgX/testX/asset/org-logo.png',
|
||||
'signatories': [],
|
||||
'version': 1,
|
||||
'is_active': True
|
||||
|
||||
@@ -37,6 +37,7 @@ from certificates.tests.factories import (
|
||||
BadgeAssertionFactory,
|
||||
)
|
||||
from lms import urls
|
||||
from util import organizations_helpers as organizations_api
|
||||
|
||||
FEATURES_WITH_CERTS_ENABLED = settings.FEATURES.copy()
|
||||
FEATURES_WITH_CERTS_ENABLED['CERTIFICATES_HTML_VIEW'] = True
|
||||
@@ -259,7 +260,6 @@ class MicrositeCertificatesViewsTests(ModuleStoreTestCase):
|
||||
'name': 'Name ' + str(i),
|
||||
'description': 'Description ' + str(i),
|
||||
'course_title': 'course_title_' + str(i),
|
||||
'org_logo_path': '/t4x/orgX/testX/asset/org-logo-{}.png'.format(i),
|
||||
'signatories': signatories,
|
||||
'version': 1,
|
||||
'is_active': is_active
|
||||
@@ -427,6 +427,39 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
|
||||
self.course.save()
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_rendering_course_organization_data(self):
|
||||
"""
|
||||
Test: organization data should render on certificate web view if course has organization.
|
||||
"""
|
||||
test_organization_data = {
|
||||
'name': 'test_organization',
|
||||
'description': 'Test Organization Description',
|
||||
'active': True,
|
||||
'logo': '/logo_test1.png/'
|
||||
}
|
||||
test_org = organizations_api.add_organization(organization_data=test_organization_data)
|
||||
organizations_api.add_organization_course(organization_data=test_org, course_id=unicode(self.course.id))
|
||||
self._add_course_certificates(count=1, signatory_count=1, is_active=True)
|
||||
test_url = get_certificate_url(
|
||||
user_id=self.user.id,
|
||||
course_id=unicode(self.course.id)
|
||||
)
|
||||
response = self.client.get(test_url)
|
||||
self.assertIn(
|
||||
'a course of study offered by test_organization',
|
||||
response.content
|
||||
)
|
||||
self.assertNotIn(
|
||||
'a course of study offered by testorg',
|
||||
response.content
|
||||
)
|
||||
self.assertIn(
|
||||
'<title>test_organization {} Certificate |'.format(self.course.number, ),
|
||||
response.content
|
||||
)
|
||||
self.assertIn('logo_test1.png', response.content)
|
||||
|
||||
@override_settings(FEATURES=FEATURES_WITH_CERTS_ENABLED)
|
||||
def test_render_html_view_valid_certificate(self):
|
||||
test_url = get_certificate_url(
|
||||
@@ -458,7 +491,6 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
|
||||
self._add_course_certificates(count=1, signatory_count=2)
|
||||
response = self.client.get(test_url)
|
||||
self.assertIn('course_title_0', response.content)
|
||||
self.assertIn('/t4x/orgX/testX/asset/org-logo-0.png', response.content)
|
||||
self.assertIn('Signatory_Name 0', response.content)
|
||||
self.assertIn('Signatory_Title 0', response.content)
|
||||
self.assertIn('Signatory_Organization 0', response.content)
|
||||
|
||||
@@ -43,6 +43,7 @@ from student.models import LinkedInAddToProfileConfiguration
|
||||
from util.json_request import JsonResponse, JsonResponseBadRequest
|
||||
from util.bad_request_rate_limiter import BadRequestRateLimiter
|
||||
from courseware.courses import course_image_url
|
||||
from util import organizations_helpers as organization_api
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -299,13 +300,20 @@ def _update_certificate_context(context, course, user, user_certificate):
|
||||
user_fullname = user.profile.name
|
||||
platform_name = microsite.get_value("platform_name", settings.PLATFORM_NAME)
|
||||
certificate_type = context.get('certificate_type')
|
||||
partner_name = course.org
|
||||
organizations = organization_api.get_course_organizations(course_id=course.id)
|
||||
if organizations:
|
||||
#TODO Need to add support for multiple organizations, Currently we are interested in the first one.
|
||||
organization = organizations[0]
|
||||
partner_name = organization.get('name', course.org)
|
||||
context['organization_logo'] = organization.get('logo', None)
|
||||
|
||||
context['username'] = user.username
|
||||
context['course_mode'] = user_certificate.mode
|
||||
context['accomplishment_user_id'] = user.id
|
||||
context['accomplishment_copy_name'] = user_fullname
|
||||
context['accomplishment_copy_username'] = user.username
|
||||
context['accomplishment_copy_course_org'] = course.org
|
||||
context['accomplishment_copy_course_org'] = partner_name
|
||||
context['accomplishment_copy_course_name'] = course.display_name
|
||||
context['course_image_url'] = course_image_url(course)
|
||||
context['share_settings'] = settings.FEATURES.get('SOCIAL_SHARING_SETTINGS', {})
|
||||
@@ -330,14 +338,10 @@ def _update_certificate_context(context, course, user, user_certificate):
|
||||
year=user_certificate.modified_date.year
|
||||
)
|
||||
|
||||
accd_course_org_html = '<span class="detail--xuniversity">{partner_name}</span>'.format(partner_name=course.org)
|
||||
accd_platform_name_html = '<span class="detail--company">{platform_name}</span>'.format(platform_name=platform_name)
|
||||
# Translators: This line appears on the certificate after the name of a course, and provides more
|
||||
# information about the organizations providing the course material to platform users
|
||||
context['accomplishment_copy_course_description'] = _('a course of study offered by {partner_name}, '
|
||||
'through {platform_name}.').format(
|
||||
partner_name=accd_course_org_html,
|
||||
platform_name=accd_platform_name_html
|
||||
partner_name=partner_name,
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
# Translators: Accomplishments describe the awards/certifications obtained by students on this platform
|
||||
@@ -412,13 +416,13 @@ def _update_certificate_context(context, course, user, user_certificate):
|
||||
'who participated in {partner_name} {course_number}').format(
|
||||
platform_name=platform_name,
|
||||
user_name=user_fullname,
|
||||
partner_name=course.org,
|
||||
partner_name=partner_name,
|
||||
course_number=course.number
|
||||
)
|
||||
|
||||
# Translators: This text is bound to the HTML 'title' element of the page and appears in the browser title bar
|
||||
context['document_title'] = _("{partner_name} {course_number} Certificate | {platform_name}").format(
|
||||
partner_name=course.org,
|
||||
partner_name=partner_name,
|
||||
course_number=course.number,
|
||||
platform_name=platform_name
|
||||
)
|
||||
|
||||
@@ -897,7 +897,6 @@ class ProgressPageTests(ModuleStoreTestCase):
|
||||
'name': 'Name 1',
|
||||
'description': 'Description 1',
|
||||
'course_title': 'course_title_1',
|
||||
'org_logo_path': '/t4x/orgX/testX/asset/org-logo-1.png',
|
||||
'signatories': [],
|
||||
'version': 1,
|
||||
'is_active': True
|
||||
|
||||
@@ -346,6 +346,9 @@ FEATURES = {
|
||||
# Milestones application flag
|
||||
'MILESTONES_APP': False,
|
||||
|
||||
# Organizations application flag
|
||||
'ORGANIZATIONS_APP': False,
|
||||
|
||||
# Prerequisite courses feature flag
|
||||
'ENABLE_PREREQUISITE_COURSES': False,
|
||||
|
||||
@@ -2402,6 +2405,9 @@ OPTIONAL_APPS = (
|
||||
|
||||
# edX Proctoring
|
||||
'edx_proctoring',
|
||||
|
||||
# Organizations App (http://github.com/edx/edx-organizations)
|
||||
'organizations',
|
||||
)
|
||||
|
||||
for app_name in OPTIONAL_APPS:
|
||||
|
||||
@@ -121,6 +121,8 @@ PASSWORD_COMPLEXITY = {}
|
||||
########################### Milestones #################################
|
||||
FEATURES['MILESTONES_APP'] = True
|
||||
|
||||
########################### Milestones #################################
|
||||
FEATURES['ORGANIZATIONS_APP'] = True
|
||||
|
||||
########################### Entrance Exams #################################
|
||||
FEATURES['ENTRANCE_EXAMS'] = True
|
||||
|
||||
@@ -520,3 +520,6 @@ PROFILE_IMAGE_MIN_BYTES = 100
|
||||
FEATURES['ENABLE_LTI_PROVIDER'] = True
|
||||
INSTALLED_APPS += ('lti_provider',)
|
||||
AUTHENTICATION_BACKENDS += ('lti_provider.users.LtiBackend',)
|
||||
|
||||
# ORGANIZATIONS
|
||||
FEATURES['ORGANIZATIONS_APP'] = True
|
||||
|
||||
@@ -75,10 +75,10 @@ course_mode_class = course_mode if course_mode else ''
|
||||
</div>
|
||||
</li>
|
||||
|
||||
% if certificate_data and certificate_data.get('org_logo_path', ''):
|
||||
% if organization_logo:
|
||||
<li class="wrapper-organization">
|
||||
<div class="organization">
|
||||
<img class="organization-logo" src="${static.url(certificate_data['org_logo_path'])}" alt="${platform_name}">
|
||||
<img class="organization-logo" src="${organization_logo.url}" alt="${platform_name}">
|
||||
</div>
|
||||
</li>
|
||||
% endif
|
||||
|
||||
@@ -57,6 +57,7 @@ git+https://github.com/edx/edx-lint.git@ed8c8d2a0267d4d42f43642d193e25f8bd575d9b
|
||||
git+https://github.com/edx/ecommerce-api-client.git@1.1.0#egg=ecommerce-api-client==1.1.0
|
||||
-e git+https://github.com/edx/edx-user-state-client.git@30c0ad4b9f57f8d48d6943eb585ec8a9205f4469#egg=edx-user-state-client
|
||||
-e git+https://github.com/edx/edx-proctoring.git@release-2015-07-29#egg=edx-proctoring
|
||||
-e git+https://github.com/edx/edx-organizations.git@release-2015-08-03#egg=edx-organizations
|
||||
|
||||
# Third Party XBlocks
|
||||
-e git+https://github.com/mitodl/edx-sga@172a90fd2738f8142c10478356b2d9ed3e55334a#egg=edx-sga
|
||||
|
||||
Reference in New Issue
Block a user