Merge lp:~allenap/launchpad/ui-convert-bug-activity-bug-412523 into lp:launchpad

Proposed by Gavin Panella
Status: Merged
Approved by: Gavin Panella
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~allenap/launchpad/ui-convert-bug-activity-bug-412523
Merge into: lp:launchpad
Diff against target: None lines
To merge this branch: bzr merge lp:~allenap/launchpad/ui-convert-bug-activity-bug-412523
Reviewer Review Type Date Requested Status
Celso Providelo (community) code Approve
Michael Nelson (community) ui Approve
Martin Albisetti Pending
Review via email: mp+10026@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

This branch converts bug-activity.pt to the new 3.0 base template according to the instructions at <https://dev.launchpad.net/VersionThreeDotO/UI/Conversion>. I am expecting to have to make more changes arising from this review, but that's what I want: it is the first bugs template to be converted, so it's also so I can figure out the process. Once I understand it better I will split up the work so the whole team can get to work on it.

I have before and after screenshots (also linked from the bug report):

  http://launchpadlibrarian.net/30223879/before-mechanical-changes.png

  http://launchpadlibrarian.net/30223898/after-mechanical-changes.png

My comments on the changes so far, taken from <https://bugs.edge.launchpad.net/malone/+bug/412523/comments/3>:

> The changes so far have been almost exclusively mechanical. I've
> chosen the main_only base template, and tried to apply the CSS
> rules. I can see the following issues with the new page:
>
> * "Mozilla Firefox" is repeated in the breadcrumbs and in the
> location-portlet.
>
> * The bug activity log has always been shown in bugtask
> context. The new application tabs block is much more prominent
> than the old and looks a bit daft in the activity log which is
> bug-related, not bugtask related.
>
>
> * Repetition of "bug #1" close together.
>
> * The table border butts against the divider at the bottom of the
> page, and creates the appearance of a double thickness border. A
> margin-bottom on that table would fix it, but that smells a
> but. Is there already a way to handle this "nicely"?

Test: ./bin/test -vvt xx-bug-activity

Lint free.

Revision history for this message
Michael Nelson (michael.nelson) wrote :
Download full text (7.2 KiB)

Hi Gavin,

Great start! It's a nice simple informational page without actions so a good one to begin with!

I've marked it as needs fixing, just to sort out the portlet divs etc.

> This branch converts bug-activity.pt to the new 3.0 base template according to
> the instructions at
> <https://dev.launchpad.net/VersionThreeDotO/UI/Conversion>. I am expecting to
> have to make more changes arising from this review, but that's what I want: it
> is the first bugs template to be converted, so it's also so I can figure out
> the process. Once I understand it better I will split up the work so the whole
> team can get to work on it.

Great idea!

>
> I have before and after screenshots (also linked from the bug report):
>
> http://launchpadlibrarian.net/30223879/before-mechanical-changes.png
>
> http://launchpadlibrarian.net/30223898/after-mechanical-changes.png

Thanks for that! So much easier... and great to enable discussion on the bug too!

I'll respond to your thoughts below, and then summarise more generally at the bottom...

>
> My comments on the changes so far, taken from
> <https://bugs.edge.launchpad.net/malone/+bug/412523/comments/3>:
>
> > The changes so far have been almost exclusively mechanical. I've
> > chosen the main_only base template, and tried to apply the CSS
> > rules. I can see the following issues with the new page:
> >
> > * "Mozilla Firefox" is repeated in the breadcrumbs and in the
> > location-portlet.

The breadcrumbs will be moving to directly below your h1 heading, and will be less prominent. I personally don't see the repetition as a problem in the context of breadcrumbs (ie. they will always display the path of your traversal by necessity).

> >
> > * The bug activity log has always been shown in bugtask
> > context. The new application tabs block is much more prominent
> > than the old and looks a bit daft in the activity log which is
> > bug-related, not bugtask related.

Hmmm... But the application tabs block is showing the user the related pillar-or-person - in this case the product. So I'm not sure why you think it's confusing in either bug/bugtask context? But I'm not sure I've properly understood your point here.

> >
> >
> > * Repetition of "bug #1" close together.

Yes, but as we chatted, I really think that 'bug #1' link should be part of the breadcrumb...

Firefox > Bug #1

Perhaps you should chat with salgado and find out if it will indeed be included in the new breadcrumb (or if he can ensure that it is). In which case, I'd be for removing it.

> >
> > * The table border butts against the divider at the bottom of the
> > page, and creates the appearance of a double thickness border. A
> > margin-bottom on that table would fix it, but that smells a
> > but. Is there already a way to handle this "nicely"?

I think this is just because you don't have the table in a portlet div. You seem to have just the top-portlet which has the link.

I think you should either have one single top-portlet (my preference), or if you need to leave the link in and you think it should be in a separate portlet, then you'd need to wrap your table in a portlet div too, but I really think you hav...

Read more...

review: Needs Fixing (ui)
Revision history for this message
Gavin Panella (allenap) wrote :

Thanks for the review Michael!

I've add a BugTask breadcrumb, that just says "Bug #X", and tests in
lp/bugs/test/test_breadcrumbs.py which is ripped off from salgado's
work on breadcrumbs.

> > > * The table border butts against the divider at the bottom of the
> > > page, and creates the appearance of a double thickness border. A
> > > margin-bottom on that table would fix it, but that smells a
> > > but. Is there already a way to handle this "nicely"?
>
> I think this is just because you don't have the table in a portlet div. You
> seem to have just the top-portlet which has the link.
>
> I think you should either have one single top-portlet (my preference), or if
> you need to leave the link in and you think it should be in a separate
> portlet, then you'd need to wrap your table in a portlet div too, but I really
> think you have just one piece of information on that page (the activity log).

I've added a single top-portlet div.

> So, other general thoughts:
> * The date formatting (which beuno mentioned)

Fixed, though I'm not using fmt:datetime because of bug 412963
(fmt:datetime displays date and time in current timezone, even when
UTC only is desired). I've added an XXX to the template.

> * Assuming the breadcrumb will include Bug #1, would it make sense to update
> the H1 to instead include the name of the bug rather than the number (or in
> addition to)?

Yes, the bug title is now in the heading.

> * Given that this page is traversable by other products (and the activity is
> related to other products as you said), I'd expect to see "Other related
> products" or something on this page, when there are some. I realise this
> wouldn't be part of the mechanical update, but it would be great to do. At
> least an XXX for a bug?

This is a weird one. The presence of the product heading doesn't
always make sense at first on the activity log page (or many other
pages that are found below the bug page). Once the breadcrumbs are
moved to below the product heading it will make a bit more sense. But
I'm not sure what value there is in drawing attention to the fact that
this activity log page can be seen in the context of another product;
the main page content will be identical. This is definitely something
the bugs team are going to have to talk about as part of our 3.0
redesign.

I've attached a couple of diffs showing the changes I've made. I had
to merge devel in the middle of my changes because the tree would no
longer build (and the bin/buildout workaround was also not working), I
made some whitespace changes, and I also fixed some lint, none of
which is interesting here.

1=== modified file 'lib/lp/bugs/browser/bugtask.py'
2--- lib/lp/bugs/browser/bugtask.py 2009-08-07 23:20:33 +0000
3+++ lib/lp/bugs/browser/bugtask.py 2009-08-13 10:14:48 +0000
4@@ -14,6 +14,7 @@
5 'BugTargetView',
6 'BugTaskContextMenu',
7 'BugTaskCreateQuestionView',
8+ 'BugTaskBreadcrumbBuilder',
9 'BugTaskEditView',
10 'BugTaskExpirableListingView',
11 'BugTaskListingItem',
12@@ -116,6 +117,7 @@
13 from lp.registry.interfaces.sourcepackage import ISourcePackage
14 from canonical.launchpad.interfaces.validation import (
15 valid_upstreamtask, validate_distrotask)
16+from canonical.launchpad.webapp.breadcrumb import BreadcrumbBuilder
17 from canonical.launchpad.webapp.interfaces import (
18 ILaunchBag, NotFoundError, UnexpectedFormData)
19
20@@ -3476,3 +3478,12 @@
21 return_dict[key] = cgi.escape(return_dict[key])
22
23 return "%(old_value)s &#8594; %(new_value)s" % return_dict
24+
25+
26+class BugTaskBreadcrumbBuilder(BreadcrumbBuilder):
27+ """Builds a breadcrumb for an `IBugTask`."""
28+ @property
29+ def text(self):
30+ return "%s: %s" % (
31+ self.context.bug.displayname,
32+ self.context.bug.title)
33
34=== modified file 'lib/lp/bugs/configure.zcml'
35--- lib/lp/bugs/configure.zcml 2009-07-23 13:44:13 +0000
36+++ lib/lp/bugs/configure.zcml 2009-08-13 10:14:48 +0000
37@@ -263,6 +263,12 @@
38 <adapter
39 factory="lp.bugs.browser.bugtask.assignee_renderer"
40 name="assignee"/>
41+ <adapter
42+ provides="canonical.launchpad.webapp.interfaces.IBreadcrumbBuilder"
43+ for="lp.bugs.interfaces.bugtask.IBugTask"
44+ factory="lp.bugs.browser.bugtask.BugTaskBreadcrumbBuilder"
45+ permission="zope.Public"/>
46+
47
48 <!-- NullBugTask -->
49
50
51=== modified file 'lib/lp/bugs/templates/bug-activity.pt'
52--- lib/lp/bugs/templates/bug-activity.pt 2009-08-12 13:02:26 +0000
53+++ lib/lp/bugs/templates/bug-activity.pt 2009-08-13 10:14:13 +0000
54@@ -10,10 +10,8 @@
55 </div>
56
57 <div metal:fill-slot="main">
58+ <div class="yui-g">
59 <div class="top-portlet">
60- <p tal:content="structure context/fmt:link" />
61- </div>
62- <div class="yui-g">
63 <table class="listing">
64 <thead>
65 <tr>
66@@ -39,5 +37,6 @@
67 </tbody>
68 </table>
69 </div>
70+ </div>
71 </div>
72 </bug-activity>
1=== modified file 'lib/lp/bugs/browser/bugtask.py'
2--- lib/lp/bugs/browser/bugtask.py 2009-08-13 10:15:14 +0000
3+++ lib/lp/bugs/browser/bugtask.py 2009-08-13 12:41:32 +0000
4@@ -3498,6 +3498,4 @@
5 """Builds a breadcrumb for an `IBugTask`."""
6 @property
7 def text(self):
8- return "%s: %s" % (
9- self.context.bug.displayname,
10- self.context.bug.title)
11+ return self.context.bug.displayname
12
13=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
14--- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-06 13:51:38 +0000
15+++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-13 12:59:41 +0000
16@@ -7,16 +7,19 @@
17 ... 'mozilla-firefox/+bug/3/+activity')
18 >>> main_content = find_main_content(anon_browser.contents)
19
20-The page heading contains a link back to the bug page.
21+The page contains a link back to the bug page:
22
23- >>> bug_link = main_content.p.a
24- >>> print '%s --> %s' % (extract_text(bug_link), bug_link['href'])
25- Bug #3: Bug Title Test --> /debian/+source/mozilla-firefox/+bug/3
26+ >>> document = find_tag_by_id(anon_browser.contents, 'document')
27+ >>> bug_link = document.find(
28+ ... 'a', href=lambda href: href.endswith('/+bug/3'))
29+ >>> print '%s\n--> %s' % (extract_text(bug_link), bug_link['href'])
30+ Bug #3
31+ --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+bug/3
32
33 The title repeats the bug number for clarity.
34
35 >>> print extract_text(main_content.h1)
36- Activity log for bug #3
37+ Activity log for bug #3 - Bug Title Test
38
39 The activity log itself is presented as a table.
40
41@@ -27,9 +30,9 @@
42 >>> for row in main_content.table('tr'):
43 ... print_row(row)
44 Date | Who | What changed | Old value | New value | Message
45- 10 Aug 05 16:30 | Sample Person | bug | | | assigned to source ...
46- 10 Aug 05 16:30 | Sample Person | bug | | | assigned to source ...
47- 24 Feb 06 21:34 | Foo Bar | mozilla-firefox: statusexplanation | | |
48+ 2005-08-10 16:30:32 | Sample Person | bug | | | assigned to source ...
49+ 2005-08-10 16:30:47 | Sample Person | bug | | | assigned to source ...
50+ 2006-02-24 21:34:52 | Foo Bar | mozilla-firefox: statusexplanation | | |
51
52
53 == Activity interleaved with comments ==
54
55=== modified file 'lib/lp/bugs/templates/bug-activity.pt'
56--- lib/lp/bugs/templates/bug-activity.pt 2009-08-13 10:14:13 +0000
57+++ lib/lp/bugs/templates/bug-activity.pt 2009-08-13 12:59:41 +0000
58@@ -6,7 +6,10 @@
59 metal:use-macro="view/macro:page/main_only">
60
61 <div metal:fill-slot="heading">
62- <h1>Activity log for bug #<span tal:replace="context/bug/id" /></h1>
63+ <h1>
64+ Activity log for bug #<span tal:replace="context/bug/id" /> -
65+ <span tal:replace="context/bug/title" />
66+ </h1>
67 </div>
68
69 <div metal:fill-slot="main">
70@@ -25,8 +28,13 @@
71 </thead>
72 <tbody>
73 <tr tal:repeat="log context/bug/activity">
74- <td tal:content="python:log.datechanged.strftime('%d %b %y %H:%M')">
75- 13 Sep 04 14:15
76+ <tal:comment condition="nothing">
77+ XXX: Gavin Panella 2009-08-12 bug=412963: Using strftime()
78+ here because fmt:datetime changes timezone, even though we
79+ always want to show only UTC.
80+ </tal:comment>
81+ <td tal:content="python:log.datechanged.strftime('%Y-%m-%d %T')">
82+ 2004-09-24 12:04:43
83 </td>
84 <td><tal:person tal:replace="structure log/person/fmt:link">person</tal:person></td>
85 <td tal:content="log/whatchanged">description</td>
86
87=== added file 'lib/lp/bugs/tests/test_breadcrumbs.py'
88--- lib/lp/bugs/tests/test_breadcrumbs.py 1970-01-01 00:00:00 +0000
89+++ lib/lp/bugs/tests/test_breadcrumbs.py 2009-08-13 13:57:47 +0000
90@@ -0,0 +1,71 @@
91+# Copyright 2009 Canonical Ltd. This software is licensed under the
92+# GNU Affero General Public License version 3 (see the file LICENSE).
93+
94+__metaclass__ = type
95+
96+import unittest
97+
98+from zope.component import getMultiAdapter
99+
100+from canonical.lazr.testing.menus import make_fake_request
101+from canonical.launchpad.webapp.publisher import RootObject
102+from canonical.testing import DatabaseFunctionalLayer
103+from lp.testing import TestCaseWithFactory
104+
105+
106+class TestBugTaskBreadcrumbBuilder(TestCaseWithFactory):
107+
108+ layer = DatabaseFunctionalLayer
109+
110+ def setUp(self):
111+ TestCaseWithFactory.setUp(self)
112+ self.product = self.factory.makeProduct(
113+ name='crumb-tester', displayname="Crumb Tester")
114+ self.bug = self.factory.makeBug(product=self.product)
115+ self.root = RootObject()
116+
117+ def test_bugtask_on_mainsite(self):
118+ request = make_fake_request(
119+ 'http://launchpad.dev/%s/+bug/%d' % (
120+ self.product.name, self.bug.id),
121+ [self.root, self.product, self.bug.default_bugtask])
122+ hierarchy = getMultiAdapter((self.root, request), name='+hierarchy')
123+ self.assertEquals(
124+ ['http://launchpad.dev/crumb-tester',
125+ 'http://launchpad.dev/crumb-tester/+bug/%d' % self.bug.id],
126+ [crumb.url for crumb in hierarchy.items()])
127+ self.assertEquals(
128+ ["Crumb Tester", "Bug #%d" % self.bug.id],
129+ [crumb.text for crumb in hierarchy.items()])
130+
131+ def test_bugtask_on_vhost(self):
132+ request = make_fake_request(
133+ 'http://bugs.launchpad.dev/%s/+bug/%d' % (
134+ self.product.name, self.bug.id),
135+ [self.root, self.product, self.bug.default_bugtask])
136+ hierarchy = getMultiAdapter((self.root, request), name='+hierarchy')
137+ self.assertEquals(
138+ ['http://bugs.launchpad.dev/crumb-tester',
139+ 'http://bugs.launchpad.dev/crumb-tester/+bug/%d' % self.bug.id],
140+ [crumb.url for crumb in hierarchy.items()])
141+ self.assertEquals(
142+ ["Crumb Tester", "Bug #%d" % self.bug.id],
143+ [crumb.text for crumb in hierarchy.items()])
144+
145+ def test_bugtask_child_on_vhost(self):
146+ request = make_fake_request(
147+ 'http://bugs.launchpad.dev/%s/+bug/%d/+activity' % (
148+ self.product.name, self.bug.id),
149+ [self.root, self.product, self.bug.default_bugtask])
150+ hierarchy = getMultiAdapter((self.root, request), name='+hierarchy')
151+ self.assertEquals(
152+ ['http://bugs.launchpad.dev/crumb-tester',
153+ 'http://bugs.launchpad.dev/crumb-tester/+bug/%d' % self.bug.id],
154+ [crumb.url for crumb in hierarchy.items()])
155+ self.assertEquals(
156+ ["Crumb Tester", "Bug #%d" % self.bug.id],
157+ [crumb.text for crumb in hierarchy.items()])
158+
159+
160+def test_suite():
161+ return unittest.TestLoader().loadTestsFromName(__name__)
Revision history for this message
Gavin Panella (allenap) wrote :

