diff --git a/horizon/tables/base.py b/horizon/tables/base.py index 8f3c54ced7..eb34512589 100644 --- a/horizon/tables/base.py +++ b/horizon/tables/base.py @@ -561,6 +561,12 @@ class Row(html.HTMLElement): "obj_id": self.table.get_object_id(self.datum)}) return "%s?%s" % (table_url, params) + def can_be_selected(self, datum): + """By default if multiselect enabled return True. You can remove the + checkbox after an ajax update here if required. + """ + return True + def get_data(self, request, obj_id): """Fetches the updated data for the row based on the object id passed in. Must be implemented by a subclass to allow AJAX updating. @@ -594,11 +600,13 @@ class Cell(html.HTMLElement): """Fetches the data to be displayed in this cell.""" table = row.table if column.auto == "multi_select": - widget = forms.CheckboxInput(check_test=lambda value: False) - # Convert value to string to avoid accidental type conversion - data = widget.render('object_ids', - unicode(table.get_object_id(datum)), - {'class': 'table-row-multi-select'}) + data = "" + if row.can_be_selected(datum): + widget = forms.CheckboxInput(check_test=lambda value: False) + # Convert value to string to avoid accidental type conversion + data = widget.render('object_ids', + unicode(table.get_object_id(datum)), + {'class': 'table-row-multi-select'}) table._data_cache[column][table.get_object_id(datum)] = data elif column.auto == "form_field": widget = column.form_field diff --git a/horizon/test/tests/tables.py b/horizon/test/tests/tables.py index 3f338b50ed..64bba3d52f 100644 --- a/horizon/test/tests/tables.py +++ b/horizon/test/tests/tables.py @@ -65,6 +65,11 @@ TEST_DATA_5 = ( 'down', 'optional_1'), ) +TEST_DATA_6 = ( + FakeObject('1', 'object_1', 'DELETED', 'down'), + FakeObject('2', 'object_2', 'CREATED', 'up'), +) + class MyLinkAction(tables.LinkAction): name = "login" @@ -95,6 +100,13 @@ class MyColumn(tables.Column): pass +class MyRowSelectable(tables.Row): + ajax = True + + def can_be_selected(self, datum): + return datum.value != 'DELETED' + + class MyRow(tables.Row): ajax = True @@ -198,6 +210,15 @@ class MyTable(tables.DataTable): row_actions = (MyAction, MyLinkAction, MyBatchAction, MyToggleAction) +class MyTableSelectable(MyTable): + class Meta: + name = "my_table" + columns = ('id', 'name', 'value', 'status') + row_class = MyRowSelectable + status_columns = ["status"] + multi_select = True + + class MyTableNotAllowedInlineEdit(MyTable): name = tables.Column(get_name, verbose_name="Verbose Name", @@ -1013,6 +1034,63 @@ class DataTableTests(test.TestCase): self.assertEqual(list(req._messages)[0].message, u"Downed Item: N/A") + def test_table_column_can_be_selected(self): + self.table = MyTableSelectable(self.request, TEST_DATA_6) + #non selectable row + row = self.table.get_rows()[0] + #selectable + row1 = self.table.get_rows()[1] + + id_col = self.table.columns['id'] + name_col = self.table.columns['name'] + value_col = self.table.columns['value'] + # transform + self.assertEqual(row.cells['id'].data, '1') # Standard attr access + self.assertEqual(row.cells['name'].data, 'custom object_1') # Callable + # name and verbose_name + self.assertEqual(unicode(id_col), "Id") + self.assertEqual(unicode(name_col), "Verbose Name") + self.assertIn("sortable", name_col.get_final_attrs().get('class', "")) + # hidden + self.assertEqual(id_col.hidden, True) + self.assertIn("hide", id_col.get_final_attrs().get('class', "")) + self.assertEqual(name_col.hidden, False) + self.assertNotIn("hide", name_col.get_final_attrs().get('class', "")) + # link, link_classes and get_link_url + self.assertIn('href="http://example.com/"', row.cells['value'].value) + self.assertIn('class="link-modal"', row.cells['value'].value) + self.assertIn('href="/auth/login/"', row.cells['status'].value) + # classes + self.assertEqual(value_col.get_final_attrs().get('class', ""), + "green blue sortable anchor normal_column") + + self.assertQuerysetEqual(row.get_cells(), + ['', + '', + '', + '', + '', + ]) + #can_be_selected = False + self.assertTrue(row.get_cells()[0].data == "") + #can_be_selected = True + self.assertIn('checkbox', row1.get_cells()[0].data) + #status + cell_status = row.cells['status'].status + self.assertEqual(row.cells['status'].get_status_class(cell_status), + 'status_down') + # status_choices + id_col.status = True + id_col.status_choices = (('1', False), ('2', True)) + cell_status = row.cells['id'].status + self.assertEqual(cell_status, False) + self.assertEqual(row.cells['id'].get_status_class(cell_status), + 'status_down') + # Ensure data is not cached on the column across table instances + self.table = MyTable(self.request, TEST_DATA_6) + row = self.table.get_rows()[0] + self.assertTrue("down" in row.cells['status'].value) + class SingleTableView(table_views.DataTableView): table_class = MyTable