From 648efe0e186ec5d91feb22007cfdc33fb39567d7 Mon Sep 17 00:00:00 2001 From: Josh Barr Date: Wed, 15 Apr 2015 09:38:51 +1200 Subject: [PATCH] allow for procedural highlighting of menu items. also highlights parents of submenus --- wagtail/wagtailadmin/menu.py | 70 +++++++++++---- .../scss/components/main-nav.scss | 85 ++++++++----------- .../wagtailadmin/shared/menu_item.html | 3 + .../shared/menu_submenu_item.html | 7 ++ 4 files changed, 100 insertions(+), 65 deletions(-) create mode 100644 wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_item.html create mode 100644 wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_submenu_item.html diff --git a/wagtail/wagtailadmin/menu.py b/wagtail/wagtailadmin/menu.py index 5fa4ff7cff..e36f26ec6c 100644 --- a/wagtail/wagtailadmin/menu.py +++ b/wagtail/wagtailadmin/menu.py @@ -11,13 +11,19 @@ from django.utils.safestring import mark_safe from wagtail.wagtailcore import hooks +from django.template import Context, loader + + + class MenuItem(with_metaclass(MediaDefiningClass)): - def __init__(self, label, url, name=None, classnames='', attrs=None, order=1000): + + def __init__(self, label, url, name=None, classnames='', attrs=None, order=1000, template='wagtailadmin/shared/menu_item.html'): self.label = label self.url = url self.classnames = classnames self.name = (name or slugify(text_type(label))) self.order = order + self.template = template if attrs: self.attr_string = flatatt(attrs) @@ -31,10 +37,22 @@ class MenuItem(with_metaclass(MediaDefiningClass)): """ return True + def is_active(self, request): + return request.path.startswith(self.url) + def render_html(self, request): - return format_html( - """""", - self.name, self.url, self.classnames, self.attr_string, self.label) + t = loader.get_template(self.template) + c = Context({ + 'name': self.name, + 'url': self.url, + 'classnames': self.classnames, + 'attr_string': self.attr_string, + 'label': self.label, + 'request': request, + 'active': self.is_active(request) + }) + + return t.render(c) class Menu(object): @@ -56,6 +74,9 @@ class Menu(object): def menu_items_for_request(self, request): return [item for item in self.registered_menu_items if item.is_shown(request)] + def menu_items_active(self, request): + return [item for item in self.menu_items_for_request(request) if item.is_active(request)] + @property def media(self): media = Media() @@ -77,16 +98,18 @@ class Menu(object): rendered_menu_items.append(item.render_html(request)) except TypeError: # fallback for older render_html methods that don't accept a request arg - rendered_menu_items.append(item.render_html()) + rendered_menu_items.append(item.render_html(request)) return mark_safe(''.join(rendered_menu_items)) class SubmenuMenuItem(MenuItem): """A MenuItem which wraps an inner Menu object""" - def __init__(self, label, menu, **kwargs): + def __init__(self, label, menu, + template='wagtailadmin/shared/menu_submenu_item.html', + **kwargs): self.menu = menu - super(SubmenuMenuItem, self).__init__(label, '#', **kwargs) + super(SubmenuMenuItem, self).__init__(label, '#', template=template, **kwargs) @property def media(self): @@ -96,17 +119,30 @@ class SubmenuMenuItem(MenuItem): # show the submenu if one or more of its children is shown return bool(self.menu.menu_items_for_request(request)) + def is_active(self, request): + return bool(self.menu.menu_items_active(request)) + def render_html(self, request): - return format_html( - """""", - self.name, self.classnames, self.attr_string, self.label, self.menu.render_html(request) - ) + + self.menu.menu_items_for_request(request) + is_active = request.path.startswith(self.url) + + if not is_active: + is_active = self.is_active(request) + + t = loader.get_template(self.template) + c = Context({ + 'name': self.name, + 'url': self.url, + 'classnames': self.classnames, + 'attr_string': self.attr_string, + 'label': self.label, + 'menu_html': self.menu.render_html(request), + 'request': request, + 'active': is_active + }) + + return t.render(c) admin_menu = Menu(register_hook_name='register_admin_menu_item', construct_hook_name='construct_main_menu') diff --git a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss index 181516da05..0e23b216dc 100644 --- a/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss +++ b/wagtail/wagtailadmin/static/wagtailadmin/scss/components/main-nav.scss @@ -2,7 +2,7 @@ $selected-highlight:darken($color-grey-1, 10%); $submenu-color:darken($color-grey-1, 5%); .nav-wrapper{ - position:relative; + position: relative; background: $color-grey-1; margin-left: -$menu-width; width: $menu-width; @@ -11,9 +11,9 @@ $submenu-color:darken($color-grey-1, 5%); min-height:800px; } #nav-toggle{ - left:$mobile-nice-padding; + left: $mobile-nice-padding; cursor:pointer; - position:absolute; + position: absolute; &:before{ font-size:40px; @@ -23,43 +23,32 @@ $submenu-color:darken($color-grey-1, 5%); } } - .nav-main{ + .menu-active { + background: $selected-highlight; + text-shadow: -1px -1px 0px rgba(0,0,0,0.3); + + & > a { + border-left-color:$color-salmon; + color:white; + } + } + + + .nav-main { top: 43px; bottom: 0px; overflow: auto; - width:100%; + width: 100%; - ul, li{ - margin:0; - padding:0; - list-style-type:none; + ul, li { + margin: 0; + padding: 0; + list-style-type: none; } - li{ + li { @include transition(border-color 0.2s ease); - position:relative; - - /* TODO: find better way to procedurally detect the appropriate menu to highlight */ - .menu-snippets &.menu-snippets, - .menu-users &.menu-users, - .menu-groups &.menu-groups, - .menu-sites &.menu-sites, - .menu-redirects &.menu-redirects, - .menu-editorspicks &.menu-editors-picks, - .menu-snippets &.menu-snippets, - .menu-documents &.menu-documents, - .menu-images &.menu-images, - .menu-search &.menu-search, - .menu-explorer &.menu-explorer, - .menu-forms &.menu-forms{ - background:$selected-highlight; - text-shadow:-1px -1px 0px rgba(0,0,0,0.3); - - a{ - border-left-color:$color-salmon; - color:white; - } - } + position: relative; } a{ @@ -101,13 +90,13 @@ $submenu-color:darken($color-grey-1, 5%); top:0.5em; margin-top:0.15em; } - - } + + } .account{ @include clearfix(); - - + + .avatar{ display:none; } @@ -119,9 +108,9 @@ $submenu-color:darken($color-grey-1, 5%); } } - .nav-submenu{ + .nav-submenu{ background:$submenu-color; - + h2{ display:none; } @@ -186,7 +175,7 @@ $submenu-color:darken($color-grey-1, 5%); padding:0; width:3em; height:100%; overflow:hidden; - + &:before{ font-family:wagtail; font-weight:200; @@ -198,7 +187,7 @@ $submenu-color:darken($color-grey-1, 5%); padding:0 1em; } } - + } /* Navigation open condition */ @@ -280,13 +269,13 @@ body.explorer-open { position:fixed; width:$menu-width - 7; bottom:0; - + } .account{ @include clearfix(); padding-right:0; padding-left:15px; - + .avatar{ display:inline-block; padding:0; @@ -307,7 +296,7 @@ body.explorer-open { } } - .nav-submenu{ + .nav-submenu{ position:fixed; height:100%; width:0; @@ -317,7 +306,7 @@ body.explorer-open { overflow:auto; max-height:100%; border-right:1px solid rgba(0,0,0,0.1); - + h2,ul{ float:right; width:$menu-width; @@ -348,9 +337,9 @@ body.explorer-open { > a{ text-shadow:-1px -1px 0px rgba(0,0,0,0.3); - + &:hover{ - background-color:transparent; + background-color:transparent; } } .nav-submenu{ @@ -399,4 +388,4 @@ body.explorer-open { display:block; } } -} \ No newline at end of file +} diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_item.html b/wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_item.html new file mode 100644 index 0000000000..4c795fc402 --- /dev/null +++ b/wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_item.html @@ -0,0 +1,3 @@ + diff --git a/wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_submenu_item.html b/wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_submenu_item.html new file mode 100644 index 0000000000..cdd4de46a4 --- /dev/null +++ b/wagtail/wagtailadmin/templates/wagtailadmin/shared/menu_submenu_item.html @@ -0,0 +1,7 @@ +