Merge lp:~sinzui/launchpad/porlet-improvements into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Merged at revision: not available
Proposed branch: lp:~sinzui/launchpad/porlet-improvements
Merge into: lp:launchpad
Diff against target: None lines
To merge this branch: bzr merge lp:~sinzui/launchpad/porlet-improvements
Reviewer Review Type Date Requested Status
Abel Deuring (community) Approve
Review via email: mp+11167@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :
Download full text (5.8 KiB)

This is my branch to improve portlets used by product and series pages.
These are the bugs that must be fixed to land the series pages. They
are large bugs that kiko, beuno, and other have reported about the
presentation.

    lp:~sinzui/launchpad/series-indexes
    Diff size: 543
    Launchpad bug: https://bugs.launchpad.net/bugs/series-indexes
    Test command: ./bin/test -vvt "tales|stories/faq|(pillar|productseries)-views"
    Pre-implementation: beuno, kiko, and geser (the user who diagnosed the
                        css issue using firebug)
    Target release: 3.1.0

= Improve portlets used by product and series pages =

Bug #423803 The downloads portlet needs improvement
    * The font size of the link must be the same as the page content
    * Remove the underline
    * ellipise the middle of long string
    * The release version must be stated for the download

Per bug 415558
    * Explain there are no downloads when there are no releases

Per bug 422290
    * the downloads link must be blue
    * Move the rdf link to the info portlet.

Bug #423946 [ProductSeriesView needs latest_release_with_download_files]
    * latest_release_with_download_files is need so that the productseries
      +index can include the downloads portlet/

Bug 423869 [distributionsourcepackage index is broken by script tag]
    * The page does not display in some browsers because the script tags
      cannot be empty, they must have a closing tag.
      <script ... /> => <script ...></script>

423096 [DSP "Help translate" involvement link broken]
    * DSP cannot be translated, remove the link.
    * ADDENDUM
      * series cannot have answers
      * distroseries cannot have codehosting.

Bug #423976 [Tweak the involvement and faq portlets]
    * FAQs porlet is inconsitent:
      List all FAQs => All FAQs
    * The Get Involved section buttons are almost there but not exactly
      there yet:
        * highlighting the whole row in gray.
        * Omit the horizontal line after the last item.
    * The registered info in the portlet should be a smaller font and grey.

Bug #419337 [The portlet on the project page gets misplaced on a wide window]
    * After working with the user on IRC, We discovered that #maincontent's
      width was specified in em, but .yui-t4 .yui-b are specified in %.
      em => %

== Rules ==

See above.

== QA ==

See http://people.canonical.com/~curtis/portlets.png

== Lint ==

Linting changed files:
  lib/canonical/launchpad/doc/tales.txt
  lib/canonical/launchpad/icing/style-3-0.css
  lib/canonical/launchpad/webapp/tales.py
  lib/lp/answers/browser/faqcollection.py
  lib/lp/answers/stories/faq-add.txt
  lib/lp/answers/stories/faq-browse-and-search.txt
  lib/lp/answers/templates/questiontarget-portlet-latestquestions.pt
  lib/lp/blueprints/templates/hassprints-portlet-coming-sprints.pt
  lib/lp/blueprints/templates/specificationtarget-portlet-latestspecs.pt
  lib/lp/bugs/templates/bugtarget-portlet-latestbugs.pt
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/browser/pillar.py
  lib/lp/registry/browser/productseries.py
  lib/lp/registry/browser/tests/pillar-views.txt
  lib/lp/registry/browser/tests/productseries-vi...

Read more...

Revision history for this message
Abel Deuring (adeuring) wrote :

Hi Curtis,

nice branch. I have only a few minor remarks.

> === modified file 'lib/canonical/launchpad/doc/tales.txt'
> --- lib/canonical/launchpad/doc/tales.txt 2009-08-20 12:24:29 +0000
> +++ lib/canonical/launchpad/doc/tales.txt 2009-09-03 17:59:56 +0000
> @@ -214,6 +214,19 @@
> >>> test_tales('foo/fmt:shorten/8', foo='abcdefghij')
> 'abcde...'
>
> +To ellisize the middle of a string. use fmt:ellipsize and pass the max

