Merge lp:~wgrant/launchpad/header-4.0 into lp:launchpad

Proposed by William Grant on 2016-09-24
Status: Work in progress
Proposed branch: lp:~wgrant/launchpad/header-4.0
Merge into: lp:launchpad
Diff against target: 228 lines (+100/-8) (has conflicts)
7 files modified
lib/canonical/launchpad/icing/css/layout.css (+2/-1)
lib/lp/app/browser/launchpad.py (+77/-1)
lib/lp/app/browser/tests/watermark.txt (+12/-4)
lib/lp/app/templates/base-layout.pt (+1/-1)
lib/lp/registry/browser/personproduct.py (+1/-1)
lib/lp/registry/interfaces/distributionsourcepackage.py (+5/-0)
lib/lp/services/webapp/interfaces.py (+2/-0)
Text conflict in lib/lp/app/browser/launchpad.py
Text conflict in lib/lp/registry/interfaces/distributionsourcepackage.py
To merge this branch: bzr merge lp:~wgrant/launchpad/header-4.0
Reviewer Review Type Date Requested Status
Launchpad code reviewers 2016-09-24 Pending
Review via email: mp+306684@code.launchpad.net
To post a comment you must log in.

Unmerged revisions

17259. By William Grant on 2014-11-27

Merge devel.

17258. By William Grant on 2014-11-24

Merge devel.

17257. By William Grant on 2014-11-17

Fix Hierarchy property duplication. Breadcrumbs and titles now.

17256. By William Grant on 2014-11-17

Merge series-breadcrumbs-later. Breadcrumbs are totally broken.

17255. By William Grant on 2014-11-16

Merge WatermarkTalesAdapter into Hierarchy. The title is now generated from breadcrumbs.

17254. By William Grant on 2014-11-16

Fix "Recipes" breadcrumb by skipping IHeadingBreadcrumbs rather than IHeadingContexts.

17253. By William Grant on 2014-11-16

Merge series-breadcrumbs-later, resolving conflicts.

17252. By William Grant on 2014-11-16

TEMP

17251. By William Grant on 2014-11-16

Construct both elements in watermark:heading.

17250. By William Grant on 2014-11-16

