diff --git a/horizon/dashboards/nova/containers/tables.py b/horizon/dashboards/nova/containers/tables.py index f19b7c4d0..f450e5165 100644 --- a/horizon/dashboards/nova/containers/tables.py +++ b/horizon/dashboards/nova/containers/tables.py @@ -92,7 +92,9 @@ class ContainersTable(tables.DataTable): objects = tables.Column("object_count", verbose_name=_('Objects'), empty_value="0") - size = tables.Column(get_size_used, verbose_name=_('Size')) + size = tables.Column(get_size_used, + verbose_name=_('Size'), + attrs={'data-type': 'size'}) def get_object_id(self, container): return container.name @@ -159,7 +161,8 @@ class ObjectsTable(tables.DataTable): size = tables.Column("size", verbose_name=_('Size'), filters=(filesizeformat,), - summation="sum") + summation="sum", + attrs={'data-type': 'size'}) def get_object_id(self, obj): return obj.name diff --git a/horizon/dashboards/nova/instances/tables.py b/horizon/dashboards/nova/instances/tables.py index 116ce1540..f42d191ad 100644 --- a/horizon/dashboards/nova/instances/tables.py +++ b/horizon/dashboards/nova/instances/tables.py @@ -268,7 +268,9 @@ class InstancesTable(tables.DataTable): link=("horizon:nova:instances:detail"), verbose_name=_("Instance Name")) 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"), + attrs={'data-type': 'size'}) keypair = tables.Column(get_keyname, verbose_name=_("Keypair")) status = tables.Column("status", filters=(title, replace_underscores), diff --git a/horizon/dashboards/nova/volumes/tables.py b/horizon/dashboards/nova/volumes/tables.py index 5d6e082d9..59239d02b 100644 --- a/horizon/dashboards/nova/volumes/tables.py +++ b/horizon/dashboards/nova/volumes/tables.py @@ -137,7 +137,9 @@ class VolumesTableBase(tables.DataTable): description = tables.Column("display_description", verbose_name=_("Description"), truncate=40) - size = tables.Column(get_size, verbose_name=_("Size")) + size = tables.Column(get_size, + verbose_name=_("Size"), + attrs={'data-type': 'size'}) status = tables.Column("status", filters=(title,), verbose_name=_("Status"), diff --git a/horizon/dashboards/syspanel/flavors/tables.py b/horizon/dashboards/syspanel/flavors/tables.py index 3380725ad..d17e2d37c 100644 --- a/horizon/dashboards/syspanel/flavors/tables.py +++ b/horizon/dashboards/syspanel/flavors/tables.py @@ -24,11 +24,17 @@ class CreateFlavor(tables.LinkAction): classes = ("ajax-modal", "btn-create") +def get_size(flavor): + return _("%sMB") % flavor.ram + + class FlavorsTable(tables.DataTable): flavor_id = tables.Column('id', verbose_name=('ID')) name = tables.Column('name', verbose_name=_('Flavor Name')) vcpus = tables.Column('vcpus', verbose_name=_('VCPUs')) - ram = tables.Column('ram', verbose_name=_('Memory')) + ram = tables.Column(get_size, + verbose_name=_('Memory'), + attrs={'data-type': 'size'}) disk = tables.Column('disk', verbose_name=_('Root Disk')) ephemeral = tables.Column('OS-FLV-EXT-DATA:ephemeral', verbose_name=_('Ephemeral Disk')) @@ -37,4 +43,4 @@ class FlavorsTable(tables.DataTable): name = "flavors" verbose_name = _("Flavors") table_actions = (CreateFlavor, DeleteFlavor) - row_actions = (DeleteFlavor, ) + row_actions = (DeleteFlavor,) diff --git a/horizon/dashboards/syspanel/instances/tables.py b/horizon/dashboards/syspanel/instances/tables.py index 8933258d6..62f097f60 100644 --- a/horizon/dashboards/syspanel/instances/tables.py +++ b/horizon/dashboards/syspanel/instances/tables.py @@ -74,7 +74,8 @@ class SyspanelInstancesTable(tables.DataTable): ip = tables.Column(get_ips, verbose_name=_("IP Address")) size = tables.Column(get_size, verbose_name=_("Size"), - classes=('nowrap-col',)) + classes=('nowrap-col',), + attrs={'data-type': 'size'}) status = tables.Column("status", filters=(title, replace_underscores), verbose_name=_("Status"), diff --git a/horizon/static/horizon/js/horizon.tables.js b/horizon/static/horizon/js/horizon.tables.js index 752dab5df..5d6849b48 100644 --- a/horizon/static/horizon/js/horizon.tables.js +++ b/horizon/static/horizon/js/horizon.tables.js @@ -148,21 +148,50 @@ horizon.datatables.confirm = function (action) { return modal; }; +$.tablesorter.addParser({ + // set a unique id + id: 'sizeSorter', + is: function(s) { + // Not an auto-detected parser + return false; + }, + // compare int values + format: function(s) { + var sizes = {BYTE: 0, B: 0, KB: 1, MB: 2, + GB: 3, TB: 4, PB: 5}; + var regex = /([\d\.,]+)\s*(byte|B|KB|MB|GB|TB|PB)+/i; + var match = s.match(regex); + if (match && match.length === 3){ + return parseFloat(match[1]) * + Math.pow(1024, sizes[match[2].toUpperCase()]); + } + return parseInt(s, 10); + }, + type: 'numeric' +}); + horizon.datatables.set_table_sorting = function (parent) { // Function to initialize the tablesorter plugin strictly on sortable columns. $(parent).find("table.table").each(function () { - var $this = $(this), + var $table = $(this), header_options = {}; - $this.find("thead th").each(function (i, val) { - // Disable if not sortable or has <= 1 item - if (!$(this).hasClass('sortable') || $this.find('tbody tr').not('.empty').length <= 1) { - header_options[i] = {sorter: false}; - } - }); - $this.tablesorter({ - headers: header_options, - cancelSelection: false - }); + // Disable if not sortable or has <= 1 item + if ($table.find('tbody tr').not('.empty').length > 1){ + $table.find("thead th").each(function (i, val) { + $th = $(this); + if (!$th.hasClass('sortable')) { + header_options[i] = {sorter: false}; + } else if ($th.data('type') == 'size'){ + // set as [i-1] as there is one more