s/ellisize/ellipsize/

> === modified file 'lib/canonical/launchpad/icing/style-3-0.css'
> --- lib/canonical/launchpad/icing/style-3-0.css 2009-09-02 14:19:45 +0000
> +++ lib/canonical/launchpad/icing/style-3-0.css 2009-09-03 21:30:01 +0000
[...]
> @@ -564,17 +564,20 @@
> border-radius: 3px;
> background: #4f843c url(/@@/bg-project-downloads.png) center right no-repeat;
> padding: 6%;
> - padding-right: 50px;
> + padding-right: 40px;
> color: #fff;
> - font-size: 108%;
> - text-decoration: underline;
> + font-size: 97%;

This is for ".downloads li a", i.e., for a "smaller" font size, not
for a heading. If we assume that the base font size is 20px (it is
is most real-world cases smaller, I think), it will be reduced to
19.4px -- that's hardly noticable. Couldn't the size stay at 100%?

> === modified file 'lib/canonical/launchpad/webapp/tales.py'
> --- lib/canonical/launchpad/webapp/tales.py 2009-08-31 12:01:46 +0000
> +++ lib/canonical/launchpad/webapp/tales.py 2009-09-03 21:23:25 +0000

[...]

> @@ -2830,6 +2831,16 @@
> else:
> return self._stringtoformat
>
> + def ellipsize(self, maxlength):
> + """Use like tal:content="context/foo/fmt:ellipsize/60"."""
> + if len(self._stringtoformat) > maxlength:
> + length = (maxlength - 3) / 2
> + return (
> + self._stringtoformat[:length] + '...' +
> + self._stringtoformat[-length:])

Not a real issue, but if maxlength is an even number, this return
a string with maxlength - 1 characters. What about using

    self._stringtoformat[:maxlength - length - 3] + ...

> + else:
> + return self._stringtoformat
> +

review: Approve
Revision history for this message
Curtis Hovey (sinzui) wrote :

On Fri, 2009-09-04 at 09:36 +0000, Abel Deuring wrote:
> Review: Approve
> Hi Curtis,
>
> nice branch. I have only a few minor remarks.
>
>
> > === modified file 'lib/canonical/launchpad/doc/tales.txt'
> > --- lib/canonical/launchpad/doc/tales.txt 2009-08-20 12:24:29 +0000
> > +++ lib/canonical/launchpad/doc/tales.txt 2009-09-03 17:59:56 +0000
> > @@ -214,6 +214,19 @@
> > >>> test_tales('foo/fmt:shorten/8', foo='abcdefghij')
> > 'abcde...'
> >
> > +To ellisize the middle of a string. use fmt:ellipsize and pass the max
>
> s/ellisize/ellipsize/

Fixed.

> > === modified file 'lib/canonical/launchpad/icing/style-3-0.css'
> > --- lib/canonical/launchpad/icing/style-3-0.css 2009-09-02 14:19:45 +0000
> > +++ lib/canonical/launchpad/icing/style-3-0.css 2009-09-03 21:30:01 +0000
> [...]
> > @@ -564,17 +564,20 @@
> > border-radius: 3px;
> > background: #4f843c url(/@@/bg-project-downloads.png) center right no-repeat;
> > padding: 6%;
> > - padding-right: 50px;
> > + padding-right: 40px;
> > color: #fff;
> > - font-size: 108%;
> > - text-decoration: underline;
> > + font-size: 97%;
>
> This is for ".downloads li a", i.e., for a "smaller" font size, not
> for a heading. If we assume that the base font size is 20px (it is
> is most real-world cases smaller, I think), it will be reduced to
> 19.4px -- that's hardly noticable. Couldn't the size stay at 100%?

The table of sizes is in style-3.0.css. 100% is 13px. The body is set to
93% (12px). You have caught a typo. I intended to type 93% to make the
font the same as the rest of the content.

