Skip to content
1 change: 1 addition & 0 deletions taccsite_cms/_settings/djangocms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
]
DJANGOCMS_PICTURE_TEMPLATES = [
('no_link_to_ext_image', _('Do not link to external image')),
('header_logo', _('Header logo')),
]

########################
Expand Down
31 changes: 28 additions & 3 deletions taccsite_cms/management/commands/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ def add_perm(group, app_label, model_name, perm_name):
else:
group.permissions.add( Permission.objects.get( name=perm_name ))

def del_perm(group, app_label, model_name, perm_name):
"""
Delete specific permission from a given group
"""
logger.debug(f'Removing permission ({app_label}.{model_name}) "{perm_name}"')
if app_label and model_name:
model = model_name.lower().replace(' ', '')
content_type = ContentType.objects.get(
app_label=app_label,
model=model
)
group.permissions.remove(
Permission.objects.get(
name=perm_name,
content_type=content_type
)
)
else:
group.permissions.remove(Permission.objects.get(name=perm_name))


# Page
Expand All @@ -44,9 +63,15 @@ def let_view_page_and_structure(group):
add_perm(group, 'cms', 'page', 'Can change page')

add_perm(group, 'cms', 'placeholder', 'Can use Structure mode')
# HELP: Not necessary on TACC (as of Core-CMS v4.17.1)
# Is necessary on WTCS (as of Core-CMS v4.20.2)
add_perm(group, 'cms', 'static placeholder', 'Can change static placeholder')
# To delete undesired permission from sites that still have it:
# ```py
# add_perm(group, 'cms', 'static placeholder', 'Can change static placeholder')
# ```
# HELP: Should "Sitewide Content Manager" keep this perm?
# SEE: https://weteachcs.org/admin/auth/group/9/change/
# FAQ: Only superuser may edit static placeholders (footer, header-content)
# TODO: After this is deployed on all sites once, delete this code
del_perm(group, 'cms', 'static placeholder', 'Can change static placeholder')



Expand Down
8 changes: 7 additions & 1 deletion taccsite_cms/settings/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,13 @@ def get_subdirs_as_module_names(path):
}

CMS_PERMISSION = True
CMS_PLACEHOLDER_CONF = {}
CMS_PLACEHOLDER_CONF = {
'header-content': {
# One PicturePlugin with template "Header logo" = custom logo
# Any other plugins render inline within the header nav
'limits': {'global': 10},
},
}

