Allow sorting menu entries
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
04fc4b4a15
commit
539d7e9d58
14
gas/sites.py
14
gas/sites.py
|
@ -7,14 +7,20 @@ from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class Entry:
|
class Entry:
|
||||||
def __init__(self, name, label, icon=None, url=None, roles=None, parent=None, children=None):
|
def __init__(self, name, label, icon=None, url=None, roles=None, parent=None, order=None):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.label = label
|
self.label = label
|
||||||
self.icon = icon
|
self.icon = icon
|
||||||
self.url = url
|
self.url = url
|
||||||
self.roles = roles
|
self.roles = roles
|
||||||
self.children = children or dict()
|
self.children = dict()
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
self.order = order if order is not None else float("inf")
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
if isinstance(other, Entry):
|
||||||
|
return (self.parent, self.order, self.label) < (other.parent, other.order, other.label)
|
||||||
|
return super().__lt__(other)
|
||||||
|
|
||||||
|
|
||||||
class GASSite(object):
|
class GASSite(object):
|
||||||
|
@ -42,7 +48,7 @@ class GASSite(object):
|
||||||
raise ImproperlyConfigured("Prefix {0} already in use".format(prefix))
|
raise ImproperlyConfigured("Prefix {0} already in use".format(prefix))
|
||||||
self._registry['urls'][prefix] = urls
|
self._registry['urls'][prefix] = urls
|
||||||
|
|
||||||
def register_menu(self, name, label, url=None, icon=None, roles=None, parent=None):
|
def register_menu(self, name, label, url=None, icon=None, roles=None, parent=None, order=None):
|
||||||
if name in self._registry['menu']:
|
if name in self._registry['menu']:
|
||||||
raise ImproperlyConfigured("Menu entry '{0}' already registered.".format(name))
|
raise ImproperlyConfigured("Menu entry '{0}' already registered.".format(name))
|
||||||
|
|
||||||
|
@ -53,7 +59,7 @@ class GASSite(object):
|
||||||
|
|
||||||
roles.add(self.base_role)
|
roles.add(self.base_role)
|
||||||
|
|
||||||
entry = Entry(name, label, icon, url, roles, parent=parent)
|
entry = Entry(name, label, icon, url, roles, parent=parent, order=order)
|
||||||
|
|
||||||
if parent:
|
if parent:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -18,6 +18,6 @@
|
||||||
|
|
||||||
<form method="post" action=".">{% csrf_token %}
|
<form method="post" action=".">{% csrf_token %}
|
||||||
<button type="submit">{% trans 'Delete' %}</button>
|
<button type="submit">{% trans 'Delete' %}</button>
|
||||||
<a href="{{ back_url }}">{% trans 'Cancel' %}</a>
|
<a href="{{ cancel_url }}">{% trans 'Cancel' %}</a>
|
||||||
</form>
|
</form>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -15,7 +15,7 @@ def show_navigation(user):
|
||||||
if user.is_superuser:
|
if user.is_superuser:
|
||||||
user_roles.add('admins')
|
user_roles.add('admins')
|
||||||
menu = site.get_root_menu(user_roles)
|
menu = site.get_root_menu(user_roles)
|
||||||
menu.sort(key=lambda a: a.label)
|
menu.sort()
|
||||||
return {
|
return {
|
||||||
'menu': menu,
|
'menu': menu,
|
||||||
'user_roles': user_roles,
|
'user_roles': user_roles,
|
||||||
|
@ -29,7 +29,6 @@ def get_children(entry, roles):
|
||||||
child for child in entry.children.values()
|
child for child in entry.children.values()
|
||||||
if child.roles.intersection(roles)
|
if child.roles.intersection(roles)
|
||||||
],
|
],
|
||||||
key=lambda a: a.label
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,66 @@ class SiteTestCase(TestCase):
|
||||||
url="gas:role_list",
|
url="gas:role_list",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_menu_ordering(self):
|
||||||
|
test_site = GASSite()
|
||||||
|
admin_roles = set(('admins',))
|
||||||
|
|
||||||
|
# With no explicit order, sort by label
|
||||||
|
test_site.register_menu(name='c', label="c")
|
||||||
|
test_site.register_menu(name='b', label="b")
|
||||||
|
test_site.register_menu(name='a', label="a")
|
||||||
|
entries = [
|
||||||
|
entry.name
|
||||||
|
for entry in sorted(test_site.get_root_menu(admin_roles))
|
||||||
|
]
|
||||||
|
self.assertEqual(entries, ['a', 'b', 'c'])
|
||||||
|
|
||||||
|
# Explicit order takes preference
|
||||||
|
test_site.register_menu(name='z', label="z", order=1)
|
||||||
|
entries = [
|
||||||
|
entry.name
|
||||||
|
for entry in sorted(test_site.get_root_menu(admin_roles))
|
||||||
|
]
|
||||||
|
self.assertEqual(entries, ['z', 'a', 'b', 'c'])
|
||||||
|
|
||||||
|
# Explicit order inside parent don't change the order
|
||||||
|
test_site.register_menu(name='y', label="y", order=2, parent='a')
|
||||||
|
entries = [
|
||||||
|
entry.name
|
||||||
|
for entry in sorted(test_site.get_root_menu(admin_roles))
|
||||||
|
]
|
||||||
|
self.assertEqual(entries, ['z', 'a', 'b', 'c'])
|
||||||
|
|
||||||
|
# With same explicit order, sort by label
|
||||||
|
test_site.register_menu(name='x', label="x", order=1)
|
||||||
|
entries = [
|
||||||
|
entry.name
|
||||||
|
for entry in sorted(test_site.get_root_menu(admin_roles))
|
||||||
|
]
|
||||||
|
self.assertEqual(entries, ['x', 'z', 'a', 'b', 'c'])
|
||||||
|
|
||||||
|
def test_menu_visibility(self):
|
||||||
|
test_site = GASSite()
|
||||||
|
admin_roles = set(('admins',))
|
||||||
|
staff_roles = set(('staff',))
|
||||||
|
|
||||||
|
test_site.register_menu(name='a', label='a', roles=admin_roles)
|
||||||
|
test_site.register_menu(name='b', label='b', roles=staff_roles)
|
||||||
|
|
||||||
|
# Admins gets all menu
|
||||||
|
entries = [
|
||||||
|
entry.name
|
||||||
|
for entry in test_site.get_root_menu(admin_roles)
|
||||||
|
]
|
||||||
|
self.assertEqual(entries, ['a', 'b'])
|
||||||
|
|
||||||
|
# Staff gets filtered menu
|
||||||
|
entries = [
|
||||||
|
entry.name
|
||||||
|
for entry in test_site.get_root_menu(staff_roles)
|
||||||
|
]
|
||||||
|
self.assertEqual(entries, ['b'])
|
||||||
|
|
||||||
|
|
||||||
class SampleAppIntegrationTest(TestCase):
|
class SampleAppIntegrationTest(TestCase):
|
||||||
def test_gas_autodiscover(self):
|
def test_gas_autodiscover(self):
|
||||||
|
|
Loading…
Reference in New Issue