Also see the screenshot of what it looks like now:

  http://launchpadlibrarian.net/30272857/post-review.png

Revision history for this message
Michael Nelson (michael.nelson) wrote :

> Also see the screenshot of what it looks like now:
>
> http://launchpadlibrarian.net/30272857/post-review.png

Thanks Gavin, for the screenshot and for adding the breadcrumb - looks great!

So, as we discussed, r=me assuming that:

1. The lack of padding between the heading and the table will be fixed by either the placement of the new breadcrumbs or a general css rule to apply padding to tables within portlets (as you've correctly got it in a top-portlet now), and,

2. The table itself will be redesigned as part of the bugs ui work later, and will include a link to the relevant product's bugtask for an activity log entry when it is different from the product displayed in the traversal (and above the app. tabs).

-M.

review: Approve (ui)
Revision history for this message
Celso Providelo (cprov) wrote :
Download full text (8.1 KiB)

> === modified file 'lib/lp/bugs/browser/bugtask.py'
> --- lib/lp/bugs/browser/bugtask.py 2009-08-10 21:05:59 +0000
> +++ lib/lp/bugs/browser/bugtask.py 2009-08-13 16:47:38 +0000
> @@ -14,6 +14,7 @@
> 'BugTargetView',
> 'BugTaskContextMenu',
> 'BugTaskCreateQuestionView',
> + 'BugTaskBreadcrumbBuilder',
> 'BugTaskEditView',
> 'BugTaskExpirableListingView',
> 'BugTaskListingItem',
> @@ -45,7 +46,6 @@
> import re
> from simplejson import dumps
> import urllib
> -from urlparse import urlparse, urlunparse
> from operator import attrgetter, itemgetter
>
> from zope import component
> @@ -116,6 +116,7 @@
> from lp.registry.interfaces.sourcepackage import ISourcePackage
> from canonical.launchpad.interfaces.validation import (
> valid_upstreamtask, validate_distrotask)
> +from canonical.launchpad.webapp.breadcrumb import BreadcrumbBuilder
> from canonical.launchpad.webapp.interfaces import (
> ILaunchBag, NotFoundError, UnexpectedFormData)
>
> @@ -3490,3 +3491,10 @@
> return_dict[key] = cgi.escape(return_dict[key])
>
> return "%(old_value)s &#8594; %(new_value)s" % return_dict
> +
> +
> +class BugTaskBreadcrumbBuilder(BreadcrumbBuilder):
> + """Builds a breadcrumb for an `IBugTask`."""
> + @property
> + def text(self):
> + return self.context.bug.displayname
>

Nice! It will look much nicer when we have the breadcrumbs below the
heading section.

> === modified file 'lib/lp/bugs/configure.zcml'
> --- lib/lp/bugs/configure.zcml 2009-07-23 13:44:13 +0000
> +++ lib/lp/bugs/configure.zcml 2009-08-13 16:47:38 +0000
> @@ -263,6 +263,12 @@
> <adapter
> factory="lp.bugs.browser.bugtask.assignee_renderer"
> name="assignee"/>
> + <adapter
> + provides="canonical.launchpad.webapp.interfaces.IBreadcrumbBuilder"
> + for="lp.bugs.interfaces.bugtask.IBugTask"
> + factory="lp.bugs.browser.bugtask.BugTaskBreadcrumbBuilder"
> + permission="zope.Public"/>
> +
>
> <!-- NullBugTask -->
>
>

It looks like you have TABs before and after this comment.

> === modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
> --- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-06 13:51:38 +0000
> +++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-13 16:47:38 +0000
> @@ -7,16 +7,19 @@
> ... 'mozilla-firefox/+bug/3/+activity')
> >>> main_content = find_main_content(anon_browser.contents)
>
> -The page heading contains a link back to the bug page.
> +The page contains a link back to the bug page:
>
> - >>> bug_link = main_content.p.a
> - >>> print '%s --> %s' % (extract_text(bug_link), bug_link['href'])
> - Bug #3: Bug Title Test --> /debian/+source/mozilla-firefox/+bug/3
> + >>> document = find_tag_by_id(anon_browser.contents, 'document')
> + >>> bug_link = document.find(
> + ... 'a', href=lambda href: href.endswith('/+bug/3'))
> + >>> print '%s\n--> %s' % (extract_text(bug_link), bug_link['href'])
> + Bug #3
> + --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+bug/3
>

