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 @@
+