Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e2f7c53
feat: #999 only cms admin edit static placeholder
wesleyboar Feb 11, 2026
f52b8b2
feat: #999 add 'header-logo' placeholder
wesleyboar Feb 11, 2026
ead8569
refactor: simplify code and format docstring
wesleyboar Feb 11, 2026
53cfef6
refactor!: header-logo → header-content
wesleyboar Mar 5, 2026
e1d19d9
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Mar 5, 2026
9fef1c3
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Apr 2, 2026
7459528
docs: heaader_logo comments
wesleyboar Apr 2, 2026
d156af6
refactor: legible header content parsing logic
wesleyboar Apr 2, 2026
d5b2a36
fix: GH-999 CMS admin can change header logo (#1142)
wesleyboar Apr 21, 2026
c7f4454
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jun 4, 2026
15a1c2d
docs(gh-999): add editable header implementation plan
wesleyboar Jun 4, 2026
053fdd7
feat: GH-999 CMS admin can change header logo - via plugin (#1171)
wesleyboar Jun 11, 2026
79f14b3
chore: delete cruft
wesleyboar Jun 11, 2026
c42f211
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jun 11, 2026
15fc05c
feat(gh-999): default Header logo form values on add (#1183)
wesleyboar Jun 16, 2026
07c0c2a
fix(gh-999): align header logo markup with settings path (#1184)
wesleyboar Jun 17, 2026
27fa19d
feat(gh-999): default Header logo alt text on add
wesleyboar Jun 17, 2026
96ed5cd
fix(gh-999): restrict Header logo plugin to header-content
wesleyboar Jun 17, 2026
7070552
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jun 17, 2026
3ee0438
refactor(gh-999): centralize header-content placeholder slot
wesleyboar Jun 17, 2026
fc6bb82
chore: whitespace
wesleyboar Jun 17, 2026
1937592
chore: plugin order (logo plugin not deprecated)
wesleyboar Jun 17, 2026
fc7eb38
fix: revert settings test change
wesleyboar Jun 17, 2026
0d4fd91
refactor: rename a constant
wesleyboar Jun 17, 2026
42a801a
docs: gh-999
wesleyboar Jun 17, 2026
c85cc71
feat(gh-999): name static placeholders in Structure sidebar
wesleyboar Jun 17, 2026
2cabc1c
chore: whitespace
wesleyboar Jun 17, 2026
e56e434
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jun 17, 2026
b737a87
Merge branches 'feat/GH-999-let-cms-admin-edit-header' and 'feat/GH-9…
wesleyboar Jun 17, 2026
34988a7
deps: @tacc/core-styles v2.57.1
wesleyboar Jun 17, 2026
440ceba
deps: @tacc/core-styles v2.57.2
wesleyboar Jun 18, 2026
606a0eb
docs(GH-999): document img-only header logo CMS limitation
wesleyboar Jun 18, 2026
559dbf7
fix(GH-1185): apply portal-logo class for img-only header logos
wesleyboar Jun 18, 2026
9beaf61
docs: clean up "Known Limitations"
wesleyboar Jun 18, 2026
a4f1a43
Merge branch 'fix/GH-1185-header-logo-portal-logo-class' of github.co…
wesleyboar Jun 18, 2026
1d01d08
chore: reduce diff
wesleyboar Jun 18, 2026
9ff3bc2
fix: expected plugins in header logo placeholder
wesleyboar Jun 18, 2026
958e340
fix: lost `portal-logo` class
wesleyboar Jun 18, 2026
74241ec
chore: delete outdated tests
wesleyboar Jun 18, 2026
56931f1
refactor: rename plugin
wesleyboar Jun 18, 2026
f878b60
chore(test): revert unused _FakePicture attributes_str helper
wesleyboar Jun 18, 2026
97d3382
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jun 18, 2026
d8d6114
refactor(gh-999): simplify header logo rendering (#1189)
wesleyboar Jun 19, 2026
7450f3f
refactor: rename a const
wesleyboar Jun 19, 2026
a6b9209
refactor: rename a const
wesleyboar Jun 19, 2026
4c79ddf
docs: clarity
wesleyboar Jun 19, 2026
cead748
docs: remove cruft
wesleyboar Jun 19, 2026
950ed99
fix(header-logo): always set id on Header logo plugin markup
wesleyboar Jun 19, 2026
d361e90
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jul 1, 2026
1d96a54
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jul 1, 2026
39a8386
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jul 3, 2026
b41b1a6
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jul 21, 2026
791d412
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jul 27, 2026
0d31361
Merge branch 'main' into feat/GH-999-let-cms-admin-edit-header
wesleyboar Jul 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file.
6 changes: 6 additions & 0 deletions djangocms_tacc_header_logo/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class TaccsiteHeaderLogoConfig(AppConfig):
name = 'djangocms_tacc_header_logo'
verbose_name = 'Header logo'
31 changes: 31 additions & 0 deletions djangocms_tacc_header_logo/cms_plugins.py

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create header logo plugin (extends Picture) so we can control:

  • requirements (via this file)
  • defaults (via forms.py)

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from cms.plugin_pool import plugin_pool
from django.utils.translation import gettext_lazy as _

from djangocms_picture.cms_plugins import PicturePlugin
from djangocms_picture.models import Picture

from .forms import TaccsiteHeaderLogoForm

HEADER_LOGO_ID = 'header-logo'
HEADER_LOGO_CLASS = 'navbar-brand'


@plugin_pool.register_plugin
class TaccsiteHeaderLogoPlugin(PicturePlugin):
"""
Components > "Header logo" Plugin
"""
model = Picture
form = TaccsiteHeaderLogoForm
module = 'TACC Site'
name = _('Header logo')

def render(self, context, instance, placeholder):
if not instance.attributes:
instance.attributes = {}

existing_class = instance.attributes.get('class', '')
instance.attributes['class'] = f'{HEADER_LOGO_CLASS} {existing_class}'.strip()
instance.attributes['id'] = HEADER_LOGO_ID

return super().render(context, instance, placeholder)
38 changes: 38 additions & 0 deletions djangocms_tacc_header_logo/forms.py

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set default configuration of a Picture-as-Header-logo.

Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from cms.models import Page
from django.conf import settings
from django.contrib.sites.models import Site
from djangocms_picture.forms import PictureForm

HEADER_LOGO_TEMPLATE_WITH_PORTAL = 'portal_logo'


def default_home_page():
site = Site.objects.get_current()
return Page.objects.filter(is_home=True, node__site=site).first()


class TaccsiteHeaderLogoForm(PictureForm):
"""
Defaults for new Header logo plugins only (admin add form).

On a TACC/Core-Portal instance, defaults to Portal logo picture template.
"""

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if self.instance.pk:
return

if settings.PORTAL_IS_TACC_CORE_PORTAL:
self.initial.setdefault('template', HEADER_LOGO_TEMPLATE_WITH_PORTAL)

home = default_home_page()
if home is not None:
self.initial.setdefault('link_page', home.pk)

self.initial.setdefault('use_no_cropping', True)
self.initial.setdefault('use_automatic_scaling', False)

attributes = dict(self.initial.get('attributes') or {})
attributes.setdefault('alt', 'Project logo')
self.initial['attributes'] = attributes
67 changes: 67 additions & 0 deletions docs/gh-999-editable-header-plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# GH-999: Editable Header

Related:

- [#999](https://github.com/TACC/Core-CMS/issues/999)
- [#1083](https://github.com/TACC/Core-CMS/pull/1083)

## Status as of 2026-06

| State | Description |
| ------------------- | --------------------------------- |
| one placeholder | `header-logo` static placeholder |
| if plugin is added | `TaccsiteHeaderLogoPlugin` is only option |
| if plugin not added | renders settings-based logo |

The branding and navs and search are still settings-based.

## Known Limitations

| Issue | Summary | Why Allow This? |
| --- | --- | --- |
| [#1185](https://github.com/TACC/Core-CMS/issues/1185) | Header logo without a link is **missing** `class="portal-logo"` on `<img>`. | Default form links logo to home, so typical sites are unaffected. |

## How to Add Other Header Plugins

Requirements:

- (for [CMS editor UX](#cms-editor-ux)) plugins render where `{% static_placeholder %}` sits
- (to skip [Failed Ideas](#failed-ideas)) pick one option from below

### A. Wrapper Plugin

| Pros | Cons |
| ------------------------------ | ---------------------------------------------- |
| One placeholder | Extra container plugin |
| Layout management consolidated | Build/Maintain wrapper |
| | Must deprecate or migrate legacy `header-logo` |

### B. Multiple Placeholders

| Pros | Cons |
| ---------------------------------- | ---------------------------------- |
| Typical CMS usage | Several placeholders to configure |
| | Layout management not consolidated |
| Can keep using `header-logo` as is | |

## CMS Editor UX

Requirements:

- Static placeholder always visible in Structure mode.
- Edit plugin: auto-refreshes page preview.
- Add/Delete plugin: auto-refreshes page preview.
- Structure mode button toggles render of Structure sidebar.

## Failed Ideas

| Idea | Problem |
| --- | --- |
| `ContentRenderer` / template tag for the logo instead of `{% static_placeholder %}` at the logo | Structure and preview break; Picture edits need refresh (removed in [#1189](https://github.com/TACC/Core-CMS/pull/1189)) |
| Published markup from code, placeholder somewhere else | Duplicate logo surfaces; draft image lags behind preview |
| Child plugins under the logo, HTML rendered elsewhere | Structure/preview break |
| `{% static_placeholder %}` not where the logo shows | Bad WYSIWYG; toolbar/Structure bugs |
| Per-region render registry (not Option A or B) | Live site publish-only; bad edit UX |
| Option A wrapper before more header plugins exist | Two plugins for one logo |
| Plugin `cache = False` only | Does not fix placeholder vs programmatic render |
| Edit-only placeholder at top of header | Structure JS errors; no real preview |
1 change: 1 addition & 0 deletions taccsite_cms/_settings/djangocms_plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
]
DJANGOCMS_PICTURE_TEMPLATES = [
('no_link_to_ext_image', _('Do not link to external image')),
('portal_logo', _('Portal logo')),

@wesleyboar wesleyboar Jun 17, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To load taccsite_cms/templates/djangocms_picture/portal_logo/picture.html, so .portal-logo class is used (which triggers a style that is only relevant for Core-Portal).

]

########################
Expand Down
12 changes: 12 additions & 0 deletions taccsite_cms/settings/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,7 @@ def gettext(s): return s
'taccsite_card',
'djangocms_tacc_image_gallery',
'djangocms_tacc_system_monitor',
'djangocms_tacc_header_logo',

# TACC CMS Plugins - DECPRECATED
'taccsite_cms.contrib.taccsite_blockquote',
Expand Down Expand Up @@ -567,6 +568,17 @@ def get_subdirs_as_module_names(path):

CMS_PERMISSION = True
CMS_PLACEHOLDER_CONF = {
None: {
'excluded_plugins': ['TaccsiteHeaderLogoPlugin'],
},
'header-logo': {
'name': _('Header logo'),
'plugins': ['TaccsiteHeaderLogoPlugin'],
'excluded_plugins': [],
'limits': {
'global': 1,
},
},
Comment on lines +571 to +581

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Name the placeholder and limit its content to a header logo.

'footer-content': {
'name': _('Footer content'),
},
Expand Down
3 changes: 3 additions & 0 deletions taccsite_cms/templates/djangocms_picture/default/picture.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
{{ instance.attributes_str }}
{% endblock %}
{# /TACC #}
{# TACC (allow attributes to be force-added to <img>): #}
{% block picture_attributes_img %}{% if picture_img_class %}class="{{ picture_img_class }}"{% endif %}{% endblock %}
{# /TACC #}
Comment on lines +62 to +64

@wesleyboar wesleyboar Jun 18, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This lets us force the class on <img> tag, because (as on any Picture with a link or caption) the class attribute is hoisted to the parent <a> or <figure>1.

Caution

If <img> has no link (<a>) then class is not hoisted, thus class="portal-logo" is not added. UI breaks.

Footnotes

  1. A long time ago, I wrote the hoisting logic to allow class-driven layout change (added via a CMS editor e.g. via "Align right"/.align-right) to apply to the Picture element (<img>) or its wrapper (<a>, <figure>).

@wesleyboar wesleyboar Jun 18, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

I accept this bug for now.1 I document this bug for now.

Footnotes

  1. Because the header logo always links to a home page.

>
{% endlocalize %}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{% extends "djangocms_picture/default/picture.html" %}
{% block picture_attributes_img %}class="portal-logo"{% endblock %}
5 changes: 4 additions & 1 deletion taccsite_cms/templates/header.html

@wesleyboar wesleyboar Jun 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keystone code is in this file.

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-logo" 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 Down