THUMBNAIL_HIGH_RESOLUTION = True
THUMBNAIL_PROCESSORS = (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% load header_content_tags %}
{% header_logo_from_picture instance picture_link as plugin_logo %}
{% include "header_logo.html" with plugin_logo=plugin_logo %}
6 changes: 4 additions & 2 deletions taccsite_cms/templates/header.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{# @var settings #}
{% load cms_tags %}

{# WARNING: Some markup is duplicated in other repositories #}
{# SEE: https://confluence.tacc.utexas.edu/x/LoCnCQ #}
Expand All @@ -22,7 +23,9 @@
{% endif %}
">
<!-- Portal Logo -->
{% include "header_logo.html" %}
{% static_placeholder "header-content" or %}
{% include "header_logo.html" %}
{% endstatic_placeholder %}

<!-- Navbar Accordian Toggle on Small Screens -->
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExpandTarget" aria-controls="navbarsExpandTarget" aria-expanded="false" aria-label="Toggle navigation">
Expand All @@ -44,7 +47,6 @@
{% endif %}
</div>
</nav>

{% endwith %}
{% endwith %}
{% endwith %}
29 changes: 27 additions & 2 deletions taccsite_cms/templates/header_logo.html
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
{# @var logo, className #}
{# @var plugin_logo (optional), className #}
{% load static custom_portal_settings %}

{% if settings.LOGO %}
{% if plugin_logo %}

{# via Picture plugin (e.g. CMS editor uploads logo image) #}
{% with plugin_logo as logo %}
<a
id="header-logo"
class="navbar-brand {{className}}"
href="{{ logo.link_href }}"
target="{{ logo.link_target }}"
>
<img
class="portal-logo {{ logo.img_class }}"
src="{% if logo.is_remote %}{{ logo.img_file_src }}{% else %}{% static logo.img_file_src %}{% endif %}"
{% if logo.img_crossorigin %}
crossorigin="{{ logo.img_crossorigin }}"
{% endif %}
{% if logo.img_alt_text %}
alt="{{ logo.img_alt_text }}"
{% endif %}
/>
</a>
{% endwith %}

{% elif settings.LOGO %}

{# via deprecated CMS setting (e.g. CMS developer sets logo image) #}
{% with settings.LOGO as logo %}
{% with filename=logo|index:1 selectors=logo|index:2 targeturl=logo|index:3 targettype=logo|index:4 accessibility=logo|index:5 corstype=logo|index:6 visibility=logo|index:7 %}
{% if visibility == "True" %}
Expand All @@ -15,6 +39,7 @@

{% else %}

{# via CMS setting (e.g. CMS developer sets logo image) #}
{% with settings.PORTAL_LOGO as logo %}
<a
id="header-logo"
Expand Down
123 changes: 123 additions & 0 deletions taccsite_cms/templatetags/header_content_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
"""Template tags for header logo (e.g. building plugin_logo from Picture plugin)."""
from django import template

from cms.models import StaticPlaceholder

register = template.Library()


def _get_header_content_parsed(request, placeholder_name):
"""
Parse content of static placeholder `placeholder_name`:

* (if present) single "Header logo" Picture as logo
* (if present) link for logo
* (if present) remaining plugins

Return (logo_plugin, logo_link, remaining_plugins).
"""
logo_plugin = None
logo_link = None
remaining_plugins = []

placeholder = StaticPlaceholder.objects.filter(
code=placeholder_name,
site_id__isnull=True
).first()

# Return NO content (if placeholder does not exist)
if not placeholder:
return (logo_plugin, logo_link, remaining_plugins)

placeholder_instance = placeholder.public
# Return NO content (if placeholder is not public)
if not placeholder_instance:
return (logo_plugin, logo_link, remaining_plugins)

plugin_list = placeholder_instance.get_plugins_list(language=request.LANGUAGE_CODE)
remaining_plugins = list(plugin_list)

if len(plugin_list) == 1:
first_plugin = plugin_list[0]
instance, plugin_type = first_plugin.get_plugin_instance()
is_picture_plugin = type(plugin_type).__name__ == 'PicturePlugin'
uses_logo_template = getattr(instance, 'template', None) == 'header_logo'

if instance and is_picture_plugin:
if uses_logo_template:
link = getattr(instance, 'get_link', lambda: None)()
logo_plugin = instance
logo_link = link or '#'
remaining_plugins = []

# Return ALL content (that is available from placeholder)
return (logo_plugin, logo_link, remaining_plugins)


@register.simple_tag(takes_context=True)
def get_header_content_parsed(context, placeholder_name):
"""
Parse content of static placeholder `placeholder_name`:

* (if present) single "Header logo" Picture as logo
* (if present) link for logo
* (if present) remaining plugins

Returns object with .logo_plugin, .logo_link, .remaining_plugins.
"""
request = context.get('request')
content_default = type('HeaderContent', (), {
'logo_plugin': None,
'logo_link': None,
'remaining_plugins': []
})()

if not request:
return content_default

logo_plugin, logo_link, remaining_plugins = _get_header_content_parsed(
request,
placeholder_name
)
content_parsed = type('HeaderContent', (), {
'logo_plugin': logo_plugin,
'logo_link': logo_link,
'remaining_plugins': remaining_plugins
})()

return content_parsed


@register.simple_tag
def header_logo_from_picture(instance, picture_link):
"""
Custom Template Tag `header_logo_from_picture`

Use: Build plugin_logo from djangocms_picture instance for header_logo.

Load custom tag into template:
{% load header_content_tags %}

Template inline usage:
{% header_logo_from_picture instance picture_link as plugin_logo %}
{% include "header_logo.html" with plugin_logo=plugin_logo %}
"""
picture = getattr(instance, 'picture', None)
attrs = getattr(instance, 'attributes', None) or {}

default_alt_text = getattr(picture, 'default_alt_text', None) if picture else None

alt = attrs.get('alt') or default_alt_text or ''
img_src = getattr(instance, 'img_src', None) or ''
link_target = getattr(instance, 'link_target', None)
is_remote = img_src.startswith('http://') or img_src.startswith('https://')

return {
'is_remote': is_remote,
'img_file_src': img_src,
'img_class': '',
'link_href': picture_link or '/',
'link_target': link_target or '',
'img_alt_text': alt,
'img_crossorigin': 'anonymous',
}