Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
ca2b8c27
Commit
ca2b8c27
authored
Dec 22, 2015
by
Matt Drayer
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #10988 from edx/saleem-latif/SOL-1493
SOL-1493: Web Certificates: Platform Branding integration
parents
05b96f8c
3967d809
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
390 additions
and
33 deletions
+390
-33
lms/djangoapps/branding/__init__.py
+0
-25
lms/djangoapps/branding/api.py
+87
-0
lms/djangoapps/certificates/api.py
+39
-1
lms/djangoapps/certificates/tests/test_api.py
+94
-0
lms/djangoapps/certificates/tests/test_views.py
+3
-1
lms/djangoapps/certificates/tests/test_webview_views.py
+151
-1
lms/djangoapps/certificates/views/webview.py
+7
-1
lms/envs/test.py
+5
-0
lms/templates/navigation-edx.html
+2
-2
lms/templates/navigation.html
+2
-2
No files found.
lms/djangoapps/branding/__init__.py
View file @
ca2b8c27
...
...
@@ -64,28 +64,3 @@ def get_university_for_request():
if no university was specified
"""
return
microsite
.
get_value
(
'university'
)
def
get_logo_url
():
"""
Return the url for the branded logo image to be used
"""
# if the MicrositeConfiguration has a value for the logo_image_url
# let's use that
image_url
=
microsite
.
get_value
(
'logo_image_url'
)
if
image_url
:
return
'{static_url}{image_url}'
.
format
(
static_url
=
settings
.
STATIC_URL
,
image_url
=
image_url
)
# otherwise, use the legacy means to configure this
university
=
microsite
.
get_value
(
'university'
)
if
university
is
None
and
settings
.
FEATURES
.
get
(
'IS_EDX_DOMAIN'
,
False
):
return
staticfiles_storage
.
url
(
'images/edx-theme/edx-logo-77x36.png'
)
elif
university
:
return
staticfiles_storage
.
url
(
'images/{uni}-on-edx-logo.png'
.
format
(
uni
=
university
))
else
:
return
staticfiles_storage
.
url
(
'images/logo.png'
)
lms/djangoapps/branding/api.py
View file @
ca2b8c27
...
...
@@ -25,6 +25,7 @@ from branding.models import BrandingApiConfig
log
=
logging
.
getLogger
(
"edx.footer"
)
EMPTY_URL
=
'#'
def
is_enabled
():
...
...
@@ -329,3 +330,89 @@ def _absolute_url_staticfile(is_secure, name):
# For local development, the returned URL will be relative,
# so we need to make it absolute.
return
_absolute_url
(
is_secure
,
url_path
)
def
get_microsite_url
(
name
):
"""
Look up and return the value for given url name in microsite configuration.
URLs are saved in "urls" dictionary inside Microsite Configuration.
Return 'EMPTY_URL' if given url name is not defined in microsite configuration urls.
"""
urls
=
microsite
.
get_value
(
"urls"
,
default
=
{})
return
urls
.
get
(
name
)
or
EMPTY_URL
def
get_url
(
name
):
"""
Lookup and return page url, lookup is performed in the following order
1. get microsite url, If microsite URL override exists, return it
2. Otherwise return the marketing URL.
:return: string containing page url.
"""
# If a microsite URL override exists, return it. Otherwise return the marketing URL.
microsite_url
=
get_microsite_url
(
name
)
if
microsite_url
!=
EMPTY_URL
:
return
microsite_url
# get marketing link, if marketing is disabled then platform url will be used instead.
url
=
marketing_link
(
name
)
return
url
or
EMPTY_URL
def
get_base_url
(
is_secure
):
"""
Return Base URL for site/microsite.
Arguments:
is_secure (bool): If true, use HTTPS as the protocol.
"""
return
_absolute_url
(
is_secure
=
is_secure
,
url_path
=
""
)
def
get_logo_url
():
"""
Return the url for the branded logo image to be used
"""
# if the MicrositeConfiguration has a value for the logo_image_url
# let's use that
image_url
=
microsite
.
get_value
(
'logo_image_url'
)
if
image_url
:
return
'{static_url}{image_url}'
.
format
(
static_url
=
settings
.
STATIC_URL
,
image_url
=
image_url
)
# otherwise, use the legacy means to configure this
university
=
microsite
.
get_value
(
'university'
)
if
university
is
None
and
settings
.
FEATURES
.
get
(
'IS_EDX_DOMAIN'
,
False
):
return
staticfiles_storage
.
url
(
'images/edx-theme/edx-logo-77x36.png'
)
elif
university
:
return
staticfiles_storage
.
url
(
'images/{uni}-on-edx-logo.png'
.
format
(
uni
=
university
))
else
:
return
staticfiles_storage
.
url
(
'images/logo.png'
)
def
get_tos_and_honor_code_url
():
"""
Lookup and return terms of services page url
"""
return
get_url
(
"TOS_AND_HONOR"
)
def
get_privacy_url
():
"""
Lookup and return privacy policies page url
"""
return
get_url
(
"PRIVACY"
)
def
get_about_url
():
"""
Lookup and return About page url
"""
return
get_url
(
"ABOUT"
)
lms/djangoapps/certificates/api.py
View file @
ca2b8c27
...
...
@@ -29,7 +29,7 @@ from certificates.models import (
CertificateTemplateAsset
,
)
from
certificates.queue
import
XQueueCertInterface
from
branding
import
api
as
branding_api
log
=
logging
.
getLogger
(
"edx.certificate"
)
...
...
@@ -491,3 +491,41 @@ def get_asset_url_by_slug(asset_slug):
except
CertificateTemplateAsset
.
DoesNotExist
:
pass
return
asset_url
def
get_certificate_header_context
(
is_secure
=
True
):
"""
Return data to be used in Certificate Header,
data returned should be customized according to the microsite settings
"""
data
=
dict
(
logo_src
=
branding_api
.
get_logo_url
(),
logo_url
=
branding_api
.
get_base_url
(
is_secure
),
)
return
data
def
get_certificate_footer_context
():
"""
Return data to be used in Certificate Footer,
data returned should be customized according to the microsite settings
"""
data
=
dict
()
# get Terms of Service and Honor Code page url
terms_of_service_and_honor_code
=
branding_api
.
get_tos_and_honor_code_url
()
if
terms_of_service_and_honor_code
!=
branding_api
.
EMPTY_URL
:
data
.
update
({
'company_tos_url'
:
terms_of_service_and_honor_code
})
# get Privacy Policy page url
privacy_policy
=
branding_api
.
get_privacy_url
()
if
privacy_policy
!=
branding_api
.
EMPTY_URL
:
data
.
update
({
'company_privacy_url'
:
privacy_policy
})
# get About page url
about
=
branding_api
.
get_about_url
()
if
about
!=
branding_api
.
EMPTY_URL
:
data
.
update
({
'company_about_url'
:
about
})
return
data
lms/djangoapps/certificates/tests/test_api.py
View file @
ca2b8c27
"""Tests for the certificates Python API. """
from
contextlib
import
contextmanager
import
ddt
from
functools
import
wraps
from
django.test
import
TestCase
,
RequestFactory
from
django.test.utils
import
override_settings
...
...
@@ -29,6 +30,8 @@ from certificates.models import (
from
certificates.queue
import
XQueueCertInterface
,
XQueueAddToQueueError
from
certificates.tests.factories
import
GeneratedCertificateFactory
from
microsite_configuration
import
microsite
FEATURES_WITH_CERTS_ENABLED
=
settings
.
FEATURES
.
copy
()
FEATURES_WITH_CERTS_ENABLED
[
'CERTIFICATES_HTML_VIEW'
]
=
True
...
...
@@ -405,3 +408,94 @@ class GenerateExampleCertificatesTest(TestCase):
"""Check the example certificate status. """
actual_status
=
certs_api
.
example_certificates_status
(
self
.
COURSE_KEY
)
self
.
assertEqual
(
list
(
expected_statuses
),
actual_status
)
def
set_microsite
(
domain
):
"""
returns a decorator that can be used on a test_case to set a specific microsite for the current test case.
:param domain: Domain of the new microsite
"""
def
decorator
(
func
):
"""
Decorator to set current microsite according to domain
"""
@wraps
(
func
)
def
inner
(
request
,
*
args
,
**
kwargs
):
"""
Execute the function after setting up the microsite.
"""
microsite
.
set_by_domain
(
domain
)
return
func
(
request
,
*
args
,
**
kwargs
)
return
inner
return
decorator
@override_settings
(
FEATURES
=
FEATURES_WITH_CERTS_ENABLED
)
@attr
(
'shard_1'
)
class
CertificatesBrandingTest
(
TestCase
):
"""Test certificates branding. """
COURSE_KEY
=
CourseLocator
(
org
=
'test'
,
course
=
'test'
,
run
=
'test'
)
def
setUp
(
self
):
super
(
CertificatesBrandingTest
,
self
)
.
setUp
()
@set_microsite
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
'domain_prefix'
])
def
test_certificate_header_data
(
self
):
"""
Test that get_certificate_header_context from certificates api
returns data customized according to site branding.
"""
# Generate certificates for the course
CourseModeFactory
.
create
(
course_id
=
self
.
COURSE_KEY
,
mode_slug
=
CourseMode
.
HONOR
)
data
=
certs_api
.
get_certificate_header_context
(
is_secure
=
True
)
# Make sure there are not unexpected keys in dict returned by 'get_certificate_header_context'
self
.
assertItemsEqual
(
data
.
keys
(),
[
'logo_src'
,
'logo_url'
]
)
self
.
assertIn
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
'logo_image_url'
],
data
[
'logo_src'
]
)
self
.
assertIn
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
'SITE_NAME'
],
data
[
'logo_url'
]
)
@set_microsite
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
'domain_prefix'
])
def
test_certificate_footer_data
(
self
):
"""
Test that get_certificate_footer_context from certificates api returns
data customized according to site branding.
"""
# Generate certificates for the course
CourseModeFactory
.
create
(
course_id
=
self
.
COURSE_KEY
,
mode_slug
=
CourseMode
.
HONOR
)
data
=
certs_api
.
get_certificate_footer_context
()
# Make sure there are not unexpected keys in dict returned by 'get_certificate_footer_context'
self
.
assertItemsEqual
(
data
.
keys
(),
[
'company_about_url'
,
'company_privacy_url'
,
'company_tos_url'
]
)
# ABOUT is present in MICROSITE_CONFIGURATION['test_microsite']["urls"] so web certificate will use that url
self
.
assertIn
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
"urls"
][
'ABOUT'
],
data
[
'company_about_url'
]
)
# PRIVACY is present in MICROSITE_CONFIGURATION['test_microsite']["urls"] so web certificate will use that url
self
.
assertIn
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
"urls"
][
'PRIVACY'
],
data
[
'company_privacy_url'
]
)
# TOS_AND_HONOR is present in MICROSITE_CONFIGURATION['test_microsite']["urls"],
# so web certificate will use that url
self
.
assertIn
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
"urls"
][
'TOS_AND_HONOR'
],
data
[
'company_tos_url'
]
)
lms/djangoapps/certificates/tests/test_views.py
View file @
ca2b8c27
...
...
@@ -305,7 +305,9 @@ class MicrositeCertificatesViewsTests(ModuleStoreTestCase):
self
.
_add_course_certificates
(
count
=
1
,
signatory_count
=
2
)
response
=
self
.
client
.
get
(
test_url
,
HTTP_HOST
=
settings
.
MICROSITE_TEST_HOSTNAME
)
self
.
assertIn
(
'platform_microsite'
,
response
.
content
)
self
.
assertIn
(
'http://www.microsite.org'
,
response
.
content
)
# logo url is taken from microsite configuration setting
self
.
assertIn
(
'http://test_microsite.localhost'
,
response
.
content
)
self
.
assertIn
(
'This is special microsite aware company_about_description content'
,
response
.
content
)
self
.
assertIn
(
'Microsite title'
,
response
.
content
)
...
...
lms/djangoapps/certificates/tests/test_webview_views.py
View file @
ca2b8c27
...
...
@@ -224,6 +224,21 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
"CERTIFICATE_TWITTER"
:
True
,
"CERTIFICATE_FACEBOOK"
:
True
,
})
@patch.dict
(
"django.conf.settings.MICROSITE_CONFIGURATION"
,
{
"test_microsite"
:
dict
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
],
urls
=
dict
(
ABOUT
=
None
,
PRIVACY
=
None
,
TOS_AND_HONOR
=
None
,
),
)
})
@patch.dict
(
"django.conf.settings.MKTG_URL_LINK_MAP"
,
{
'ABOUT'
:
None
,
'PRIVACY'
:
None
,
'TOS_AND_HONOR'
:
None
,
})
def
test_rendering_maximum_data
(
self
):
"""
Tests at least one data item from different context update methods to
...
...
@@ -268,7 +283,7 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
)
# Test an item from html cert configuration
self
.
assertIn
(
'<a class="logo" href="http://
www.edx.org/honor_logo.png
">'
,
'<a class="logo" href="http://
test_microsite.localhost
">'
,
response
.
content
)
# Test an item from course info
...
...
@@ -862,3 +877,138 @@ class CertificatesViewsTests(ModuleStoreTestCase, EventTrackingTestCase):
settings
.
MEDIA_URL
)
)
@override_settings
(
FEATURES
=
FEATURES_WITH_CERTS_ENABLED
)
def
test_certificate_branding
(
self
):
"""
Test that link urls in certificate web view are customized according to site branding and
microsite configuration.
"""
self
.
_add_course_certificates
(
count
=
1
,
signatory_count
=
1
,
is_active
=
True
)
self
.
course
.
save
()
self
.
store
.
update_item
(
self
.
course
,
self
.
user
.
id
)
test_url
=
get_certificate_url
(
user_id
=
self
.
user
.
id
,
course_id
=
unicode
(
self
.
course
.
id
)
)
response
=
self
.
client
.
get
(
test_url
,
HTTP_HOST
=
settings
.
MICROSITE_TEST_HOSTNAME
)
# logo_image_url Tis present in MICROSITE_CONFIGURATION['test_microsite']["urls"],
# so web certificate will use that.
self
.
assertContains
(
response
,
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
'logo_image_url'
],
)
# ABOUT is present in MICROSITE_CONFIGURATION['test_microsite']["urls"] so web certificate will use that url.
self
.
assertContains
(
response
,
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
"urls"
][
'ABOUT'
],
)
# PRIVACY is present in MICROSITE_CONFIGURATION['test_microsite']["urls"] so web certificate will use that url.
self
.
assertContains
(
response
,
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
"urls"
][
'PRIVACY'
],
)
# TOS_AND_HONOR is present in MICROSITE_CONFIGURATION['test_microsite']["urls"],
# so web certificate will use that url.
self
.
assertContains
(
response
,
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
][
"urls"
][
'TOS_AND_HONOR'
],
)
@override_settings
(
FEATURES
=
FEATURES_WITH_CERTS_ENABLED
)
@patch.dict
(
"django.conf.settings.MICROSITE_CONFIGURATION"
,
{
"test_microsite"
:
dict
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
],
urls
=
dict
(
ABOUT
=
None
,
PRIVACY
=
None
,
TOS_AND_HONOR
=
None
,
),
)
})
def
test_certificate_branding_without_microsite_urls
(
self
):
"""
Test that links from MKTG_URL_LINK_MAP setting are used if corresponding microsite urls are not present.
microsite configuration.
"""
self
.
_add_course_certificates
(
count
=
1
,
signatory_count
=
1
,
is_active
=
True
)
self
.
course
.
save
()
self
.
store
.
update_item
(
self
.
course
,
self
.
user
.
id
)
configuration
=
CertificateHtmlViewConfiguration
.
get_config
()
test_url
=
get_certificate_url
(
user_id
=
self
.
user
.
id
,
course_id
=
unicode
(
self
.
course
.
id
)
)
response
=
self
.
client
.
get
(
test_url
,
HTTP_HOST
=
settings
.
MICROSITE_TEST_HOSTNAME
)
# ABOUT is not present in MICROSITE_CONFIGURATION['test_microsite']["urls"],
# so web certificate will use MKTG_URL_LINK_MAP['ABOUT'] url.
self
.
assertContains
(
response
,
settings
.
MKTG_URL_LINK_MAP
[
'ABOUT'
],
)
# PRIVACY is not present in MICROSITE_CONFIGURATION['test_microsite']["urls"],
# so web certificate will use MKTG_URL_LINK_MAP['PRIVACY'] url.
self
.
assertContains
(
response
,
settings
.
MKTG_URL_LINK_MAP
[
'PRIVACY'
],
)
# TOS_AND_HONOR is not present in MICROSITE_CONFIGURATION['test_microsite']["urls"] or MKTG_URL_LINK_MAP,
# so web certificate will use CertificateHtmlViewConfiguration url.
self
.
assertContains
(
response
,
configuration
[
'microsites'
][
'testmicrosite'
][
'company_tos_url'
],
)
@override_settings
(
FEATURES
=
FEATURES_WITH_CERTS_ENABLED
)
@patch.dict
(
"django.conf.settings.MICROSITE_CONFIGURATION"
,
{
"test_microsite"
:
dict
(
settings
.
MICROSITE_CONFIGURATION
[
'test_microsite'
],
urls
=
dict
(
ABOUT
=
None
,
PRIVACY
=
None
,
TOS_AND_HONOR
=
None
,
),
)
})
@patch.dict
(
"django.conf.settings.MKTG_URL_LINK_MAP"
,
{
'ABOUT'
:
None
,
'PRIVACY'
:
None
,
'TOS_AND_HONOR'
:
None
,
})
def
test_certificate_without_branding_urls
(
self
):
"""
Test that links from CertificateHtmlViewConfiguration are used if
corresponding microsite or marketing urls are not present.
"""
self
.
_add_course_certificates
(
count
=
1
,
signatory_count
=
1
,
is_active
=
True
)
self
.
course
.
save
()
self
.
store
.
update_item
(
self
.
course
,
self
.
user
.
id
)
configuration
=
CertificateHtmlViewConfiguration
.
get_config
()
test_url
=
get_certificate_url
(
user_id
=
self
.
user
.
id
,
course_id
=
unicode
(
self
.
course
.
id
)
)
response
=
self
.
client
.
get
(
test_url
,
HTTP_HOST
=
settings
.
MICROSITE_TEST_HOSTNAME
)
# ABOUT is not present in MICROSITE_CONFIGURATION['test_microsite']["urls"] or MKTG_URL_LINK_MAP,
# so web certificate will use CertificateHtmlViewConfiguration url.
self
.
assertContains
(
response
,
configuration
[
'microsites'
][
'testmicrosite'
][
'company_about_url'
],
)
# PRIVACY is not present in MICROSITE_CONFIGURATION['test_microsite']["urls"] or MKTG_URL_LINK_MAP,
# so web certificate will use CertificateHtmlViewConfiguration url.
self
.
assertContains
(
response
,
configuration
[
'microsites'
][
'testmicrosite'
][
'company_privacy_url'
],
)
# TOS_AND_HONOR is not present in MICROSITE_CONFIGURATION['test_microsite']["urls"] or MKTG_URL_LINK_MAP,
# so web certificate will use CertificateHtmlViewConfiguration url.
self
.
assertContains
(
response
,
configuration
[
'microsites'
][
'testmicrosite'
][
'company_tos_url'
],
)
lms/djangoapps/certificates/views/webview.py
View file @
ca2b8c27
...
...
@@ -34,7 +34,9 @@ from certificates.api import (
get_certificate_url
,
emit_certificate_event
,
has_html_certificates_enabled
,
get_certificate_template
get_certificate_template
,
get_certificate_header_context
,
get_certificate_footer_context
,
)
from
certificates.models
import
(
GeneratedCertificate
,
...
...
@@ -540,6 +542,10 @@ def render_html_view(request, user_id, course_id):
# Append microsite overrides
_update_microsite_context
(
context
,
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
())
# Append/Override the existing view context values with any course-specific static values from Advanced Settings
context
.
update
(
course
.
cert_html_view_overrides
)
...
...
lms/envs/test.py
View file @
ca2b8c27
...
...
@@ -446,6 +446,11 @@ MICROSITE_CONFIGURATION = {
"ENABLE_SHOPPING_CART"
:
True
,
"ENABLE_PAID_COURSE_REGISTRATION"
:
True
,
"SESSION_COOKIE_DOMAIN"
:
"test_microsite.localhost"
,
"urls"
:
{
'ABOUT'
:
'testmicrosite/about'
,
'PRIVACY'
:
'testmicrosite/privacy'
,
'TOS_AND_HONOR'
:
'testmicrosite/tos-and-honor'
,
},
},
"microsite_with_logistration"
:
{
"domain_prefix"
:
"logistration"
,
...
...
lms/templates/navigation-edx.html
View file @
ca2b8c27
...
...
@@ -9,7 +9,7 @@ from microsite_configuration import microsite
from
microsite_configuration
.
templatetags
.
microsite
import
platform_name
#
App
that
handles
subdomain
specific
branding
import
branding
from
branding
import
api
as
branding_api
#
app
that
handles
site
status
messages
from
status
.
status
import
get_site_status_msg
%
>
...
...
@@ -41,7 +41,7 @@ site_status_msg = get_site_status_msg(course_id)
<h1
class=
"logo"
itemscope=
""
itemtype=
"http://schema.org/Organization"
>
<a
href=
"${marketing_link('ROOT')}"
itemprop=
"url"
>
<
%
block
name=
"navigation_logo"
>
<img
src=
"${static.url(branding.get_logo_url())}"
alt=
"${_("
{
platform_name
}
Home
Page
").
format
(
platform_name=
platform_name())}"
itemprop=
"logo"
/>
<img
src=
"${static.url(branding
_api
.get_logo_url())}"
alt=
"${_("
{
platform_name
}
Home
Page
").
format
(
platform_name=
platform_name())}"
itemprop=
"logo"
/>
</
%
block>
</a>
</h1>
...
...
lms/templates/navigation.html
View file @
ca2b8c27
...
...
@@ -10,7 +10,7 @@ from microsite_configuration.templatetags.microsite import platform_name
from
lms
.
djangoapps
.
ccx
.
overrides
import
get_current_ccx
#
App
that
handles
subdomain
specific
branding
import
branding
from
branding
import
api
as
branding_api
#
app
that
handles
site
status
messages
from
status
.
status
import
get_site_status_msg
%
>
...
...
@@ -42,7 +42,7 @@ site_status_msg = get_site_status_msg(course_id)
<h1
class=
"logo"
>
<a
href=
"${marketing_link('ROOT')}"
>
<
%
block
name=
"navigation_logo"
>
<img
src=
"${static.url(branding.get_logo_url())}"
alt=
"${_("
{
platform_name
}
Home
Page
").
format
(
platform_name=
platform_name())}"/
>
<img
src=
"${static.url(branding
_api
.get_logo_url())}"
alt=
"${_("
{
platform_name
}
Home
Page
").
format
(
platform_name=
platform_name())}"/
>
</
%
block>
</a>
</h1>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment