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:
parent
ff09b75886
commit
e98f2429fa
|
@ -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)
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -581,12 +581,19 @@ class DataTableTests(test.TestCase):
|
|||
update_string = "action=row_update&table=my_table&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">'
|
||||
'<strong>evil</strong></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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,)
|
||||
|
|
Loading…
Reference in New Issue