I wonder if there would be any value in using print_locatio...

Read more...

review: Approve
Revision history for this message
Gavin Panella (allenap) wrote :
Download full text (4.4 KiB)

On Thu, 13 Aug 2009 17:09:06 -0000
Celso Providelo <email address hidden> wrote:

> Review: Approve

Woohoo! Thank you :)

...
> > === modified file 'lib/lp/bugs/configure.zcml'
> > --- lib/lp/bugs/configure.zcml 2009-07-23 13:44:13 +0000
> > +++ lib/lp/bugs/configure.zcml 2009-08-13 16:47:38 +0000
> > @@ -263,6 +263,12 @@
> > <adapter
> > factory="lp.bugs.browser.bugtask.assignee_renderer"
> > name="assignee"/>
> > + <adapter
> > + provides="canonical.launchpad.webapp.interfaces.IBreadcrumbBuilder"
> > + for="lp.bugs.interfaces.bugtask.IBugTask"
> > + factory="lp.bugs.browser.bugtask.BugTaskBreadcrumbBuilder"
> > + permission="zope.Public"/>
> > +
> >
> > <!-- NullBugTask -->
> >
> >
>
> It looks like you have TABs before and after this comment.

All of the configure.zcml files generated during the move from c/l to
lp/* are chock full of weird whitespace. I started a utility to clean
this up a while back, but have not finished it. If I fix this comment,
I need to fix all the whitespace in this file, so I'd like to leave it
for now, until I have an automated solution.

>
> > === modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
> > --- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-06 13:51:38 +0000
> > +++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-13 16:47:38 +0000
> > @@ -7,16 +7,19 @@
> > ... 'mozilla-firefox/+bug/3/+activity')
> > >>> main_content = find_main_content(anon_browser.contents)
> >
> > -The page heading contains a link back to the bug page.
> > +The page contains a link back to the bug page:
> >
> > - >>> bug_link = main_content.p.a
> > - >>> print '%s --> %s' % (extract_text(bug_link), bug_link['href'])
> > - Bug #3: Bug Title Test --> /debian/+source/mozilla-firefox/+bug/3
> > + >>> document = find_tag_by_id(anon_browser.contents, 'document')
> > + >>> bug_link = document.find(
> > + ... 'a', href=lambda href: href.endswith('/+bug/3'))
> > + >>> print '%s\n--> %s' % (extract_text(bug_link), bug_link['href'])
> > + Bug #3
> > + --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+bug/3
> >
>
> I wonder if there would be any value in using print_location() helper
> here. it prints the hierarchy, not exactly the links, but we know the
> links are properly rendered by BreadcrumbBuilder (we have specific
> tests for that).
>
> What do you think ?

I've never used print_location() before, but you're right, it fits the
bill nicely. I've had to modify it to work with the new application
tabs, so maybe you could have a look at the attached diff just to make
sure it's okay?

>
> > The title repeats the bug number for clarity.
> >
> > >>> print extract_text(main_content.h1)
> > - Activity log for bug #3
> > + Activity log for bug #3 - Bug Title Test
> >
> > The activity log itself is presented as a table.
> >
> > @@ -27,9 +30,9 @@
> > >>> for row in main_content.table('tr'):
> > ... print_row(row)
> > Date | Who | What changed | Old value | New value | Message
> > - 10 Aug 05 16:30 | Sample Person | bug | | | assigne...

Read more...

1=== modified file 'lib/canonical/launchpad/testing/pages.py'
2--- lib/canonical/launchpad/testing/pages.py 2009-06-25 05:30:52 +0000
3+++ lib/canonical/launchpad/testing/pages.py 2009-08-14 09:19:59 +0000
4@@ -542,15 +542,26 @@
5 def print_location_apps(contents):
6 """Print the application tabs' text and URL."""
7 location_apps = find_tag_by_id(contents, 'lp-apps')
8- for tab in location_apps.findAll('span'):
9- tab_text = extract_text(tab)
10- if tab['class'].find('active') != -1:
11- tab_text += ' (selected)'
12- if tab.a:
13- link = tab.a['href']
14- else:
15- link = 'not linked'
16- print "* %s - %s" % (tab_text, link)
17+ if location_apps is None:
18+ location_apps = first_tag_by_class(contents, 'location-portlet')
19+ if location_apps is not None:
20+ location_apps = location_apps.ul.findAll('li')
21+ else:
22+ location_apps = location_apps.findAll('span')
23+ if location_apps is None:
24+ print "(Application tabs omitted)"
25+ elif len(location_apps) == 0:
26+ print "(No application tabs)"
27+ else:
28+ for tab in location_apps:
29+ tab_text = extract_text(tab)
30+ if tab['class'].find('active') != -1:
31+ tab_text += ' (selected)'
32+ if tab.a:
33+ link = tab.a['href']
34+ else:
35+ link = 'not linked'
36+ print "* %s - %s" % (tab_text, link)
37
38
39 def print_tag_with_id(contents, id):
40
41=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-activity.txt'
42--- lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-13 12:59:41 +0000
43+++ lib/lp/bugs/stories/bugs/xx-bug-activity.txt 2009-08-14 09:20:08 +0000
44@@ -7,19 +7,20 @@
45 ... 'mozilla-firefox/+bug/3/+activity')
46 >>> main_content = find_main_content(anon_browser.contents)
47
48-The page contains a link back to the bug page:
49-
50- >>> document = find_tag_by_id(anon_browser.contents, 'document')
51- >>> bug_link = document.find(
52- ... 'a', href=lambda href: href.endswith('/+bug/3'))
53- >>> print '%s\n--> %s' % (extract_text(bug_link), bug_link['href'])
54- Bug #3
55- --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+bug/3
56-
57-The title repeats the bug number for clarity.
58-
59- >>> print extract_text(main_content.h1)
60- Activity log for bug #3 - Bug Title Test
61+
62+The page contains a link back to the bug page in the breadcrumbs and
63+the main heading repeats the bug number for clarity:
64+
65+ >>> print_location(anon_browser.contents)
66+ Hierarchy: Launchpad > Debian > ?mozilla-firefox? package > Bug #3
67+ Tabs:
68+ * Overview - http://launchpad.dev/debian/+source/mozilla-firefox
69+ * Code - http://code.launchpad.dev/debian/+source/mozilla-firefox
70+ * Bugs (selected) - http://bugs.launchpad.dev/debian/+source/mozilla-firefox
71+ * Blueprints - not linked
72+ * Translations - not linked
73+ * Answers - http://answers.launchpad.dev/debian/+source/mozilla-firefox
74+ Main heading: Activity log for bug #3: Bug Title Test
75
76 The activity log itself is presented as a table.
77
78
79=== modified file 'lib/lp/bugs/templates/bug-activity.pt'
80--- lib/lp/bugs/templates/bug-activity.pt 2009-08-13 14:06:31 +0000
81+++ lib/lp/bugs/templates/bug-activity.pt 2009-08-13 14:25:35 +0000
82@@ -7,7 +7,7 @@
83
84 <div metal:fill-slot="heading">
85 <h1>
86- Activity log for bug #<span tal:replace="context/bug/id" /> -
87+ Activity log for bug #<span tal:replace="context/bug/id" />:
88 <span tal:replace="context/bug/title" />
89 </h1>
90 </div>
Revision history for this message
Gavin Panella (allenap) wrote :

Several tests broke, and one of them required quite a lot of work to
fix. Basically, breadcrumbs were still being generated when viewing a
bug that the user did not have permission to view. I've added a test to
test_breadcrumbs and changed the adapter to cope with this scenario.

I've attached an incremental diff.

Thanks in advance.

1=== modified file 'lib/lp/bugs/browser/bugtask.py'
2--- lib/lp/bugs/browser/bugtask.py 2009-08-13 14:07:18 +0000
3+++ lib/lp/bugs/browser/bugtask.py 2009-08-14 16:30:27 +0000
4@@ -62,6 +62,7 @@
5 from zope.schema.interfaces import IContextSourceBinder, IList
6 from zope.schema.vocabulary import (
7 getVocabularyRegistry, SimpleVocabulary, SimpleTerm)
8+from zope.security.interfaces import Unauthorized
9 from zope.security.proxy import (
10 isinstance as zope_isinstance, removeSecurityProxy)
11 from zope.traversing.interfaces import IPathAdapter
12@@ -3495,6 +3496,18 @@
13
14 class BugTaskBreadcrumbBuilder(BreadcrumbBuilder):
15 """Builds a breadcrumb for an `IBugTask`."""
16+
17 @property
18 def text(self):
19 return self.context.bug.displayname
20+
21+ def make_breadcrumb(self):
22+ """Return a breadcrumb for this `BugTask`.
23+
24+ If the user does not have permission to view the bug for
25+ whatever reason, don't return a breadcrumb.
26+ """
27+ try:
28+ return super(BugTaskBreadcrumbBuilder, self).make_breadcrumb()
29+ except Unauthorized:
30+ return None
31
32=== modified file 'lib/lp/bugs/stories/bug-release-management/nomination-navigation.txt'
33--- lib/lp/bugs/stories/bug-release-management/nomination-navigation.txt 2009-07-01 13:16:44 +0000
34+++ lib/lp/bugs/stories/bug-release-management/nomination-navigation.txt 2009-08-14 14:44:07 +0000
35@@ -11,7 +11,7 @@
36 ... 'http://bugs.launchpad.dev/ubuntu/+source/mozilla-firefox/+bug/1'
37 ... '/nominations/2/+editstatus')
38 >>> print_location(admin_browser.contents)
39- Hierarchy: Launchpad > Ubuntu > ?mozilla-firefox? package
40+ Hierarchy: Launchpad > Ubuntu > ?mozilla-firefox? package > Bug #1
41 Tabs:
42 * Overview - http://launchpad.dev/ubuntu/+source/mozilla-firefox
43 * Code - http://code.launchpad.dev/ubuntu/+source/mozilla-firefox
44
45=== modified file 'lib/lp/bugs/stories/bugs/xx-bug-index.txt'
46--- lib/lp/bugs/stories/bugs/xx-bug-index.txt 2009-07-31 08:12:47 +0000
47+++ lib/lp/bugs/stories/bugs/xx-bug-index.txt 2009-08-14 15:11:58 +0000
48@@ -10,9 +10,25 @@
49 >>> anon_browser.title
50 '...Blackhole Trash folder...'
51
52-The bug id in the upper left corner of the page is linked to the bug itself.
53-
54- >>> anon_browser.getLink('Bug #2').click()
55+The breadcrumbs and other navigation include a link to the bug itself.
56+
57+ >>> print_location(anon_browser.contents)
58+ Hierarchy: Launchpad > Debian > ?mozilla-firefox? package > Bug #2 (blackhole)
59+ Tabs:
60+ * Overview - http://launchpad.dev/debian/+source/mozilla-firefox
61+ * Code - http://code.launchpad.dev/debian/+source/mozilla-firefox
62+ * Bugs (selected) - http://bugs.launchpad.dev/debian/+source/mozilla-firefox
63+ * Blueprints - not linked
64+ * Translations - not linked
65+ * Answers - http://answers.launchpad.dev/debian/+source/mozilla-firefox
66+ Main heading: Blackhole Trash folder
67+
68+The bug id in the upper left corner of the main page content is also
69+linked to the bug itself.
70+
71+ >>> bug_link = first_tag_by_class(
72+ ... anon_browser.contents, 'object identifier').a
73+ >>> anon_browser.open(bug_link.get('href'))
74 >>> print anon_browser.title
75 Bug #2 in Tomcat:...Blackhole Trash folder...
76
77
78=== modified file 'lib/lp/bugs/tests/test_breadcrumbs.py'
79--- lib/lp/bugs/tests/test_breadcrumbs.py 2009-08-13 13:57:47 +0000
80+++ lib/lp/bugs/tests/test_breadcrumbs.py 2009-08-14 16:32:02 +0000
81@@ -10,7 +10,8 @@
82 from canonical.lazr.testing.menus import make_fake_request
83 from canonical.launchpad.webapp.publisher import RootObject
84 from canonical.testing import DatabaseFunctionalLayer
85-from lp.testing import TestCaseWithFactory
86+from lp.testing import (
87+ ANONYMOUS, TestCaseWithFactory, login)
88
89
90 class TestBugTaskBreadcrumbBuilder(TestCaseWithFactory):
91@@ -18,7 +19,7 @@
92 layer = DatabaseFunctionalLayer
93
94 def setUp(self):
95- TestCaseWithFactory.setUp(self)
96+ super(TestBugTaskBreadcrumbBuilder, self).setUp()
97 self.product = self.factory.makeProduct(
98 name='crumb-tester', displayname="Crumb Tester")
99 self.bug = self.factory.makeBug(product=self.product)
100@@ -66,6 +67,23 @@
101 ["Crumb Tester", "Bug #%d" % self.bug.id],
102 [crumb.text for crumb in hierarchy.items()])
103
104+ def test_bugtask_private_bug(self):
105+ # A breadcrumb is not generated for a bug that the user does
106+ # not have permission to view.
107+ login('foo.bar@canonical.com')
108+ self.bug.setPrivate(True, self.bug.owner)
109+ login(ANONYMOUS)
110+ request = make_fake_request(
111+ 'http://bugs.launchpad.dev/%s/+bug/%d/+activity' % (
112+ self.product.name, self.bug.id),
113+ [self.root, self.product, self.bug.default_bugtask])
114+ hierarchy = getMultiAdapter((self.root, request), name='+hierarchy')
115+ self.assertEquals(
116+ ['http://bugs.launchpad.dev/crumb-tester'],
117+ [crumb.url for crumb in hierarchy.items()])
118+ self.assertEquals(
119+ ["Crumb Tester"], [crumb.text for crumb in hierarchy.items()])
120+
121
122 def test_suite():
123 return unittest.TestLoader().loadTestsFromName(__name__)
Revision history for this message
Celso Providelo (cprov) wrote :

> Several tests broke, and one of them required quite a lot of work to
> fix. Basically, breadcrumbs were still being generated when viewing a
> bug that the user did not have permission to view. I've added a test to
> test_breadcrumbs and changed the adapter to cope with this scenario.
>
> I've attached an incremental diff.
>
> Thanks in advance.

Gavin.

I'm happy with the way you fixed breadcrumbs for private bugs, thanks for catching this problem before landing.

Regarding the previous diff, thanks for fixing print_location() and you are right that having 'UTC' repeated on each row would be bad ... the bug report is enough to sort this problem in the future.

All good!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/templates/bug-activity.pt'
2--- lib/lp/bugs/templates/bug-activity.pt 2009-07-17 17:59:07 +0000
3+++ lib/lp/bugs/templates/bug-activity.pt 2009-08-12 13:02:26 +0000
4@@ -1,20 +1,19 @@
5-<html
6- xmlns="http://www.w3.org/1999/xhtml"
7- xmlns:tal="http://xml.zope.org/namespaces/tal"
8- xmlns:metal="http://xml.zope.org/namespaces/metal"
9- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
10- xml:lang="en"
11- lang="en"
12- dir="ltr"
13- metal:use-macro="view/macro:page/onecolumn"
14->
15- <body>
16-<div metal:fill-slot="main">
17+<bug-activity
18+ xmlns="http://www.w3.org/1999/xhtml"
19+ xmlns:tal="http://xml.zope.org/namespaces/tal"
20+ xmlns:metal="http://xml.zope.org/namespaces/metal"
21+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
22+ metal:use-macro="view/macro:page/main_only">
23
24- <div id="maincontent">
25- <p tal:content="structure view/current_bugtask/fmt:link" />
26+ <div metal:fill-slot="heading">
27 <h1>Activity log for bug #<span tal:replace="context/bug/id" /></h1>
28+ </div>
29
30+ <div metal:fill-slot="main">
31+ <div class="top-portlet">
32+ <p tal:content="structure context/fmt:link" />
33+ </div>
34+ <div class="yui-g">
35 <table class="listing">
36 <thead>
37 <tr>
38@@ -39,9 +38,6 @@
39 </tr>
40 </tbody>
41 </table>
42+ </div>
43 </div>
44-
45-</div>
46-
47-</body>
48-</html>
49+</bug-activity>