Skip to content

Commit

Permalink
Added smart breadcrumbs feature
Browse files Browse the repository at this point in the history
Smart breadcums are designed to replace breadcrumbs built into
django admin, so they reflect menu content.
  • Loading branch information
gbdlin committed Mar 22, 2019
1 parent 946ba3e commit 533ef3a
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 14 deletions.
2 changes: 2 additions & 0 deletions admin_toolbox/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@
sidebar = ADMIN_TOOLBOX.get('sidebar', {
'default': 'admin_toolbox.builders.AppsListBuilder',
})

breadcrumbs = ADMIN_TOOLBOX.get('breadcrumbs', 'smart')
20 changes: 11 additions & 9 deletions admin_toolbox/templates/admin/base.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load i18n admin_static admin_toolbox_sidebar %}<!DOCTYPE html>
{% load i18n admin_static admin_toolbox_sidebar admin_toolbox_breadcrumbs %}<!DOCTYPE html>
{% get_current_language as LANGUAGE_CODE %}{% get_current_language_bidi as LANGUAGE_BIDI %}
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}
class="{% if request.user.is_authenticated %}w-su-sidebar{% endif %}">
Expand Down Expand Up @@ -56,14 +56,16 @@
{% block nav-global %}{% endblock %}
</div>
<!-- END Header -->
{% if True|check_show_breadcrumbs %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
{% if title %} &rsaquo; {{ title }}{% endif %}
</div>
{% endblock %}
{% endif %}
{# {% if True|check_show_breadcrumbs %}#}
{% rebreadcrumbs %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
{% if title %} &rsaquo; {{ title }}{% endif %}
</div>
{% endblock %}
{% endrebreadcrumbs %}
{# {% endif %}#}
{% if request.user.is_authenticated %}
<div id="su-content">
{% admin_sidebar_content %}
Expand Down
10 changes: 10 additions & 0 deletions admin_toolbox/templates/admin_toolbox/breadcrumbs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="breadcrumbs">
{% for url, title in nodes %}
{% if not forloop.first %}&rsaquo;{% endif %}
{% if url == None %}
{{ title }}
{% else %}
<a href="{{ url }}">{{ title }}</a>
{% endif %}
{% endfor %}
</div>
82 changes: 82 additions & 0 deletions admin_toolbox/templatetags/admin_toolbox_breadcrumbs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from operator import itemgetter

from django.core.exceptions import ImproperlyConfigured
from django.template.loader import render_to_string
from django.utils.translation import ugettext as _
from six import text_type
from django import template
try:
from bs4 import BeautifulSoup
except ImportError:
BeautifulSoup = None
from admin_toolbox import settings

from .admin_toolbox_sidebar import admin_sidebar_content

register = template.Library()


@register.tag()
def rebreadcrumbs(parser, token):
nodelist = parser.parse(('endrebreadcrumbs',))
parser.delete_first_token()

return RerenderBreadcrumbs(nodelist)


class RerenderBreadcrumbs(template.Node):
def __init__(self, nodelist):
self.nodelist = nodelist
pass

def parse_node(self, node):
soup = BeautifulSoup(node)
if soup.find_all('a'):
node = soup.a
return node['href'], text_type(node.text).strip()
else:
return None, node.strip()

def render(self, context):
tx = self.nodelist.render(context)
print('----------', tx, '-------------')

if not settings.breadcrumbs:
return ''

if settings.breadcrumbs == 'smart':
if BeautifulSoup is None:
raise ImproperlyConfigured('beautifulsoup4 package is required for smart breadcrumbs to operate.')
soup = BeautifulSoup(tx)
tx = "".join(map(text_type, soup.div.contents if soup.div else []))

nodes = [self.parse_node(node) for node in tx.split('›') if node]

if not nodes:
nodes = [
(None, _('Home'))
]

active_path = admin_sidebar_content(context)['active_path']

index_node = nodes[0]
if active_path and active_path[-1]['url'] in set(map(itemgetter(0), nodes)):
nodes = nodes[list(map(itemgetter(0), nodes)).index(active_path[-1]['url']) + 1:]
nodes = [index_node] + [
(node.get('url'), node['name']) for node in active_path
] + nodes
elif active_path:
nodes = [index_node] + [
(node.get('url'), node['name']) for node in active_path
]
if len(nodes) > 1:
nodes[-1] = (None, nodes[-1][1])
elif len(nodes) > 1:
nodes = [index_node, nodes[-1]]

return render_to_string('admin_toolbox/breadcrumbs.html', context={'nodes': nodes})

return tx
4 changes: 3 additions & 1 deletion admin_toolbox/templatetags/admin_toolbox_sidebar.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,16 @@ def admin_sidebar_content(context, menu_name='default'):
key=lambda x: (-len(x[1]), x[0])
)
current_items = items
active_path = []
if track_active:
for index in track_active[0][0]:
current_items[index]['active'] = True
active_path.append(current_items[index])
current_items = current_items[index]['items'] if 'items' in current_items[index] else []

return {
'items': items,

'active_path': active_path
}


Expand Down
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,9 @@
'six',
],

# extras_require={
# 'dev': ['check-manifest'],
# 'test': ['coverage'],
# },
extras_require={
'smart-breadcrumbs': ['beautifulsoup4'],
},

setup_requires=[
'setuptools_scm',
Expand Down

0 comments on commit 533ef3a

Please sign in to comment.