Remove duplicated headings from horizon tables

Many panels in horizon only contain a single table, in these cases the
tables often have the same name as the panel, leading to duplicated
headings, e.g. Instances (panel heading) then Instances (table
heading). This patch adds an attribute the table to hide or show the
title, since the majority of panels have this duplication this flag
is set to hide the heading by default allowing a developer to re-enable
it for specific cases.

Tabbed panels also often lead to duplicated titles between the panel
heading and the tabs themselves, that is not fixed, however how this
patch reduces the duplication in the case of Volumes (panel name),
Volumes (tab name) and Volumes (table name), by hiding the table
heading.

Change-Id: I65efa53cc881417288e5c5b29bfa7d539e97c7dd
Closes-Bug: 1379044
This commit is contained in:
Sam Betts 2014-11-12 14:38:48 +00:00
parent ff09b75886
commit e98f2429fa
6 changed files with 24 additions and 2 deletions

View File

@ -943,6 +943,11 @@ class DataTableOptions(object):
Boolean to control whether or not to show the table's footer.
Default: ``True``.
.. attribute:: hidden_title
Boolean to control whether or not to show the table's title.
Default: ``True``.
.. attribute:: permissions
A list of permission names which this table requires in order to be
@ -968,6 +973,7 @@ class DataTableOptions(object):
self.pagination_param = getattr(options, 'pagination_param', 'marker')
self.browser_table = getattr(options, 'browser_table', None)
self.footer = getattr(options, 'footer', True)
self.hidden_title = getattr(options, 'hidden_title', True)
self.no_data_message = getattr(options,
"no_data_message",
_("No items to display."))
@ -1253,7 +1259,8 @@ class DataTable(object):
def render(self):
"""Renders the table using the template from the table options."""
table_template = template.loader.get_template(self._meta.template)
extra_context = {self._meta.context_var_name: self}
extra_context = {self._meta.context_var_name: self,
'hidden_title': self._meta.hidden_title}
context = template.RequestContext(self.request, extra_context)
return table_template.render(context)

View File

@ -9,7 +9,9 @@
{% block table_caption %}
<tr class='table_caption'>
<th class='table_header' colspan='{{ columns|length }}'>
<h3 class='table_title'>{{ table }}</h3>
{% if not hidden_title %}
<h3 class='table_title'>{{ table }}</h3>
{% endif %}
{{ table.render_table_actions }}
</th>
</tr>

View File

@ -581,12 +581,19 @@ class DataTableTests(test.TestCase):
update_string = "action=row_update&amp;table=my_table&amp;obj_id="
self.assertContains(resp, update_string, 3)
self.assertContains(resp, "data-update-interval", 3)
# Verify no table heading
self.assertNotContains(resp, "<h3 class='table_title'")
# Verify our XSS protection
self.assertContains(resp, '<a href="http://example.com/" '
'data-tip="click for dialog" '
'data-type="modal dialog" '
'class="link-modal">'
'&lt;strong&gt;evil&lt;/strong&gt;</a>', 1)
# Hidden Title = False shows the table title
self.table._meta.hidden_title = False
resp = http.HttpResponse(self.table.render())
self.assertContains(resp, "<h3 class='table_title'", 1)
# Filter = False hides the search box
self.table._meta.filter = False
table_actions = self.table.render_table_actions()

View File

@ -139,6 +139,7 @@ class HostAggregatesTable(tables.DataTable):
class Meta:
name = "host_aggregates"
hidden_title = False
verbose_name = _("Host Aggregates")
table_actions = (AggregateFilterAction,
CreateAggregateAction,
@ -166,6 +167,7 @@ class AvailabilityZonesTable(tables.DataTable):
class Meta:
name = "availability_zones"
hidden_title = False
verbose_name = _("Availability Zones")
table_actions = (AvailabilityZoneFilterAction,)
multi_select = False

View File

@ -80,6 +80,7 @@ class VolumeTypesTable(tables.DataTable):
class Meta:
name = "volume_types"
hidden_title = False
verbose_name = _("Volume Types")
table_actions = (CreateVolumeType, DeleteVolumeType,)
row_actions = (ViewVolumeTypeExtras,
@ -158,6 +159,7 @@ class QosSpecsTable(tables.DataTable):
class Meta:
name = "qos_specs"
hidden_title = False
verbose_name = _("QoS Specs")
table_actions = (CreateQosSpec, DeleteQosSpecs,)
row_actions = (ManageQosSpec, EditConsumer, DeleteQosSpecs)

View File

@ -54,6 +54,7 @@ class GlobalUsageTable(BaseUsageTable):
class Meta:
name = "global_usage"
hidden_title = False
verbose_name = _("Usage")
columns = ("project", "vcpus", "disk", "memory",
"hours", "disk_hours")
@ -83,6 +84,7 @@ class ProjectUsageTable(BaseUsageTable):
class Meta:
name = "project_usage"
hidden_title = False
verbose_name = _("Usage")
columns = ("instance", "vcpus", "disk", "memory", "uptime")
table_actions = (CSVSummary,)