diff --git a/manila_ui/dashboards/admin/share_networks/tables.py b/manila_ui/dashboards/admin/share_networks/tables.py index 657b2858..06f5be7f 100644 --- a/manila_ui/dashboards/admin/share_networks/tables.py +++ b/manila_ui/dashboards/admin/share_networks/tables.py @@ -16,10 +16,20 @@ from horizon import tables import manila_ui.dashboards.project.share_networks.tables as sn_tables +class ShareNetworksFilterAction(tables.FilterAction): + filter_type = "server" + filter_choices = ( + ('name', _("Name "), True), + ('description', _("Description "), True), + ) + + class ShareNetworksTable(tables.DataTable): name = tables.WrappingColumn( "name", verbose_name=_("Name"), link="horizon:admin:share_networks:share_network_detail") + description = tables.WrappingColumn( + "description", verbose_name=_("Description")) project = tables.Column("project_name", verbose_name=_("Project")) def get_object_display(self, share_network): @@ -32,7 +42,7 @@ class ShareNetworksTable(tables.DataTable): name = "share_networks" verbose_name = _("Share Networks") table_actions = ( - tables.NameFilterAction, + ShareNetworksFilterAction, sn_tables.Delete, ) row_class = sn_tables.UpdateRow diff --git a/manila_ui/dashboards/admin/share_networks/views.py b/manila_ui/dashboards/admin/share_networks/views.py index 3345b778..945ca164 100644 --- a/manila_ui/dashboards/admin/share_networks/views.py +++ b/manila_ui/dashboards/admin/share_networks/views.py @@ -15,13 +15,13 @@ """ Admin views for managing share networks. """ +import re from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from horizon import exceptions from horizon import tables from horizon.utils import memoized - from manila_ui.api import manila from manila_ui.dashboards.admin.share_networks import tables as sn_tables from manila_ui.dashboards.admin.share_networks import tabs as sn_tabs @@ -46,8 +46,31 @@ class ShareNetworksView(tables.MultiTableView): exceptions.handle( self.request, _("Unable to retrieve share networks")) utils.set_project_name_to_objects(self.request, share_networks) + share_networks = self.get_filters(share_networks) return share_networks + def get_filters(self, share_networks): + table = self._tables['share_networks'] + filters = self.get_server_filter_info(table.request, table) + filter_string = filters['value'] + filter_field = filters['field'] + if filter_string and filter_field: + filtered_data = [] + for share_network in share_networks: + if filter_field == 'name': + if share_network.name == filter_string: + filtered_data.append(share_network) + + if filter_field == 'description': + re_string = re.compile(filter_string) + if (share_network.description and + re.search(re_string, + share_network.description)): + filtered_data.append(share_network) + return filtered_data + else: + return share_networks + class ShareNetworkDetailView(p_views.Detail): tab_group_class = sn_tabs.ShareNetworkDetailTabs diff --git a/manila_ui/dashboards/project/share_networks/tables.py b/manila_ui/dashboards/project/share_networks/tables.py index 38d76ba8..2b0a224c 100644 --- a/manila_ui/dashboards/project/share_networks/tables.py +++ b/manila_ui/dashboards/project/share_networks/tables.py @@ -93,6 +93,14 @@ class UpdateRow(tables.Row): return share_net +class ShareNetworksFilterAction(tables.FilterAction): + filter_type = "server" + filter_choices = ( + ('name', _("Name "), True), + ('description', _("Description "), True), + ) + + class ShareNetworksTable(tables.DataTable): STATUS_CHOICES = ( ("ACTIVE", True), @@ -122,7 +130,7 @@ class ShareNetworksTable(tables.DataTable): name = "share_networks" verbose_name = _("Share Networks") table_actions = ( - tables.NameFilterAction, + ShareNetworksFilterAction, Create, Delete, ) diff --git a/manila_ui/dashboards/project/share_networks/views.py b/manila_ui/dashboards/project/share_networks/views.py index 7e0a2a1b..0b22a8c6 100644 --- a/manila_ui/dashboards/project/share_networks/views.py +++ b/manila_ui/dashboards/project/share_networks/views.py @@ -12,6 +12,8 @@ # License for the specific language governing permissions and limitations # under the License. +import re + from django.urls import reverse_lazy from django.utils.translation import gettext_lazy as _ from horizon import exceptions @@ -45,8 +47,31 @@ class ShareNetworksView(tables.MultiTableView): share_networks = [] exceptions.handle( self.request, _("Unable to retrieve share networks")) + share_networks = self.get_filters(share_networks) return share_networks + def get_filters(self, share_networks): + table = self._tables['share_networks'] + filters = self.get_server_filter_info(table.request, table) + filter_string = filters['value'] + filter_field = filters['field'] + if filter_string and filter_field: + filtered_data = [] + for share_network in share_networks: + if filter_field == 'name': + if share_network.name == filter_string: + filtered_data.append(share_network) + + if filter_field == 'description': + re_string = re.compile(filter_string) + if (share_network.description and + re.search(re_string, + share_network.description)): + filtered_data.append(share_network) + return filtered_data + else: + return share_networks + class Update(workflows.WorkflowView): workflow_class = sn_workflows.UpdateShareNetworkWorkflow diff --git a/manila_ui/tests/dashboards/admin/share_networks/tests.py b/manila_ui/tests/dashboards/admin/share_networks/tests.py index c298ae3f..2d308c3a 100644 --- a/manila_ui/tests/dashboards/admin/share_networks/tests.py +++ b/manila_ui/tests/dashboards/admin/share_networks/tests.py @@ -22,6 +22,7 @@ from oslo_utils import timeutils from unittest import mock from manila_ui.api import manila as api_manila +from manila_ui.dashboards.admin import share_networks from manila_ui.dashboards.admin import utils from manila_ui.tests.dashboards.project import test_data from manila_ui.tests import helpers as test @@ -30,6 +31,20 @@ from manila_ui.tests.test_data import keystone_data INDEX_URL = reverse('horizon:admin:share_networks:index') +class ShareNetworksTableMock(mock.Mock): + def __init__(self, *args, **kwargs): + mock.Mock.__init__(self) + self.request = {} + self.share_networks = {} + + +class ShareNetwork: + def __init__(self, id, name, description): + self.id = id + self.name = name + self.description = description + + class ShareNetworksTests(test.BaseAdminViewTests): def setUp(self): @@ -178,12 +193,70 @@ class ShareNetworksTests(test.BaseAdminViewTests): mock.Mock(return_value=[ test_data.active_share_network, test_data.inactive_share_network])) - res = self.client.post(INDEX_URL, formData) - self.assertRedirectsNoFollow(res, INDEX_URL) api_keystone.tenant_list.assert_called_once_with(mock.ANY) api_manila.share_network_delete.assert_called_once_with( mock.ANY, share_network.id) api_manila.share_network_list.assert_called_once_with( mock.ANY, detailed=True, search_opts={'all_tenants': True}) + + def test_get_filters(self): + share_net = [ + ShareNetwork('share_net_1', 'share_net_name_1', 'desc1'), + ShareNetwork('share_net_2', 'share_net_name_2', 'desc2'), + ShareNetwork('share_net_3', 'share_net_name_3', 'desc3'), + ] + share_networks_view = share_networks.views.ShareNetworksView() + share_networks_view._tables = { + 'share_networks': ShareNetworksTableMock() + } + + mock_filters = { + 'action': '', + 'value_param': 'share_networks__filter__q', + 'value': '', + 'field_param': 'share_networks__filter__q_field', + 'field': None, + 'changed': False + } + self.mock_object(share_networks_view, 'get_server_filter_info', + mock.Mock(return_value=mock_filters)) + + # Test with empty filter string and no filter field selected + filtered_data = share_networks_view.get_filters(share_net) + self.assertEqual(len(filtered_data), len(share_net)) + self.assertEqual(filtered_data, share_net) + + mock_filters_name = { + 'action': '', + 'value_param': 'share_networks__filter__q', + 'value': 'share_net_name_1', + 'field_param': 'share_networks__filter__q_field', + 'field': 'name', + 'changed': False + } + self.mock_object(share_networks_view, 'get_server_filter_info', + mock.Mock(return_value=mock_filters_name)) + + # Test with specific filter string ("share_net_name_1") on "name" field + filtered_data = share_networks_view.get_filters(share_net) + self.assertEqual(len(filtered_data), 1) + self.assertEqual(filtered_data[0].name, 'share_net_name_1') + + mock_filters_description = { + 'action': '', + 'value_param': 'share_networks__filter__q', + 'value': 'desc1', + 'field_param': 'share_networks__filter__q_field', + 'field': 'description', + 'changed': False + } + + self.mock_object(share_networks_view, 'get_server_filter_info', + mock.Mock(return_value=mock_filters_description)) + + # Test with specific filter string ("desc1") on "description" field + filtered_data = share_networks_view.get_filters(share_net) + self.assertEqual(len(filtered_data), 1) + self.assertEqual(filtered_data[0].description, 'desc1') diff --git a/releasenotes/notes/add-filter-choices-to-share-networks-d34e4aa6a1eb88ae.yaml b/releasenotes/notes/add-filter-choices-to-share-networks-d34e4aa6a1eb88ae.yaml new file mode 100644 index 00000000..300eaa27 --- /dev/null +++ b/releasenotes/notes/add-filter-choices-to-share-networks-d34e4aa6a1eb88ae.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Added the possibility to filter share networks by their name or + description. +