Allows row status to be determined as the aggregate of multiple columns.
Instances table handles both status columns correctly now. Fixes bug 948419. Syspanel instances table no longer has "launch instance" action. Fixes bug 952609. Allows ajax-updating for volumes table. Fixes bug 948396. Change-Id: I8657c79d0ab7ec5972cc7c4886d7f009a1710876
This commit is contained in:
parent
24f6bc59b2
commit
44f670e104
@ -201,13 +201,20 @@ class InstancesTable(tables.DataTable):
|
|||||||
(None, True),
|
(None, True),
|
||||||
("none", True)
|
("none", True)
|
||||||
)
|
)
|
||||||
|
STATUS_CHOICES = (
|
||||||
|
("active", True),
|
||||||
|
("error", False),
|
||||||
|
)
|
||||||
name = tables.Column("name", link="horizon:nova:instances_and_volumes:" \
|
name = tables.Column("name", link="horizon:nova:instances_and_volumes:" \
|
||||||
"instances:detail",
|
"instances:detail",
|
||||||
verbose_name=_("Instance Name"))
|
verbose_name=_("Instance Name"))
|
||||||
ip = tables.Column(get_ips, verbose_name=_("IP Address"))
|
ip = tables.Column(get_ips, verbose_name=_("IP Address"))
|
||||||
size = tables.Column(get_size, verbose_name=_("Size"))
|
size = tables.Column(get_size, verbose_name=_("Size"))
|
||||||
status = tables.Column("status", filters=(title,),
|
status = tables.Column("status",
|
||||||
verbose_name=_("Status"))
|
filters=(title,),
|
||||||
|
verbose_name=_("Status"),
|
||||||
|
status=True,
|
||||||
|
status_choices=STATUS_CHOICES)
|
||||||
task = tables.Column("OS-EXT-STS:task_state",
|
task = tables.Column("OS-EXT-STS:task_state",
|
||||||
verbose_name=_("Task"),
|
verbose_name=_("Task"),
|
||||||
filters=(title,),
|
filters=(title,),
|
||||||
@ -220,7 +227,7 @@ class InstancesTable(tables.DataTable):
|
|||||||
class Meta:
|
class Meta:
|
||||||
name = "instances"
|
name = "instances"
|
||||||
verbose_name = _("Instances")
|
verbose_name = _("Instances")
|
||||||
status_column = "task"
|
status_columns = ["status", "task"]
|
||||||
table_actions = (LaunchLink, TerminateInstance)
|
table_actions = (LaunchLink, TerminateInstance)
|
||||||
row_actions = (EditInstance, ConsoleLink, LogLink, SnapshotLink,
|
row_actions = (EditInstance, ConsoleLink, LogLink, SnapshotLink,
|
||||||
TogglePause, ToggleSuspend, RebootInstance,
|
TogglePause, ToggleSuspend, RebootInstance,
|
||||||
|
@ -74,6 +74,12 @@ class CreateSnapshot(tables.LinkAction):
|
|||||||
return volume.status == "available"
|
return volume.status == "available"
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateRow(tables.UpdateAction):
|
||||||
|
def get_data(self, request, volume_id):
|
||||||
|
volume = api.volume_get(request, volume_id)
|
||||||
|
return volume
|
||||||
|
|
||||||
|
|
||||||
def get_size(volume):
|
def get_size(volume):
|
||||||
return _("%s GB") % volume.size
|
return _("%s GB") % volume.size
|
||||||
|
|
||||||
@ -95,12 +101,21 @@ def get_attachment(volume):
|
|||||||
|
|
||||||
|
|
||||||
class VolumesTableBase(tables.DataTable):
|
class VolumesTableBase(tables.DataTable):
|
||||||
|
STATUS_CHOICES = (
|
||||||
|
("in-use", True),
|
||||||
|
("available", True),
|
||||||
|
("creating", None),
|
||||||
|
("error", False),
|
||||||
|
)
|
||||||
name = tables.Column("displayName", verbose_name=_("Name"))
|
name = tables.Column("displayName", verbose_name=_("Name"))
|
||||||
description = tables.Column("displayDescription",
|
description = tables.Column("displayDescription",
|
||||||
verbose_name=_("Description"))
|
verbose_name=_("Description"))
|
||||||
size = tables.Column(get_size, verbose_name=_("Size"))
|
size = tables.Column(get_size, verbose_name=_("Size"))
|
||||||
status = tables.Column("status", filters=(title,),
|
status = tables.Column("status",
|
||||||
verbose_name=_("Status"))
|
filters=(title,),
|
||||||
|
verbose_name=_("Status"),
|
||||||
|
status=True,
|
||||||
|
status_choices=STATUS_CHOICES)
|
||||||
|
|
||||||
def get_object_display(self, obj):
|
def get_object_display(self, obj):
|
||||||
return obj.displayName
|
return obj.displayName
|
||||||
@ -113,8 +128,10 @@ class VolumesTable(VolumesTableBase):
|
|||||||
class Meta:
|
class Meta:
|
||||||
name = "volumes"
|
name = "volumes"
|
||||||
verbose_name = _("Volumes")
|
verbose_name = _("Volumes")
|
||||||
|
status_columns = ["status"]
|
||||||
table_actions = (CreateVolume, DeleteVolume,)
|
table_actions = (CreateVolume, DeleteVolume,)
|
||||||
row_actions = (EditAttachments, CreateSnapshot, DeleteVolume)
|
row_actions = (EditAttachments, CreateSnapshot,
|
||||||
|
DeleteVolume, UpdateRow)
|
||||||
|
|
||||||
|
|
||||||
class DetachVolume(tables.BatchAction):
|
class DetachVolume(tables.BatchAction):
|
||||||
|
@ -38,6 +38,10 @@ class SyspanelInstancesTable(tables.DataTable):
|
|||||||
(None, True),
|
(None, True),
|
||||||
("none", True)
|
("none", True)
|
||||||
)
|
)
|
||||||
|
STATUS_CHOICES = (
|
||||||
|
("active", True),
|
||||||
|
("error", False),
|
||||||
|
)
|
||||||
tenant = tables.Column("tenant_name", verbose_name=_("Tenant"))
|
tenant = tables.Column("tenant_name", verbose_name=_("Tenant"))
|
||||||
user = tables.Column("user_id", verbose_name=_("User"))
|
user = tables.Column("user_id", verbose_name=_("User"))
|
||||||
internal_id = tables.Column("internal_identifier",
|
internal_id = tables.Column("internal_identifier",
|
||||||
@ -48,8 +52,11 @@ class SyspanelInstancesTable(tables.DataTable):
|
|||||||
verbose_name=_("Instance Name"))
|
verbose_name=_("Instance Name"))
|
||||||
ip = tables.Column(get_ips, verbose_name=_("IP Address"))
|
ip = tables.Column(get_ips, verbose_name=_("IP Address"))
|
||||||
size = tables.Column(get_size, verbose_name=_("Size"))
|
size = tables.Column(get_size, verbose_name=_("Size"))
|
||||||
status = tables.Column("status", filters=(title,),
|
status = tables.Column("status",
|
||||||
verbose_name=_("Status"))
|
filters=(title,),
|
||||||
|
verbose_name=_("Status"),
|
||||||
|
status=True,
|
||||||
|
status_choices=STATUS_CHOICES)
|
||||||
task = tables.Column("OS-EXT-STS:task_state",
|
task = tables.Column("OS-EXT-STS:task_state",
|
||||||
verbose_name=_("Task"),
|
verbose_name=_("Task"),
|
||||||
filters=(title,),
|
filters=(title,),
|
||||||
@ -62,8 +69,8 @@ class SyspanelInstancesTable(tables.DataTable):
|
|||||||
class Meta:
|
class Meta:
|
||||||
name = "instances"
|
name = "instances"
|
||||||
verbose_name = _("Instances")
|
verbose_name = _("Instances")
|
||||||
status_column = "task"
|
status_columns = ["status", "task"]
|
||||||
table_actions = (LaunchLink, TerminateInstance)
|
table_actions = (TerminateInstance,)
|
||||||
row_actions = (EditInstance, ConsoleLink, LogLink, SnapshotLink,
|
row_actions = (EditInstance, ConsoleLink, LogLink, SnapshotLink,
|
||||||
TogglePause, ToggleSuspend, RebootInstance,
|
TogglePause, ToggleSuspend, RebootInstance,
|
||||||
TerminateInstance, UpdateRow)
|
TerminateInstance, UpdateRow)
|
||||||
|
@ -55,4 +55,4 @@ class ServicesTable(tables.DataTable):
|
|||||||
verbose_name = _("Services")
|
verbose_name = _("Services")
|
||||||
table_actions = (ServiceFilterAction,)
|
table_actions = (ServiceFilterAction,)
|
||||||
multi_select = False
|
multi_select = False
|
||||||
status_column = "enabled"
|
status_columns = ["enabled"]
|
||||||
|
@ -264,8 +264,8 @@ class Row(object):
|
|||||||
|
|
||||||
.. attribute:: status
|
.. attribute:: status
|
||||||
|
|
||||||
Boolean value representing the status of this row according
|
Boolean value representing the status of this row calculated from
|
||||||
to the value of the table's ``status_column`` value if it is set.
|
the values of the table's ``status_columns`` if they are set.
|
||||||
|
|
||||||
.. attribute:: status_class
|
.. attribute:: status_class
|
||||||
|
|
||||||
@ -299,15 +299,17 @@ class Row(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def status(self):
|
def status(self):
|
||||||
column_name = self.table._meta.status_column
|
column_names = self.table._meta.status_columns
|
||||||
if column_name:
|
if column_names:
|
||||||
return self.cells[column_name].status
|
statuses = dict([(column_name, self.cells[column_name].status) for
|
||||||
|
column_name in column_names])
|
||||||
|
return self.table.calculate_row_status(statuses)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def status_class(self):
|
def status_class(self):
|
||||||
column_name = self.table._meta.status_column
|
column_names = self.table._meta.status_columns
|
||||||
if column_name:
|
if column_names:
|
||||||
return self.cells[column_name].get_status_class(self.status)
|
return self.table.get_row_status_class(self.status)
|
||||||
else:
|
else:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
@ -371,7 +373,7 @@ class Cell(object):
|
|||||||
return self._status
|
return self._status
|
||||||
|
|
||||||
if self.column.status or \
|
if self.column.status or \
|
||||||
self.column.table._meta.status_column == self.column.name:
|
self.column.name in self.column.table._meta.status_columns:
|
||||||
#returns the first matching status found
|
#returns the first matching status found
|
||||||
data_value_lower = unicode(self.data).lower()
|
data_value_lower = unicode(self.data).lower()
|
||||||
for status_name, status_value in self.column.status_choices:
|
for status_name, status_value in self.column.status_choices:
|
||||||
@ -453,20 +455,18 @@ class DataTableOptions(object):
|
|||||||
The name of the context variable which will contain the table when
|
The name of the context variable which will contain the table when
|
||||||
it is rendered. Defaults to ``"table"``.
|
it is rendered. Defaults to ``"table"``.
|
||||||
|
|
||||||
.. attribute:: status_column
|
.. attribute:: status_columns
|
||||||
|
|
||||||
The name of a column on this table which represents the "state"
|
A list or tuple of column names which represents the "state"
|
||||||
of the data object being represented. The collumn must already be
|
of the data object being represented.
|
||||||
designated as a status column by passing the ``status=True``
|
|
||||||
parameter to the column.
|
|
||||||
|
|
||||||
If ``status_column`` is set, when the rows are rendered the value
|
If ``status_columns`` is set, when the rows are rendered the value
|
||||||
of this column will be used to add an extra class to the row in
|
of this column will be used to add an extra class to the row in
|
||||||
the form of ``"status_up"`` or ``"status_down"`` for that row's
|
the form of ``"status_up"`` or ``"status_down"`` for that row's
|
||||||
data.
|
data.
|
||||||
|
|
||||||
This is useful for displaying the enabled/disabled status of a
|
The row status is used by other Horizon components to trigger tasks
|
||||||
service, for example.
|
such as dynamic AJAX updating.
|
||||||
|
|
||||||
.. attribute:: row_class
|
.. attribute:: row_class
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ class DataTableOptions(object):
|
|||||||
or self.name.title()
|
or self.name.title()
|
||||||
self.verbose_name = unicode(verbose_name)
|
self.verbose_name = unicode(verbose_name)
|
||||||
self.columns = getattr(options, 'columns', None)
|
self.columns = getattr(options, 'columns', None)
|
||||||
self.status_column = getattr(options, 'status_column', None)
|
self.status_columns = getattr(options, 'status_columns', [])
|
||||||
self.table_actions = getattr(options, 'table_actions', [])
|
self.table_actions = getattr(options, 'table_actions', [])
|
||||||
self.row_actions = getattr(options, 'row_actions', [])
|
self.row_actions = getattr(options, 'row_actions', [])
|
||||||
self.row_class = getattr(options, 'row_class', Row)
|
self.row_class = getattr(options, 'row_class', Row)
|
||||||
@ -893,6 +893,46 @@ class DataTable(object):
|
|||||||
"""
|
"""
|
||||||
return http.urlquote_plus(self.get_object_id(self.data[-1]))
|
return http.urlquote_plus(self.get_object_id(self.data[-1]))
|
||||||
|
|
||||||
|
def calculate_row_status(self, statuses):
|
||||||
|
"""
|
||||||
|
Returns a boolean value determining the overall row status
|
||||||
|
based on the dictionary of column name to status mappings passed in.
|
||||||
|
|
||||||
|
By default, it uses the following logic:
|
||||||
|
|
||||||
|
#. If any statuses are ``False``, return ``False``.
|
||||||
|
#. If no statuses are ``False`` but any or ``None``, return ``None``.
|
||||||
|
#. If all statuses are ``True``, return ``True``.
|
||||||
|
|
||||||
|
This provides the greatest protection against false positives without
|
||||||
|
weighting any particular columns.
|
||||||
|
|
||||||
|
The ``statuses`` parameter is passed in as a dictionary mapping
|
||||||
|
column names to their statuses in order to allow this function to
|
||||||
|
be overridden in such a way as to weight one column's status over
|
||||||
|
another should that behavior be desired.
|
||||||
|
"""
|
||||||
|
values = statuses.values()
|
||||||
|
if any([status is False for status in values]):
|
||||||
|
return False
|
||||||
|
elif any([status is None for status in values]):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_row_status_class(self, status):
|
||||||
|
"""
|
||||||
|
Returns a css class name determined by the status value. This class
|
||||||
|
name is used to indicate the status of the rows in the table if
|
||||||
|
any ``status_columns`` have been specified.
|
||||||
|
"""
|
||||||
|
if status is True:
|
||||||
|
return "status_up"
|
||||||
|
elif status is False:
|
||||||
|
return "status_down"
|
||||||
|
else:
|
||||||
|
return "status_unknown"
|
||||||
|
|
||||||
def get_columns(self):
|
def get_columns(self):
|
||||||
""" Returns this table's columns including auto-generated ones."""
|
""" Returns this table's columns including auto-generated ones."""
|
||||||
return self.columns.values()
|
return self.columns.values()
|
||||||
|
@ -147,7 +147,7 @@ class MyTable(tables.DataTable):
|
|||||||
class Meta:
|
class Meta:
|
||||||
name = "my_table"
|
name = "my_table"
|
||||||
verbose_name = "My Table"
|
verbose_name = "My Table"
|
||||||
status_column = "status"
|
status_columns = ["status"]
|
||||||
columns = ('id', 'name', 'value', 'optional', 'status')
|
columns = ('id', 'name', 'value', 'optional', 'status')
|
||||||
table_actions = (MyFilterAction, MyAction, MyBatchAction)
|
table_actions = (MyFilterAction, MyAction, MyBatchAction)
|
||||||
row_actions = (MyAction, MyLinkAction, MyUpdateAction,
|
row_actions = (MyAction, MyLinkAction, MyUpdateAction,
|
||||||
|
Loading…
Reference in New Issue
Block a user