Merge lp:~julian-edwards/launchpad/dsp-redesign into lp:launchpad

Proposed by Julian Edwards
Status: Merged
Approved by: Barry Warsaw
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~julian-edwards/launchpad/dsp-redesign
Merge into: lp:launchpad
Diff against target: None lines
To merge this branch: bzr merge lp:~julian-edwards/launchpad/dsp-redesign
Reviewer Review Type Date Requested Status
Barry Warsaw (community) code Approve
Review via email: mp+10850@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Julian Edwards (julian-edwards) wrote :
Download full text (5.7 KiB)

= Summary =
DistributionSourcePackage 3.0

I already have ui=beuno.

== Proposed fix ==
Many changes! 3.0 goodness. View and see.
e.g. https://dogfood.launchpad.net/ubuntu/+source/amarok

== Implementation details ==
The old page was tough to render, this one is no different. The hard part is
the table of the versions in each series.

Most of the logic is done in the view class, which pumps out rows of
dictionaries that the template then throws on the page. It uses 3 different
types of row:
 * a distro series header
 * package details
 * blank row

The type of row is determined by boolean dictionary properties in each row
returned by view/version_table. I couldn't think of a better way of doing
this since all the knowledge of how to render stuff is in the view.

The package detail rows also have a JS expander that does an XHR call to get
more data. This is the same XHR call that the PPA page does to open rows
there. I had to tweak the JS a little to make it work outside of an archive
context. It does this by coding the archive url in the template as a <script>
element - not pleasant but having discussed this at length with Michael and
Celso we could not think of any other way of doing it.

== Tests ==
bin/test -vvt xx-distribution-packages.txt -t xx-distributionsourcepackage-
packaging.txt -t xx-distrorelease-sources.txt -t xx-package-diff.txt

== Demo and Q/A ==
I set this up on dogfood since the .dev data is rubbish.
See:
https://dogfood.launchpad.net/ubuntu/+source/amarok
https://dogfood.launchpad.net/ubuntu/+source/firefox-3.5
etc.

= Launchpad lint =
Once again I have been foiled by lint being at the bottom of the email
template instead of at the top. I'm not re-writing this email, so please
consider the lint fixing done as I will be doing it right after sending this.

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/browser/sourcepackage.py
  lib/lp/registry/templates/distributionsourcepackage-index.pt
  lib/lp/soyuz/stories/soyuz/xx-distrorelease-sources.txt
  lib/lp/soyuz/stories/soyuz/xx-package-diff.txt
  lib/lp/soyuz/templates/archive-macros.pt
  lib/lp/registry/browser/distributionsourcepackage.py
  lib/lp/registry/stories/distribution/xx-distribution-packages.txt
  lib/canonical/launchpad/templates/structural-subscription-target-portlet-
subscribers.pt
  lib/lp/registry/stories/distribution/xx-distributionsourcepackage-
packaging.txt
  lib/lp/registry/browser/distribution.py

== XmlLint notices ==

lib/lp/registry/templates/distributionsourcepackage-index.pt
    71: parser error : Opening and ending tag mismatch: strong line 71 and a
    ew bug<tal:plural content="string:s" condition="python:
newbugs!=1"/><strong></a
    ^
    73: parser error : Opening and ending tag mismatch: strong line 71 and div
    </div>
    ^
    137: parser error : AttValue: " or ' expected
    <td colspan=3>
    ^
    137: parser error : attributes construct error
    <td colspan=3>
    ^
    137: parser error : Couldn't find end of Start Tag td line 137
    <td colspa...

Read more...

Revision history for this message
Barry Warsaw (barry) wrote :
Download full text (16.3 KiB)

> == Proposed fix ==
> Many changes! 3.0 goodness. View and see.
> e.g. https://dogfood.launchpad.net/ubuntu/+source/amarok

Looks great, thanks for working on this!

> == Implementation details ==
> The old page was tough to render, this one is no different. The hard part is
> the table of the versions in each series.
>
> Most of the logic is done in the view class, which pumps out rows of
> dictionaries that the template then throws on the page. It uses 3 different
> types of row:
> * a distro series header
> * package details
> * blank row
>
> The type of row is determined by boolean dictionary properties in each row
> returned by view/version_table. I couldn't think of a better way of doing
> this since all the knowledge of how to render stuff is in the view.
>
> The package detail rows also have a JS expander that does an XHR call to get
> more data. This is the same XHR call that the PPA page does to open rows
> there. I had to tweak the JS a little to make it work outside of an archive
> context. It does this by coding the archive url in the template as a <script>
> element - not pleasant but having discussed this at length with Michael and
> Celso we could not think of any other way of doing it.

It sounds like you had pretty thorough pre-imps about a number of tricky
issues. That helps with the review a lot, thanks for having them.

> == Demo and Q/A ==
> I set this up on dogfood since the .dev data is rubbish.
> See:
> https://dogfood.launchpad.net/ubuntu/+source/amarok
> https://dogfood.launchpad.net/ubuntu/+source/firefox-3.5
> etc.

That was very helpful!

> = Launchpad lint =
> Once again I have been foiled by lint being at the bottom of the email
> template instead of at the top. I'm not re-writing this email, so please
> consider the lint fixing done as I will be doing it right after sending this.

