diff --git a/horizon/browsers/base.py b/horizon/browsers/base.py index e4a8979206..802b635364 100644 --- a/horizon/browsers/base.py +++ b/horizon/browsers/base.py @@ -19,6 +19,7 @@ from django.utils.translation import ugettext_lazy as _ from horizon.tables import DataTable from horizon.utils import html +from .breadcrumb import Breadcrumb class ResourceBrowser(html.HTMLElement): @@ -48,6 +49,18 @@ class ResourceBrowser(html.HTMLElement): This table class must set browser_table attribute in Meta to ``"content"``. + .. attribute:: navigation_kwarg_name + + This attribute represents the key of the navigatable items in the + kwargs property of this browser's view. + Defaults to ``"navigation_kwarg"``. + + .. attribute:: content_kwarg_name + + This attribute represents the key of the content items in the + kwargs property of this browser's view. + Defaults to ``"content_kwarg"``. + .. attribute:: template String containing the template which should be used to render @@ -57,20 +70,43 @@ class ResourceBrowser(html.HTMLElement): The name of the context variable which will contain the browser when it is rendered. Defaults to ``"browser"``. + + .. attribute:: has_breadcrumb + + Indicates if the content table of the browser would have breadcrumb. + Defaults to false. + + .. attribute:: breadcrumb_template + + This is a template used to render the breadcrumb. + Defaults to ``"horizon/common/_breadcrumb.html"``. """ name = None verbose_name = None navigation_table_class = None content_table_class = None + navigation_kwarg_name = "navigation_kwarg" + content_kwarg_name = "content_kwarg" navigable_item_name = _("Navigation Item") template = "horizon/common/_resource_browser.html" context_var_name = "browser" + has_breadcrumb = False + breadcrumb_template = "horizon/common/_breadcrumb.html" + breadcrumb_url = None def __init__(self, request, tables_dict=None, attrs=None, **kwargs): super(ResourceBrowser, self).__init__() self.name = self.name or self.__class__.__name__ self.verbose_name = self.verbose_name or self.name.title() self.request = request + self.kwargs = kwargs + self.has_breadcrumb = getattr(self, "has_breadcrumb") + if self.has_breadcrumb: + self.breadcrumb_template = getattr(self, "breadcrumb_template") + self.breadcrumb_url = getattr(self, "breadcrumb_url") + if not self.breadcrumb_url: + raise ValueError("You must specify a breadcrumb_url " + "if the has_breadcrumb is set to True.") self.attrs.update(attrs or {}) self.check_table_class(self.content_table_class, "content_table_class") self.check_table_class(self.navigation_table_class, @@ -91,6 +127,19 @@ class ResourceBrowser(html.HTMLElement): """ self.navigation_table = tables[self.navigation_table_class._meta.name] self.content_table = tables[self.content_table_class._meta.name] + if self.has_breadcrumb: + self.prepare_breadcrumb(tables) + + def prepare_breadcrumb(self, tables): + navigation_item = self.kwargs.get(self.navigation_kwarg_name) + content_path = self.kwargs.get(self.content_kwarg_name) + if self.has_breadcrumb and navigation_item and content_path: + for table in tables.values(): + table.breadcrumb = Breadcrumb(self.request, + self.breadcrumb_template, + navigation_item, + content_path, + self.breadcrumb_url) def render(self): browser_template = template.loader.get_template(self.template) diff --git a/horizon/browsers/breadcrumb.py b/horizon/browsers/breadcrumb.py new file mode 100644 index 0000000000..ba1ca748f5 --- /dev/null +++ b/horizon/browsers/breadcrumb.py @@ -0,0 +1,48 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2012 Nebula, Inc. +# +# 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 import template + +from horizon.utils import html + + +class Breadcrumb(html.HTMLElement): + def __init__(self, request, template, root, + subfolder_path, url, attr=None): + super(Breadcrumb, self).__init__() + self.template = template + self.request = request + self.root = root + self.subfolder_path = subfolder_path + self.url = url + self._subfolders = [] + + def get_subfolders(self): + if self.subfolder_path and not self._subfolders: + (parent, slash, folder) = self.subfolder_path.strip('/') \ + .rpartition('/') + while folder: + path = "%s%s%s/" % (parent, slash, folder) + self._subfolders.insert(0, (folder, path)) + (parent, slash, folder) = parent.rpartition('/') + return self._subfolders + + def render(self): + """ Renders the table using the template from the table options. """ + breadcrumb_template = template.loader.get_template(self.template) + extra_context = {"breadcrumb": self} + context = template.RequestContext(self.request, extra_context) + return breadcrumb_template.render(context) diff --git a/horizon/browsers/views.py b/horizon/browsers/views.py index 933795e10b..c2e8b437d8 100644 --- a/horizon/browsers/views.py +++ b/horizon/browsers/views.py @@ -14,8 +14,6 @@ # License for the specific language governing permissions and limitations # under the License. -from collections import defaultdict - from django.utils.translation import ugettext_lazy as _ from horizon.tables import MultiTableView @@ -31,8 +29,8 @@ class ResourceBrowserView(MultiTableView): % self.__class__.__name__) self.table_classes = (self.browser_class.navigation_table_class, self.browser_class.content_table_class) - super(ResourceBrowserView, self).__init__(*args, **kwargs) self.navigation_selection = False + super(ResourceBrowserView, self).__init__(*args, **kwargs) def get_browser(self): if not hasattr(self, "browser"): diff --git a/horizon/dashboards/nova/containers/browsers.py b/horizon/dashboards/nova/containers/browsers.py index 68aab4c996..bb8de593a2 100644 --- a/horizon/dashboards/nova/containers/browsers.py +++ b/horizon/dashboards/nova/containers/browsers.py @@ -31,3 +31,7 @@ class ContainerBrowser(browsers.ResourceBrowser): navigation_table_class = ContainersTable content_table_class = ObjectsTable navigable_item_name = _("Container") + navigation_kwarg_name = "container_name" + content_kwarg_name = "subfolder_path" + has_breadcrumb = True + breadcrumb_url = "horizon:nova:containers:index" diff --git a/horizon/dashboards/nova/containers/templates/containers/index.html b/horizon/dashboards/nova/containers/templates/containers/index.html index 1dc45d98ea..3779a89431 100644 --- a/horizon/dashboards/nova/containers/templates/containers/index.html +++ b/horizon/dashboards/nova/containers/templates/containers/index.html @@ -4,21 +4,7 @@ {% block page_header %}