Use breadcrumb text rather than object title in the watermark. DistributionSourcePackages need not duplicate the distribution.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/icing/css/layout.css'
2--- lib/canonical/launchpad/icing/css/layout.css 2014-11-27 06:34:33 +0000
3+++ lib/canonical/launchpad/icing/css/layout.css 2016-09-24 06:25:43 +0000
4@@ -104,6 +104,7 @@
5 .watermark-apps-portlet ul.facetmenu {
6 margin-top: 12px;
7 margin-left: -0.5em;
8+ border-bottom: 1px solid #747474;
9 white-space: nowrap;
10 }
11 .watermark-apps-portlet ul.facetmenu li {
12@@ -112,7 +113,7 @@
13 }
14 .watermark-apps-portlet ul.facetmenu li a,
15 .watermark-apps-portlet ul.facetmenu li span {
16- padding: 0.3em 0.5em;
17+ padding: 0.2em 0.5em;
18 margin-right: 0.4em;
19 }
20 .watermark-apps-portlet ul.facetmenu li a:link,
21
22=== modified file 'lib/lp/app/browser/launchpad.py'
23--- lib/lp/app/browser/launchpad.py 2016-06-22 21:04:30 +0000
24+++ lib/lp/app/browser/launchpad.py 2016-09-24 06:25:43 +0000
25@@ -394,6 +394,24 @@
26 return crumbs
27
28 @property
29+ def items_for_body(self):
30+ """Return breadcrumbs to display in the page body.
31+
32+ While all breadcrumbs should be included in the document title,
33+ the first few are represented specially in the body's header
34+ (aka. watermark), so we don't want to duplicate them.
35+ """
36+ crumbs = []
37+ print "items=%r" % self.items
38+ for crumb in self.items:
39+ if IHeadingBreadcrumb.providedBy(crumb):
40+ crumbs = []
41+ continue
42+ crumbs.append(crumb)
43+ print "crumbs=%r" % crumbs
44+ return crumbs
45+
46+ @property
47 def display_breadcrumbs(self):
48 """Return whether the breadcrumbs should be displayed."""
49 # If there is only one breadcrumb then it does not make sense
50@@ -402,7 +420,65 @@
51 # to display breadcrumbs either.
52 has_major_heading = IMajorHeadingView.providedBy(
53 self._naked_context_view)
54- return len(self.items_for_body) > 1 and not has_major_heading
55+<<<<<<< TREE
56+ return len(self.items_for_body) > 1 and not has_major_heading
57+=======
58+ return len(self.items_for_body) > 1 and not has_major_heading
59+
60+ @property
61+ def heading_breadcrumbs(self):
62+ crumbs = [
63+ crumb for crumb in self.items
64+ if IHeadingBreadcrumb.providedBy(crumb)]
65+ assert len(crumbs) <= 2
66+ return crumbs
67+
68+ def heading(self):
69+ """Return the heading text for the page.
70+
71+ If the view provides `IEditableContextTitle` then the top heading is
72+ rendered from the view's `title_edit_widget` and is generally
73+ editable.
74+
75+ Otherwise, if the context provides `IHeadingContext` then we return an
76+ H1, else an H2.
77+ """
78+ # Check the view; is the title editable?
79+ if IEditableContextTitle.providedBy(self.context):
80+ return self.context.title_edit_widget()
81+ # The title is static, but only the context's index view gets an H1.
82+ heading = 'h1' if IMajorHeadingView.providedBy(self.context) else 'h2'
83+ # If there is actually no root context, then it's a top-level
84+ # context-less page so Launchpad.net is shown as the branding.
85+ crumbs = self.heading_breadcrumbs
86+ if len(crumbs) >= 1:
87+ title = crumbs[0].detail
88+ else:
89+ title = 'Launchpad.net'
90+ # For non-editable titles, generate the static heading.
91+ markup = structured(
92+ "<%(heading)s>%(title)s</%(heading)s>",
93+ heading=heading, title=title).escapedtext
94+ if len(crumbs) >= 2:
95+ markup += structured(
96+ '\n<%(heading)s class="secondary">%(title)s</%(heading)s>',
97+ heading=heading, title=crumbs[1].detail).escapedtext
98+ return markup
99+
100+ def logo(self):
101+ """Return the logo image for the top header breadcrumb's context."""
102+ logo_context = (
103+ self.heading_breadcrumbs[0].context if self.heading_breadcrumbs
104+ else None)
105+ adapter = queryAdapter(logo_context, IPathAdapter, 'image')
106+ if logo_context != self.context.context and logo_context is not None:
107+ return structured(
108+ '<a href="%s">%s</a>',
109+ canonical_url(logo_context, rootsite='mainsite'),
110+ structured(adapter.logo())).escapedtext
111+ else:
112+ return adapter.logo()
113+>>>>>>> MERGE-SOURCE
114
115 @property
116 def heading_breadcrumbs(self):
117
118=== modified file 'lib/lp/app/browser/tales.py'
119=== modified file 'lib/lp/app/browser/tests/watermark.txt'
120--- lib/lp/app/browser/tests/watermark.txt 2015-07-08 16:05:11 +0000
121+++ lib/lp/app/browser/tests/watermark.txt 2016-09-24 06:25:43 +0000
122@@ -4,14 +4,14 @@
123
124 The watermark is the image and heading used on all the main Launchpad
125 pages. The image and heading are determined by Hierarchy from the
126-IRootContext for the context object.
127+IHeadingBreadcrumbs in the context object's breadcrumbs.
128
129
130 Watermark headings
131 ==================
132
133 Hierarchy.heading() is used when you want a heading for the nearest
134-object that implements IRootContext.
135+object that implements IHeadingBreadcrumb.
136
137 >>> from lp.app.browser.launchpad import Hierarchy
138 >>> from lp.services.webapp.servers import LaunchpadTestRequest
139@@ -26,7 +26,7 @@
140 ... req.traversed_objects.append(view)
141 ... return Hierarchy(view, req)
142
143-Products directly implement IRootContext.
144+Products directly implement IHeadingContext.
145
146 >>> widget = factory.makeProduct(displayname='Widget')
147 >>> print get_hierarchy(widget).heading()
148@@ -38,7 +38,7 @@
149 >>> print get_hierarchy(dev_focus).heading()
150 <h...><a...>Widget</a></h...>
151
152-ProjectGroups also directly implement IRootContext ...
153+ProjectGroups also directly implement IHeadingContext ...
154
155 >>> kde = factory.makeProject(displayname='KDE')
156 >>> print get_hierarchy(kde).heading()
157@@ -50,6 +50,14 @@
158 >>> print get_hierarchy(mint).heading()
159 <h...><a...>Mint Linux</a></h...>
160
161+... and distribution source packacges ...
162+
163+ >>> dpkg = factory.makeDistributionSourcePackage(
164+ ... distribution=mint, sourcepackagename=u"dpkg")
165+ >>> print test_tales('view/watermark:heading', view=view(dpkg))
166+ <h...>Mint Linux</h...>
167+ <h...>“dpkg” package</h...>
168+
169 ... and people ...
170
171 >>> eric = factory.makePerson(displayname="Eric the Viking")
172
173=== modified file 'lib/lp/app/templates/base-layout.pt'
174--- lib/lp/app/templates/base-layout.pt 2016-09-14 11:13:06 +0000
175+++ lib/lp/app/templates/base-layout.pt 2016-09-24 06:25:43 +0000
176@@ -110,7 +110,7 @@
177 >Page Label
178 </h1>
179 <tal:breadcrumbs replace="structure view/@@+hierarchy">
180- ProjectName > Branches > Merge Proposals > fix-for-navigation
181+ Merge Proposals > fix-for-navigation
182 </tal:breadcrumbs>
183 <div id="registration" class="registering"
184 tal:condition="not: view/macro:is-page-contentless">
185
186=== modified file 'lib/lp/registry/browser/personproduct.py'
187--- lib/lp/registry/browser/personproduct.py 2015-07-08 16:05:11 +0000
188+++ lib/lp/registry/browser/personproduct.py 2016-09-24 06:25:43 +0000
189@@ -50,7 +50,7 @@
190
191 @property
192 def text(self):
193- return self.context.product.displayname
194+ return self.context.product.title
195
196 @property
197 def url(self):
198
199=== modified file 'lib/lp/registry/interfaces/distributionsourcepackage.py'
200--- lib/lp/registry/interfaces/distributionsourcepackage.py 2015-10-12 16:16:28 +0000
201+++ lib/lp/registry/interfaces/distributionsourcepackage.py 2016-09-24 06:25:43 +0000
202@@ -40,8 +40,13 @@
203 from lp.soyuz.enums import ArchivePurpose
204
205
206+<<<<<<< TREE
207 class IDistributionSourcePackage(IHeadingContext, IBugTarget, IHasBranches,
208 IHasMergeProposals, IHasOfficialBugTags,
209+=======
210+class IDistributionSourcePackage(IBugTarget, IHasBranches,
211+ IHasMergeProposals, IHasOfficialBugTags,
212+>>>>>>> MERGE-SOURCE
213 IStructuralSubscriptionTarget,
214 IQuestionTarget, IHasDrivers,
215 IHasGitRepositories):
216
217=== modified file 'lib/lp/services/webapp/interfaces.py'
218--- lib/lp/services/webapp/interfaces.py 2016-09-14 11:12:13 +0000
219+++ lib/lp/services/webapp/interfaces.py 2016-09-24 06:25:43 +0000
220@@ -236,6 +236,8 @@
221 class IBreadcrumb(Interface):
222 """A breadcrumb link."""
223
224+ context = Attribute("Object that this breadcrumb represents.")
225+
226 url = Attribute('Absolute url of this breadcrumb.')
227
228 text = Attribute('Text of this breadcrumb.')