menu: include parenthood in subentries hint class logic (#86069)
gitea/combo/pipeline/head This commit looks good
Details
gitea/combo/pipeline/head This commit looks good
Details
This commit is contained in:
parent
dd877aad7c
commit
902051bf47
|
@ -355,6 +355,16 @@ class Page(models.Model):
|
|||
return self._children
|
||||
return Page.objects.filter(parent_id=self.id)
|
||||
|
||||
def has_navigable_children(self):
|
||||
if hasattr(self, '_children'):
|
||||
for child in self._children:
|
||||
if not getattr(child, 'exclude_from_navigation', True):
|
||||
return True
|
||||
return Page.objects.filter(
|
||||
parent_id=self.id,
|
||||
exclude_from_navigation=False,
|
||||
).exists()
|
||||
|
||||
def has_children(self):
|
||||
if hasattr(self, '_children'):
|
||||
return bool(self._children)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<ul class="{{ is_submenu|yesno:"submenu,menu" }} {% if is_submenu %}hide-on-escape{% endif %}">
|
||||
{% spaceless %}
|
||||
{% for menuitem in menuitems %}
|
||||
<li data-menu-page-id="{{ menuitem.page.id }}" class="{% if depth > 1 %}contains-hidden-elements{% endif %} {{ is_submenu|yesno:"submenu,menu" }}--item menu-{{ menuitem.page.slug }} {% if menuitem.selected %}selected{% endif %}">
|
||||
<li data-menu-page-id="{{ menuitem.page.id }}" class="{% if depth > 1 and menuitem.page.has_navigable_children %}contains-subentries{% endif %} {{ is_submenu|yesno:"submenu,menu" }}--item menu-{{ menuitem.page.slug }} {% if menuitem.selected %}selected{% endif %}">
|
||||
<a
|
||||
{% if menuitem.selected %}title="{{ menuitem.page.title }} - {% trans "active page" %}"{% endif %}
|
||||
href="{% page_absolute_url menuitem.page %}"
|
||||
|
|
|
@ -15,6 +15,7 @@ from django.test import override_settings
|
|||
from django.test.utils import CaptureQueriesContext
|
||||
from django.urls import reverse
|
||||
from django.utils.http import quote
|
||||
from lxml import etree
|
||||
|
||||
try:
|
||||
import mellon # pylint: disable=unused-import
|
||||
|
@ -655,7 +656,9 @@ def test_repeated_slug(app):
|
|||
assert 'Grand child of second (named third)' in resp.text
|
||||
|
||||
|
||||
def test_menu(app):
|
||||
def test_menu(app, admin_user):
|
||||
from combo.public.menu import render_menu
|
||||
|
||||
Page.objects.all().delete()
|
||||
page = Page.objects.create(
|
||||
title='Page1', slug='index', template_name='standard', exclude_from_navigation=False
|
||||
|
@ -669,6 +672,87 @@ def test_menu(app):
|
|||
assert 'data-menu-page-id="%s"' % page.id
|
||||
assert 'menu-page2' in resp.text
|
||||
assert 'menu-page3' in resp.text
|
||||
assert not resp.pyquery('.contains-subentries')
|
||||
|
||||
page4 = Page.objects.create(
|
||||
title='Page4', slug='page4', template_name='standard', parent=page, exclude_from_navigation=False
|
||||
)
|
||||
page5 = Page.objects.create(
|
||||
title='Page5', slug='page5', template_name='standard', parent=page4, exclude_from_navigation=False
|
||||
)
|
||||
page6 = Page.objects.create(
|
||||
title='Page6', slug='page6', template_name='standard', parent=page4, exclude_from_navigation=False
|
||||
)
|
||||
page7 = Page.objects.create(
|
||||
title='Page7', slug='page7', template_name='standard', parent=page5, exclude_from_navigation=False
|
||||
)
|
||||
|
||||
resp = app.get('/', status=200)
|
||||
# default menu depth is 1, children not rendered therefore not marked as potentially hidden
|
||||
assert not resp.pyquery('.contains-subentries')
|
||||
|
||||
request = mock.Mock()
|
||||
request.user = admin_user
|
||||
context = {
|
||||
'request': request,
|
||||
'page': page,
|
||||
'root_page': page,
|
||||
}
|
||||
# on the contrary, Publik templates use the custom show_menu templatetag calling the render_menu util directly:
|
||||
rendered = render_menu(
|
||||
context=context,
|
||||
level=1,
|
||||
root_page=None,
|
||||
depth=3, # dig deeper & retrieve Page4's hidden children in its own submenu
|
||||
ignore_visibility=False,
|
||||
)
|
||||
|
||||
contains_children = [page4.id, page5.id]
|
||||
childfree = [page6.id, page7.id]
|
||||
descendants = list(etree.fromstring(rendered).iterdescendants())
|
||||
assert descendants
|
||||
|
||||
for element in descendants:
|
||||
# check that only parent pages are classified as containers of hidden elements
|
||||
assert bool(int(element.attrib.get('data-menu-page-id', '-1')) in contains_children) is bool(
|
||||
'contains-subentries' in element.attrib.get('class', '')
|
||||
)
|
||||
if (page_id := int(element.attrib.get('data-menu-page-id', '-1'))) in contains_children:
|
||||
contains_children.remove(page_id)
|
||||
elif page_id in childfree:
|
||||
childfree.remove(page_id)
|
||||
# check that all pages have been rendered and parsed in the previous assert
|
||||
assert not contains_children
|
||||
assert not childfree
|
||||
|
||||
# page7 is now excluded from navigation, as it is page5's only child, the latter
|
||||
# should not bear the "contains-subentries" class
|
||||
page7.exclude_from_navigation = True
|
||||
page7.save()
|
||||
|
||||
rendered = render_menu(
|
||||
context=context,
|
||||
level=1,
|
||||
root_page=None,
|
||||
depth=3,
|
||||
ignore_visibility=False,
|
||||
)
|
||||
|
||||
contains_children = [page4.id]
|
||||
childfree = [page5.id, page6.id]
|
||||
descendants = list(etree.fromstring(rendered).iterdescendants())
|
||||
assert descendants
|
||||
|
||||
for element in descendants:
|
||||
assert bool(int(element.attrib.get('data-menu-page-id', '-1')) in contains_children) is bool(
|
||||
'contains-subentries' in element.attrib.get('class', '')
|
||||
)
|
||||
if (page_id := int(element.attrib.get('data-menu-page-id', '-1'))) in contains_children:
|
||||
contains_children.remove(page_id)
|
||||
elif page_id in childfree:
|
||||
childfree.remove(page_id)
|
||||
assert not contains_children
|
||||
assert not childfree
|
||||
|
||||
|
||||
def test_404(app):
|
||||
|
|
Loading…
Reference in New Issue