Use breadcrumb nav across Horizon
We've added breadcrumbs to the Details pages, but its a pretty inconsistent experience. This patch adds breadcrumbs to the base template, making the breadcrumbs consistent across all pages; this will be useful when the side nav is hidden for responsive design. This patch also makes the breadcrumbs on the detail pages behave better with theming. - Made the detail header and actions avoid using floats - Moved breadcrumb truncating to the front end, so that it can be customised easily via CSS - Manually added breadcrumb for ngcontainers page - Removed overly specific HTML check from Key Pair Details test - Fixed <dt> alignment on Key Pair Details page Closes-Bug: 1554812 Partially-Implements: blueprint navigation-improvements Change-Id: Ibcd4c369b5d8ad62f7c839c0deeaefc750677b40
This commit is contained in:

committed by
Diana Whitten

parent
a55663a49a
commit
d5b24d7b97
15
horizon/templates/bootstrap/breadcrumb.html
Normal file
15
horizon/templates/bootstrap/breadcrumb.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{% spaceless %}
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
{% for name, target in breadcrumb %}
|
||||||
|
{% if forloop.last %}
|
||||||
|
<li class="breadcrumb-item-truncate active">{{ name }}</li>
|
||||||
|
{% elif target %}
|
||||||
|
<li class="breadcrumb-item-truncate">
|
||||||
|
<a href="{{ target }}">{{ name }}</a>
|
||||||
|
</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="breadcrumb-item-truncate">{{ name }}</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ol>
|
||||||
|
{% endspaceless %}
|
@@ -1,26 +0,0 @@
|
|||||||
{% load truncate_filter %}
|
|
||||||
|
|
||||||
<ol class="breadcrumb">
|
|
||||||
{% if breadcrumb %}
|
|
||||||
{% for name, target in breadcrumb %}
|
|
||||||
{% if target %}
|
|
||||||
<li><a href="{{ target }}">{{ name|truncate:20 }}</a></li>
|
|
||||||
{% else %}
|
|
||||||
<li class="active">{{ name|truncate:20 }}</li>
|
|
||||||
{% endif %}
|
|
||||||
{% endfor %}
|
|
||||||
{% else %}
|
|
||||||
{% if panel %}
|
|
||||||
<li><a href="{{ panel.get_absolute_url }}">{{ panel.name }}</a></li>
|
|
||||||
{% endif %}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<li class="active">{{ page_title }}</li>
|
|
||||||
|
|
||||||
{% if actions %}
|
|
||||||
<form class='actions_column pull-right' action='{{ url }}' method="POST">
|
|
||||||
{% csrf_token %}
|
|
||||||
{{ actions }}
|
|
||||||
</form>
|
|
||||||
{% endif %}
|
|
||||||
</ol>
|
|
@@ -1,15 +1,12 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load breadcrumb_nav %}
|
|
||||||
|
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{{ page_title }}
|
{{ page_title }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include 'horizon/common/_detail_header.html' %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
16
horizon/templates/horizon/common/_detail_header.html
Normal file
16
horizon/templates/horizon/common/_detail_header.html
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<div class='page-header'>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-sm-9 text-left">
|
||||||
|
<span class="h1">{{ page_title }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xs-12 col-sm-3 text-right">
|
||||||
|
{% if actions %}
|
||||||
|
<div class='actions_column' action='{{ url }}' method="POST">
|
||||||
|
{% csrf_token %}
|
||||||
|
{{ actions }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -1,4 +1,4 @@
|
|||||||
# Copyright 2015 Cisco Systems, Inc.
|
# Copyright 2016 Cisco Systems, Inc.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@@ -17,11 +17,44 @@ from django import template
|
|||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
|
||||||
@register.inclusion_tag('horizon/common/_breadcrumb_nav.html',
|
@register.inclusion_tag('bootstrap/breadcrumb.html',
|
||||||
takes_context=True)
|
takes_context=True)
|
||||||
def breadcrumb_nav(context):
|
def breadcrumb_nav(context):
|
||||||
return {'actions': context.get('actions'),
|
"""A logic heavy function for automagically creating a breadcrumb.
|
||||||
'breadcrumb': context.get('custom_breadcrumb'),
|
It uses the dashboard, panel group(if it exists), then current panel.
|
||||||
'url': context.get('url'),
|
Can also use a "custom_breadcrumb" context item to add extra items.
|
||||||
'page_title': context['page_title'],
|
"""
|
||||||
'panel': context.request.horizon['panel'], }
|
breadcrumb = []
|
||||||
|
dashboard = context.request.horizon['dashboard']
|
||||||
|
try:
|
||||||
|
panel_groups = dashboard.get_panel_groups()
|
||||||
|
except KeyError:
|
||||||
|
panel_groups = None
|
||||||
|
panel_group = None
|
||||||
|
panel = context.request.horizon['panel']
|
||||||
|
|
||||||
|
# Add panel group, if there is one
|
||||||
|
if panel_groups:
|
||||||
|
for group in panel_groups.values():
|
||||||
|
if panel.slug in group.panels and group.slug != 'default':
|
||||||
|
panel_group = group
|
||||||
|
break
|
||||||
|
|
||||||
|
# Remove panel reference if that is the current page
|
||||||
|
if panel.get_absolute_url() == context.request.path:
|
||||||
|
panel = None
|
||||||
|
|
||||||
|
# Get custom breadcrumb, if there is one.
|
||||||
|
custom_breadcrumb = context.get('custom_breadcrumb')
|
||||||
|
|
||||||
|
# Build list of tuples (name, optional url)
|
||||||
|
breadcrumb.append((dashboard.name,))
|
||||||
|
if panel_group:
|
||||||
|
breadcrumb.append((panel_group.name,))
|
||||||
|
if panel:
|
||||||
|
breadcrumb.append((panel.name, panel.get_absolute_url()))
|
||||||
|
if custom_breadcrumb:
|
||||||
|
breadcrumb.extend(custom_breadcrumb)
|
||||||
|
breadcrumb.append((context.get('page_title'),))
|
||||||
|
|
||||||
|
return {'breadcrumb': breadcrumb}
|
||||||
|
@@ -1,12 +1,9 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load breadcrumb_nav %}
|
|
||||||
{% block title %}{% trans "Hypervisor Servers" %}{% endblock %}
|
{% block title %}{% trans "Hypervisor Servers" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -12,7 +12,6 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from django.core.urlresolvers import reverse
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from horizon import exceptions
|
from horizon import exceptions
|
||||||
@@ -69,7 +68,6 @@ class AdminDetailView(tables.DataTableView):
|
|||||||
context = super(AdminDetailView, self).get_context_data(**kwargs)
|
context = super(AdminDetailView, self).get_context_data(**kwargs)
|
||||||
hypervisor_name = self.kwargs['hypervisor'].split('_', 1)[1]
|
hypervisor_name = self.kwargs['hypervisor'].split('_', 1)[1]
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Hypervisors"), reverse('horizon:admin:hypervisors:index')),
|
|
||||||
(hypervisor_name,), ]
|
(hypervisor_name,), ]
|
||||||
context['custom_breadcrumb'] = breadcrumb
|
context['custom_breadcrumb'] = breadcrumb
|
||||||
return context
|
return context
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n breadcrumb_nav %}
|
{% load i18n %}
|
||||||
{% block title %}{% trans "Volume Type Encryption Details" %}{% endblock %}
|
{% block title %}{% trans "Volume Type Encryption Details" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -1,13 +1,10 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load breadcrumb_nav %}
|
|
||||||
|
|
||||||
{% block title %}{% trans "Project Details" %}{% endblock %}
|
{% block title %}{% trans "Project Details" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -1,13 +1,10 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% load breadcrumb_nav %}
|
|
||||||
|
|
||||||
{% block title %}{% trans "User Details" %}{% endblock %}
|
{% block title %}{% trans "User Details" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -116,10 +116,6 @@ class KeyPairViewTests(test.TestCase):
|
|||||||
url = reverse('horizon:project:access_and_security:keypairs:detail',
|
url = reverse('horizon:project:access_and_security:keypairs:detail',
|
||||||
kwargs={'keypair_name': keypair.name})
|
kwargs={'keypair_name': keypair.name})
|
||||||
res = self.client.get(url, context)
|
res = self.client.get(url, context)
|
||||||
|
|
||||||
# Note(Itxaka): With breadcrumbs, the title is in a list as active
|
|
||||||
self.assertContains(res, '<li class="active">Key Pair Details</li>',
|
|
||||||
1, 200)
|
|
||||||
self.assertContains(res, "<dd>%s</dd>" % keypair.name, 1, 200)
|
self.assertContains(res, "<dd>%s</dd>" % keypair.name, 1, 200)
|
||||||
|
|
||||||
@test.create_stubs({api.nova: ("keypair_create", "keypair_delete")})
|
@test.create_stubs({api.nova: ("keypair_create", "keypair_delete")})
|
||||||
|
@@ -1,15 +1,14 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n sizeformat breadcrumb_nav %}
|
{% load i18n sizeformat %}
|
||||||
|
|
||||||
{% block title %}{% trans "Key Pair Details" %}{% endblock %}
|
{% block title %}{% trans "Key Pair Details" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
<div class="detail">
|
||||||
<dl class="dl-horizontal">
|
<dl class="dl-horizontal">
|
||||||
<dt>{% trans "Name" %}</dt>
|
<dt>{% trans "Name" %}</dt>
|
||||||
<dd>{{ keypair.name|default:_("None") }}</dd>
|
<dd>{{ keypair.name|default:_("None") }}</dd>
|
||||||
@@ -28,4 +27,5 @@
|
|||||||
<div class="key-text word-wrap">{{ keypair.public_key|default:_("None") }}</div>
|
<div class="key-text word-wrap">{{ keypair.public_key|default:_("None") }}</div>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -1,12 +1,10 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n breadcrumb_nav %}
|
{% load i18n %}
|
||||||
|
|
||||||
{% block title %}{% trans "Manage Security Group Rules" %}{% endblock %}
|
{% block title %}{% trans "Manage Security Group Rules" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -2,6 +2,14 @@
|
|||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
{% block title %}{% trans "Containers" %}{% endblock %}
|
{% block title %}{% trans "Containers" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumb_nav %}
|
||||||
|
<ol class="breadcrumb">
|
||||||
|
<li>{% trans "Project" %}</li>
|
||||||
|
<li>{% trans "Object Store" %}</li>
|
||||||
|
<li class="active">{% trans "Containers" %}</li>
|
||||||
|
</ol>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block ng_route_base %}
|
{% block ng_route_base %}
|
||||||
<base href="{{ WEBROOT }}">
|
<base href="{{ WEBROOT }}">
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -90,8 +90,6 @@ class RuleDetailsView(tabs.TabView):
|
|||||||
rule = self.get_data()
|
rule = self.get_data()
|
||||||
table = fw_tabs.RulesTable(self.request)
|
table = fw_tabs.RulesTable(self.request)
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Firewalls"),
|
|
||||||
reverse_lazy('horizon:project:firewalls:firewalls')),
|
|
||||||
(_("Rules"), reverse_lazy('horizon:project:firewalls:rules'))]
|
(_("Rules"), reverse_lazy('horizon:project:firewalls:rules'))]
|
||||||
context["custom_breadcrumb"] = breadcrumb
|
context["custom_breadcrumb"] = breadcrumb
|
||||||
context["rule"] = rule
|
context["rule"] = rule
|
||||||
@@ -126,8 +124,6 @@ class PolicyDetailsView(tabs.TabView):
|
|||||||
policy = self.get_data()
|
policy = self.get_data()
|
||||||
table = fw_tabs.PoliciesTable(self.request)
|
table = fw_tabs.PoliciesTable(self.request)
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Firewalls"),
|
|
||||||
reverse_lazy('horizon:project:firewalls:firewalls')),
|
|
||||||
(_("Policies"),
|
(_("Policies"),
|
||||||
reverse_lazy('horizon:project:firewalls:policies'))]
|
reverse_lazy('horizon:project:firewalls:policies'))]
|
||||||
context["custom_breadcrumb"] = breadcrumb
|
context["custom_breadcrumb"] = breadcrumb
|
||||||
|
@@ -136,7 +136,6 @@ class VipDetailsView(tabs.TabView):
|
|||||||
context['vip'] = vip
|
context['vip'] = vip
|
||||||
vip_nav = vip.pool.name_or_id
|
vip_nav = vip.pool.name_or_id
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Load Balancers"), self.get_redirect_url()),
|
|
||||||
(vip_nav,
|
(vip_nav,
|
||||||
reverse('horizon:project:loadbalancers:vipdetails',
|
reverse('horizon:project:loadbalancers:vipdetails',
|
||||||
args=(vip.id,))),
|
args=(vip.id,))),
|
||||||
@@ -173,7 +172,6 @@ class MemberDetailsView(tabs.TabView):
|
|||||||
context['member'] = member
|
context['member'] = member
|
||||||
member_nav = member.pool.name_or_id
|
member_nav = member.pool.name_or_id
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Load Balancers"), self.get_redirect_url()),
|
|
||||||
(member_nav,
|
(member_nav,
|
||||||
reverse('horizon:project:loadbalancers:pooldetails',
|
reverse('horizon:project:loadbalancers:pooldetails',
|
||||||
args=(member.pool.id,))),
|
args=(member.pool.id,))),
|
||||||
@@ -213,7 +211,6 @@ class MonitorDetailsView(tabs.TabView):
|
|||||||
monitor = self.get_data()
|
monitor = self.get_data()
|
||||||
context['monitor'] = monitor
|
context['monitor'] = monitor
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Load Balancers"), self.get_redirect_url()),
|
|
||||||
(_("Monitors"), reverse('horizon:project:loadbalancers:monitors')),
|
(_("Monitors"), reverse('horizon:project:loadbalancers:monitors')),
|
||||||
]
|
]
|
||||||
context["custom_breadcrumb"] = breadcrumb
|
context["custom_breadcrumb"] = breadcrumb
|
||||||
|
@@ -89,7 +89,6 @@ class DetailView(tabs.TabView):
|
|||||||
network_id=port.network_id)
|
network_id=port.network_id)
|
||||||
# TODO(robcresswell) Add URL for "Ports" crumb after bug/1416838
|
# TODO(robcresswell) Add URL for "Ports" crumb after bug/1416838
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Networks"), self.get_redirect_url()),
|
|
||||||
((port.network_name or port.network_id), port.network_url),
|
((port.network_name or port.network_id), port.network_url),
|
||||||
(_("Ports"),), ]
|
(_("Ports"),), ]
|
||||||
context["custom_breadcrumb"] = breadcrumb
|
context["custom_breadcrumb"] = breadcrumb
|
||||||
|
@@ -158,7 +158,6 @@ class DetailView(tabs.TabView):
|
|||||||
network_id=subnet.network_id)
|
network_id=subnet.network_id)
|
||||||
# TODO(robcresswell) Add URL for "Subnets" crumb after bug/1416838
|
# TODO(robcresswell) Add URL for "Subnets" crumb after bug/1416838
|
||||||
breadcrumb = [
|
breadcrumb = [
|
||||||
(_("Networks"), self.get_redirect_url()),
|
|
||||||
(network_nav, subnet.network_url),
|
(network_nav, subnet.network_url),
|
||||||
(_("Subnets"),), ]
|
(_("Subnets"),), ]
|
||||||
context["custom_breadcrumb"] = breadcrumb
|
context["custom_breadcrumb"] = breadcrumb
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n breadcrumb_nav %}
|
{% load i18n %}
|
||||||
{% block title %}{% trans "Network Details"%}{% endblock %}
|
{% block title %}{% trans "Network Details"%}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
{% load i18n breadcrumb_nav %}
|
{% load i18n %}
|
||||||
{% block title %}{% trans "Volume Encryption Details" %}{% endblock %}
|
{% block title %}{% trans "Volume Encryption Details" %}{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
<div class='page-header'>
|
{% include "horizon/common/_detail_header.html" %}
|
||||||
{% breadcrumb_nav %}
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block main %}
|
{% block main %}
|
||||||
|
@@ -1273,7 +1273,7 @@ class VolumeViewTests(test.TestCase):
|
|||||||
|
|
||||||
self.assertContains(res,
|
self.assertContains(res,
|
||||||
"Volume Encryption Details: %s" % volume.name,
|
"Volume Encryption Details: %s" % volume.name,
|
||||||
1, 200)
|
2, 200)
|
||||||
self.assertContains(res, "<dd>%s</dd>" % volume.volume_type, 1, 200)
|
self.assertContains(res, "<dd>%s</dd>" % volume.volume_type, 1, 200)
|
||||||
self.assertContains(res, "<dd>%s</dd>" % enc_meta.provider, 1, 200)
|
self.assertContains(res, "<dd>%s</dd>" % enc_meta.provider, 1, 200)
|
||||||
self.assertContains(res, "<dd>%s</dd>" % enc_meta.control_location, 1,
|
self.assertContains(res, "<dd>%s</dd>" % enc_meta.control_location, 1,
|
||||||
@@ -1301,7 +1301,7 @@ class VolumeViewTests(test.TestCase):
|
|||||||
|
|
||||||
self.assertContains(res,
|
self.assertContains(res,
|
||||||
"Volume Encryption Details: %s" % volume.name,
|
"Volume Encryption Details: %s" % volume.name,
|
||||||
1, 200)
|
2, 200)
|
||||||
self.assertContains(res, "<h3>Volume is Unencrypted</h3>", 1, 200)
|
self.assertContains(res, "<h3>Volume is Unencrypted</h3>", 1, 200)
|
||||||
|
|
||||||
self.assertNoMessages()
|
self.assertNoMessages()
|
||||||
|
@@ -76,3 +76,6 @@ $members-list-roles-width: 125px !default;
|
|||||||
// https://github.com/twbs/bootstrap/issues/13443
|
// https://github.com/twbs/bootstrap/issues/13443
|
||||||
$dropdown-item-padding-vertical: 3px;
|
$dropdown-item-padding-vertical: 3px;
|
||||||
$dropdown-item-padding-horizontal: 20px;
|
$dropdown-item-padding-horizontal: 20px;
|
||||||
|
|
||||||
|
// This defines the max-width for a breadcrumb item before it will be truncated
|
||||||
|
$breadcrumb-item-width: 15em !default;
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
.breadcrumb {
|
||||||
|
margin-top: $line-height-computed;
|
||||||
|
|
||||||
|
.breadcrumb-item-truncate {
|
||||||
|
@include text-overflow();
|
||||||
|
vertical-align: middle;
|
||||||
|
max-width: $breadcrumb-item-width;
|
||||||
|
}
|
||||||
|
}
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
// Dashboard Components
|
// Dashboard Components
|
||||||
@import "components/bar_charts";
|
@import "components/bar_charts";
|
||||||
|
@import "components/breadcrumbs";
|
||||||
@import "components/charts";
|
@import "components/charts";
|
||||||
@import "components/checkboxes";
|
@import "components/checkboxes";
|
||||||
@import "components/datepicker";
|
@import "components/datepicker";
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
{% load branding i18n %}
|
{% load branding i18n %}
|
||||||
{% load context_selection %}
|
{% load context_selection %}
|
||||||
|
{% load breadcrumb_nav %}
|
||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
@@ -36,6 +38,10 @@
|
|||||||
<div class='container-fluid'>
|
<div class='container-fluid'>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
|
{% block breadcrumb_nav %}
|
||||||
|
{% breadcrumb_nav %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block page_header %}
|
{% block page_header %}
|
||||||
{% include "horizon/common/_page_header.html" with title=page_title %}
|
{% include "horizon/common/_page_header.html" with title=page_title %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@@ -772,9 +772,9 @@ $badge-border-radius: 10px !default;
|
|||||||
//##
|
//##
|
||||||
|
|
||||||
$breadcrumb-padding-vertical: 8px !default;
|
$breadcrumb-padding-vertical: 8px !default;
|
||||||
$breadcrumb-padding-horizontal: 10px !default;
|
$breadcrumb-padding-horizontal: 15px !default;
|
||||||
//** Breadcrumb background color
|
//** Breadcrumb background color
|
||||||
$breadcrumb-bg: $body-bg !default;
|
$breadcrumb-bg: #f5f5f5 !default;
|
||||||
//** Breadcrumb text color
|
//** Breadcrumb text color
|
||||||
$breadcrumb-color: $gray !default;
|
$breadcrumb-color: $gray !default;
|
||||||
//** Text color of current page in the breadcrumb
|
//** Text color of current page in the breadcrumb
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
.page-header {
|
.page-header {
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
@import "/bootstrap/scss/bootstrap/mixins/_vendor-prefixes.scss";
|
@import "/bootstrap/scss/bootstrap/mixins/_vendor-prefixes.scss";
|
||||||
|
|
||||||
@import "components/breadcrumb_header";
|
|
||||||
@import "components/context_selection";
|
@import "components/context_selection";
|
||||||
@import "components/login";
|
@import "components/login";
|
||||||
@import "components/messages";
|
@import "components/messages";
|
||||||
|
@@ -1,10 +0,0 @@
|
|||||||
/* Breadcrumb used as a header in the details pages */
|
|
||||||
.page-header > .breadcrumb {
|
|
||||||
font-size: $font-size-h3;
|
|
||||||
margin-bottom: 0;
|
|
||||||
padding: 8px 0px;
|
|
||||||
|
|
||||||
.actions_column {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- >
|
||||||
|
[`blueprint navigation-improvements <https://blueprints.launchpad.net/horizon/+spec/navigation-improvements>`_] Breadcrumb navigation has been added across Horizon.
|
||||||
|
|
||||||
|
upgrade:
|
||||||
|
- The breadcrumb navigation inside the details pages now applies across
|
||||||
|
Horizon. A small change in the logic means that ``custom_breadcrumb``
|
||||||
|
items in the context no longer need to specify the panel name and link.
|
||||||
|
See [`blueprint navigation-improvements <https://blueprints.launchpad.net/horizon/+spec/navigation-improvements>`_]
|
Reference in New Issue
Block a user