From fe0df4579cd091caa49a5a0a14bc3b3d93bcd1a4 Mon Sep 17 00:00:00 2001 From: Shu Muto Date: Thu, 25 May 2017 18:39:15 +0900 Subject: [PATCH] Enable to refresh ngdetails view For now refreshing ngdetails view by browser using F5 key or reload button, it causes 404 error from django. To fix this issue, this patch adds the url for '/ngdetails'. Furthermore, to specify current navigation and to check access grants to current panel, each access to Horizon django framework needs its dashboard and panel objects. It means that we need to specify dashboard and panel that ngdetails view belongs to. Also, this patch adds the process and settings to specify dashboard and panel object for each ngdetails view. Change-Id: I4bcffd2e222ce2df186551cceba0aa38f600d9c8 Closes-Bug: #1681627 --- horizon/__init__.py | 2 + horizon/base.py | 47 +++++++++++++++++++ horizon/browsers/views.py | 18 +++++++ .../enabled/_1050_project_images_panel.py | 7 +++ .../enabled/_3010_identity_domains_panel.py | 19 ++++++++ .../enabled/_3030_identity_users_panel.py | 19 ++++++++ 6 files changed, 112 insertions(+) diff --git a/horizon/__init__.py b/horizon/__init__.py index cbd7a41b15..185935cdbb 100644 --- a/horizon/__init__.py +++ b/horizon/__init__.py @@ -47,6 +47,7 @@ if Horizon: get_dashboard = Horizon.get_dashboard get_default_dashboard = Horizon.get_default_dashboard get_dashboards = Horizon.get_dashboards + get_details_path = Horizon.get_details_path urls = Horizon._lazy_urls # silence flake8 about unused imports here: @@ -62,5 +63,6 @@ __all__ = [ "get_dashboard", "get_default_dashboard", "get_dashboards", + "get_details_path", "urls", ] diff --git a/horizon/base.py b/horizon/base.py index 0b2ef870b6..c730a73f46 100644 --- a/horizon/base.py +++ b/horizon/base.py @@ -693,6 +693,7 @@ class Site(Registry, HorizonComponent): namespace = 'horizon' slug = 'horizon' urls = 'horizon.site_urls' + details = {} def __repr__(self): return u"" % self.slug @@ -822,6 +823,24 @@ class Site(Registry, HorizonComponent): """ return self.get_default_dashboard().get_absolute_url() + def get_details_path(self, resource_type): + """Returns classes of dashboard and panel for details view + + This method returns the specified :class:`~horizon.Dashboard` instance + and :class:`~horizon.Panel` instance for details view specified by + resource_type. + """ + details = self.details.get(resource_type) + dashboard = None + panel = None + if details is not None: + dashboard = self.get_dashboard(details.get('dashboard')) + panel = dashboard.get_panel(details.get('panel')) + else: + dashboard = self.get_default_dashboard() + panel = dashboard.get_panels()[0] + return dashboard, panel + @property def _lazy_urls(self): """Lazy loading for URL patterns. @@ -906,6 +925,7 @@ class Site(Registry, HorizonComponent): # are added to them and Dashboard._autodiscover() doesn't wipe out any # panels previously added when its panel groups are instantiated. panel_configs = [] + details_configs = [] for config in panel_customization: if config.get('PANEL'): panel_configs.append(config) @@ -914,9 +934,16 @@ class Site(Registry, HorizonComponent): else: LOG.warning("Skipping %s because it doesn't have PANEL or " "PANEL_GROUP defined.", config.__name__) + + if config.get('ADD_DETAIL_PAGES'): + details_configs.append(config) + # Now process the panels. for config in panel_configs: self._process_panel_configuration(config) + # And process the details views. + for config in details_configs: + self._process_details_configuration(config) def _process_panel_configuration(self, config): """Add, remove and set default panels on the dashboard.""" @@ -1004,6 +1031,26 @@ class Site(Registry, HorizonComponent): '%(exc)s', {'panel_group': panel_group_slug, 'exc': e}) + def _process_details_configuration(self, config): + """Add details view.""" + detail_pages = config.get('ADD_DETAIL_PAGES') + urlpatterns = self._get_default_urlpatterns() + views = import_module('horizon.browsers.views') + for details in detail_pages: + try: + urlpatterns.append(url(r'^ngdetails/%s/[^/]+' % details, + views.AngularDetailsView.as_view(), + name='ngdetails')) + _decorate_urlconf(urlpatterns, require_auth) + dashboard, panel = detail_pages[details] + self.details[details] = {'dashboard': dashboard, + 'panel': panel} + except Exception as e: + LOG.warning('Could not add %(details) to %(panel)s on ' + '%(dashboard)s: %(exc)s', + {'dashboard': dashboard, 'panel': panel, + 'details': details, 'exc': e}) + class HorizonSite(Site): """A singleton implementation of Site. diff --git a/horizon/browsers/views.py b/horizon/browsers/views.py index 9d4bf769dc..3085a3b483 100644 --- a/horizon/browsers/views.py +++ b/horizon/browsers/views.py @@ -15,6 +15,7 @@ from django.utils.translation import ugettext_lazy as _ from django.views import generic +import horizon from horizon.tables import MultiTableView from horizon.utils import memoized @@ -83,3 +84,20 @@ class AngularIndexView(generic.TemplateView): else: context["page_title"] = self.page_title return context + + +class AngularDetailsView(AngularIndexView): + '''View for Angularized details view + + To use surely the template same as AngularIndexView, this class + inherits AngularIndexView. + ''' + + def get_context_data(self, **kwargs): + context = super(AngularDetailsView, self).get_context_data(**kwargs) + resource_path = self.request.path.partition('/ngdetails/')[2] + resource_type = resource_path.split('/')[0] + dashboard, panel = horizon.get_details_path(resource_type) + self.request.horizon['dashboard'] = dashboard + self.request.horizon['panel'] = panel + return context diff --git a/openstack_dashboard/enabled/_1050_project_images_panel.py b/openstack_dashboard/enabled/_1050_project_images_panel.py index 88e1a825d6..5f44e4279a 100644 --- a/openstack_dashboard/enabled/_1050_project_images_panel.py +++ b/openstack_dashboard/enabled/_1050_project_images_panel.py @@ -21,3 +21,10 @@ PANEL_GROUP = 'compute' # Python panel class of the PANEL to be added. ADD_PANEL = 'openstack_dashboard.dashboards.project.images.panel.Images' + +# The details view to be belonged to the PANEL_DASHBOARD and PANEL. +# If the details view uses ngdetails, this setting is needed to refresh the +# details view. +ADD_DETAIL_PAGES = { + 'OS::Glance::Image': (PANEL_DASHBOARD, PANEL) +} diff --git a/openstack_dashboard/enabled/_3010_identity_domains_panel.py b/openstack_dashboard/enabled/_3010_identity_domains_panel.py index e8aff7cafd..6ebcb1ef32 100644 --- a/openstack_dashboard/enabled/_3010_identity_domains_panel.py +++ b/openstack_dashboard/enabled/_3010_identity_domains_panel.py @@ -1,3 +1,15 @@ +# 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. + # The slug of the panel to be added to HORIZON_CONFIG. Required. PANEL = 'domains' # The slug of the dashboard the PANEL associated with. Required. @@ -7,3 +19,10 @@ PANEL_GROUP = 'default' # Python panel class of the PANEL to be added. ADD_PANEL = 'openstack_dashboard.dashboards.identity.domains.panel.Domains' + +# The details view to be belonged to the PANEL_DASHBOARD and PANEL. +# If the details view uses ngdetails, this setting is needed to refresh the +# details view. +ADD_DETAIL_PAGES = { + 'OS::Keystone::Domain': (PANEL_DASHBOARD, PANEL) +} diff --git a/openstack_dashboard/enabled/_3030_identity_users_panel.py b/openstack_dashboard/enabled/_3030_identity_users_panel.py index 52b45330db..be59ef35ab 100644 --- a/openstack_dashboard/enabled/_3030_identity_users_panel.py +++ b/openstack_dashboard/enabled/_3030_identity_users_panel.py @@ -1,3 +1,15 @@ +# 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. + # The slug of the panel to be added to HORIZON_CONFIG. Required. PANEL = 'users' # The slug of the dashboard the PANEL associated with. Required. @@ -7,3 +19,10 @@ PANEL_GROUP = 'default' # Python panel class of the PANEL to be added. ADD_PANEL = 'openstack_dashboard.dashboards.identity.users.panel.Users' + +# The details view to be belonged to the PANEL_DASHBOARD and PANEL. +# If the details view uses ngdetails, this setting is needed to refresh the +# details view. +ADD_DETAIL_PAGES = { + 'OS::Keystone::User': (PANEL_DASHBOARD, PANEL) +}