From ac9335893255d5c7bbcec983ba7718e82fdedb3b Mon Sep 17 00:00:00 2001 From: David Gutman Date: Thu, 13 Sep 2018 11:44:28 +0200 Subject: [PATCH] Change user details view in a tab view Change the existing user details view into a tabbed view with currently just one tab (overview tab) which presents general informations of the user. This is done to be able to add other tabs to the user details view. Change-Id: I38a33a3b218caf5d76eabd513e22aa118cc26ea1 Partial-Bug: #1792524 --- .../dashboards/identity/users/tabs.py | 34 +++++++++++++++ .../dashboards/identity/users/tests.py | 43 ++++++++++++++++++- .../dashboards/identity/users/views.py | 13 ++++-- 3 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 openstack_dashboard/dashboards/identity/users/tabs.py diff --git a/openstack_dashboard/dashboards/identity/users/tabs.py b/openstack_dashboard/dashboards/identity/users/tabs.py new file mode 100644 index 0000000000..55dfd7ca94 --- /dev/null +++ b/openstack_dashboard/dashboards/identity/users/tabs.py @@ -0,0 +1,34 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + + +from django.utils.translation import ugettext_lazy as _ + +from horizon import tabs + + +class OverviewTab(tabs.Tab): + """Overview of the user. + + Global user informations such as user name, domain ID, email... + """ + name = _("Overview") + slug = "overview" + template_name = 'identity/users/_detail_overview.html' + + def get_context_data(self, request): + return {"user": self.tab_group.kwargs['user']} + + +class UserDetailTabs(tabs.DetailTabsGroup): + slug = "user_details" + tabs = (OverviewTab,) diff --git a/openstack_dashboard/dashboards/identity/users/tests.py b/openstack_dashboard/dashboards/identity/users/tests.py index f8dfca0030..271d787806 100644 --- a/openstack_dashboard/dashboards/identity/users/tests.py +++ b/openstack_dashboard/dashboards/identity/users/tests.py @@ -24,6 +24,7 @@ from django.urls import reverse import mock from openstack_dashboard import api +from openstack_dashboard.dashboards.identity.users import tabs from openstack_dashboard.test import helpers as test @@ -858,7 +859,9 @@ class UsersViewTests(test.BaseAdminViewTests): res = self.client.get(USER_DETAIL_URL, args=[user.id]) - self.assertTemplateUsed(res, 'identity/users/detail.html') + # The first tab is overview, it is the one loaded without query param + # in the url. + self.assertTemplateUsed(res, 'identity/users/_detail_overview.html') self.assertEqual(res.context['user'].name, user.name) self.assertEqual(res.context['user'].id, user.id) self.assertEqual(res.context['tenant_name'], tenant.name) @@ -881,6 +884,44 @@ class UsersViewTests(test.BaseAdminViewTests): self.mock_user_get.assert_called_once_with(test.IsHttpRequest(), '1', admin=False) + @test.create_mocks({api.keystone: ('domain_get', + 'user_get', + 'tenant_get')}) + def test_detail_view_overview_tab(self): + """Test the overview tab of the detail view . + + Test the overview tab using directly the url targeting the tab. + """ + domain = self._get_default_domain() + user = self.users.get(id="1") + tenant = self.tenants.get(id=user.project_id) + + self.mock_domain_get.return_value = domain + self.mock_user_get.return_value = user + self.mock_tenant_get.return_value = tenant + + # Url of the overview tab of the detail view + url = USER_DETAIL_URL % [user.id] + detail_view = tabs.UserDetailTabs(self.request, user=user) + overview_tab_link = "?%s=%s" % ( + detail_view.param_name, + detail_view.get_tab("overview").get_id() + ) + url += overview_tab_link + + res = self.client.get(url) + + self.assertTemplateUsed(res, 'identity/users/_detail_overview.html') + self.assertEqual(res.context['user'].name, user.name) + self.assertEqual(res.context['user'].id, user.id) + self.assertEqual(res.context['tenant_name'], tenant.name) + + self.mock_domain_get.assert_called_once_with(test.IsHttpRequest(), '1') + self.mock_user_get.assert_called_once_with(test.IsHttpRequest(), '1', + admin=False) + self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(), + user.project_id) + @test.create_mocks({api.keystone: ('user_get', 'domain_get', 'tenant_list',)}) diff --git a/openstack_dashboard/dashboards/identity/users/views.py b/openstack_dashboard/dashboards/identity/users/views.py index 45cbf4040c..576413300f 100644 --- a/openstack_dashboard/dashboards/identity/users/views.py +++ b/openstack_dashboard/dashboards/identity/users/views.py @@ -30,8 +30,8 @@ from horizon import exceptions from horizon import forms from horizon import messages from horizon import tables +from horizon import tabs from horizon.utils import memoized -from horizon import views from openstack_dashboard import api from openstack_dashboard import policy @@ -40,6 +40,8 @@ from openstack_dashboard.dashboards.identity.users \ import forms as project_forms from openstack_dashboard.dashboards.identity.users \ import tables as project_tables +from openstack_dashboard.dashboards.identity.users \ + import tabs as user_tabs from openstack_dashboard.utils import identity LOG = logging.getLogger(__name__) @@ -197,8 +199,9 @@ class CreateView(forms.ModalFormView): 'role_id': getattr(default_role, "id", None)} -class DetailView(views.HorizonTemplateView): - template_name = 'identity/users/detail.html' +class DetailView(tabs.TabView): + tab_group_class = user_tabs.UserDetailTabs + template_name = 'horizon/common/_detail.html' page_title = "{{ user.name }}" def get_context_data(self, **kwargs): @@ -261,6 +264,10 @@ class DetailView(views.HorizonTemplateView): def get_redirect_url(self): return reverse('horizon:identity:users:index') + def get_tabs(self, request, *args, **kwargs): + user = self.get_data() + return self.tab_group_class(request, user=user, **kwargs) + class ChangePasswordView(forms.ModalFormView): template_name = 'identity/users/change_password.html'