diff --git a/horizon/base.py b/horizon/base.py index a2b3e8b480..8e6c10dfbf 100644 --- a/horizon/base.py +++ b/horizon/base.py @@ -46,6 +46,8 @@ from horizon.decorators import require_perms # noqa from horizon import loaders +# Name of the panel group for panels to be displayed without a group. +DEFAULT_PANEL_GROUP = 'default' LOG = logging.getLogger(__name__) @@ -335,7 +337,7 @@ class PanelGroup(object): """ def __init__(self, dashboard, slug=None, name=None, panels=None): self.dashboard = dashboard - self.slug = slug or getattr(self, "slug", "default") + self.slug = slug or getattr(self, "slug", DEFAULT_PANEL_GROUP) self.name = name or getattr(self, "name", None) # Our panels must be mutable so it can be extended by others. self.panels = list(panels or getattr(self, "panels", [])) @@ -561,6 +563,7 @@ class Dashboard(Registry, HorizonComponent): self.panels = [self.panels] # Now iterate our panel sets. + default_created = False for panel_set in self.panels: # Instantiate PanelGroup classes. if not isinstance(panel_set, collections.Iterable) and \ @@ -573,7 +576,14 @@ class Dashboard(Registry, HorizonComponent): # Put our results into their appropriate places panels_to_discover.extend(panel_group.panels) panel_groups.append((panel_group.slug, panel_group)) + if panel_group.slug == DEFAULT_PANEL_GROUP: + default_created = True + # Plugin panels can be added to a default panel group. Make sure such a + # default group exists. + if not default_created: + default_group = PanelGroup(self) + panel_groups.insert(0, (default_group.slug, default_group)) self._panel_groups = collections.OrderedDict(panel_groups) # Do the actual discovery diff --git a/openstack_dashboard/test/test_panels/another_panel/__init__.py b/openstack_dashboard/test/test_panels/another_panel/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openstack_dashboard/test/test_panels/another_panel/panel.py b/openstack_dashboard/test/test_panels/another_panel/panel.py new file mode 100644 index 0000000000..e78c32d201 --- /dev/null +++ b/openstack_dashboard/test/test_panels/another_panel/panel.py @@ -0,0 +1,18 @@ +# 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. + +import horizon + + +class AnotherPanel(horizon.Panel): + name = "Another Plugin Panel" + slug = 'another_panel' diff --git a/openstack_dashboard/test/test_panels/another_panel/templates/another_panel/index.html b/openstack_dashboard/test/test_panels/another_panel/templates/another_panel/index.html new file mode 100644 index 0000000000..0d824f23ec --- /dev/null +++ b/openstack_dashboard/test/test_panels/another_panel/templates/another_panel/index.html @@ -0,0 +1,11 @@ +{% extends 'base.html' %} +{% load i18n %} +{% block title %}Another Plugin-based Panel{% endblock %} + +{% block main %} +
+
+ Another Plugin-based Panel +
+
+{% endblock %} diff --git a/openstack_dashboard/test/test_panels/another_panel/urls.py b/openstack_dashboard/test/test_panels/another_panel/urls.py new file mode 100644 index 0000000000..862857fd3b --- /dev/null +++ b/openstack_dashboard/test/test_panels/another_panel/urls.py @@ -0,0 +1,21 @@ +# 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.conf.urls import patterns +from django.conf.urls import url + +from openstack_dashboard.test.test_panels.another_panel import views + +urlpatterns = patterns( + '', + url(r'^$', views.IndexView.as_view(), name='index'), +) diff --git a/openstack_dashboard/test/test_panels/another_panel/views.py b/openstack_dashboard/test/test_panels/another_panel/views.py new file mode 100644 index 0000000000..35882683ed --- /dev/null +++ b/openstack_dashboard/test/test_panels/another_panel/views.py @@ -0,0 +1,20 @@ +# 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 views + + +class IndexView(views.HorizonTemplateView): + template_name = 'admin/another_panel/index.html' + page_title = _("Another Plugin-based Panel") diff --git a/openstack_dashboard/test/test_plugins/panel_group_config/_50_admin_add_panel_to_default_group.py b/openstack_dashboard/test/test_plugins/panel_group_config/_50_admin_add_panel_to_default_group.py new file mode 100644 index 0000000000..6e6a97f593 --- /dev/null +++ b/openstack_dashboard/test/test_plugins/panel_group_config/_50_admin_add_panel_to_default_group.py @@ -0,0 +1,10 @@ +# The name of the panel to be added to HORIZON_CONFIG. Required. +PANEL = 'another_panel' +# The name of the dashboard the PANEL associated with. Required. +PANEL_DASHBOARD = 'admin' +# The name of the panel group the PANEL is associated with. +PANEL_GROUP = 'default' + +# Python panel class of the PANEL to be added. +ADD_PANEL = \ + 'openstack_dashboard.test.test_panels.another_panel.panel.AnotherPanel' diff --git a/openstack_dashboard/test/test_plugins/panel_group_tests.py b/openstack_dashboard/test/test_plugins/panel_group_tests.py index 7e85802de6..4b8046693d 100644 --- a/openstack_dashboard/test/test_plugins/panel_group_tests.py +++ b/openstack_dashboard/test/test_plugins/panel_group_tests.py @@ -18,6 +18,8 @@ from django.test.utils import override_settings import horizon from openstack_dashboard.test import helpers as test +from openstack_dashboard.test.test_panels.another_panel \ + import panel as another_panel from openstack_dashboard.test.test_panels.plugin_panel \ import panel as plugin_panel from openstack_dashboard.test.test_panels.second_panel \ @@ -76,3 +78,10 @@ class PanelGroupPluginTests(test.PluginTestCase): def test_unregistered_panel_group(self): dashboard = horizon.get_dashboard("admin") self.assertIsNone(dashboard.get_panel_group("nonexistent_panel")) + + def test_add_panel_to_default_panel_group(self): + dashboard = horizon.get_dashboard('admin') + default_panel_group = dashboard.get_panel_group('default') + self.assertIsNotNone(default_panel_group) + self.assertIn(another_panel.AnotherPanel, + [p.__class__ for p in default_panel_group])