launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #17547
[Merge] lp:~wgrant/launchpad/ifacet into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/ifacet into lp:launchpad.
Commit message:
Provide IFacet utilities describing the default view name, title and rootsite. Use them to generate breadcrumbs, and use a new IMultiFacetedBreadcrumb to decide where to place the facet breadcrumb.
Requested reviews:
William Grant (wgrant): code
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/ifacet/+merge/242619
--
Your team Launchpad code reviewers is subscribed to branch lp:launchpad.
=== modified file 'lib/lp/answers/browser/questiontarget.py'
--- lib/lp/answers/browser/questiontarget.py 2014-04-24 02:53:05 +0000
+++ lib/lp/answers/browser/questiontarget.py 2014-11-24 06:00:00 +0000
@@ -6,7 +6,6 @@
__metaclass__ = type
__all__ = [
- 'AnswersFacetBreadcrumb',
'AskAQuestionButtonPortlet',
'ManageAnswerContactView',
'SearchQuestionsView',
@@ -85,7 +84,6 @@
)
from lp.services.webapp.authorization import check_permission
from lp.services.webapp.batching import BatchNavigator
-from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.escaping import structured
from lp.services.webapp.publisher import LaunchpadView
from lp.services.worlddata.helpers import (
@@ -960,8 +958,3 @@
"""Return a link to the manage answer contact view."""
text = 'Set answer contact'
return Link('+answer-contact', text, icon='edit')
-
-
-class AnswersFacetBreadcrumb(Breadcrumb):
- rootsite = 'answers'
- text = 'Questions'
=== modified file 'lib/lp/answers/configure.zcml'
--- lib/lp/answers/configure.zcml 2014-04-24 08:21:42 +0000
+++ lib/lp/answers/configure.zcml 2014-11-24 06:00:00 +0000
@@ -18,6 +18,10 @@
component="lp.answers.publisher.AnswersLayer"
provides="zope.publisher.interfaces.browser.IDefaultBrowserLayer"
name="answers" />
+ <utility
+ component="lp.answers.publisher.AnswersFacet"
+ provides="lp.services.webapp.interfaces.IFacet"
+ name="answers" />
<subscriber
for=".interfaces.question.IQuestion
@@ -257,26 +261,7 @@
<allow interface="lp.services.webapp.vocabulary.IHugeVocabulary"/>
</class>
-
<lp:help-folder folder="help" name="+help-answers"/>
- <adapter
- name="answers"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.answers.interfaces.questiontarget.IQuestionTarget"
- factory="lp.answers.browser.questiontarget.AnswersFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="answers"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.projectgroup.IProjectGroup"
- factory="lp.answers.browser.questiontarget.AnswersFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="answers"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.person.IPerson"
- factory="lp.answers.browser.questiontarget.AnswersFacetBreadcrumb"
- permission="zope.Public"/>
<webservice:register module="lp.answers.interfaces.webservice" />
</configure>
=== modified file 'lib/lp/answers/publisher.py'
--- lib/lp/answers/publisher.py 2011-12-24 17:49:30 +0000
+++ lib/lp/answers/publisher.py 2014-11-24 06:00:00 +0000
@@ -6,6 +6,7 @@
__metaclass__ = type
__all__ = [
'AnswersBrowserRequest',
+ 'AnswersFacet',
'AnswersLayer',
'answers_request_publication_factory',
]
@@ -17,6 +18,7 @@
IDefaultBrowserLayer,
)
+from lp.services.webapp.interfaces import IFacet
from lp.services.webapp.publication import LaunchpadBrowserPublication
from lp.services.webapp.servers import (
LaunchpadBrowserRequest,
@@ -24,6 +26,15 @@
)
+class AnswersFacet:
+ implements(IFacet)
+
+ name = "answers"
+ rootsite = "answers"
+ text = "Questions"
+ default_view = "+questions"
+
+
class AnswersLayer(IBrowserRequest, IDefaultBrowserLayer):
"""The Answers layer."""
=== modified file 'lib/lp/app/browser/launchpad.py'
--- lib/lp/app/browser/launchpad.py 2014-11-17 18:36:16 +0000
+++ lib/lp/app/browser/launchpad.py 2014-11-24 06:00:00 +0000
@@ -35,6 +35,7 @@
getGlobalSiteManager,
getUtility,
queryAdapter,
+ queryUtility,
)
from zope.datetime import (
DateTimeError,
@@ -143,8 +144,10 @@
from lp.services.webapp.interfaces import (
IBreadcrumb,
ICanonicalUrlData,
+ IFacet,
ILaunchBag,
ILaunchpadRoot,
+ IMultiFacetedBreadcrumb,
INavigationMenu,
)
from lp.services.webapp.menu import get_facet
@@ -253,8 +256,6 @@
class Hierarchy(LaunchpadView):
"""The hierarchy part of the location bar on each page."""
- vhost_breadcrumb = True
-
@property
def objects(self):
"""The objects for which we want breadcrumbs."""
@@ -294,20 +295,21 @@
if breadcrumb is not None:
breadcrumbs.append(breadcrumb)
- facet = get_facet(self._naked_context_view)
- if (len(breadcrumbs) != 0 and facet is not None and
- self.vhost_breadcrumb):
+ facet = queryUtility(IFacet, name=get_facet(self._naked_context_view))
+ if breadcrumbs and facet is not None:
# We have breadcrumbs and we're on a custom facet, so we'll
# sneak an extra breadcrumb for the facet we're on.
-
# Iterate over the context of our breadcrumbs in reverse order and
- # for the first one we find an adapter named after the facet we're
- # on, generate an extra breadcrumb and insert it in our list.
+ # find the first one that implements IMultiFactedBreadcrumb.
+ # It'll be facet-agnostic, so insert a facet-specific one
+ # after it.
for idx, breadcrumb in reversed(list(enumerate(breadcrumbs))):
- extra_breadcrumb = queryAdapter(
- breadcrumb.context, IBreadcrumb, name=facet)
- if extra_breadcrumb is not None:
- breadcrumbs.insert(idx + 1, extra_breadcrumb)
+ if IMultiFacetedBreadcrumb.providedBy(breadcrumb):
+ breadcrumbs.insert(
+ idx + 1,
+ Breadcrumb(
+ breadcrumb.context, rootsite=facet.rootsite,
+ text=facet.text))
break
if len(breadcrumbs) > 0:
page_crumb = self.makeBreadcrumbForRequestedPage()
@@ -333,26 +335,18 @@
URL and the page's name (i.e. the last path segment of the URL).
If the view is the default one for the object or the current
- facet, return None -- we'll have injected a *FacetBreadcrumb
+ facet, return None -- we'll have injected a facet Breadcrumb
earlier in the hierarchy which links here.
"""
- # XXX wgrant 2014-02-25: We should eventually define the
- # facet-level defaults in app-level ZCML rather than hardcoding
- # them centrally.
- facet_defaults = {
- 'answers': '+questions',
- 'branches': '+branches',
- 'bugs': '+bugs',
- 'specifications': '+specs',
- 'translations': '+translations',
- }
-
url = self.request.getURL()
obj = self.request.traversed_objects[-2]
default_view_name = getDefaultViewName(obj, self.request)
view = self._naked_context_view
- facet = get_facet(view)
- if view.__name__ not in (default_view_name, facet_defaults.get(facet)):
+ default_views = [default_view_name]
+ facet = queryUtility(IFacet, name=get_facet(view))
+ if facet is not None:
+ default_views.append(facet.default_view)
+ if view.__name__ not in default_views:
title = getattr(view, 'page_title', None)
if title is None:
title = getattr(view, 'label', None)
=== modified file 'lib/lp/blueprints/browser/configure.zcml'
--- lib/lp/blueprints/browser/configure.zcml 2014-02-26 03:05:44 +0000
+++ lib/lp/blueprints/browser/configure.zcml 2014-11-24 06:00:00 +0000
@@ -9,20 +9,6 @@
xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
i18n_domain="launchpad">
- <adapter
- name="specifications"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.blueprints.interfaces.specificationtarget.IHasSpecifications"
- factory="lp.blueprints.browser.specificationtarget.BlueprintsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="specifications"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.person.IPerson"
- factory="lp.blueprints.browser.specificationtarget.BlueprintsFacetBreadcrumb"
- permission="zope.Public"/>
-
-
<browser:navigation
module="lp.blueprints.browser.sprint"
classes="
=== modified file 'lib/lp/blueprints/browser/specificationtarget.py'
--- lib/lp/blueprints/browser/specificationtarget.py 2014-02-19 00:35:25 +0000
+++ lib/lp/blueprints/browser/specificationtarget.py 2014-11-24 06:00:00 +0000
@@ -56,7 +56,6 @@
)
from lp.services.webapp.authorization import check_permission
from lp.services.webapp.batching import BatchNavigator
-from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.menu import (
enabled_with_permission,
Link,
@@ -461,8 +460,3 @@
</ul>
</div>
""" % self.target_url
-
-
-class BlueprintsFacetBreadcrumb(Breadcrumb):
- rootsite = 'blueprints'
- text = 'Blueprints'
=== modified file 'lib/lp/blueprints/browser/sprint.py'
--- lib/lp/blueprints/browser/sprint.py 2014-11-17 18:36:16 +0000
+++ lib/lp/blueprints/browser/sprint.py 2014-11-24 06:00:00 +0000
@@ -84,6 +84,7 @@
Breadcrumb,
TitleBreadcrumb,
)
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
class SprintFacets(StandardLaunchpadFacets):
@@ -102,7 +103,7 @@
class SprintBreadcrumb(TitleBreadcrumb):
- implements(IHeadingBreadcrumb)
+ implements(IHeadingBreadcrumb, IMultiFacetedBreadcrumb)
class SprintOverviewMenu(NavigationMenu):
=== modified file 'lib/lp/blueprints/configure.zcml'
--- lib/lp/blueprints/configure.zcml 2014-11-17 18:36:16 +0000
+++ lib/lp/blueprints/configure.zcml 2014-11-24 06:00:00 +0000
@@ -21,7 +21,10 @@
component="lp.blueprints.publisher.BlueprintsLayer"
provides="zope.publisher.interfaces.browser.IDefaultBrowserLayer"
name="blueprints" />
-
+ <utility
+ component="lp.blueprints.publisher.SpecificationsFacet"
+ provides="lp.services.webapp.interfaces.IFacet"
+ name="specifications" />
<lp:help-folder folder="help" name="+help-blueprints" />
=== modified file 'lib/lp/blueprints/publisher.py'
--- lib/lp/blueprints/publisher.py 2011-12-24 17:49:30 +0000
+++ lib/lp/blueprints/publisher.py 2014-11-24 06:00:00 +0000
@@ -8,6 +8,7 @@
'BlueprintsBrowserRequest',
'BlueprintsLayer',
'blueprints_request_publication_factory',
+ 'SpecificationsFacet',
]
@@ -17,6 +18,7 @@
IDefaultBrowserLayer,
)
+from lp.services.webapp.interfaces import IFacet
from lp.services.webapp.publication import LaunchpadBrowserPublication
from lp.services.webapp.servers import (
LaunchpadBrowserRequest,
@@ -24,6 +26,15 @@
)
+class SpecificationsFacet:
+ implements(IFacet)
+
+ name = "specifications"
+ rootsite = "blueprints"
+ text = "Blueprints"
+ default_view = "+specs"
+
+
class BlueprintsLayer(IBrowserRequest, IDefaultBrowserLayer):
"""The Blueprints layer."""
=== modified file 'lib/lp/bugs/browser/bugtarget.py'
--- lib/lp/bugs/browser/bugtarget.py 2014-06-09 22:32:44 +0000
+++ lib/lp/bugs/browser/bugtarget.py 2014-11-24 06:00:00 +0000
@@ -6,7 +6,6 @@
__metaclass__ = type
__all__ = [
- "BugsFacetBreadcrumb",
"BugsPatchesView",
"BugTargetBugListingView",
"BugTargetBugTagsView",
@@ -138,7 +137,6 @@
)
from lp.services.webapp.authorization import check_permission
from lp.services.webapp.batching import BatchNavigator
-from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.escaping import structured
# A simple vocabulary for the subscribe_to_existing_bug form field.
@@ -1268,11 +1266,6 @@
return canonical_url(self.context)
-class BugsFacetBreadcrumb(Breadcrumb):
- rootsite = 'bugs'
- text = 'Bugs'
-
-
class BugsPatchesView(LaunchpadView):
"""View list of patch attachments associated with bugs."""
=== modified file 'lib/lp/bugs/browser/configure.zcml'
--- lib/lp/bugs/browser/configure.zcml 2014-11-16 08:31:41 +0000
+++ lib/lp/bugs/browser/configure.zcml 2014-11-24 06:00:00 +0000
@@ -265,12 +265,6 @@
class="lp.bugs.browser.bug.DeprecatedAssignedBugsView"
attribute="__call__"
permission="launchpad.AnyPerson"/>
- <adapter
- name="bugs"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.person.IPerson"
- factory="lp.bugs.browser.bugtarget.BugsFacetBreadcrumb"
- permission="zope.Public"/>
<browser:page
for="lp.registry.interfaces.person.IPerson"
name="+team-bugs-macro"
=== modified file 'lib/lp/bugs/configure.zcml'
--- lib/lp/bugs/configure.zcml 2014-02-24 06:50:46 +0000
+++ lib/lp/bugs/configure.zcml 2014-11-24 06:00:00 +0000
@@ -23,6 +23,10 @@
component="lp.bugs.publisher.BugsLayer"
provides="zope.publisher.interfaces.browser.IDefaultBrowserLayer"
name="bugs" />
+ <utility
+ component="lp.bugs.publisher.BugsFacet"
+ provides="lp.services.webapp.interfaces.IFacet"
+ name="bugs" />
<lp:help-folder folder="help" name="+help-bugs" />
@@ -982,18 +986,6 @@
<allow
interface="lp.bugs.interfaces.bugnotification.IBugNotificationSet"/>
</securedutility>
- <adapter
- name="bugs"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.bugs.interfaces.bugtarget.IBugTarget"
- factory="lp.bugs.browser.bugtarget.BugsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="bugs"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.projectgroup.IProjectGroup"
- factory="lp.bugs.browser.bugtarget.BugsFacetBreadcrumb"
- permission="zope.Public"/>
<!-- ProcessApportBlobJobs -->
<class class="lp.bugs.model.apportjob.ProcessApportBlobJob">
=== modified file 'lib/lp/bugs/publisher.py'
--- lib/lp/bugs/publisher.py 2011-12-24 17:49:30 +0000
+++ lib/lp/bugs/publisher.py 2014-11-24 06:00:00 +0000
@@ -18,7 +18,10 @@
IDefaultBrowserLayer,
)
-from lp.services.webapp.interfaces import ILaunchpadContainer
+from lp.services.webapp.interfaces import (
+ IFacet,
+ ILaunchpadContainer,
+ )
from lp.services.webapp.publication import LaunchpadBrowserPublication
from lp.services.webapp.publisher import LaunchpadContainer
from lp.services.webapp.servers import (
@@ -27,6 +30,15 @@
)
+class BugsFacet:
+ implements(IFacet)
+
+ name = "bugs"
+ rootsite = "bugs"
+ text = "Bugs"
+ default_view = "+bugs"
+
+
class BugsLayer(IBrowserRequest, IDefaultBrowserLayer):
"""The Bugs layer."""
=== modified file 'lib/lp/code/browser/branchlisting.py'
--- lib/lp/code/browser/branchlisting.py 2014-02-25 06:38:58 +0000
+++ lib/lp/code/browser/branchlisting.py 2014-11-24 06:00:00 +0000
@@ -12,7 +12,6 @@
'DistributionSourcePackageBranchesView',
'DistroSeriesBranchListingView',
'GroupedDistributionSourcePackageBranchesView',
- 'CodeFacetBreadcrumb',
'PersonBranchesMenu',
'PersonCodeSummaryView',
'PersonOwnedBranchesView',
@@ -132,15 +131,9 @@
precache_permission_for_objects,
)
from lp.services.webapp.batching import TableBatchNavigator
-from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.publisher import LaunchpadView
-class CodeFacetBreadcrumb(Breadcrumb):
- rootsite = 'code'
- text = 'Code'
-
-
class BranchBadges(HasBadgeBase):
badges = "private", "bug", "blueprint", "warning", "mergeproposal"
=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml 2014-11-16 19:56:32 +0000
+++ lib/lp/code/browser/configure.zcml 2014-11-24 06:00:00 +0000
@@ -881,13 +881,6 @@
template="../templates/active-reviews.pt"/>
<adapter
- name="branches"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.code.interfaces.hasbranches.IHasBranches"
- factory="lp.code.browser.branchlisting.CodeFacetBreadcrumb"
- permission="zope.Public"/>
-
- <adapter
provides="lp.services.webapp.interfaces.IBreadcrumb"
for="lp.code.interfaces.branch.IBranch"
factory="lp.code.browser.branch.BranchBreadcrumb"
=== modified file 'lib/lp/code/browser/tests/test_sourcepackagerecipe.py'
--- lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2014-11-17 00:13:29 +0000
+++ lib/lp/code/browser/tests/test_sourcepackagerecipe.py 2014-11-24 06:00:00 +0000
@@ -1083,11 +1083,8 @@
def test_index(self):
build = self.makeSuccessfulBuild()
-
- # XXX wgrant 2014-11-16 wgrant: The "Code" breadcrumb shouldn't
- # be there, but it's difficult to avoid and hopefully temporary.
self.assertTextMatchesExpressionIgnoreWhitespace("""\
- Master Chef Recipes Code cake_recipe
+ Master Chef Code Recipes cake_recipe
.*
Description Edit
This recipe .*changes.
@@ -1440,13 +1437,11 @@
def test_request_builds_page(self):
"""Ensure the +request-builds page is sane."""
recipe = self.makeRecipe()
- # XXX wgrant 2014-11-16 wgrant: The "Code" breadcrumb shouldn't
- # be there, but it's difficult to avoid and hopefully temporary.
pattern = dedent("""\
Request builds for cake_recipe
Master Chef
+ Code
Recipes
- Code
cake_recipe
Request builds for cake_recipe
Archive:
=== modified file 'lib/lp/code/configure.zcml'
--- lib/lp/code/configure.zcml 2014-02-18 11:40:52 +0000
+++ lib/lp/code/configure.zcml 2014-11-24 06:00:00 +0000
@@ -21,6 +21,10 @@
component="lp.code.publisher.CodeLayer"
provides="zope.publisher.interfaces.browser.IDefaultBrowserLayer"
name="code" />
+ <utility
+ component="lp.code.publisher.BranchesFacet"
+ provides="lp.services.webapp.interfaces.IFacet"
+ name="branches" />
<!-- Branch Merge Queues -->
<securedutility
=== modified file 'lib/lp/code/publisher.py'
--- lib/lp/code/publisher.py 2011-12-24 17:49:30 +0000
+++ lib/lp/code/publisher.py 2014-11-24 06:00:00 +0000
@@ -5,6 +5,7 @@
__metaclass__ = type
__all__ = [
+ 'BranchesFacet',
'CodeBrowserRequest',
'CodeLayer',
'code_request_publication_factory',
@@ -18,7 +19,10 @@
IDefaultBrowserLayer,
)
-from lp.services.webapp.interfaces import ILaunchpadContainer
+from lp.services.webapp.interfaces import (
+ IFacet,
+ ILaunchpadContainer,
+ )
from lp.services.webapp.publication import LaunchpadBrowserPublication
from lp.services.webapp.publisher import LaunchpadContainer
from lp.services.webapp.servers import (
@@ -27,6 +31,15 @@
)
+class BranchesFacet:
+ implements(IFacet)
+
+ name = "branches"
+ rootsite = "code"
+ text = "Code"
+ default_view = "+branches"
+
+
class CodeLayer(IBrowserRequest, IDefaultBrowserLayer):
"""The Code layer."""
=== modified file 'lib/lp/registry/browser/distributionsourcepackage.py'
--- lib/lp/registry/browser/distributionsourcepackage.py 2014-11-17 18:36:16 +0000
+++ lib/lp/registry/browser/distributionsourcepackage.py 2014-11-24 06:00:00 +0000
@@ -69,7 +69,7 @@
)
from lp.services.webapp.batching import BatchNavigator
from lp.services.webapp.breadcrumb import Breadcrumb
-from lp.services.webapp.interfaces import IBreadcrumb
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
from lp.services.webapp.menu import (
ApplicationMenu,
enabled_with_permission,
@@ -102,7 +102,7 @@
class DistributionSourcePackageBreadcrumb(Breadcrumb):
"""Builds a breadcrumb for an `IDistributionSourcePackage`."""
- implements(IBreadcrumb, IHeadingBreadcrumb)
+ implements(IHeadingBreadcrumb, IMultiFacetedBreadcrumb)
@property
def text(self):
=== modified file 'lib/lp/registry/browser/distroseries.py'
--- lib/lp/registry/browser/distroseries.py 2014-08-01 06:12:40 +0000
+++ lib/lp/registry/browser/distroseries.py 2014-11-24 06:00:00 +0000
@@ -27,7 +27,10 @@
from zope.component import getUtility
from zope.event import notify
from zope.formlib import form
-from zope.interface import Interface
+from zope.interface import (
+ implements,
+ Interface,
+ )
from zope.lifecycleevent import ObjectCreatedEvent
from zope.schema import (
Choice,
@@ -90,6 +93,7 @@
from lp.services.webapp.batching import BatchNavigator
from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.escaping import structured
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
from lp.services.webapp.menu import (
ApplicationMenu,
enabled_with_permission,
@@ -198,6 +202,7 @@
class DistroSeriesBreadcrumb(Breadcrumb):
"""Builds a breadcrumb for an `IDistroSeries`."""
+ implements(IMultiFacetedBreadcrumb)
@property
def text(self):
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2014-11-17 18:36:16 +0000
+++ lib/lp/registry/browser/person.py 2014-11-24 06:00:00 +0000
@@ -252,6 +252,7 @@
from lp.services.webapp.breadcrumb import DisplaynameBreadcrumb
from lp.services.webapp.interfaces import (
ILaunchBag,
+ IMultiFacetedBreadcrumb,
IOpenLaunchBag,
)
from lp.services.webapp.login import (
@@ -276,7 +277,7 @@
class PersonBreadcrumb(DisplaynameBreadcrumb):
- implements(IHeadingBreadcrumb)
+ implements(IHeadingBreadcrumb, IMultiFacetedBreadcrumb)
class RestrictedMembershipsPersonView(LaunchpadView):
=== modified file 'lib/lp/registry/browser/personproduct.py'
--- lib/lp/registry/browser/personproduct.py 2014-02-26 04:41:31 +0000
+++ lib/lp/registry/browser/personproduct.py 2014-11-24 06:00:00 +0000
@@ -12,6 +12,7 @@
from zope.component import queryAdapter
+from zope.interface import implements
from zope.traversing.interfaces import IPathAdapter
from lp.app.errors import NotFoundError
@@ -19,11 +20,11 @@
from lp.registry.interfaces.personproduct import IPersonProduct
from lp.services.webapp import (
canonical_url,
- Link,
Navigation,
StandardLaunchpadFacets,
)
from lp.services.webapp.breadcrumb import Breadcrumb
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
class PersonProductNavigation(Navigation):
@@ -43,6 +44,7 @@
class PersonProductBreadcrumb(Breadcrumb):
"""Breadcrumb for an `IPersonProduct`."""
+ implements(IMultiFacetedBreadcrumb)
@property
def text(self):
=== modified file 'lib/lp/registry/browser/pillar.py'
--- lib/lp/registry/browser/pillar.py 2014-11-17 18:36:16 +0000
+++ lib/lp/registry/browser/pillar.py 2014-11-24 06:00:00 +0000
@@ -67,6 +67,7 @@
Breadcrumb,
DisplaynameBreadcrumb,
)
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
from lp.services.webapp.menu import (
ApplicationMenu,
enabled_with_permission,
@@ -83,7 +84,7 @@
class PillarBreadcrumb(DisplaynameBreadcrumb):
"""Breadcrumb that uses the displayname or title as appropriate."""
- implements(IHeadingBreadcrumb)
+ implements(IHeadingBreadcrumb, IMultiFacetedBreadcrumb)
@property
def detail(self):
=== modified file 'lib/lp/registry/browser/productseries.py'
--- lib/lp/registry/browser/productseries.py 2014-07-07 03:32:50 +0000
+++ lib/lp/registry/browser/productseries.py 2014-11-24 06:00:00 +0000
@@ -136,6 +136,7 @@
from lp.services.webapp.batching import BatchNavigator
from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.escaping import structured
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
from lp.services.worlddata.helpers import browser_languages
from lp.services.worlddata.interfaces.country import ICountry
from lp.services.worlddata.interfaces.language import ILanguageSet
@@ -188,6 +189,7 @@
class ProductSeriesBreadcrumb(Breadcrumb):
"""Builds a breadcrumb for an `IProductSeries`."""
+ implements(IMultiFacetedBreadcrumb)
@property
def text(self):
=== modified file 'lib/lp/registry/browser/sourcepackage.py'
--- lib/lp/registry/browser/sourcepackage.py 2014-11-19 00:22:50 +0000
+++ lib/lp/registry/browser/sourcepackage.py 2014-11-24 06:00:00 +0000
@@ -94,7 +94,7 @@
)
from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.escaping import structured
-from lp.services.webapp.interfaces import IBreadcrumb
+from lp.services.webapp.interfaces import IMultiFacetedBreadcrumb
from lp.services.webapp.publisher import LaunchpadView
from lp.services.worlddata.helpers import browser_languages
from lp.services.worlddata.interfaces.country import ICountry
@@ -203,7 +203,7 @@
@adapter(ISourcePackage)
class SourcePackageBreadcrumb(Breadcrumb):
"""Builds a breadcrumb for an `ISourcePackage`."""
- implements(IBreadcrumb)
+ implements(IMultiFacetedBreadcrumb)
@property
def text(self):
=== modified file 'lib/lp/registry/browser/team.py'
--- lib/lp/registry/browser/team.py 2014-11-17 18:36:16 +0000
+++ lib/lp/registry/browser/team.py 2014-11-24 06:00:00 +0000
@@ -173,7 +173,10 @@
)
from lp.services.webapp.breadcrumb import Breadcrumb
from lp.services.webapp.escaping import structured
-from lp.services.webapp.interfaces import ILaunchBag
+from lp.services.webapp.interfaces import (
+ ILaunchBag,
+ IMultiFacetedBreadcrumb,
+ )
class TeamPrivacyAdapter:
@@ -1247,7 +1250,7 @@
class TeamBreadcrumb(Breadcrumb):
"""Builds a breadcrumb for an `ITeam`."""
- implements(IHeadingBreadcrumb)
+ implements(IHeadingBreadcrumb, IMultiFacetedBreadcrumb)
@property
def text(self):
=== modified file 'lib/lp/registry/configure.zcml'
--- lib/lp/registry/configure.zcml 2014-11-17 18:36:16 +0000
+++ lib/lp/registry/configure.zcml 2014-11-24 06:00:00 +0000
@@ -1864,7 +1864,8 @@
factory="lp.registry.adapters.sourcepackage_to_distribution"
permission="zope.Public"/>
<adapter
- factory="lp.registry.browser.sourcepackage.SourcePackageBreadcrumb"/>
+ provides="lp.services.webapp.interfaces.IBreadcrumb"
+ factory="lp.registry.browser.sourcepackage.SourcePackageBreadcrumb" />
<adapter
provides="lp.registry.interfaces.sourcepackagename.ISourcePackageName"
for="lp.registry.interfaces.sourcepackage.ISourcePackage"
=== modified file 'lib/lp/services/webapp/breadcrumb.py'
--- lib/lp/services/webapp/breadcrumb.py 2014-11-16 09:15:46 +0000
+++ lib/lp/services/webapp/breadcrumb.py 2014-11-24 06:00:00 +0000
@@ -33,8 +33,10 @@
_detail = None
_url = None
inside = None
+ _rootsite = None
- def __init__(self, context, url=None, text=None, inside=None):
+ def __init__(self, context, url=None, text=None, inside=None,
+ rootsite=None):
self.context = context
if url is not None:
self._url = url
@@ -42,6 +44,8 @@
self.text = text
if inside is not None:
self.inside = inside
+ if rootsite is not None:
+ self._rootsite = rootsite
@property
def rootsite(self):
@@ -50,6 +54,8 @@
If the `ICanonicalUrlData` for our context defines a rootsite, we
return that, otherwise we return 'mainsite'.
"""
+ if self._rootsite is not None:
+ return self._rootsite
url_data = ICanonicalUrlData(self.context)
if url_data.rootsite:
return url_data.rootsite
=== modified file 'lib/lp/services/webapp/interfaces.py'
--- lib/lp/services/webapp/interfaces.py 2014-11-16 09:15:46 +0000
+++ lib/lp/services/webapp/interfaces.py 2014-11-24 06:00:00 +0000
@@ -78,6 +78,14 @@
# Menus and Facets
#
+class IFacet(Interface):
+ """Interface for metadata about facets."""
+
+ rootsite = Attribute("Rootsite name")
+ title = Attribute("Title")
+ default_view = Attribute("Default view for multi-faceted objects")
+
+
class IMenu(Interface):
"""Public interface for facets, menus, extra facets and extra menus."""
@@ -234,6 +242,10 @@
'Next object up the chain. If not specified, the URL parent is used.')
+class IMultiFacetedBreadcrumb(Interface):
+ """A breadcrumb link for an object that transcends facets."""
+
+
#
# Canonical URLs
#
=== modified file 'lib/lp/translations/browser/translations.py'
--- lib/lp/translations/browser/translations.py 2014-02-24 06:50:46 +0000
+++ lib/lp/translations/browser/translations.py 2014-11-24 06:00:00 +0000
@@ -10,7 +10,6 @@
'TranslationsLanguageBreadcrumb',
'TranslationsMixin',
'TranslationsRedirectView',
- 'TranslationsFacetBreadcrumb',
]
from zope.component import getUtility
@@ -164,11 +163,6 @@
target, request, status=301)
-class TranslationsFacetBreadcrumb(Breadcrumb):
- rootsite = 'translations'
- text = 'Translations'
-
-
class TranslationsLanguageBreadcrumb(Breadcrumb):
"""Breadcrumb for objects with language."""
=== modified file 'lib/lp/translations/configure.zcml'
--- lib/lp/translations/configure.zcml 2014-02-24 06:50:46 +0000
+++ lib/lp/translations/configure.zcml 2014-11-24 06:00:00 +0000
@@ -17,11 +17,14 @@
<publisher
name="translations"
factory="lp.translations.publisher.translations_request_publication_factory"/>
-
<utility
component="lp.translations.publisher.TranslationsLayer"
provides="zope.publisher.interfaces.browser.IDefaultBrowserLayer"
name="translations" />
+ <utility
+ component="lp.translations.publisher.TranslationsFacet"
+ provides="lp.services.webapp.interfaces.IFacet"
+ name="translations" />
<lp:help-folder folder="help" name="+help-translations" />
@@ -219,45 +222,6 @@
interface="lp.translations.interfaces.pofiletranslator.IPOFileTranslatorSet"/>
</securedutility>
- <!-- Breadcrumbs for DistroSeries, Distribution, ProductSeries, Product,
- ProjectGroup, TranslationsPerson -->
- <adapter
- name="translations"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.distribution.IDistribution"
- factory="lp.translations.browser.translations.TranslationsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="translations"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.distroseries.IDistroSeries"
- factory="lp.translations.browser.translations.TranslationsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="translations"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.product.IProduct"
- factory="lp.translations.browser.translations.TranslationsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="translations"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.productseries.IProductSeries"
- factory="lp.translations.browser.translations.TranslationsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="translations"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.projectgroup.IProjectGroup"
- factory="lp.translations.browser.translations.TranslationsFacetBreadcrumb"
- permission="zope.Public"/>
- <adapter
- name="translations"
- provides="lp.services.webapp.interfaces.IBreadcrumb"
- for="lp.registry.interfaces.person.IPerson"
- factory="lp.translations.browser.translations.TranslationsFacetBreadcrumb"
- permission="zope.Public"/>
-
<!-- Subscribers to registry objects -->
<subscriber
=== modified file 'lib/lp/translations/publisher.py'
--- lib/lp/translations/publisher.py 2011-12-24 17:49:30 +0000
+++ lib/lp/translations/publisher.py 2014-11-24 06:00:00 +0000
@@ -17,6 +17,7 @@
IDefaultBrowserLayer,
)
+from lp.services.webapp.interfaces import IFacet
from lp.services.webapp.publication import LaunchpadBrowserPublication
from lp.services.webapp.servers import (
LaunchpadBrowserRequest,
@@ -24,6 +25,15 @@
)
+class TranslationsFacet:
+ implements(IFacet)
+
+ name = "translations"
+ rootsite = "translations"
+ text = "Translations"
+ default_view = "+translations"
+
+
class TranslationsLayer(IBrowserRequest, IDefaultBrowserLayer):
"""The Translations layer."""
=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-export.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-export.txt 2010-12-28 17:16:56 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-export.txt 2014-11-24 06:00:00 +0000
@@ -19,8 +19,8 @@
>>> user_browser.getLink('Download').click()
>>> print user_browser.title
- Download translation : Spanish (es)...
- ...evolution... package : Translations : Hoary (5.04) : Ubuntu
+ Download translation : Spanish (es)... : Translations :
+ ...evolution... package : Hoary (5.04) : Ubuntu
>>> print find_main_content(user_browser.contents)
<...
=== modified file 'lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt'
--- lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt 2011-12-24 15:18:32 +0000
+++ lib/lp/translations/stories/standalone/xx-pofile-translate-message-filtering.txt 2014-11-24 06:00:00 +0000
@@ -48,8 +48,8 @@
... 'http://translations.launchpad.dev/ubuntu/hoary/'
... '+source/evolution/+pots/evolution-2.2/es/+translate')
>>> print user_browser.title
- Spanish (es) : Template ...evolution-2.2... : ...evolution... package :
- Translations : Hoary (5.04) : Ubuntu
+ Spanish (es) : Template ...evolution-2.2... : Translations :
+ ...evolution... package : Hoary (5.04) : Ubuntu
He can see that there are 22 messages.
@@ -126,7 +126,7 @@
>>> user_browser.getControl('Change').click()
>>> print user_browser.title
English (Australia) (en_AU) : Template ...evolution-2.2... :
- ...evolution... package : Translations : Hoary (5.04) : Ubuntu
+ Translations : ...evolution... package : Hoary (5.04) : Ubuntu
>>> contents = find_main_content(user_browser.contents)
>>> print_batch_header(contents)
=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-index.txt'
--- lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2012-08-06 06:09:19 +0000
+++ lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2014-11-24 06:00:00 +0000
@@ -12,8 +12,8 @@
>>> anon_browser.open("http://translations.launchpad.dev/"
... "ubuntu/hoary/+source/evolution/+pots/evolution-2.2/")
>>> print anon_browser.title
- Template ...evolution-2.2... :
- ...evolution... package : Translations : Hoary (5.04) : Ubuntu
+ Template ...evolution-2.2... : Translations :
+ ...evolution... package : Hoary (5.04) : Ubuntu
The owner of the template is diplayed.
=== modified file 'lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt'
--- lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt 2009-11-09 17:08:21 +0000
+++ lib/lp/translations/stories/standalone/xx-rosetta-sourcepackage-list.txt 2014-11-24 06:00:00 +0000
@@ -8,7 +8,7 @@
... 'http://translations.launchpad.dev/ubuntu/hoary/'
... '+source/evolution')
>>> anon_browser.title
- '...evolution...package : Translations : Hoary (5.04) : Ubuntu'
+ 'Translations : ...evolution...package : Hoary (5.04) : Ubuntu'
>>> content = find_main_content(anon_browser.contents)
>>> print extract_text(content.findAll('h1')[0]).encode(
=== modified file 'lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt'
--- lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt 2013-09-27 04:13:23 +0000
+++ lib/lp/translations/stories/standalone/xx-sourcepackage-export.txt 2014-11-24 06:00:00 +0000
@@ -166,7 +166,7 @@
... 'http://translations.launchpad.dev/'
... 'ubuntu/hoary/+source/mozilla/+export')
>>> browser.title
- 'Download : \xe2\x80\x9cmozilla...
+ 'Download : Translations : \xe2\x80\x9cmozilla...
>>> browser.getControl('Request Download').click()
References