Table checkbox display problem when updating row
Multi-process: If there only one table action, DeleteAction. Assume the first time retrieving an empty table in one process, the checkbox is hidden. In the other process, creating a item, like a instance. Now, the checkbox is shown in second process. Then updating the item state in first process, the checkbox will be hidden. In second process, the checkbox will be shown. For above case, we need set the checkbox visibility every time when updating single row by ajax. Change-Id: Ib230ad775070ee089c8f82e7df3ec30c1cda7aa0 Closes-Bug: #1799151
This commit is contained in:
parent
673bf049a0
commit
3ac9037677
@ -687,7 +687,10 @@ class BatchAction(Action):
|
||||
def _allowed(self, request, datum=None):
|
||||
# Override the default internal action method to prevent batch
|
||||
# actions from appearing on tables with no data.
|
||||
if not self.table.data and not datum:
|
||||
# Updating single row of table by ajax prove that there is one
|
||||
# data at least.
|
||||
action = request.GET.get('action')
|
||||
if action != 'row_update' and not self.table.data and not datum:
|
||||
return False
|
||||
return super(BatchAction, self)._allowed(request, datum)
|
||||
|
||||
|
@ -1105,6 +1105,8 @@ class DataTableOptions(object):
|
||||
# Set self.filter if we have any FilterActions
|
||||
filter_actions = [action for action in self.table_actions if
|
||||
issubclass(action, FilterAction)]
|
||||
batch_actions = [action for action in self.table_actions if
|
||||
issubclass(action, BatchAction)]
|
||||
if len(filter_actions) > 1:
|
||||
raise NotImplementedError("Multiple filter actions are not "
|
||||
"currently supported.")
|
||||
@ -1137,7 +1139,7 @@ class DataTableOptions(object):
|
||||
len(self.row_actions) > 0)
|
||||
self.multi_select = getattr(options,
|
||||
'multi_select',
|
||||
len(self.table_actions) > 0)
|
||||
len(batch_actions) > 0)
|
||||
|
||||
# Set runtime table defaults; not configurable.
|
||||
self.has_prev_data = False
|
||||
@ -1301,6 +1303,16 @@ class DataTable(object):
|
||||
|
||||
self.needs_summary_row = any([col.summation
|
||||
for col in self.columns.values()])
|
||||
# For multi-process, we need to set the multi_column to be visible
|
||||
# or hidden each time.
|
||||
# Example: first process the multi_column visible but second
|
||||
# process the column is hidden. Updating row by ajax will
|
||||
# make the bug#1799151
|
||||
if request.GET.get('action') == 'row_update':
|
||||
bound_actions = self.get_table_actions()
|
||||
batch_actions = [action for action in bound_actions
|
||||
if isinstance(action, BatchAction)]
|
||||
self.set_multiselect_column_visibility(bool(batch_actions))
|
||||
|
||||
def __str__(self):
|
||||
return six.text_type(self._meta.verbose_name)
|
||||
@ -1570,7 +1582,7 @@ class DataTable(object):
|
||||
if self._meta.table_actions_menu_label:
|
||||
extra_context['table_actions_menu_label'] = \
|
||||
self._meta.table_actions_menu_label
|
||||
self.set_multiselect_column_visibility(len(batch_actions) > 0)
|
||||
self.set_multiselect_column_visibility(bool(batch_actions))
|
||||
return table_actions_template.render(extra_context, self.request)
|
||||
|
||||
def render_row_actions(self, datum, row=False):
|
||||
|
@ -500,7 +500,7 @@ class DataTableTests(test.TestCase):
|
||||
class TempTable(MyTable):
|
||||
class Meta(object):
|
||||
columns = ('id',)
|
||||
table_actions = (MyFilterAction, MyAction,)
|
||||
table_actions = (MyFilterAction, MyAction, MyBatchAction)
|
||||
row_actions = (MyAction, MyLinkAction,)
|
||||
actions_column = False
|
||||
self.table = TempTable(self.request, TEST_DATA)
|
||||
@ -528,7 +528,7 @@ class DataTableTests(test.TestCase):
|
||||
class TempTable(MyTable):
|
||||
class Meta(object):
|
||||
columns = ('id',)
|
||||
table_actions = (MyFilterAction, MyAction,)
|
||||
table_actions = (MyFilterAction, MyAction, MyBatchAction)
|
||||
self.table = TempTable(self.request, TEST_DATA)
|
||||
self.assertQuerysetEqual(self.table.columns.values(),
|
||||
['<Column: multi_select>',
|
||||
@ -550,7 +550,7 @@ class DataTableTests(test.TestCase):
|
||||
|
||||
class Meta(object):
|
||||
name = "temp_table"
|
||||
table_actions = (MyFilterAction, MyAction,)
|
||||
table_actions = (MyFilterAction, MyAction, MyBatchAction)
|
||||
row_actions = (MyAction, MyLinkAction,)
|
||||
|
||||
self.table = TempTable(self.request, TEST_DATA)
|
||||
|
@ -5181,7 +5181,8 @@ class InstanceAjaxTests(helpers.TestCase, InstanceTestHelperMixin):
|
||||
@helpers.create_mocks({api.nova: ("server_get",
|
||||
"flavor_get",
|
||||
"extension_supported",
|
||||
"is_feature_available"),
|
||||
"is_feature_available",
|
||||
"tenant_absolute_limits"),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_row_update(self):
|
||||
server = self.servers.first()
|
||||
@ -5220,7 +5221,8 @@ class InstanceAjaxTests(helpers.TestCase, InstanceTestHelperMixin):
|
||||
@helpers.create_mocks({api.nova: ("server_get",
|
||||
"flavor_get",
|
||||
'is_feature_available',
|
||||
"extension_supported"),
|
||||
"extension_supported",
|
||||
"tenant_absolute_limits"),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_row_update_instance_error(self):
|
||||
server = self.servers.first()
|
||||
@ -5280,7 +5282,8 @@ class InstanceAjaxTests(helpers.TestCase, InstanceTestHelperMixin):
|
||||
@helpers.create_mocks({api.nova: ("server_get",
|
||||
"flavor_get",
|
||||
'is_feature_available',
|
||||
"extension_supported"),
|
||||
"extension_supported",
|
||||
"tenant_absolute_limits"),
|
||||
api.network: ('servers_update_addresses',)})
|
||||
def test_row_update_flavor_not_found(self):
|
||||
server = self.servers.first()
|
||||
|
@ -1137,7 +1137,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
||||
|
||||
self.assertEqual(res.status_code, 200)
|
||||
mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id)
|
||||
mock_limits.assert_called_once()
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
mock_limits, 2,
|
||||
mock.call(test.IsHttpRequest()))
|
||||
|
||||
self.assertNotContains(res, 'Delete Volume')
|
||||
self.assertNotContains(res, 'delete')
|
||||
@ -1275,7 +1277,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
||||
content)
|
||||
self.assertNotIn('disabled', content)
|
||||
mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id)
|
||||
mock_limits.assert_called_once()
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
mock_limits, 2,
|
||||
mock.call(test.IsHttpRequest()))
|
||||
|
||||
@mock.patch.object(cinder, 'tenant_absolute_limits')
|
||||
@mock.patch.object(cinder, 'volume_get')
|
||||
@ -1306,7 +1310,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
||||
self.assertIn('disabled', content,
|
||||
'The create snapshot button should be disabled')
|
||||
mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id)
|
||||
mock_limits.assert_called_once()
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
mock_limits, 2,
|
||||
mock.call(test.IsHttpRequest()))
|
||||
|
||||
@test.create_mocks({
|
||||
api.nova: ['server_list'],
|
||||
@ -1504,7 +1510,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
||||
self.assertEqual(volume.name, volume.id)
|
||||
|
||||
mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id)
|
||||
mock_limits.assert_called_once()
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
mock_limits, 2,
|
||||
mock.call(test.IsHttpRequest()))
|
||||
|
||||
@test.create_mocks({
|
||||
api.nova: ['server_get'],
|
||||
@ -1748,7 +1756,9 @@ class VolumeViewTests(test.ResetImageAPIVersionMixin, test.TestCase):
|
||||
self.assertContains(res, 'retype')
|
||||
|
||||
mock_get.assert_called_once_with(test.IsHttpRequest(), volume.id)
|
||||
mock_limits.assert_called_once()
|
||||
self.assert_mock_multiple_calls_with_same_arguments(
|
||||
mock_limits, 2,
|
||||
mock.call(test.IsHttpRequest()))
|
||||
|
||||
@test.create_mocks({
|
||||
cinder: ['volume_type_list',
|
||||
|
Loading…
Reference in New Issue
Block a user