> > === modified file 'lib/canonical/launchpad/webapp/tales.py'
> > --- lib/canonical/launchpad/webapp/tales.py 2009-08-31 12:01:46 +0000
> > +++ lib/canonical/launchpad/webapp/tales.py 2009-09-03 21:23:25 +0000
>
> [...]
>
> > @@ -2830,6 +2831,16 @@
> > else:
> > return self._stringtoformat
> >
> > + def ellipsize(self, maxlength):
> > + """Use like tal:content="context/foo/fmt:ellipsize/60"."""
> > + if len(self._stringtoformat) > maxlength:
> > + length = (maxlength - 3) / 2
> > + return (
> > + self._stringtoformat[:length] + '...' +
> > + self._stringtoformat[-length:])
>
> Not a real issue, but if maxlength is an even number, this return
> a string with maxlength - 1 characters. What about using
>
> self._stringtoformat[:maxlength - length - 3] + ...

Your approach is better, I used it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/doc/tales.txt'
2--- lib/canonical/launchpad/doc/tales.txt 2009-08-20 12:24:29 +0000
3+++ lib/canonical/launchpad/doc/tales.txt 2009-09-03 17:59:56 +0000
4@@ -214,6 +214,19 @@
5 >>> test_tales('foo/fmt:shorten/8', foo='abcdefghij')
6 'abcde...'
7
8+To ellisize the middle of a string. use fmt:ellipsize and pass the max
9+length.
10+
11+ >>> print test_tales('foo/fmt:ellipsize/25',
12+ ... foo='foo-bar-baz-bazoo_22.443.tar.gz')
13+ foo-bar-baz....443.tar.gz
14+
15+The string is not ellipsized if it is less than the max length.
16+
17+ >>> print test_tales('foo/fmt:ellipsize/25',
18+ ... foo='firefox-0.9.2.orig.tar.gz')
19+ firefox-0.9.2.orig.tar.gz
20+
21 To preserve newlines in text when displaying as HTML, use fmt:nl_to_br:
22
23 >>> test_tales('foo/fmt:nl_to_br',
24
25=== modified file 'lib/canonical/launchpad/icing/style-3-0.css'
26--- lib/canonical/launchpad/icing/style-3-0.css 2009-09-02 14:19:45 +0000
27+++ lib/canonical/launchpad/icing/style-3-0.css 2009-09-03 21:30:01 +0000
28@@ -7,7 +7,7 @@
29 #maincontent {
30 float: left;
31 width: 100%;
32- margin-right: -25em;
33+ margin-right: -25%;
34 }
35 #maincontent ol, #maincontent ul {
36 padding-left: auto;
37@@ -397,6 +397,9 @@
38 color: #666;
39 font-style: italic;
40 }
41+li .registered {
42+ font-style: normal;
43+ }
44 .description {
45 clear: both;
46 font-size: 100%;
47@@ -546,9 +549,6 @@
48 background: #fbfbfb;
49 }
50
51-.downloads a {
52- color: #4f843c;
53- }
54 .downloads li {
55 margin: 0;
56 padding: 2px 0 0;
57@@ -564,17 +564,20 @@
58 border-radius: 3px;
59 background: #4f843c url(/@@/bg-project-downloads.png) center right no-repeat;
60 padding: 6%;
61- padding-right: 50px;
62+ padding-right: 40px;
63 color: #fff;
64- font-size: 108%;
65- text-decoration: underline;
66+ font-size: 97%;
67+ }
68+.downloads .version {
69+ -moz-border-radius: 5px 5px 0 0;
70+ -webkit-border-radius: 5px 5px 0 0;
71+ -khtml-border-radius: 5px 5px 0 0;
72+ border-radius: 5px 5px 0 0;
73+ background: #d3e3c7;
74+ padding: 0 1em;
75 }
76 .downloads .released {
77- margin: .3em 0 1em 0;
78- padding: 0 .2em 0 0;
79- text-align: right;
80- }
81-.downloads .released span {
82+ margin: .3em 0 .5em 0;
83 -moz-border-radius: 0 0 5px 5px;
84 -webkit-border-radius: 0 0 5px 5px;
85 -khtml-border-radius: 0 0 5px 5px;
86@@ -583,7 +586,7 @@
87 padding: 0.2em 1em;
88 }
89 .downloads .alternate {
90- text-align: right;
91+ padding: 0 0 0 1em;
92 }
93
94 ul.super-add-action {
95@@ -610,11 +613,8 @@
96 text-decoration: underline;
97 }
98
99-.involvement ul {
100- border-top: 1px solid #d0d0d0;
101- }
102 .involvement li {
103- border-bottom: 1px solid #d0d0d0;
104+ border-top: 1px solid #d0d0d0;
105 padding: 0;
106 font-size: 108%;
107 font-weight: bold;
108@@ -643,6 +643,10 @@
109 color: #5ba4c6;
110 background: url(/@@/blueprints-arrow-right.png) right center no-repeat;
111 }
112+.involvement a:hover {
113+ text-decoration: none;
114+ background-color: #eee;
115+ }
116
117 .announcements li {
118 margin-bottom: 0.5em;
119
120=== modified file 'lib/canonical/launchpad/webapp/tales.py'
121--- lib/canonical/launchpad/webapp/tales.py 2009-08-31 12:01:46 +0000
122+++ lib/canonical/launchpad/webapp/tales.py 2009-09-03 21:23:25 +0000
123@@ -205,14 +205,15 @@
124 def navigation(self):
125 """Navigation menu links list."""
126 try:
127- # NavigationMenus may be associated with a content object or one of
128- # its views. The context we need is the one from the TAL expression.
129+ # NavigationMenus may be associated with a content object or one
130+ # of its views. The context we need is the one from the TAL
131+ # expression.
132 context = self._tales_context
133 if self._selectedfacetname is not None:
134 selectedfacetname = self._selectedfacetname
135 else:
136- # XXX sinzui 2008-05-09 bug=226917: We should be retrieving the
137- # facet name from the layer implemented by the request.
138+ # XXX sinzui 2008-05-09 bug=226917: We should be retrieving
139+ # the facet name from the layer implemented by the request.
140 view = get_current_view(self._request)
141 selectedfacetname = get_facet(view)
142 try:
143@@ -2830,6 +2831,16 @@
144 else:
145 return self._stringtoformat
146
147+ def ellipsize(self, maxlength):
148+ """Use like tal:content="context/foo/fmt:ellipsize/60"."""
149+ if len(self._stringtoformat) > maxlength:
150+ length = (maxlength - 3) / 2
151+ return (
152+ self._stringtoformat[:length] + '...' +
153+ self._stringtoformat[-length:])
154+ else:
155+ return self._stringtoformat
156+
157 def format_diff(self):
158 """Format the string as a diff in a table with line numbers."""
159 # Trim off trailing carriage returns.
160@@ -2918,6 +2929,12 @@
161 "you need to traverse a number after fmt:shorten")
162 maxlength = int(furtherPath.pop())
163 return self.shorten(maxlength)
164+ elif name == 'ellipsize':
165+ if len(furtherPath) == 0:
166+ raise TraversalError(
167+ "you need to traverse a number after fmt:ellipsize")
168+ maxlength = int(furtherPath.pop())
169+ return self.ellipsize(maxlength)
170 elif name == 'diff':
171 return self.format_diff()
172 elif name == 'css-id':
173
174=== modified file 'lib/lp/answers/browser/faqcollection.py'
175--- lib/lp/answers/browser/faqcollection.py 2009-08-11 04:35:26 +0000
176+++ lib/lp/answers/browser/faqcollection.py 2009-09-03 20:22:58 +0000
177@@ -41,7 +41,7 @@
178 # which an adapter exists that gives the proper context.
179 collection = IFAQCollection(self.context)
180 url = canonical_url(collection, rootsite='answers') + '/+faqs'
181- return Link(url, 'List all FAQs', icon='info')
182+ return Link(url, 'All FAQs', icon='info')
183
184 @enabled_with_permission('launchpad.Moderate')
185 def create_faq(self):
186
187=== modified file 'lib/lp/answers/stories/faq-add.txt'
188--- lib/lp/answers/stories/faq-add.txt 2009-08-27 16:19:54 +0000
189+++ lib/lp/answers/stories/faq-add.txt 2009-09-03 20:22:58 +0000
190@@ -7,7 +7,7 @@
191 the project owner, therefore he cannot create a new FAQ.
192
193 >>> user_browser.open('http://answers.launchpad.dev/firefox')
194- >>> user_browser.getLink('List all FAQs').click()
195+ >>> user_browser.getLink('All FAQs').click()
196
197 >>> user_browser.getLink('Create a new FAQ')
198 Traceback (most recent call last):
199@@ -27,7 +27,7 @@
200
201 >>> owner_browser = setupBrowser(auth='Basic test@canonical.com:test')
202 >>> owner_browser.open('http://answers.launchpad.dev/firefox')
203- >>> owner_browser.getLink('List all FAQs').click()
204+ >>> owner_browser.getLink('All FAQs').click()
205 >>> owner_browser.title
206 'FAQs for Mozilla Firefox'
207
208
209=== modified file 'lib/lp/answers/stories/faq-browse-and-search.txt'
210--- lib/lp/answers/stories/faq-browse-and-search.txt 2009-06-16 19:03:34 +0000
211+++ lib/lp/answers/stories/faq-browse-and-search.txt 2009-09-03 20:22:58 +0000
212@@ -6,12 +6,12 @@
213 Kermit. She wants to watch the wedding scene of The Muppets Take
214 Manhattan but is unable to play the DVD. She goes to the Kubuntu support
215 page on Launchpad to try to get some help. She clicks the
216-'List all FAQs' link to obtain the list of common questions hoping to
217+'All FAQs' link to obtain the list of common questions hoping to
218 find her problem there (surely playing a DVD must be common thing to do
219 with a computer these days).
220
221 >>> browser.open('http://answers.launchpad.dev/kubuntu')
222- >>> browser.getLink('List all FAQs').click()
223+ >>> browser.getLink('All FAQs').click()
224
225 Unfortunately, it seems that nobody has problems or questions about
226 Kubuntu:
227@@ -31,7 +31,7 @@
228 happening on the Ubuntu project.
229
230 >>> browser.open('http://answers.launchpad.dev/ubuntu')
231- >>> browser.getLink('List all FAQs').click()
232+ >>> browser.getLink('All FAQs').click()
233 >>> print browser.title
234 FAQs for Ubuntu
235
236@@ -152,12 +152,12 @@
237 == Distribution Source Packages and FAQs ==
238
239 Altough distribution source packages aren't directly associated with
240-FAQs. The 'List all FAQs' link that appears in that context links to the
241+FAQs. The 'All FAQs' link that appears in that context links to the
242 distribution FAQs.
243
244 >>> browser.open('http://answers.launchpad.dev/ubuntu/'
245 ... '+source/mozilla-firefox')
246- >>> browser.getLink('List all FAQs').click()
247+ >>> browser.getLink('All FAQs').click()
248 >>> print browser.title
249 FAQs for Ubuntu
250 >>> print browser.url
251
252=== modified file 'lib/lp/answers/templates/questiontarget-portlet-latestquestions.pt'
253--- lib/lp/answers/templates/questiontarget-portlet-latestquestions.pt 2009-08-21 15:26:27 +0000
254+++ lib/lp/answers/templates/questiontarget-portlet-latestquestions.pt 2009-09-03 21:15:40 +0000
255@@ -15,7 +15,9 @@
256 tal:attributes="class string: ${question/image:sprite_css};
257 href question/fmt:url;"
258 tal:content="question/title/fmt:shorten/80">question title</a>
259- <br />Posted <tal:when replace="question/datecreated/fmt:displaydate" />
260+ <br /><span class="registered">
261+ Posted <tal:when replace="question/datecreated/fmt:displaydate" />
262+ </span>
263 </li>
264 </ul>
265 </div>
266
267=== modified file 'lib/lp/blueprints/templates/hassprints-portlet-coming-sprints.pt'
268--- lib/lp/blueprints/templates/hassprints-portlet-coming-sprints.pt 2009-08-21 15:26:27 +0000
269+++ lib/lp/blueprints/templates/hassprints-portlet-coming-sprints.pt 2009-09-03 21:15:40 +0000
270@@ -16,7 +16,9 @@
271 tal:attributes="href sprint/fmt:url"
272 tal:content="sprint/title" />
273 on <tal:when replace="sprint/time_starts/fmt:date" />
274- <br/>Registered <tal:when replace="sprint/datecreated/fmt:displaydate" />
275+ <br/><span class="registered">
276+ Registered <tal:when replace="sprint/datecreated/fmt:displaydate" />
277+ </span>
278 </li>
279 </ul>
280 </div>
281
282=== modified file 'lib/lp/blueprints/templates/specificationtarget-portlet-latestspecs.pt'
283--- lib/lp/blueprints/templates/specificationtarget-portlet-latestspecs.pt 2009-08-21 15:26:27 +0000
284+++ lib/lp/blueprints/templates/specificationtarget-portlet-latestspecs.pt 2009-09-03 21:15:40 +0000
285@@ -15,7 +15,9 @@
286 <ul>
287 <li tal:repeat="spec specs">
288 <a tal:replace="structure spec/fmt:link" />
289- <br />Registered <tal:when replace="spec/datecreated/fmt:displaydate" />
290+ <br /><span class="registered">
291+ Registered <tal:when replace="spec/datecreated/fmt:displaydate" />
292+ </span>
293 </li>
294 </ul>
295 </div>
296
297=== modified file 'lib/lp/bugs/templates/bugtarget-portlet-latestbugs.pt'
298--- lib/lp/bugs/templates/bugtarget-portlet-latestbugs.pt 2009-08-21 15:26:27 +0000
299+++ lib/lp/bugs/templates/bugtarget-portlet-latestbugs.pt 2009-09-03 21:15:40 +0000
300@@ -11,7 +11,9 @@
301 <ul>
302 <li tal:repeat="bugtask view/latestBugTasks">
303 <a tal:replace="structure bugtask/fmt:link" />
304- <br />Reported <tal:when replace="bugtask/datecreated/fmt:displaydate" />
305+ <br /><span class="registered">
306+ Reported <tal:when replace="bugtask/datecreated/fmt:displaydate" />
307+ </span>
308 </li>
309 </ul>
310 </div>
311
312=== modified file 'lib/lp/registry/browser/configure.zcml'
313--- lib/lp/registry/browser/configure.zcml 2009-09-02 13:28:19 +0000
314+++ lib/lp/registry/browser/configure.zcml 2009-09-03 21:30:01 +0000
315@@ -2007,6 +2007,9 @@
316 name="+portlet-details"
317 template="../templates/productrelease-portlet-details.pt"/>
318 <browser:page
319+ name="+portlet-downloads"
320+ template="../templates/productrelease-portlet-downloads.pt"/>
321+ <browser:page
322 name="+portlet-summary"
323 template="../templates/object-portlet-summary.pt"/>
324 </browser:pages>
325
326=== modified file 'lib/lp/registry/browser/pillar.py'
327--- lib/lp/registry/browser/pillar.py 2009-09-01 10:37:35 +0000
328+++ lib/lp/registry/browser/pillar.py 2009-09-03 19:26:16 +0000
329@@ -20,9 +20,11 @@
330 from canonical.launchpad.webapp.publisher import LaunchpadView, nearest
331 from canonical.launchpad.webapp.tales import MenuAPI
332
333+from lp.registry.interfaces.distroseries import IDistroSeries
334 from lp.registry.interfaces.distributionsourcepackage import (
335 IDistributionSourcePackage)
336 from lp.registry.interfaces.pillar import IPillar
337+from lp.registry.interfaces.productseries import IProductSeries
338 from lp.registry.interfaces.project import IProject
339
340
341@@ -81,13 +83,19 @@
342 # Projectgroups do not support submit code, override the
343 # default.
344 self.official_codehosting = False
345- elif IDistributionSourcePackage.providedBy(self.context):
346- # Distro source packages don't have blueprints, override
347- # the default.
348- self._set_official_launchpad(pillar)
349- self.official_blueprints = False
350 else:
351 self._set_official_launchpad(pillar)
352+ if IProductSeries.providedBy(self.context):
353+ self.official_answers = False
354+ elif IDistroSeries.providedBy(self.context):
355+ self.official_answers = False
356+ self.official_codehosting = False
357+ elif IDistributionSourcePackage.providedBy(self.context):
358+ self.official_blueprints = False
359+ self.official_rosetta = False
360+ else:
361+ # The context is used by all apps.
362+ pass
363
364 def _set_official_launchpad(self, pillar):
365 """Does the pillar officially use launchpad."""
366
367=== modified file 'lib/lp/registry/browser/productseries.py'
368--- lib/lp/registry/browser/productseries.py 2009-08-29 11:21:46 +0000
369+++ lib/lp/registry/browser/productseries.py 2009-09-03 19:58:21 +0000
370@@ -473,6 +473,13 @@
371 '%s/+milestone/{name}/+productseries-table-row' %
372 canonical_url(self.context.product, path_only_if_possible=True))
373
374+ @property
375+ def latest_release_with_download_files(self):
376+ for release in self.context.releases:
377+ if len(list(release.files)) > 0:
378+ return release
379+ return None
380+
381
382 class ProductSeriesUbuntuPackagingView(ProductSeriesView):
383 """A view to show series package in Ubuntu."""
384
385=== modified file 'lib/lp/registry/browser/tests/pillar-views.txt'
386--- lib/lp/registry/browser/tests/pillar-views.txt 2009-09-01 10:37:35 +0000
387+++ lib/lp/registry/browser/tests/pillar-views.txt 2009-09-03 19:26:16 +0000
388@@ -98,11 +98,13 @@
389 >>> view = create_view(series, '+get-involved')
390 >>> for link in view.enabled_links:
391 ... print link.name
392- report_bug ask_question
393+ report_bug
394
395-ProductSeries can use this view. The product is used to set the links.
396+ProductSeries can use this view. The product is used to set the links,
397+but the answers link will be disbaled.
398
399 >>> series = factory.makeProductSeries(product=product)
400+ >>> product.official_answers = True
401 >>> view = create_view(series, '+get-involved')
402 >>> for link in view.enabled_links:
403 ... print link.name
404@@ -110,10 +112,11 @@
405
406 DistributionSourcePackages can use this view. The distribution is used to
407 set the links. Despite the fact that the distribution uses blueprints,
408-the blueprint link is not enabled for DistributionSourcePackages.
409+and translations those links are not enabled for DistributionSourcePackages.
410
411 >>> login_person(distribution.owner)
412 >>> distribution.official_blueprints = True
413+ >>> distribution.official_rosetta = True
414 >>> package = factory.makeDistributionSourcePackage(
415 ... distribution=distribution)
416 >>> view = create_view(package, '+get-involved')
417
418=== modified file 'lib/lp/registry/browser/tests/productseries-views.txt'
419--- lib/lp/registry/browser/tests/productseries-views.txt 2009-08-11 21:15:25 +0000
420+++ lib/lp/registry/browser/tests/productseries-views.txt 2009-09-03 19:58:21 +0000
421@@ -72,6 +72,20 @@
422 >>> view.is_obsolete
423 True
424
425+The view provides access to the latest release if it has one.
426+
427+ >>> from lp.registry.interfaces.product import IProductSet
428+
429+ >>> print view.latest_release_with_download_files
430+ None
431+
432+ >>> firefox = getUtility(IProductSet).getByName('firefox')
433+ >>> #login_person(firefox.owner)
434+ >>> series_with_downloads = firefox.getSeries('trunk')
435+ >>> view = create_initialized_view(series_with_downloads, name='+index')
436+ >>> print view.latest_release_with_download_files.version
437+ 0.9.2
438+
439
440 Edit ProductSeries
441 ------------------
442
443=== modified file 'lib/lp/registry/templates/distributionsourcepackage-index.pt'
444--- lib/lp/registry/templates/distributionsourcepackage-index.pt 2009-09-01 10:21:45 +0000
445+++ lib/lp/registry/templates/distributionsourcepackage-index.pt 2009-09-03 21:23:25 +0000
446@@ -13,7 +13,7 @@
447 <tal:devmode condition="devmode">
448 <tal:archive_js define="lp_js string:${icingroot}/build">
449 <script type="text/javascript"
450- tal:attributes="src string:${lp_js}/soyuz/base.js"/>
451+ tal:attributes="src string:${lp_js}/soyuz/base.js"></script>
452 </tal:archive_js>
453 </tal:devmode>
454 </metal:block>
455
456=== modified file 'lib/lp/registry/templates/product-index.pt'
457--- lib/lp/registry/templates/product-index.pt 2009-08-31 21:20:55 +0000
458+++ lib/lp/registry/templates/product-index.pt 2009-09-03 17:59:56 +0000
459@@ -118,6 +118,10 @@
460 </dl>
461 </div>
462
463+ <p>
464+ <a tal:replace="structure overview_menu/rdf/fmt:link" />
465+ </p>
466+
467 <p id="registrant">
468 Registered
469 <tal:created replace="context/datecreated/fmt:approximatedate" />
470@@ -201,33 +205,20 @@
471 <h2>Downloads</h2>
472
473 <tal:release condition="release">
474- <ul>
475- <li tal:repeat="file release/files">
476- <a tal:attributes="href file/fmt:url;
477- title file/description;"
478- tal:content="file/libraryfile/filename" />
479- </li>
480- </ul>
481-
482- <div class="released">
483- <span>
484- released <tal:date replace="release/datereleased/fmt:displaydate" />
485- </span>
486- </div>
487+ <tal:downloads replace="structure release/@@+portlet-downloads"/>
488 </tal:release>
489
490- <div class="alternate">
491- <a style="text-decoration: underline;"
492+ <p class="alternate">
493+ <a class="sprint info"
494 tal:define="link overview_menu/downloads"
495- tal:attributes="href link/fmt:url;
496- title link/summary"
497- tal:content="structure link/escapedtext" /> |
498- <a style="text-decoration: underline;"
499- tal:define="link overview_menu/rdf"
500- tal:attributes="href link/fmt:url;
501- title link/summary"
502- tal:content="structure link/escapedtext" />
503- </div>
504+ tal:condition="release"
505+ tal:attributes="href link/fmt:url;
506+ title link/summary">All downloads</a>
507+ <tal:no-files condition="not: release">
508+ <tal:name replace="context/displayname" /> does not have any
509+ download files.
510+ </tal:no-files>
511+ </p>
512 </div>
513
514 <div tal:replace="structure context/@@+get-involved" />
515
516=== added file 'lib/lp/registry/templates/productrelease-portlet-downloads.pt'
517--- lib/lp/registry/templates/productrelease-portlet-downloads.pt 1970-01-01 00:00:00 +0000
518+++ lib/lp/registry/templates/productrelease-portlet-downloads.pt 2009-09-03 21:23:25 +0000
519@@ -0,0 +1,23 @@
520+<div
521+ xmlns="http://www.w3.org/1999/xhtml"
522+ xmlns:tal="http://xml.zope.org/namespaces/tal"
523+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
524+ i18n:domain="launchpad"
525+ tal:omit-tag="">
526+ <div class="version">
527+ Latest version is <tal:version replace="context/version" />
528+ </div>
529+
530+ <ul>
531+ <li tal:repeat="file context/files">
532+ <a tal:attributes="href file/fmt:url;
533+ title file/description;"
534+ tal:content="file/libraryfile/filename/fmt:ellipsize/25" />
535+ </li>
536+ </ul>
537+
538+ <div class="released">
539+ released <tal:date replace="context/datereleased/fmt:displaydate" />
540+ </div>
541+</div
542+>
543