Minor extensibility improvements.
* Allow exceptions.handle to include user-defined exception types. Fixes bug 948536. * Adds a wrapper around the form/table header/table in the base _data_table.html template for easier targeting/styling. * Moves the rest of the main nav templating into a single template for easier customization. Fixes bug 948508. Change-Id: I045c29744ee01f60b080f2c1bbdc79ea5acf1b86
This commit is contained in:
parent
8ff0f46b46
commit
a32f67967e
@ -49,6 +49,9 @@ HORIZON_CONFIG = {
|
||||
# Name of a default dashboard; defaults to first alphabetically if None
|
||||
'default_dashboard': None,
|
||||
'user_home': None,
|
||||
'exceptions': {'unauthorized': [],
|
||||
'not_found': [],
|
||||
'recoverable': []}
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,6 +21,7 @@ Exceptions raised by the Horizon code and the machinery for handling them.
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.utils.translation import ugettext as _
|
||||
from cloudfiles import errors as swiftclient
|
||||
@ -107,6 +108,10 @@ class HandledException(HorizonException):
|
||||
self.wrapped = wrapped
|
||||
|
||||
|
||||
HORIZON_CONFIG = getattr(settings, "HORIZON_CONFIG", {})
|
||||
EXCEPTION_CONFIG = HORIZON_CONFIG.get("exceptions", {})
|
||||
|
||||
|
||||
UNAUTHORIZED = (keystoneclient.Unauthorized,
|
||||
keystoneclient.Forbidden,
|
||||
novaclient.Unauthorized,
|
||||
@ -115,12 +120,15 @@ UNAUTHORIZED = (keystoneclient.Unauthorized,
|
||||
glanceclient.NotAuthorized,
|
||||
swiftclient.AuthenticationFailed,
|
||||
swiftclient.AuthenticationError)
|
||||
UNAUTHORIZED += tuple(EXCEPTION_CONFIG.get('unauthorized', []))
|
||||
|
||||
NOT_FOUND = (keystoneclient.NotFound,
|
||||
novaclient.NotFound,
|
||||
glanceclient.NotFound,
|
||||
swiftclient.NoSuchContainer,
|
||||
swiftclient.NoSuchObject)
|
||||
NOT_FOUND += tuple(EXCEPTION_CONFIG.get('not_found', []))
|
||||
|
||||
|
||||
# NOTE(gabriel): This is very broad, and may need to be dialed in.
|
||||
RECOVERABLE = (keystoneclient.ClientException,
|
||||
@ -128,6 +136,7 @@ RECOVERABLE = (keystoneclient.ClientException,
|
||||
glanceclient.GlanceException,
|
||||
swiftclient.Error,
|
||||
AlreadyExists)
|
||||
RECOVERABLE += tuple(EXCEPTION_CONFIG.get('recoverable', []))
|
||||
|
||||
|
||||
def handle(request, message=None, redirect=None, ignore=False, escalate=False):
|
||||
|
@ -1,9 +1,13 @@
|
||||
{% load horizon %}
|
||||
{% for component in components %}
|
||||
{% load horizon i18n %}
|
||||
<h1 class="brand clearfix"><a href="{% url horizon:user_home %}">{% trans "OpenStack Dashboard" %}</a></h1>
|
||||
<div class='clearfix'>
|
||||
<ul class="nav nav-tabs">
|
||||
{% for component in components %}
|
||||
{% if user|can_haz:component %}
|
||||
<li{% if current == component.slug %} class="active"{% endif %}>
|
||||
<a href="{{ component.get_absolute_url }}" tabindex='1'>{{ component.name }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1,37 +1,39 @@
|
||||
<form action="{{ table.get_absolute_url }}" method="POST">{% csrf_token %}
|
||||
<div class='table_header'>
|
||||
<h3 class='table_title'>{{ table }}</h3>
|
||||
{{ table.render_table_actions }}
|
||||
</div>
|
||||
{% with columns=table.get_columns rows=table.get_rows %}
|
||||
<table id="{{ table.name }}" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for column in columns %}
|
||||
<th class="{{ column.get_classes }}">{{ column }}</th>
|
||||
{% endfor %}
|
||||
<div class="table_wrapper">
|
||||
<form action="{{ table.get_absolute_url }}" method="POST">{% csrf_token %}
|
||||
<div class='table_header'>
|
||||
<h3 class='table_title'>{{ table }}</h3>
|
||||
{{ table.render_table_actions }}
|
||||
</div>
|
||||
{% with columns=table.get_columns rows=table.get_rows %}
|
||||
<table id="{{ table.name }}" class="table table-bordered table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
{% for column in columns %}
|
||||
<th class="{{ column.get_classes }}">{{ column }}</th>
|
||||
{% endfor %}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
{{ row.render }}
|
||||
{% empty %}
|
||||
<tr class="{% cycle 'odd' 'even' %} empty">
|
||||
<td colspan="{{ table.get_columns|length }}">{{ table.get_empty_message }}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in rows %}
|
||||
{{ row.render }}
|
||||
{% empty %}
|
||||
<tr class="{% cycle 'odd' 'even' %} empty">
|
||||
<td colspan="{{ table.get_columns|length }}">{{ table.get_empty_message }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="{{ table.get_columns|length }}">
|
||||
<span>Displaying {{ rows|length }} item{{ rows|pluralize }}</span>
|
||||
{% if table.has_more_data %}
|
||||
<span class="spacer">|</span>
|
||||
<a href="?marker={{ table.get_marker }}">More »</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="{{ table.get_columns|length }}">
|
||||
<span>Displaying {{ rows|length }} item{{ rows|pluralize }}</span>
|
||||
{% if table.has_more_data %}
|
||||
<span class="spacer">|</span>
|
||||
<a href="?marker={{ table.get_marker }}">More »</a>
|
||||
{% endif %}
|
||||
</td>
|
||||
</td>
|
||||
</td>
|
||||
</tfoot>
|
||||
</table>
|
||||
{% endwith %}
|
||||
</form>
|
||||
</tfoot>
|
||||
</table>
|
||||
{% endwith %}
|
||||
</form>
|
||||
</div>
|
||||
|
@ -1,12 +1,7 @@
|
||||
{% load horizon i18n %}
|
||||
|
||||
<div class='sidebar'>
|
||||
<h1 class="brand clearfix"><a href="{% url horizon:user_home %}">{% trans "OpenStack Dashboard" %}</a></h1>
|
||||
<div class='clearfix'>
|
||||
<ul class="nav nav-tabs">
|
||||
{% horizon_main_nav %}
|
||||
</ul>
|
||||
</div>
|
||||
{% horizon_main_nav %}
|
||||
|
||||
{% if request.horizon.dashboard.supports_tenants %}
|
||||
<div id="tenant_switcher" class="dropdown switcher_bar" tabindex='1'>
|
||||
|
Loading…
x
Reference in New Issue
Block a user