This bites me all the time too :(. No problem.

The code looks generally pretty good. I have a number of comments, but I
think they will be easy to address, so I'll give the branch merge-conditional,
r=me with their consideration.

=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml 2009-08-27 11:34:14 +0000
+++ lib/lp/registry/browser/configure.zcml 2009-08-27 20:18:32 +0000
> @@ -523,6 +523,7 @@
> classes="
> DistributionSourcePackageFacets
> DistributionSourcePackageOverviewMenu
> + DistributionSourcePackageActionMenu
> DistributionSourcePackageBugsMenu"

Please sort alphabetically.

> module="lp.registry.browser.distributionsourcepackage"/>
> <browser:url

=== modified file 'lib/lp/registry/browser/distributionsourcepackage.py'
--- lib/lp/registry/browser/distributionsourcepackage.py 2009-08-27 10:13:51 +0000
+++ lib/lp/registry/browser/distributionsourcepackage.py 2009-08-27 20:18:32 +0000
> @@ -127,7 +149,29 @@
> return self._package_diffs
>
>
> +class IDistributionSourcePackageActionMenu(Interface):
> + """Marker interface for the action menu."""
> +
> +
> +class DistributionSourcePackageActionMenu(
> + NavigationMenu, DistributionSourcePackageLinksMixin):
> + """Ac...

review: Approve (code)
Revision history for this message
Julian Edwards (julian-edwards) wrote :
Download full text (5.8 KiB)

On Friday 28 August 2009 20:36:11 Barry Warsaw wrote:
> Review: Approve code
>
> > == Proposed fix ==
> > Many changes! 3.0 goodness. View and see.
> > e.g. https://dogfood.launchpad.net/ubuntu/+source/amarok
>
> Looks great, thanks for working on this!

Thanks for your patience with the review Barry, and once again apologies for
inflicting Soyuz *and* tales on you! :)

> It sounds like you had pretty thorough pre-imps about a number of tricky
> issues. That helps with the review a lot, thanks for having them.

Yeah, just a few :)

> > I set this up on dogfood since the .dev data is rubbish.
> > See:
> > https://dogfood.launchpad.net/ubuntu/+source/amarok
> > https://dogfood.launchpad.net/ubuntu/+source/firefox-3.5
> > etc.
>
> That was very helpful!

I <3 dogfood.

> The code looks generally pretty good. I have a number of comments, but I
> think they will be easy to address, so I'll give the branch
> merge-conditional, r=me with their consideration.

Ok great, thanks! I've addressed all your comments, see inline.

> > +class DistributionSourcePackageActionMenu(
> > + NavigationMenu, DistributionSourcePackageLinksMixin):
> > + """Action menu for distro source packages."""
> > + usedfor = IDistributionSourcePackageActionMenu
> > + facet = 'overview'
> > + title = 'Actions'
> > + links = ('change_log', 'subscribe', 'edit')
>
> While I prefer using tuples for these, as you've shown here, our defacto
> standard is to use lists. Is there a reason why you did it this way?
> Otherwise, might as well stick with the trend and use a list here too.

I've changed it to lists for now, if we later decide we want tuples as we
discussed in IRC then it's easily changed.

> > @property
> > def page_title(self):
> > @@ -268,6 +312,7 @@
> > """Render a submit input for the delete_packaging_action."""
> > assert self.can_delete_packaging, 'User cannot delete
> > Packaging.' return ('<input type="submit" class="button" value="Delete
> > Link" ' + 'style="padding: 0pt; font-size: 80%%" '
>
> Do you think it would be better to move this style setting into a class
> inside style-3-0.css?

I don't think so - this is a one-off style for this particular case (it makes
the row look stupidly fat otherwise) and it doesn't make sense to me to
increase the size of the main style sheet for that.

> You should be able to write these last two lines as:
>
> result = sorted(series, key=operator.attrgetter('version'),
> reverse=True)

Heh, yes, thanks for fixing my Python dyslexia.

> > + if version not in pocket_dict:
> > + pocket_dict[version] = [pub]
> > + else:
> > + pocket_dict[version].append(pub)
>
> What do you think about this instead...
>
> pocket_dict.setdefault(version, []).append(pub)

I think it's so good, I used it.

> > + # After the title row, we list each package version that's
> > + # currently published, and which pockets it's published in.
> > + pocket_dict = self.published_by_version(package)
> > + for version in pocket_dict.iterkeys():
>
> Is there a...

Read more...

Revision history for this message
Barry Warsaw (barry) wrote :
Download full text (6.0 KiB)

On Sep 01, 2009, at 10:36 AM, Julian Edwards wrote:

>On Friday 28 August 2009 20:36:11 Barry Warsaw wrote:
>> Review: Approve code
>>
>> > == Proposed fix ==
>> > Many changes! 3.0 goodness. View and see.
>> > e.g. https://dogfood.launchpad.net/ubuntu/+source/amarok
>>
>> Looks great, thanks for working on this!
>
>Thanks for your patience with the review Barry, and once again apologies for
>inflicting Soyuz *and* tales on you! :)

Don't worry, I'll get you back someday with Mailman and ZCML. :)

>> > +class DistributionSourcePackageActionMenu(
>> > + NavigationMenu, DistributionSourcePackageLinksMixin):
>> > + """Action menu for distro source packages."""
>> > + usedfor = IDistributionSourcePackageActionMenu
>> > + facet = 'overview'
>> > + title = 'Actions'
>> > + links = ('change_log', 'subscribe', 'edit')
>>
>> While I prefer using tuples for these, as you've shown here, our defacto
>> standard is to use lists. Is there a reason why you did it this way?
>> Otherwise, might as well stick with the trend and use a list here too.
>
>I've changed it to lists for now, if we later decide we want tuples as we
>discussed in IRC then it's easily changed.

Agreed. I put this in the tech-debt category and we should change it globally
at some point. I've also put this on the agenda for tomorrow's reviewer
meetings.

>> > @property
>> > def page_title(self):
>> > @@ -268,6 +312,7 @@
>> > """Render a submit input for the delete_packaging_action."""
>> > assert self.can_delete_packaging, 'User cannot delete
>> > Packaging.' return ('<input type="submit" class="button" value="Delete
>> > Link" ' + 'style="padding: 0pt; font-size: 80%%" '
>>
>> Do you think it would be better to move this style setting into a class
>> inside style-3-0.css?
>
>I don't think so - this is a one-off style for this particular case (it makes
>the row look stupidly fat otherwise) and it doesn't make sense to me to
>increase the size of the main style sheet for that.

Hmm. I wonder if we need a policy for these kinds of things. OTOH, it /is/
nice to have one-off style changes more local to the code they affect. I
often find it difficult to figure out what a style affects by just looking at
the css file.

>> You should be able to write these last two lines as:
>>
>> result = sorted(series, key=operator.attrgetter('version'),
>> reverse=True)
>
>Heh, yes, thanks for fixing my Python dyslexia.

:)

>> > + if version not in pocket_dict:
>> > + pocket_dict[version] = [pub]
>> > + else:
>> > + pocket_dict[version].append(pub)
>>
>> What do you think about this instead...
>>
>> pocket_dict.setdefault(version, []).append(pub)
>
>I think it's so good, I used it.

Yay!

>> > + # After the title row, we list each package version that's
>> > + # currently published, and which pockets it's published in.
>> > + pocket_dict = self.published_by_version(package)
>> > + for version in pocket_dict.iterkeys():
>>
>> Is there a known efficiency reason to use iterkeys()? Is pocket_dict huge?...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/templates/structural-subscription-target-portlet-subscribers.pt'
2--- lib/canonical/launchpad/templates/structural-subscription-target-portlet-subscribers.pt 2009-07-17 17:59:07 +0000
3+++ lib/canonical/launchpad/templates/structural-subscription-target-portlet-subscribers.pt 2009-08-27 12:54:28 +0000
4@@ -38,7 +38,6 @@
5 </ul>
6 </div>
7 <div tal:condition="not: parent_target/bug_subscriptions">
8- <i>There are no bug subscriptions.</i>
9 <a tal:attributes="href string:${parent_target/fmt:url}/+subscribe">
10 (subscribe)
11 </a>
12
13=== modified file 'lib/lp/registry/browser/configure.zcml'
14--- lib/lp/registry/browser/configure.zcml 2009-08-27 11:34:14 +0000
15+++ lib/lp/registry/browser/configure.zcml 2009-08-27 20:18:32 +0000
16@@ -523,6 +523,7 @@
17 classes="
18 DistributionSourcePackageFacets
19 DistributionSourcePackageOverviewMenu
20+ DistributionSourcePackageActionMenu
21 DistributionSourcePackageBugsMenu"
22 module="lp.registry.browser.distributionsourcepackage"/>
23 <browser:url
24
25=== modified file 'lib/lp/registry/browser/distribution.py'
26--- lib/lp/registry/browser/distribution.py 2009-08-27 10:48:44 +0000
27+++ lib/lp/registry/browser/distribution.py 2009-08-27 20:18:32 +0000
28@@ -449,7 +449,7 @@
29
30 def subscribe(self):
31 text = 'Subscribe to bug mail'
32- return Link('+subscribe', text)
33+ return Link('+subscribe', text, icon='edit')
34
35
36 class DistributionBountiesMenu(ApplicationMenu):
37
38=== modified file 'lib/lp/registry/browser/distributionsourcepackage.py'
39--- lib/lp/registry/browser/distributionsourcepackage.py 2009-08-27 10:13:51 +0000
40+++ lib/lp/registry/browser/distributionsourcepackage.py 2009-08-27 20:18:32 +0000
41@@ -12,15 +12,20 @@
42 'DistributionSourcePackageView',
43 ]
44
45+from datetime import datetime
46 import itertools
47 import operator
48+import pytz
49
50-from zope.component import getUtility
51+from zope.component import getUtility, provideAdapter
52 from zope.formlib import form
53+from zope.interface import implements, Interface
54 from zope.schema import Choice
55 from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
56
57+from canonical.cachedproperty import cachedproperty
58 from canonical.launchpad import _
59+from lp.answers.interfaces.questionenums import QuestionStatus
60 from lp.soyuz.interfaces.archive import IArchiveSet
61 from lp.soyuz.interfaces.distributionsourcepackagerelease import (
62 IDistributionSourcePackageRelease)
63@@ -36,7 +41,9 @@
64 from canonical.launchpad.webapp import (
65 ApplicationMenu, LaunchpadEditFormView, LaunchpadFormView, Link,
66 Navigation, StandardLaunchpadFacets, action, canonical_url, redirection)
67-from canonical.launchpad.webapp.menu import enabled_with_permission
68+from canonical.launchpad.webapp.interfaces import INavigationMenu
69+from canonical.launchpad.webapp.menu import (
70+ enabled_with_permission, NavigationMenu)
71 from canonical.launchpad.webapp.breadcrumb import Breadcrumb
72
73 from lazr.delegates import delegates
74@@ -58,12 +65,7 @@
75 enable_only = ['overview', 'bugs', 'answers', 'branches']
76
77
78-class DistributionSourcePackageOverviewMenu(ApplicationMenu):
79-
80- usedfor = IDistributionSourcePackage
81- facet = 'overview'
82- links = ['subscribe', 'publishinghistory', 'edit']
83-
84+class DistributionSourcePackageLinksMixin:
85 def subscribe(self):
86 return Link('+subscribe', 'Subscribe to bug mail', icon='edit')
87
88@@ -77,6 +79,26 @@
89 # is the only editable property of a source package right now.
90 return Link('+edit', 'Edit bug reporting guidelines', icon='edit')
91
92+ def new_bugs(self):
93+ base_path = "+bugs"
94+ get_data = "?field.status:list=NEW"
95+ return Link(base_path + get_data, "New bugs", site="bugs")
96+
97+ def open_questions(self):
98+ base_path = "+questions"
99+ get_data = "?field.status=OPEN"
100+ return Link(base_path + get_data, "Open Questions", site="answers")
101+
102+
103+class DistributionSourcePackageOverviewMenu(
104+ ApplicationMenu, DistributionSourcePackageLinksMixin):
105+
106+ usedfor = IDistributionSourcePackage
107+ facet = 'overview'
108+ links = [
109+ 'subscribe', 'publishinghistory', 'edit', 'new_bugs',
110+ 'open_questions']
111+
112
113 class DistributionSourcePackageBugsMenu(
114 DistributionSourcePackageOverviewMenu):
115@@ -127,7 +149,29 @@
116 return self._package_diffs
117
118
119+class IDistributionSourcePackageActionMenu(Interface):
120+ """Marker interface for the action menu."""
121+
122+
123+class DistributionSourcePackageActionMenu(
124+ NavigationMenu, DistributionSourcePackageLinksMixin):
125+ """Action menu for distro source packages."""
126+ usedfor = IDistributionSourcePackageActionMenu
127+ facet = 'overview'
128+ title = 'Actions'
129+ links = ('change_log', 'subscribe', 'edit')
130+
131+ def change_log(self):
132+ text = 'View full change log'
133+ return Link('+changelog', text, icon="info")
134+
135+
136 class DistributionSourcePackageView(LaunchpadFormView):
137+ implements(IDistributionSourcePackageActionMenu)
138+
139+ @property
140+ def page_title(self):
141+ return self.context.title
142
143 @property
144 def page_title(self):
145@@ -268,6 +312,7 @@
146 """Render a submit input for the delete_packaging_action."""
147 assert self.can_delete_packaging, 'User cannot delete Packaging.'
148 return ('<input type="submit" class="button" value="Delete Link" '
149+ 'style="padding: 0pt; font-size: 80%%" '
150 'name="%s"/>' % (self.delete_packaging_action.__name__,))
151
152 def handleDeletePackagingError(self, action, data, errors):
153@@ -301,41 +346,112 @@
154 distroseries=distroseries.displayname)))
155 self.next_url = canonical_url(self.context)
156
157- def version_listing(self):
158- result = []
159- for sourcepackage in self.context.get_distroseries_packages():
160- packaging = sourcepackage.direct_packaging
161+ @cachedproperty
162+ def active_distroseries_packages(self):
163+ """Cached proxy call to context/get_distroseries_packages."""
164+ return self.context.get_distroseries_packages()
165+
166+ @property
167+ def packages_by_active_distroseries(self):
168+ """Dict of packages keyed by distroseries."""
169+ packages_dict = {}
170+ for package in self.active_distroseries_packages:
171+ packages_dict[package.distroseries] = package
172+ return packages_dict
173+
174+ @property
175+ def active_series(self):
176+ """Return active distroseries where this package is published.
177+
178+ Used in the template code that shows the table of versions.
179+ The returned series are sorted in reverse order of creation.
180+ """
181+ series = set()
182+ for package in self.active_distroseries_packages:
183+ series.add(package.distroseries)
184+ result = list(series)
185+ result.sort(key=operator.attrgetter("version"), reverse=True)
186+ return result
187+
188+ def published_by_version(self, sourcepackage):
189+ """Return a dict of publications keyed by version.
190+
191+ :param sourcepackage: ISourcePackage
192+ """
193+ publications = sourcepackage.distroseries.getPublishedReleases(
194+ sourcepackage.sourcepackagename)
195+ pocket_dict = {}
196+ for pub in publications:
197+ version = pub.source_package_version
198+ if version not in pocket_dict:
199+ pocket_dict[version] = [pub]
200+ else:
201+ pocket_dict[version].append(pub)
202+ return pocket_dict
203+
204+ @property
205+ def version_table(self):
206+ """Rows of data for the template to render in the packaging table."""
207+ rows = []
208+ packages_by_series = self.packages_by_active_distroseries
209+ for distroseries in self.active_series:
210+ # The first row for each series is the "title" row.
211+ packaging = packages_by_series[distroseries].direct_packaging
212 if packaging is None:
213 delete_packaging_form_id = None
214- packaging_field = None
215+ hidden_packaging_field = None
216 else:
217 delete_packaging_form_id = "delete_%s_%s_%s" % (
218 packaging.distroseries.name,
219 packaging.productseries.product.name,
220 packaging.productseries.name)
221- packaging_field = self._renderHiddenPackagingField(packaging)
222- series_result = []
223- for published in \
224- sourcepackage.published_by_pocket.iteritems():
225- for drspr in published[1]:
226- series_result.append({
227- 'series': sourcepackage.distroseries,
228- 'pocket': published[0].name.lower(),
229- 'package': drspr,
230- 'packaging': packaging,
231- 'delete_packaging_form_id': delete_packaging_form_id,
232- 'packaging_field': packaging_field,
233- 'sourcepackage': sourcepackage
234- })
235- for row in range(len(series_result)-1, 0, -1):
236- for column in ['series', 'pocket', 'package', 'packaging',
237- 'packaging_field', 'sourcepackage']:
238- if (series_result[row][column] ==
239- series_result[row-1][column]):
240- series_result[row][column] = None
241- for row in series_result:
242- result.append(row)
243- return result
244+ hidden_packaging_field = self._renderHiddenPackagingField(
245+ packaging)
246+ package = packages_by_series[distroseries]
247+ title_row = {
248+ 'blank_row': False,
249+ 'title_row': True,
250+ 'data_row': False,
251+ 'distroseries': distroseries,
252+ 'series_package': package,
253+ 'packaging': packaging,
254+ 'hidden_packaging_field': hidden_packaging_field,
255+ 'delete_packaging_form_id': delete_packaging_form_id,
256+ }
257+ rows.append(title_row)
258+
259+ # After the title row, we list each package version that's
260+ # currently published, and which pockets it's published in.
261+ pocket_dict = self.published_by_version(package)
262+ for version in pocket_dict.iterkeys():
263+ most_recent_publication = pocket_dict[version][0]
264+ if most_recent_publication.datepublished is None:
265+ published_since = None
266+ else:
267+ published_since = datetime.now(
268+ tz=pytz.UTC) - most_recent_publication.datepublished
269+ row = {
270+ 'blank_row': False,
271+ 'title_row': False,
272+ 'data_row': True,
273+ 'version': version,
274+ 'publication': most_recent_publication,
275+ 'pockets': ", ".join(
276+ [pub.pocket.name for pub in pocket_dict[version]]),
277+ 'component': most_recent_publication.component_name,
278+ 'published_since': published_since,
279+ }
280+ rows.append(row)
281+ # We need a blank row after each section, so the series
282+ # header row doesn't appear too close to the previous
283+ # section.
284+ rows.append({
285+ 'blank_row': True,
286+ 'title_row': False,
287+ 'data_row': False,
288+ })
289+
290+ return rows
291
292 def releases(self):
293 dspr_pubs = self.context.getReleasesAndPublishingHistory()
294@@ -357,6 +473,11 @@
295 dspr, spphs, spr_diffs.get(dspr.sourcepackagerelease, []))
296 for (dspr, spphs) in dspr_pubs]
297
298+ @cachedproperty
299+ def open_questions(self):
300+ """Return result set containing open questions for this package."""
301+ return self.context.searchQuestions(status=QuestionStatus.OPEN)
302+
303
304 class DistributionSourcePackageEditView(LaunchpadEditFormView):
305 """Edit a distribution source package."""
306
307=== modified file 'lib/lp/registry/browser/sourcepackage.py'
308--- lib/lp/registry/browser/sourcepackage.py 2009-08-24 20:28:33 +0000
309+++ lib/lp/registry/browser/sourcepackage.py 2009-08-25 10:58:26 +0000
310@@ -84,7 +84,8 @@
311
312 usedfor = ISourcePackage
313 facet = 'overview'
314- links = ['packaging', 'edit_packaging', 'changelog', 'builds']
315+ links = [
316+ 'packaging', 'edit_packaging', 'changelog', 'builds', 'set_upstream']
317
318 def changelog(self):
319 return Link('+changelog', 'View changelog', icon='list')
320@@ -95,6 +96,9 @@
321 def edit_packaging(self):
322 return Link('+edit-packaging', 'Change upstream link', icon='edit')
323
324+ def set_upstream(self):
325+ return Link("+edit-packaging", "Set upstream link", icon="add")
326+
327 def builds(self):
328 text = 'Show builds'
329 return Link('+builds', text, icon='info')
330
331=== modified file 'lib/lp/registry/stories/distribution/xx-distribution-packages.txt'
332--- lib/lp/registry/stories/distribution/xx-distribution-packages.txt 2009-08-26 12:05:05 +0000
333+++ lib/lp/registry/stories/distribution/xx-distribution-packages.txt 2009-08-28 14:59:57 +0000
334@@ -1,4 +1,9 @@
335-= Distribution Package Search Results =
336+============================
337+Distribution Source Packages
338+============================
339+
340+Distribution Package Search Results
341+-----------------------------------
342
343 Although there is a separate search page, we can search from the
344 distribution overview page which takes us there and displays the
345@@ -24,11 +29,10 @@
346 >>> browser.url
347 'http://localhost/ubuntu/+source/pmount'
348
349-Get pmount 0.1-1 version
350+Get pmount 0.1-2 version
351
352- >>> browser.getLink("0.1-1").click()
353- >>> browser.url
354- 'http://localhost/ubuntu/+source/pmount/0.1-1'
355+ >>> browser.getLink("0.1-2").url
356+ 'http://localhost/ubuntu/+source/pmount/0.1-2'
357
358 Ensure that the correct binaries appear on the search results. We only
359 show one link to mozilla-firefox on the results page under each distro
360@@ -109,7 +113,8 @@
361 pmount
362
363
364-== Distribution package change summary ==
365+Distribution package change summary
366+-----------------------------------
367
368 Before we can test the page we publish netapplet to the ubuntutest main
369 archive as well as some new PPAs.
370@@ -179,20 +184,154 @@
371
372 >>> logout()
373
374-A /$DISTRO/+source/$PACKAGE page shows for a given source package all
375-the distro releases in which it was published (see table at the top of
376-the page). The information presented in each row is as follows: the
377-distro series name and status as well as the package component, pocket
378-and version.
379+
380+A /$DISTRO/+source/$PACKAGE page shows an overview of a source package in
381+a distribution. There are several sections of information.
382+
383+ >>> user_browser.open("http://launchpad.dev/ubuntu/+source/iceweasel/")
384+
385+Under the title there's a short paragraph that says how many 'new' bugs
386+and open questions the package has.
387+
388+ >>> print extract_text(find_tag_by_id(
389+ ... user_browser.contents, 'bugs-and-questions-summary'))
390+ This package has 0 new bugs and 0 open questions.
391+
392+Links exist to jump to the query page for the new bugs and open questions.
393+
394+ >>> print user_browser.getLink("0 new bugs").url
395+ http://bugs.launchpad.dev/ubuntu/+source/iceweasel/+bugs?field.status:list=NEW
396+
397+ >>> print user_browser.getLink("0 open questions").url
398+ http://answers.launchpad.dev/ubuntu/+source/iceweasel/+questions?field.status=OPEN
399+
400+The page also has a table that shows the distro series in which the package is
401+published, and if there is a link to a product series. If there is no upstream
402+set then a link to set one is given at the end of the row. For each distro
403+series a list of the versions available in that series are presented, along
404+with which pocket has each version, the component in which it's published, and
405+the time elapsed since it was published.
406+
407+ >>> print extract_text(find_tag_by_id(
408+ ... user_browser.contents, 'packages_list'))
409+ The Warty Warthog Release (current stable release) Set upstream link
410+ 1.0 release (main) ... weeks ago
411+
412+Each 'version' line contains an expandable row that shows more information
413+about that version. To show it, click the expander icon. If the user has
414+javascript enabled, the information is shown in-place.
415+
416+ >>> expander_url = find_tags_by_class(
417+ ... user_browser.contents, 'expander')[0]
418+ >>> print expander_url
419+ <a class="expander" href="/ubuntu/+archive/primary/+sourcepub/26/+listing-archive-extra" id="pub26-expander">
420+ <img style... src="/@@/treeCollapsed" alt="Show details" title="Show details" id="pub26-arrow" />
421+ </a>
422+
423+ >>> browser.open(user_browser.getLink(id="pub26-expander").url)
424+ >>> print extract_text(browser.contents)
425+ Publishing details
426+ Published
427+ on 2006-04-11
428+ Copied from ubuntu warty in PPA for Mark Shuttleworth
429+ Changelog
430+ Builds
431+ i386
432+ Built packages
433+ mozilla-firefox ff from iceweasel
434+ Package files
435+ firefox-0.9.2.orig.tar.gz (9.5 MiB)
436+ iceweasel-1.0.dsc (123 bytes)
437+ mozilla-firefox_0.9_i386.deb (3 bytes)
438+
439+There's also a section on the page that gives some package information:
440+
441+ >>> print extract_text(find_tag_by_id(user_browser.contents, 'current'))
442+ Package information
443+ Maintainer: Foo Bar
444+ Urgency:* Low Urgency
445+ Component:* main
446+ Architectures:* any
447+ *actual publishing details may vary in this distribution, these are just the package defaults.
448+
449+And if the source has direct packaging linkage, the upstream's description
450+is used in another section:
451+
452+ >>> print extract_text(find_tag_by_id(user_browser.contents, 'upstream'))
453+ This package is not linked to an upstream product.
454+
455+As can be seen, the packaging is not linked yet. We can do that now using the
456+"Set upstream link" link.
457+
458+ >>> user_browser.getLink("Set upstream link").click()
459+ >>> print user_browser.url
460+ http://launchpad.dev/ubuntu/warty/+source/iceweasel/+edit-packaging
461+
462+ >>> user_browser.getControl(
463+ ... name='field.productseries').value = "firefox/trunk"
464+ >>> user_browser.getControl('Change').click()
465+
466+Go back to the source page, and now the upstream's description is shown.
467+
468+ >>> user_browser.open("http://launchpad.dev/ubuntu/+source/iceweasel/")
469+ >>> print extract_text(find_tag_by_id(user_browser.contents, 'upstream'))
470+ Upstream
471+ The Mozilla Firefox web browser
472+
473+
474+Distribution source packages side-bar
475+-------------------------------------
476+
477+The page has a side-bar with a global actions menu, a "Get Involved"
478+menu, a "Latest release" portlet and a "Bug subscriptions" portlet.
479+
480+ >>> print extract_text(
481+ ... find_tag_by_id(user_browser.contents, 'global-actions'))
482+ View full change log
483+ Subscribe to bug mail
484+
485+ >>> print extract_text(
486+ ... find_tag_by_id(user_browser.contents, 'involvement'))
487+ Get Involved
488+ Report a bug
489+ Ask a question
490+ Help translate
491+
492+ >>> print extract_text(
493+ ... find_tag_by_id(user_browser.contents, 'latest-release'))
494+ Latest release
495+ Version: 1.0
496+ Uploaded by: Mark Shuttleworth
497+ On date: ...
498+
499+ >>> print extract_text(
500+ ... find_tag_by_id(user_browser.contents,
501+ ... 'portlet-structural-subscribers'))
502+ Bug subscriptions
503+ ...
504+
505+(see bugs/stories/structural-subscriptions/xx-bug-subscriptions.txt for more
506+on structural subscriptions)
507+
508+
509+Related PPAs
510+------------
511+
512+Switching to a different source now, "netapplet" is published in two
513+distroseries. The distroseries are presented in order, most recent first.
514
515 >>> browser.open("http://launchpad.dev/ubuntutest/+source/netapplet/")
516- >>> print extract_text(find_tag_by_id(browser.contents, 'packaging'))
517- ubuntutest version Upstream version
518- hoary-test development main release 1.0.1a None defined
519- breezy-autotest development main release 1.3.1 None defined
520-
521-Directly after the distro releases, the three latest PPA uploads of
522-this source package are displayed.
523+ >>> print extract_text(find_tag_by_id(browser.contents, 'packages_list'))
524+ Mock Hoary (active development) Set upstream link
525+ 1.0.1a release (main) (not published)
526+ Breezy Badger Autotest (active development) Set upstream link
527+ 1.3.1 release (main) (not published)
528+
529+(See more about packaging in:
530+registry/stories/distribution/xx-distributionsourcepackage-packaging.txt)
531+
532+At the bottom of the page, the three latest PPA uploads of this source package
533+are displayed.
534
535 >>> print extract_text(find_tag_by_id(browser.contents, 'ppa_packaging'))
536 PPA named nightly for Person-name2 owned by Person-name2
537@@ -208,14 +347,17 @@
538 >>> link.text
539 "...more untrusted versions of..."
540
541+
542+Source package change logs
543+--------------------------
544+
545 /$DISTRO/+source/$PACKAGE/+changelog pages contain a version history that lists
546 each published version of a package with its changelog entry for that version.
547+To navigate to this page, click on the "View full change log" link from
548+the index page.
549
550-XXX julian 2009-08-26
551-The +changelog page is currently NOT linked from +index. The index page is
552-currently undergoing a redesign and the link to it will be added therein.
553-Until then, +changelog is a hidden page, but needs to land ahead of that
554-redesign.
555+ >>> browser.open("http://launchpad.dev/ubuntu/+source/foobar/")
556+ >>> browser.getLink("View full change log").click()
557
558 Each version history entry has a header with the version as the title
559 and details of the publishing status in each distroseries it's published
560@@ -223,7 +365,6 @@
561
562 Package "foobar" is deleted:
563
564- >>> browser.open("http://launchpad.dev/ubuntu/+source/foobar/+changelog")
565 >>> first_header = find_tag_by_id(browser.contents,
566 ... "detail_foobar_1.0")
567 >>> print extract_text(first_header)
568@@ -290,25 +431,35 @@
569 changelog:
570
571 >>> user_browser.open(
572- ... "http://launchpad.dev/ubuntu/+source/commercialpackage/")
573+ ... "http://launchpad.dev/ubuntu/+source/commercialpackage/"
574+ ... "+changelog")
575 >>> changelog = find_tag_by_id(
576 ... user_browser.contents, 'commercialpackage_1.0-1')
577 >>> changelog.find('a')
578 <a href="http://launchpad.dev/~name16" class="sprite person">&nbsp;foo.bar@canonical.com</a>
579
580
581-== Packages that are not published ==
582+Packages that are not published
583+-------------------------------
584
585 If the package being viewed has no publishing history, a blank table is
586 displayed:
587
588 >>> user_browser.open(
589 ... "http://launchpad.dev/ubuntu/+source/a52dec/")
590- >>> print extract_text(find_tag_by_id(user_browser.contents, 'packaging'))
591- Ubuntu version Upstream version
592-
593-
594-== Version history ==
595+ >>> print extract_text(find_tag_by_id(
596+ ... user_browser.contents, 'packages_list'))
597+
598+The package information portlet also reflects that the package is not present
599+at all in the distribution.
600+
601+ >>> print extract_text(find_tag_by_id(
602+ ... user_browser.contents, 'current'))
603+ There is no current release for this source package in Ubuntu.
604+
605+
606+Version history
607+---------------
608
609 The sourcepackage version history in a distribution is presented as
610 all distinct sourcepackage releases and their corresponding changelogs
611
612=== renamed file 'lib/canonical/launchpad/pagetests/packaging/xx-distributionsourcepackage-packaging-concurrent-deletion.txt' => 'lib/lp/registry/stories/distribution/xx-distributionsourcepackage-packaging-concurrent-deletion.txt'
613=== renamed file 'lib/canonical/launchpad/pagetests/packaging/xx-distributionsourcepackage-packaging.txt' => 'lib/lp/registry/stories/distribution/xx-distributionsourcepackage-packaging.txt'
614--- lib/canonical/launchpad/pagetests/packaging/xx-distributionsourcepackage-packaging.txt 2009-06-13 19:58:26 +0000
615+++ lib/lp/registry/stories/distribution/xx-distributionsourcepackage-packaging.txt 2009-08-27 20:42:12 +0000
616@@ -9,15 +9,13 @@
617 package in this distribution, and the packaging associations for this
618 source package in each series of this distribution.
619
620-If there are multiple releases in a distroseries, the values that are
621-identical are not repeated.
622-
623 >>> content = anon_browser.contents
624- >>> print extract_text(find_tag_by_id(content, 'packaging'))
625- Ubuntu version Upstream version
626- hoary development main release 1.0.9a-4ubuntu1 None defined
627- warty current main release 1.0.9a-4 alsa-utils trunk series
628- main 1.0.8-1ubuntu1
629+ >>> print extract_text(find_tag_by_id(content, 'packages_list'))
630+ The Hoary Hedgehog Release (active development) Set upstream link
631+ 1.0.9a-4ubuntu1 release (main) ... weeks ago
632+ The Warty Warthog Release (current stable release) alsa-utils trunk series
633+ 1.0.8-1ubuntu1 release (main) ... weeks ago
634+ 1.0.9a-4 release (main) ... weeks ago
635
636
637 === Delete Link Button ===
638@@ -48,11 +46,12 @@
639 >>> for tag in find_tags_by_class(content, 'informational'):
640 ... print extract_text(tag)
641 Removed upstream association between alsa-utils trunk and Warty.
642- >>> print extract_text(find_tag_by_id(content, 'packaging'))
643- Ubuntu version Upstream version
644- hoary development main release 1.0.9a-4ubuntu1 None defined
645- warty current main release 1.0.9a-4 None defined
646- main 1.0.8-1ubuntu1
647+ >>> print extract_text(find_tag_by_id(content, 'packages_list'))
648+ The Hoary Hedgehog Release (active development) Set upstream link
649+ 1.0.9a-4ubuntu1 release (main) ... weeks ago
650+ The Warty Warthog Release (current stable release) Set upstream link
651+ 1.0.8-1ubuntu1 release (main) ... weeks ago
652+ 1.0.9a-4 release (main) ... weeks ago
653
654
655 == Multiple package links ==
656@@ -80,9 +79,11 @@
657
658 >>> user_browser.open(
659 ... 'http://launchpad.dev/ubuntu/+source/evolution')
660- >>> print extract_text(find_tag_by_id(user_browser.contents, 'packaging'))
661- Ubuntu version Upstream version
662- hoary development main release 1.0 Evolution no-crashes series
663+ >>> print extract_text(find_tag_by_id(
664+ ... user_browser.contents, 'packages_list'))
665+ The Hoary Hedgehog Release (active development) Evolution no-crashes series
666+ 1.0 release (main) ... weeks ago
667+
668
669 Once he deletes the link, the older link shows:
670
671@@ -92,6 +93,7 @@
672 ... print message
673 Removed upstream association between Evolution no-crashes and Hoary.
674
675- >>> print extract_text(find_tag_by_id(user_browser.contents, 'packaging'))
676- Ubuntu version Upstream version
677- hoary development main release 1.0 Evolution trunk series
678+ >>> print extract_text(
679+ ... find_tag_by_id(user_browser.contents, 'packages_list'))
680+ The Hoary Hedgehog Release (active development) Evolution trunk series
681+ 1.0 release (main) ... weeks ago
682
683=== modified file 'lib/lp/registry/templates/distributionsourcepackage-index.pt'
684--- lib/lp/registry/templates/distributionsourcepackage-index.pt 2009-07-17 17:59:07 +0000
685+++ lib/lp/registry/templates/distributionsourcepackage-index.pt 2009-08-28 15:25:46 +0000
686@@ -3,28 +3,52 @@
687 xmlns:tal="http://xml.zope.org/namespaces/tal"
688 xmlns:metal="http://xml.zope.org/namespaces/metal"
689 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
690- xml:lang="en"
691- lang="en"
692- dir="ltr"
693- metal:use-macro="context/@@main_template/master"
694+ metal:use-macro="view/macro:page/main_side"
695 i18n:domain="launchpad"
696 >
697
698 <body>
699
700- <metal:portlets fill-slot="portlets">
701- <div tal:replace="structure context/@@+portlet-structural-subscribers" />
702- <div tal:replace="structure context/@@+portlet-latestbugs" />
703- <div tal:replace="structure context/@@+portlet-latestquestions" />
704- </metal:portlets>
705-
706-<div metal:fill-slot="main">
707-
708- <h1>
709- &ldquo;<span tal:replace="context/name" />&rdquo; source package in
710- <span tal:replace="context/distribution/displayname" />
711- </h1>
712-
713+<metal:block fill-slot="head_epilogue">
714+ <tal:devmode condition="devmode">
715+ <tal:archive_js define="lp_js string:${icingroot}/build">
716+ <script type="text/javascript"
717+ tal:attributes="src string:${lp_js}/soyuz/base.js">
718+ </script>
719+ </tal:archive_js>
720+ </tal:devmode>
721+</metal:block>
722+
723+<tal:heading metal:fill-slot="heading">
724+ <h1 tal:content="view/page_title"/>
725+</tal:heading>
726+
727+<tal:side metal:fill-slot="side">
728+ <tal:menu replace="structure view/@@+global-actions" />
729+
730+ <tal:involved replace="structure context/@@+get-involved" />
731+
732+ <tal:current define="current context/currentrelease">
733+ <div class="portlet" id="latest-release" tal:condition="current">
734+ <h2>Latest release</h2>
735+ <dl>
736+ <dt>Version:</dt>
737+ <dd><a tal:content="current/version"
738+ tal:attributes="href current/fmt:url">3.2.1-3</a>
739+ </dd>
740+ <dt>Uploaded by:</dt>
741+ <dd><a tal:replace="structure current/creator/fmt:link">Foo Bar</a></dd>
742+ <dt>On date:</dt>
743+ <dd tal:content="current/dateuploaded/fmt:datetime"/>
744+ </dl>
745+ </div>
746+ </tal:current>
747+
748+ <tal:subscribers
749+ replace="structure context/@@+portlet-structural-subscribers"/>
750+</tal:side>
751+
752+<tal:main metal:fill-slot="main">
753 <p class="error message"
754 tal:condition="view/errors"
755 tal:content="view/error_count" />
756@@ -40,61 +64,165 @@
757 Field specific error for the hidden packaging field.
758 </p>
759
760- <h2>Published versions and upstream associations</h2>
761-
762- <table id="packaging" class="listing">
763- <thead>
764- <tr>
765- <th colspan="5">
766- <span tal:replace="context/distribution/displayname" /> version
767- </th>
768- <th>Upstream version</th>
769- </tr>
770- </thead>
771- <tbody>
772- <tr tal:repeat="row view/version_listing">
773- <td><span tal:condition="row/series"
774- tal:content="row/series/name">hoary</span></td>
775- <td><span tal:condition="row/series"
776- tal:content="row/series/status/name/fmt:lower" /></td>
777- <td><span tal:condition="row/package"
778- tal:content="row/package/component/name/fmt:lower" /></td>
779- <td tal:content="row/pocket">release</td>
780- <td><a tal:content="row/package/version"
781- tal:attributes="href row/package/fmt:url">2.2.1-1</a>
782- </td>
783- <td>
784- <tal:distroseries_row condition="row/series">
785- <span tal:condition="row/packaging"
786- tal:replace="row/packaging/productseries/title" />
787- <tal:no_direct condition="not: row/packaging">
788- None defined
789- </tal:no_direct>
790- <a tal:attributes="
791- href string:${row/sourcepackage/fmt:url}/+edit-packaging"
792- title="Edit upstream association">
793- <img src="/@@/edit" />
794- </a>
795- <form tal:condition="row/packaging_field"
796- style="display: inline"
797- action=""
798- method="POST"
799- tal:attributes="action request/URL;
800- id row/delete_packaging_form_id">
801- <tal:hidden replace="structure row/packaging_field" />
802- <tal:action
803- replace="structure view/renderDeletePackagingAction" />
804- </form>
805- </tal:distroseries_row>
806- </td>
807- </tr>
808- </tbody>
809- </table>
810- <p style="text-align: right">
811- <a href="+publishinghistory">See full publishing history...</a>
812- </p>
813-
814- <div tal:define="ppa_versions view/related_ppa_versions"
815+ <div class="top-portlet" id="bugs-and-questions-summary"
816+ tal:define="newbugs context/new_bugtasks/count;
817+ open_questions view/open_questions/count">
818+ This package has
819+ <a tal:attributes="href view/menu:overview/new_bugs/url"><strong class="bugs-stat"><tal:newbugs content="newbugs"/> new bug<tal:plural content="string:s" condition="python: newbugs!=1"/><strong></a>
820+ and <a tal:attributes="href view/menu:overview/open_questions/url"><strong class="answers-stat"><tal:openq content="open_questions"/> open question<tal:plural content="string:s" condition="python: open_questions!=1"/>.</strong></a>
821+ </div>
822+
823+ <div class="yui-g">
824+
825+ <div class="yui-u first" tal:define="current context/currentrelease">
826+ <div class="portlet" tal:condition="current" id="current">
827+ <h2>Package information</h2>
828+ <div class="two-column-list">
829+ <dl>
830+ <dt>Maintainer:</dt>
831+ <dd>
832+ <a tal:replace="structure current/maintainer/fmt:link">Foo Bar</a>
833+ </dd>
834+ </dl>
835+ <dl>
836+ <dt>Urgency:<sup>*</sup></dt>
837+ <dd tal:content="current/urgency/title"/>
838+ </dl>
839+ <dl>
840+ <dt>Component:<sup>*</sup></dt>
841+ <dd tal:content="current/component/name"/>
842+ </dl>
843+ <dl>
844+ <dt>Architectures:<sup>*</sup></dt>
845+ <dd tal:content="current/architecturehintlist"/>
846+ </dl>
847+ </div>
848+ <p style="font-size: 80%;">
849+ <sup>*</sup>actual publishing details may vary in this distribution, these are just the package defaults.
850+ </p>
851+ </div><!--portlet-->
852+ <div class="portlet" tal:condition="not: current" id="current">
853+ There is no current release for this source package in
854+ <span tal:replace="context/distribution/displayname">ubuntu</span>.
855+ </div>
856+ </div><!--yui-u-->
857+
858+ <div class="yui-u">
859+ <div class="portlet" id="upstream">
860+ <tal:project define="project context/upstream_product">
861+ <div tal:condition="project">
862+ <h2>Upstream</h2>
863+ <div style="float:left; padding:0 1em 1em 0;"
864+ tal:content="structure project/image:logo"/>
865+ <div tal:content="structure project/summary" />
866+ </div>
867+ <tal:noproject condition="not: project">
868+ This package is not linked to an upstream product.
869+ </tal:noproject>
870+ </tal:project>
871+ </div><!--portlet -->
872+ </div><!--yui-u -->
873+
874+ </div><!--yui-g -->
875+
876+
877+ <div class="yui-u"
878+ tal:define="archive context/latest_overall_publication/archive|nothing">
879+
880+ <table class="listing" id="packages_list">
881+ <tal:rows repeat="row view/version_table">
882+
883+ <tal:title_row condition="row/title_row">
884+ <tr class="section-heading shaded" style="vertical-align: middle">
885+ <td colspan=3>
886+ <img tal:replace="structure context/distribution/image:icon"/>
887+ <a tal:attributes="href row/series_package/fmt:url"
888+ tal:content="row/distroseries/title"/>
889+ (<span tal:replace="row/distroseries/status/title/lower"/>)
890+ <div style="float:right;">
891+ <a tal:condition="not: row/packaging"
892+ tal:replace="structure row/series_package/menu:overview/set_upstream/fmt:link"/>
893+ <tal:has_packaging condition="row/packaging">
894+ <img tal:replace="structure row/packaging/productseries/image:icon"/>
895+ <tal:title replace="row/packaging/productseries/title"/>
896+ <a tal:attributes="
897+ href row/series_package/menu:overview/edit_packaging/url">
898+ <img src="/@@/edit">
899+ </a>
900+ <form style="display: inline"
901+ method="POST"
902+ tal:condition="row/hidden_packaging_field"
903+ tal:attributes="action request/URL;
904+ id row/delete_packaging_form_id">
905+ <tal:hidden replace="structure row/hidden_packaging_field" />
906+ <tal:action replace="structure view/renderDeletePackagingAction" />
907+ </form>
908+ </tal:has_packaging>
909+ </div><!--float right-->
910+ </td>
911+ </tr>
912+ </tal:title_row>
913+
914+ <tal:package_row condition="row/data_row">
915+ <tal:define define="pubid row/publication/id">
916+
917+ <tr class="archive_package_row">
918+ <td style="white-space: nowrap">
919+ <a class="expander"
920+ tal:attributes="id string:pub${pubid}-expander;
921+ href string:${archive/fmt:url}/+sourcepub/${pubid}/+listing-archive-extra">
922+ <img style="padding-right:0.5em;" src="/@@/treeCollapsed"
923+ alt="Show details" title="Show details"
924+ tal:attributes="id string:pub${pubid}-arrow"/>
925+ </a>
926+ <a tal:attributes="href row/version">
927+ <img src="/@@/package-source" />
928+ <tal:version content="row/version"/>
929+ </a>
930+ </td>
931+ <td>
932+ <tal:pockets content="row/pockets/lower"/>
933+ (<tal:component content="row/component"/>)
934+ </td>
935+ <td>
936+ <tal:last_published condition="row/published_since">
937+ <span tal:replace="row/published_since/fmt:approximateduration"/>
938+ ago
939+ </tal:last_published>
940+ <tal:not_published
941+ condition="not: row/published_since"
942+ content="string:(not published)"/>
943+ </td>
944+ </tr>
945+ <tr tal:attributes="id string:pub${pubid}" style="display: none">
946+ <td colspan=3>
947+ <div class="package-details"
948+ tal:attributes="id string:pub${pubid}-container" />
949+ </td>
950+ </tr>
951+
952+ </tal:define>
953+ </tal:package_row>
954+
955+ <tal:blank_row condition="row/blank_row">
956+ <tr><td colspan=3 style="padding-bottom: 1em; border-top: 0" /></tr>
957+ </tal:blank_row>
958+
959+ </tal:rows>
960+ </table>
961+ <script
962+ tal:content="string:LP.client.cache['archive_context_url'] = '${archive/fmt:url}';"/>
963+ <metal:js use-macro="archive/@@+macros/expandable-table-js"/>
964+
965+ <p style="float:right; padding-top:1em">
966+ <a href="+publishinghistory">See full publishing history</a>
967+ </p>
968+
969+ </div>
970+
971+ <div class="yui-u">
972+ <div class="portlet"
973+ tal:define="ppa_versions view/related_ppa_versions"
974 tal:condition="ppa_versions" id="related-ppa-versions">
975 <div id="slide-trigger">
976 <div class="widget-hd">
977@@ -103,7 +231,7 @@
978 </div>
979 </div>
980 <div class="widget-bd">
981- <p>The following <strong>unsupported</strong> and
982+ <p>The following <strong>unsupported</strong> and
983 <strong>untrusted</strong> Personal Archives (PPAs) provide
984 packages of
985 '<span tal:replace="context/name" />':</p>
986@@ -171,14 +299,9 @@
987 </script>
988
989 </div>
990-
991- <h2>Version history</h2>
992-
993- <tal:block
994- repeat="dspr view/releases"
995- replace="structure dspr/@@+changes">
996- </tal:block>
997-
998-</div>
999+ </div>
1000+
1001+</tal:main>
1002+
1003 </body>
1004 </html>
1005
1006=== modified file 'lib/lp/soyuz/stories/soyuz/xx-distrorelease-sources.txt'
1007--- lib/lp/soyuz/stories/soyuz/xx-distrorelease-sources.txt 2009-06-16 18:31:28 +0000
1008+++ lib/lp/soyuz/stories/soyuz/xx-distrorelease-sources.txt 2009-08-26 15:24:40 +0000
1009@@ -38,10 +38,10 @@
1010 >>> print browser.url
1011 http://launchpad.dev/ubuntu/+source/mozilla-firefox
1012
1013-Click the "Show publishing history" link to see specific information
1014+Click the "See full publishing history" link to see specific information
1015 about Firefox's publishing history.
1016
1017- >>> browser.getLink("Show publishing history").click()
1018+ >>> browser.getLink("See full publishing history").click()
1019 >>> print extract_text(find_tag_by_id(browser.contents, 'publishing-summary'))
1020 Date Status Target Pocket Component Section Version
1021 2006-02-13 12:19:00 UTC Published Warty release main web 0.9
1022@@ -54,7 +54,7 @@
1023 By clicking in the 'target' distroseries we will get to the
1024 SourcePackage page:
1025
1026- >>> browser.getLink("warty").click()
1027+ >>> browser.getLink("The Warty Warthog Release").click()
1028 >>> browser.url
1029 'http://launchpad.dev/ubuntu/warty/+source/mozilla-firefox'
1030
1031@@ -438,9 +438,8 @@
1032 distroseries and archive are shown.
1033
1034 >>> anon_browser.open(
1035- ... 'http://launchpad.dev/ubuntu/+source/alsa-utils')
1036-
1037- >>> anon_browser.getLink("Show publishing history").click()
1038+ ... 'http://launchpad.dev/ubuntu/+source/alsa-utils/'
1039+ ... '+publishinghistory')
1040
1041 >>> print extract_text(
1042 ... find_tag_by_id(anon_browser.contents, 'publishing-summary'))
1043
1044=== modified file 'lib/lp/soyuz/stories/soyuz/xx-package-diff.txt'
1045--- lib/lp/soyuz/stories/soyuz/xx-package-diff.txt 2009-05-06 20:53:05 +0000
1046+++ lib/lp/soyuz/stories/soyuz/xx-package-diff.txt 2009-08-26 15:24:40 +0000
1047@@ -125,10 +125,11 @@
1048
1049 == Ubuntu sources ==
1050
1051-All diffs are visible in the 'biscuit source in ubuntu' page, right
1052-below the changelog text for each uploaded version.
1053+All diffs are visible in the 'biscuit source in ubuntu' change log page, right
1054+below the text for each uploaded version.
1055
1056- >>> anon_browser.open('http://launchpad.dev/ubuntu/+source/biscuit')
1057+ >>> anon_browser.open(
1058+ ... 'http://launchpad.dev/ubuntu/+source/biscuit/+changelog')
1059 >>> changes = find_tags_by_class(anon_browser.contents, 'boardComment')
1060 >>> for change in changes:
1061 ... print 30 * '='
1062
1063=== modified file 'lib/lp/soyuz/templates/archive-macros.pt'
1064--- lib/lp/soyuz/templates/archive-macros.pt 2009-07-17 17:59:07 +0000
1065+++ lib/lp/soyuz/templates/archive-macros.pt 2009-08-25 17:05:15 +0000
1066@@ -64,9 +64,18 @@
1067 }
1068 };
1069
1070+ /*
1071+ * If a page wants to use this outside of an archive context then it
1072+ * car define LP.client.cache['archive_context'], which should be a
1073+ * full or relative URL to the context archive page required.
1074+ */
1075+ var base_url = (typeof(LP.client.cache['archive_context_url']) != "undefined") ? LP.client.cache['archive_context_url'] : '';
1076+ if (base_url !== ''){
1077+ base_url += '/'
1078+ }
1079 var pub_id = container.get('id').replace(
1080 '-container', '').replace('pub', '');
1081- var uri = '+sourcepub/' + pub_id + '/+listing-archive-extra';
1082+ var uri = base_url + '+sourcepub/' + pub_id + '/+listing-archive-extra';
1083 Y.io(uri, config);
1084 }
1085