Merge lp://staging/~intellectronica/launchpad/bugs-index-redesign into lp://staging/launchpad

Proposed by Eleanor Berger
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp://staging/~intellectronica/launchpad/bugs-index-redesign
Merge into: lp://staging/launchpad
Diff against target: None lines
To merge this branch: bzr merge lp://staging/~intellectronica/launchpad/bugs-index-redesign
Reviewer Review Type Date Requested Status
Graham Binns (community) code Approve
Canonical Launchpad Engineering code Pending
Review via email: mp+12084@code.staging.launchpad.net
To post a comment you must log in.
Revision history for this message
Eleanor Berger (intellectronica) wrote :

This branch converts the bugtarget bugs index page to 3.0 style UI and changes a few things, as has been discussed on the ML.

The diff is quite long at 902 lines. Sorry about that. A lot of that is removal of unused code and really simple pagetest changes, so it isn't really as scary as it might appear.

Revision history for this message
Graham Binns (gmb) wrote :

This branch is excellent; I've no complaints. r=me; awesome stuff!

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/icing/style.css'
--- lib/canonical/launchpad/icing/style.css 2009-09-16 10:03:52 +0000
+++ lib/canonical/launchpad/icing/style.css 2009-09-18 14:43:52 +0000
@@ -2228,6 +2228,30 @@
2228.questionstatusEXPIRED {color: #666;} /* dark grey */2228.questionstatusEXPIRED {color: #666;} /* dark grey */
2229.questionstatusINVALID {color: #c00;} /* red */2229.questionstatusINVALID {color: #c00;} /* red */
22302230
2231.search-box {
2232 text-align: left;
2233 float: left;
2234 border:1px solid #d6d6d6;
2235 margin: 0.5em 0 0.5em 0;
2236 color: #717171;
2237 padding: 8px;
2238 -moz-border-radius: 5px;
2239 -o-border-radius: 5px;
2240 -webkit-border-radius: 5px;
2241}
2242
2243.search-box form.primary.search {
2244 margin: 0.5em;
2245}
2246
2247.bug-links td.bugs-count {
2248 text-align: right;
2249 padding-right: 0.5em;
2250}
2251
2252.bug-links td.bugs-link {
2253 text-align: left;
2254}
22312255
2232/* --- Other --- */2256/* --- Other --- */
22332257
22342258
=== modified file 'lib/lp/bugs/browser/bugtarget.py'
--- lib/lp/bugs/browser/bugtarget.py 2009-09-10 12:47:31 +0000
+++ lib/lp/bugs/browser/bugtarget.py 2009-09-18 17:43:21 +0000
@@ -1200,6 +1200,13 @@
1200 BugTaskStatus.UNKNOWN: 'purple',1200 BugTaskStatus.UNKNOWN: 'purple',
1201 }1201 }
12021202
1203 override_title_breadcrumbs = True
1204
1205 @property
1206 def label(self):
1207 """The display label for the view."""
1208 return 'Bugs in %s' % self.context.title
1209
1203 def initialize(self):1210 def initialize(self):
1204 BugTaskSearchListingView.initialize(self)1211 BugTaskSearchListingView.initialize(self)
1205 bug_statuses_to_show = list(UNRESOLVED_BUGTASK_STATUSES)1212 bug_statuses_to_show = list(UNRESOLVED_BUGTASK_STATUSES)
@@ -1211,39 +1218,6 @@
1211 BugCountDataItem(status.title, count, self.status_color[status])1218 BugCountDataItem(status.title, count, self.status_color[status])
1212 for status, count in bug_counts]1219 for status, count in bug_counts]
12131220
1214 def getChartJavascript(self):
1215 """Return a snippet of Javascript that draws a pie chart."""
1216 # XXX: Bjorn Tillenius 2007-02-13:
1217 # This snippet doesn't work in IE, since (I think) there
1218 # has to be a delay between creating the canvas element and
1219 # using it to draw the chart.
1220 js_template = """
1221 function drawGraph() {
1222 var options = {
1223 "drawBackground": false,
1224 "colorScheme": [%(color_list)s],
1225 "xTicks": [%(label_list)s]};
1226 var data = [%(data_list)s];
1227 var plotter = PlotKit.EasyPlot(
1228 "pie", options, $("bugs-chart"), [data]);
1229 }
1230 registerLaunchpadFunction(drawGraph);
1231 """
1232 # The color list should inlude only colors for slices that will
1233 # be drawn in the pie chart, so colors that don't have any bugs
1234 # associated with them.
1235 color_list = ', '.join(
1236 data_item.color for data_item in self.bug_count_items
1237 if data_item.count > 0)
1238 label_list = ', '.join([
1239 '{v:%i, label:"%s"}' % (index, data_item.label)
1240 for index, data_item in enumerate(self.bug_count_items)])
1241 data_list = ', '.join([
1242 '[%i, %i]' % (index, data_item.count)
1243 for index, data_item in enumerate(self.bug_count_items)])
1244 return js_template % dict(
1245 color_list=color_list, label_list=label_list, data_list=data_list)
1246
1247 @property1221 @property
1248 def uses_launchpad_bugtracker(self):1222 def uses_launchpad_bugtracker(self):
1249 """Whether this distro or product tracks bugs in launchpad.1223 """Whether this distro or product tracks bugs in launchpad.
@@ -1317,6 +1291,24 @@
1317 return tags[:10]1291 return tags[:10]
13181292
1319 @property1293 @property
1294 def tags_cloud_data(self):
1295 """The data for rendering a tags cloud"""
1296 official_tags = set(self.context.official_bug_tags)
1297 tags = self.getUsedBugTagsWithURLs()
1298 tags.sort(key=itemgetter('tag'))
1299 max_count = float(max([1] + [tag['count'] for tag in tags]))
1300 for tag in tags:
1301 if tag['tag'] in official_tags:
1302 if tag['count'] == 0:
1303 tag['factor'] = 1.5
1304 else:
1305 tag['factor'] = 1.5 + (tag['count'] / max_count)
1306 else:
1307 tag['factor'] = 1 + (tag['count'] / max_count)
1308 print tags
1309 return tags
1310
1311 @property
1320 def show_manage_tags_link(self):1312 def show_manage_tags_link(self):
1321 """Should a link to a "manage official tags" page be shown?"""1313 """Should a link to a "manage official tags" page be shown?"""
1322 return (IOfficialBugTagTargetRestricted.providedBy(self.context) and1314 return (IOfficialBugTagTargetRestricted.providedBy(self.context) and
13231315
=== modified file 'lib/lp/bugs/browser/bugtask.py'
--- lib/lp/bugs/browser/bugtask.py 2009-09-11 20:38:21 +0000
+++ lib/lp/bugs/browser/bugtask.py 2009-09-18 16:08:07 +0000
@@ -2683,6 +2683,54 @@
2683 url = "%s/+expirable-bugs" % canonical_url(self.context)2683 url = "%s/+expirable-bugs" % canonical_url(self.context)
2684 return dict(count=count, url=url, label=label)2684 return dict(count=count, url=url, label=label)
26852685
2686 @property
2687 def new_bugs_info(self):
2688 """Return a dict with new bugs info."""
2689 return dict(
2690 count=self.context.new_bugtasks.count,
2691 url=get_buglisting_search_filter_url(
2692 status=BugTaskStatus.NEW.title))
2693
2694 @property
2695 def open_bugs_info(self):
2696 """Return a dict with open bugs info."""
2697 return dict(
2698 count=self.context.open_bugtasks.count,
2699 url=canonical_url(
2700 self.context, rootsite='bugs', view_name='+bugs'))
2701
2702 @property
2703 def critical_bugs_info(self):
2704 """Return a dict with critical bugs info."""
2705 return dict(
2706 count=self.context.critical_bugtasks.count,
2707 url=get_buglisting_search_filter_url(
2708 status=[status.title for status
2709 in UNRESOLVED_BUGTASK_STATUSES],
2710 importance=BugTaskImportance.CRITICAL.title))
2711
2712 @property
2713 def my_bugs_info(self):
2714 """Return a dict with info on bugs assigned to the user, or None."""
2715 if self.user:
2716 return dict(
2717 count=self.context.searchTasks(
2718 BugTaskSearchParams(
2719 user=self.user, assignee=self.user,
2720 status=any(*UNRESOLVED_BUGTASK_STATUSES),
2721 omit_dupes=True)).count(),
2722 url=get_buglisting_search_filter_url(assignee=self.user.name))
2723 else:
2724 return None
2725
2726 @property
2727 def hot_bugtasks(self):
2728 """Return the 10 most recently updated bugtasks for this target."""
2729 params = BugTaskSearchParams(
2730 orderby="-date_last_updated", omit_dupes=True, user=self.user)
2731 return list(self.context.searchTasks(params)[:10])
2732
2733
26862734
2687class BugNominationsView(BugTaskSearchListingView):2735class BugNominationsView(BugTaskSearchListingView):
2688 """View for accepting/declining bug nominations."""2736 """View for accepting/declining bug nominations."""
26892737
=== modified file 'lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt'
--- lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt 2009-09-10 20:12:12 +0000
+++ lib/lp/bugs/stories/bugs/xx-distribution-bugs-page.txt 2009-09-18 16:08:07 +0000
@@ -11,7 +11,7 @@
1111
12The page has a link to see all open bugs.12The page has a link to see all open bugs.
1313
14 >>> anon_browser.getLink('List all open bugs').click()14 >>> anon_browser.getLink('Open bugs').click()
15 >>> anon_browser.url15 >>> anon_browser.url
16 'http://bugs.launchpad.dev/ubuntu/+bugs'16 'http://bugs.launchpad.dev/ubuntu/+bugs'
17 >>> find_tag_by_id(anon_browser.contents, 'buglisting') is not None17 >>> find_tag_by_id(anon_browser.contents, 'buglisting') is not None
@@ -31,9 +31,7 @@
31fixed in some other context.31fixed in some other context.
3232
33 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')33 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')
34 >>> fixed_elsewhere_link = anon_browser.getLink('bugs fixed elsewhere')34 >>> fixed_elsewhere_link = anon_browser.getLink('Bugs fixed elsewhere')
35 >>> fixed_elsewhere_link.text
36 '0 bugs fixed elsewhere'
3735
38The link takes you to the list of the bugs fixed elsewhere.36The link takes you to the list of the bugs fixed elsewhere.
3937
@@ -52,9 +50,7 @@
52It also displays the number of open bugs associated with a CVE.50It also displays the number of open bugs associated with a CVE.
5351
54 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')52 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')
55 >>> cve_bugs_link = anon_browser.getLink('open CVE bugs')53 >>> cve_bugs_link = anon_browser.getLink('Open CVE bugs')
56 >>> cve_bugs_link.text
57 '2 open CVE bugs'
5854
59The link takes you to the list of bugs with CVEs linked to them.55The link takes you to the list of bugs with CVEs linked to them.
6056
@@ -78,9 +74,7 @@
7874
79 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')75 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')
80 >>> expirable_bugs_link = anon_browser.getLink(76 >>> expirable_bugs_link = anon_browser.getLink(
81 ... 'incomplete bugs can expire')77 ... 'Incomplete bugs')
82 >>> expirable_bugs_link.text
83 '0 incomplete bugs can expire'
8478
85The link goes to the expirable bugs page, where the anonymous user can79The link goes to the expirable bugs page, where the anonymous user can
86see which bugs will expire if they are not confirmed.80see which bugs will expire if they are not confirmed.
@@ -93,27 +87,8 @@
93see any link reporting that bugs can expire.87see any link reporting that bugs can expire.
9488
95 >>> anon_browser.open('http://bugs.launchpad.dev/debian')89 >>> anon_browser.open('http://bugs.launchpad.dev/debian')
96 >>> expirable_bugs_link = anon_browser.getLink(90 >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
97 ... 'incomplete bugs can expire')
98 Traceback (most recent call last):91 Traceback (most recent call last):
99 ...92 ...
100 LinkNotFoundError93 LinkNotFoundError
10194
102
103== Open Bugs Statistics ==
104
105There's also some statistics about the open bugs for the distribution.
106This is displayed as a chart, which is generated using Javascript, but
107for those browsers not supporting Javascript, the statistics are
108displayed as normal text:
109
110 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu')
111 >>> stats_div = find_tag_by_id(anon_browser.contents, 'bugs-chart')
112 >>> for li_tag in stats_div.noscript.ul('li'):
113 ... print li_tag.renderContents()
114 3 New bugs
115 0 Incomplete bugs
116 1 Confirmed bugs
117 0 Triaged bugs
118 0 In Progress bugs
119 0 Fix Committed bugs
12095
=== modified file 'lib/lp/bugs/stories/bugs/xx-distrorelease-bugs-page.txt'
--- lib/lp/bugs/stories/bugs/xx-distrorelease-bugs-page.txt 2009-09-10 20:12:12 +0000
+++ lib/lp/bugs/stories/bugs/xx-distrorelease-bugs-page.txt 2009-09-18 17:43:21 +0000
@@ -13,7 +13,7 @@
1313
14The page has a link to see all open bugs.14The page has a link to see all open bugs.
1515
16 >>> anon_browser.getLink('List all open bugs').click()16 >>> anon_browser.getLink('Open bugs').click()
17 >>> anon_browser.url17 >>> anon_browser.url
18 'http://bugs.launchpad.dev/ubuntu/warty/+bugs'18 'http://bugs.launchpad.dev/ubuntu/warty/+bugs'
19 >>> find_tag_by_id(anon_browser.contents, 'buglisting') is not None19 >>> find_tag_by_id(anon_browser.contents, 'buglisting') is not None
@@ -33,9 +33,7 @@
33other context.33other context.
3434
35 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/warty')35 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/warty')
36 >>> fixed_elsewhere_link = anon_browser.getLink('bugs fixed elsewhere')36 >>> fixed_elsewhere_link = anon_browser.getLink('Bugs fixed elsewhere')
37 >>> fixed_elsewhere_link.text
38 '0 bugs fixed elsewhere'
3937
40The link takes you to the list of the bugs fixed elsewhere.38The link takes you to the list of the bugs fixed elsewhere.
4139
@@ -55,10 +53,7 @@
55can expire when the project has enabled bug expiration.53can expire when the project has enabled bug expiration.
5654
57 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/warty')55 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/warty')
58 >>> expirable_bugs_link = anon_browser.getLink(56 >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
59 ... 'incomplete bugs can expire')
60 >>> expirable_bugs_link.text
61 '0 incomplete bugs can expire'
6257
63The link goes to the expirable bugs page, where the anonymous user can58The link goes to the expirable bugs page, where the anonymous user can
64see which bugs will expire if they are not confirmed.59see which bugs will expire if they are not confirmed.
@@ -67,27 +62,3 @@
67 >>> print anon_browser.title62 >>> print anon_browser.title
68 +expirable-bugs : Bugs in warty : 4.10 : Ubuntu63 +expirable-bugs : Bugs in warty : 4.10 : Ubuntu
6964
70
71== Bugs Statistics ==
72
73There's also some statistics about the open and fixed bugs. This is
74displayed as a chart, which is generated using Javascript, but for those
75browsers not supporting Javascript, the statistics are displayed as
76normal text:
77
78As opposed to the normal distribution Bugs page, Fix Released bugs are
79included here, since it's a good measurement of seeing whether the
80release is on track.
81
82 >>> anon_browser.open('http://bugs.launchpad.dev/ubuntu/warty')
83 >>> stats_div = find_tag_by_id(anon_browser.contents, 'bugs-chart')
84 >>> for li_tag in stats_div.noscript.ul('li'):
85 ... print li_tag.renderContents()
86 1 New bugs
87 0 Incomplete bugs
88 0 Confirmed bugs
89 0 Triaged bugs
90 0 In Progress bugs
91 0 Fix Committed bugs
92 0 Fix Released bugs
93
9465
=== modified file 'lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt'
--- lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt 2009-09-10 20:12:12 +0000
+++ lib/lp/bugs/stories/bugs/xx-incomplete-bugs.txt 2009-09-18 17:43:21 +0000
@@ -144,10 +144,7 @@
144 >>> user_browser.title144 >>> user_browser.title
145 'Bugs in Jokosher Audio Editor'145 'Bugs in Jokosher Audio Editor'
146146
147 >>> expirable_bugs_link = user_browser.getLink(147 >>> expirable_bugs_link = user_browser.getLink('Incomplete bugs')
148 ... 'incomplete bugs can expire')
149 >>> expirable_bugs_link.text
150 '2 incomplete bugs can expire'
151148
152The link is to the expirable bugs page. No Privileges Person can see149The link is to the expirable bugs page. No Privileges Person can see
153the bug he set to Incomplete previously.150the bug he set to Incomplete previously.
@@ -190,7 +187,7 @@
190 >>> user_browser.getControl(name='field.comment').value = "bump"187 >>> user_browser.getControl(name='field.comment').value = "bump"
191 >>> user_browser.getControl('Post Comment').click()188 >>> user_browser.getControl('Post Comment').click()
192 >>> user_browser.getLink('Bugs').click()189 >>> user_browser.getLink('Bugs').click()
193 >>> user_browser.getLink('incomplete bugs can expire').click()190 >>> user_browser.getLink('Incomplete bugs').click()
194 >>> contents = find_main_content(user_browser.contents)191 >>> contents = find_main_content(user_browser.contents)
195 >>> buglisting = contents.find('table', id='buglisting')192 >>> buglisting = contents.find('table', id='buglisting')
196 >>> print extract_text(buglisting.thead)193 >>> print extract_text(buglisting.thead)
@@ -212,11 +209,7 @@
212 None209 None
213210
214 >>> user_browser.getLink('Bugs').click()211 >>> user_browser.getLink('Bugs').click()
215 >>> expirable_bugs_link = user_browser.getLink(212 >>> expirable_bugs_link = user_browser.getLink('Incomplete bugs')
216 ... 'incomplete bug can expire')
217 >>> expirable_bugs_link.text
218 '1 incomplete bug can expire'
219
220 >>> expirable_bugs_link.click()213 >>> expirable_bugs_link.click()
221 >>> contents = find_main_content(user_browser.contents)214 >>> contents = find_main_content(user_browser.contents)
222 >>> buglisting = contents.find('table', id='buglisting')215 >>> buglisting = contents.find('table', id='buglisting')
223216
=== modified file 'lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt'
--- lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt 2009-09-15 09:49:49 +0000
+++ lib/lp/bugs/stories/bugs/xx-product-bugs-page.txt 2009-09-18 17:43:21 +0000
@@ -16,7 +16,7 @@
1616
17The page has a link to see all open bugs.17The page has a link to see all open bugs.
1818
19 >>> anon_browser.getLink('List all open bugs').click()19 >>> anon_browser.getLink('Open bugs').click()
20 >>> anon_browser.url20 >>> anon_browser.url
21 'http://bugs.launchpad.dev/firefox/+bugs'21 'http://bugs.launchpad.dev/firefox/+bugs'
22 >>> find_tag_by_id(anon_browser.contents, 'buglisting') is not None22 >>> find_tag_by_id(anon_browser.contents, 'buglisting') is not None
@@ -34,14 +34,10 @@
34It also displays the number of open bugs associated with a CVE.34It also displays the number of open bugs associated with a CVE.
3535
36 >>> anon_browser.open('http://bugs.launchpad.dev/evolution')36 >>> anon_browser.open('http://bugs.launchpad.dev/evolution')
37 >>> cve_bugs_link = anon_browser.getLink('open CVE bugs')37 >>> cve_bugs_link = anon_browser.getLink('Open CVE bugs')
38 >>> cve_bugs_link.text
39 '0 open CVE bugs'
4038
41 >>> anon_browser.open('http://bugs.launchpad.dev/firefox')39 >>> anon_browser.open('http://bugs.launchpad.dev/firefox')
42 >>> cve_bugs_link = anon_browser.getLink('open CVE bug')40 >>> cve_bugs_link = anon_browser.getLink('Open CVE bugs')
43 >>> cve_bugs_link.text
44 '1 open CVE bug'
4541
46The link takes you to the list of bugs with CVEs linked to them.42The link takes you to the list of bugs with CVEs linked to them.
4743
@@ -78,9 +74,7 @@
78Mozilla Firefox that are fixed in some other context:74Mozilla Firefox that are fixed in some other context:
7975
80 >>> anon_browser.goBack(1)76 >>> anon_browser.goBack(1)
81 >>> fixed_elsewhere_link = anon_browser.getLink('bugs fixed elsewhere')77 >>> fixed_elsewhere_link = anon_browser.getLink('Bugs fixed elsewhere')
82 >>> fixed_elsewhere_link.text
83 '0 bugs fixed elsewhere'
8478
85The link takes you to the list of the bugs fixed elsewhere:79The link takes you to the list of the bugs fixed elsewhere:
8680
@@ -98,9 +92,7 @@
98are fixed in some other context:92are fixed in some other context:
9993
100 >>> anon_browser.open('http://bugs.launchpad.dev/thunderbird')94 >>> anon_browser.open('http://bugs.launchpad.dev/thunderbird')
101 >>> fixed_elsewhere_link = anon_browser.getLink('bugs fixed elsewhere')95 >>> fixed_elsewhere_link = anon_browser.getLink('Bugs fixed elsewhere')
102 >>> fixed_elsewhere_link.text
103 '0 bugs fixed elsewhere'
10496
105Again, the link takes you to the list of the bugs fixed elsewhere.:97Again, the link takes you to the list of the bugs fixed elsewhere.:
10698
@@ -121,10 +113,7 @@
121is such a project.113is such a project.
122114
123 >>> anon_browser.open('http://bugs.launchpad.dev/jokosher')115 >>> anon_browser.open('http://bugs.launchpad.dev/jokosher')
124 >>> expirable_bugs_link = anon_browser.getLink(116 >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
125 ... 'incomplete bugs can expire')
126 >>> expirable_bugs_link.text
127 '0 incomplete bugs can expire'
128117
129The link goes to the expirable bugs page, where the anonymous user can118The link goes to the expirable bugs page, where the anonymous user can
130see which bugs will expire if they are not confirmed.119see which bugs will expire if they are not confirmed.
@@ -137,11 +126,7 @@
137series has the link because Jokosher has enabled bug expiration.126series has the link because Jokosher has enabled bug expiration.
138127
139 >>> anon_browser.open('http://bugs.launchpad.dev/jokosher/trunk')128 >>> anon_browser.open('http://bugs.launchpad.dev/jokosher/trunk')
140 >>> expirable_bugs_link = anon_browser.getLink(129 >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
141 ... 'incomplete bugs can expire')
142 >>> expirable_bugs_link.text
143 '0 incomplete bugs can expire'
144
145 >>> expirable_bugs_link.click()130 >>> expirable_bugs_link.click()
146 >>> print anon_browser.title131 >>> print anon_browser.title
147 +expirable-bugs : Bugs in trunk : Series trunk : Jokosher132 +expirable-bugs : Bugs in trunk : Series trunk : Jokosher
@@ -150,31 +135,12 @@
150cannot see any link reporting that bugs can expire.135cannot see any link reporting that bugs can expire.
151136
152 >>> anon_browser.open('http://bugs.launchpad.dev/thunderbird')137 >>> anon_browser.open('http://bugs.launchpad.dev/thunderbird')
153 >>> expirable_bugs_link = anon_browser.getLink(138 >>> expirable_bugs_link = anon_browser.getLink('Incomplete bugs')
154 ... 'incomplete bugs can expire')
155 Traceback (most recent call last):139 Traceback (most recent call last):
156 ...140 ...
157 LinkNotFoundError141 LinkNotFoundError
158142
159143
160== Open Bugs Statistics ==
161
162There's also some statistics about the open bugs. This is displayed as
163a chart, which is generated using Javascript, but for those browsers not
164supporting Javascript, the statistics are displayed as normal text:
165
166 >>> anon_browser.open('http://bugs.launchpad.dev/firefox')
167 >>> stats_div = find_tag_by_id(anon_browser.contents, 'bugs-chart')
168 >>> for li_tag in stats_div.noscript.ul('li'):
169 ... print li_tag.renderContents()
170 3 New bugs
171 0 Incomplete bugs
172 0 Confirmed bugs
173 0 Triaged bugs
174 0 In Progress bugs
175 0 Fix Committed bugs
176
177
178== Tags and Filters ==144== Tags and Filters ==
179145
180There's also portlets for easy searching by tags and filters. Its content is146There's also portlets for easy searching by tags and filters. Its content is
@@ -182,11 +148,9 @@
182148
183 >>> tags_portlet = find_tag_by_id(anon_browser.contents, 'portlet-tags')149 >>> tags_portlet = find_tag_by_id(anon_browser.contents, 'portlet-tags')
184 >>> anon_browser.getLink(id='tags-content-link').click()150 >>> anon_browser.getLink(id='tags-content-link').click()
185 >>> for tag_link in find_tags_by_class(151 >>> print extract_text(anon_browser.contents)
186 ... anon_browser.contents, 'section')[0]('a'):152 Tags
187 ... print tag_link.renderContents()153 doc layout-test
188 doc
189 layout-test
190154
191They are there to provide easy navigation for bugs with a certain155They are there to provide easy navigation for bugs with a certain
192tag...156tag...
193157
=== modified file 'lib/lp/bugs/templates/bugtarget-bugs.pt'
--- lib/lp/bugs/templates/bugtarget-bugs.pt 2009-07-18 00:05:49 +0000
+++ lib/lp/bugs/templates/bugtarget-bugs.pt 2009-09-18 17:43:21 +0000
@@ -6,7 +6,7 @@
6 xml:lang="en"6 xml:lang="en"
7 lang="en"7 lang="en"
8 dir="ltr"8 dir="ltr"
9 metal:use-macro="view/macro:page/default2.0"9 metal:use-macro="view/macro:page/main_side"
10 i18n:domain="malone"10 i18n:domain="malone"
11>11>
12 <metal:block fill-slot="head_epilogue">12 <metal:block fill-slot="head_epilogue">
@@ -14,18 +14,140 @@
14 <script type="text/javascript" src="/+icing/PlotKit_Packed.js"></script>14 <script type="text/javascript" src="/+icing/PlotKit_Packed.js"></script>
15 </metal:block>15 </metal:block>
16 <metal:portlets fill-slot="portlets">16 <metal:portlets fill-slot="portlets">
17 <tal:block content="structure context/@@+portlet-bugfilters" />
18 <tal:block content="structure context/@@+portlet-bugtags" />
19 <tal:releasecriticalbugs
20 tal:condition="view/shouldShowReleaseCriticalPortlet"
21 tal:content="structure context/@@+portlet-bugtasklist-seriesbugs" />
22 </metal:portlets>17 </metal:portlets>
23 <body>18 <body>
19 <tal:side metal:fill-slot="side">
20 <div id="involvement" class="portlet involvement">
21 <ul>
22 <li style="border: none">
23 <a href="+filebug" class="menu-link-filebug sprite bugs">
24 Report a bug
25 </a>
26 </li>
27 <li>
28 <a href="+filebug" class="menu-link-filebug sprite answers">
29 Ask a question
30 </a>
31 </li>
32 </ul>
33 </div>
34 <div class="portlet">
35 <table class="bug-links">
36 <tr tal:define="open_bugs_info view/open_bugs_info">
37 <td class="bugs-count" tal:content="open_bugs_info/count" />
38 <td class="bugs-link">
39 <a tal:attributes="href open_bugs_info/url">Open bugs</a>
40 </td>
41 </tr>
42 <tr tal:condition="view/user"
43 tal:define="my_bugs_info view/my_bugs_info">
44 <td class="bugs-count" tal:content="my_bugs_info/count" />
45 <td class="bugs-link">
46 <a tal:attributes="href my_bugs_info/url">Bugs assigned to me</a>
47 </td>
48 </tr>
49 <tr tal:define="critical_bugs_info view/critical_bugs_info">
50 <td class="bugs-count" tal:content="critical_bugs_info/count" />
51 <td class="bugs-link">
52 <a tal:attributes="href critical_bugs_info/url">Critical bugs</a>
53 </td>
54 </tr>
55 <tr tal:define="fixed_elsewhere view/bugs_fixed_elsewhere_info">
56 <td class="bugs-count" tal:content="fixed_elsewhere/count" />
57 <td class="bugs-link">
58 <a tal:attributes="href fixed_elsewhere/url">
59 Bugs fixed elsewhere
60 </a>
61 </td>
62 </tr>
63 <tr tal:define="new_bugs_info view/new_bugs_info">
64 <td class="bugs-count" tal:content="new_bugs_info/count" />
65 <td class="bugs-link">
66 <a tal:attributes="href new_bugs_info/url">New bugs</a>
67 </td>
68 </tr>
69 <tr tal:define="cve_bugs_info view/open_cve_bugs_info">
70 <td class="bugs-count" tal:content="cve_bugs_info/count" />
71 <td class="bugs-link">
72 <a tal:attributes="href cve_bugs_info/url">Open CVE bugs</a>
73 -
74 <a href="+cve">CVE reports</a>
75 </td>
76 </tr>
77 <tr tal:define="expirable_bugs_info view/expirable_bugs_info"
78 tal:condition="expirable_bugs_info">
79 <td class="bugs-count" tal:content="expirable_bugs_info/count" />
80 <td class="bugs-link">
81 <a tal:attributes="href expirable_bugs_info/url">
82 Incomplete bugs
83 </a>
84 (can expire)
85 </td>
86 </tr>
87 <tr tal:define="subscribe_link context/menu:bugs/subscribe">
88 <td class="bugs-count" style="padding-top: 1em">
89 <a tal:attributes="href subscribe_link/url">
90 <img tal:attributes="src subscribe_link/icon_url" />
91 </a>
92 </td>
93 <td class="bugs-link">
94 <a tal:attributes="href subscribe_link/url"
95 tal:content="subscribe_link/escapedtext" />
96 </td>
97 </tr>
98 </table>
99 </div>
100 <div tal:replace="structure context/@@+portlet-bugtags" />
101 <tal:releasecriticalbugs
102 tal:condition="view/shouldShowReleaseCriticalPortlet"
103 tal:content="structure context/@@+portlet-bugtasklist-seriesbugs" />
104 </tal:side>
24 <div metal:fill-slot="main" class="tab-bugs"105 <div metal:fill-slot="main" class="tab-bugs"
25 tal:define="search_url string:+bugs;106 tal:define="search_url string:+bugs;
26 advanced_search_url string:+bugs?advanced=1">107 advanced_search_url string:+bugs?advanced=1">
27 <h1>Bugs in <tal:context replace="context/title">Ubuntu</tal:context></h1>108
28 <div style="text-align: center; clear: both;">109 <div class="portlet" style="float: right; border: none">
110 <ul>
111 <li>
112 <strong>Bug tracker:</strong>
113 <tal:bugtracker replace="structure view/bugtracker" />
114 </li>
115 <li tal:define="bug_supervisor context/bug_supervisor">
116 Bug supervisor:
117 <tal:none condition="not:bug_supervisor">None set</tal:none>
118 <a tal:condition="bug_supervisor"
119 tal:replace="structure bug_supervisor/fmt:link">Bob Johnson</a>
120 <tal:edit-bug-supervisor
121 condition="context/menu:bugs/bugsupervisor|nothing">
122 <a tal:define="link context/menu:bugs/bugsupervisor"
123 tal:condition="link/enabled"
124 tal:attributes="href link/url; title link/text">
125 <img tal:attributes="alt link/text" src="/@@/edit" />
126 </a>
127 </tal:edit-bug-supervisor>
128 </li>
129 <li tal:define="securitycontact context/security_contact">
130 Security contact:
131 <tal:none condition="not:securitycontact">None set</tal:none>
132 <a tal:condition="securitycontact"
133 tal:replace="structure securitycontact/fmt:link">
134 Billy Anderson
135 </a>
136 <tal:edit-securitycontact
137 condition="context/menu:bugs/securitycontact|nothing">
138 <a tal:define="link context/menu:bugs/securitycontact"
139 tal:condition="link/enabled"
140 tal:attributes="href link/url; title link/text">
141 <img tal:attributes="alt link/text" src="/@@/edit" />
142 </a>
143 </tal:edit-securitycontact>
144 </li>
145 <li>
146 </li>
147 </ul>
148 </div>
149
150 <div class="search-box">
29 <metal:search151 <metal:search
30 use-macro="context/@@+bugtarget-macros-search/simple-search-form"152 use-macro="context/@@+bugtarget-macros-search/simple-search-form"
31 />153 />
@@ -34,165 +156,39 @@
34 $('field.searchtext').focus();156 $('field.searchtext').focus();
35 --></script>157 --></script>
36158
37 <div class="columns">159 <h2 style="margin-top: 1em">Hot bugs</h2>
38 <script type="text/javascript"160
39 tal:content="structure view/getChartJavascript">161 <table class="listing" id="hot-bugs">
40 </script>162 <thead>
41 <div class="two column left">163 <tr>
42 <div id="bugs-chart" height="200" width="200">164 <th colspan="3">Summary</th>
43 <noscript>165 <th>Status</th>
44 <ul>166 <th>Importance</th>
45 <li tal:repeat="bug_count view/bug_count_items"167 <th>Last changed</th>
46 tal:content="string:${bug_count/count} ${bug_count/label} bugs">168 </tr>
47 12 Unconfirmed bugs169 </thead>
48 </li>170 <tbody>
49 </ul>171 <tr tal:repeat="bugtask view/hot_bugtasks">
50 </noscript>172 <td class="icon left">
51 </div>173 <img alt="" src="/@@/bug" />
52 </div>174 </td>
53 <div class="two column right">175 <td style="text-align: right">
54 <h2>Key contacts</h2>176 #<span tal:replace="bugtask/id" />
55 <table class="summary" style="width: 100%;">177 </td>
56 <tbody>178 <td>
57 <tr>179 <a tal:attributes="href bugtask/fmt:url"
58 <th>Driver:</th>180 tal:content="bugtask/title" />
59 <td colspan="2">181 </td>
60 <tal:none condition="not:context/driver">None set</tal:none>182 <td tal:attributes="class string:status${bugtask/status/name}"
61 <a183 tal:content="bugtask/status/title" />
62 tal:condition="context/driver"184 <td tal:attributes="
63 tal:replace="structure context/driver/fmt:link"185 class string:importance${bugtask/importance/name}"
64 >John Smith</a>186 tal:content="bugtask/importance/title" />
65 </td>187 <td tal:content="bugtask/bug/date_last_updated/fmt:displaydate" />
66 </tr>188 </tr>
67 <tr tal:define="bug_supervisor context/bug_supervisor">189 </tbody>
68 <th>Bug supervisor:</th>190 </table>
69 <td>191
70 <tal:none condition="not:bug_supervisor"
71 >None set</tal:none>
72 <a
73 tal:condition="bug_supervisor"
74 tal:replace="structure bug_supervisor/fmt:link"
75 >Bob Johnson</a>
76 </td>
77 <td>
78 <tal:edit-bug-supervisor
79 condition="context/menu:bugs/bugsupervisor|nothing">
80 <a tal:define="link context/menu:bugs/bugsupervisor"
81 tal:condition="link/enabled"
82 tal:attributes="href link/url; title link/text">
83 <img tal:attributes="alt link/text" src="/@@/edit" />
84 </a>
85 </tal:edit-bug-supervisor>
86 </td>
87 </tr>
88 <tr tal:define="securitycontact context/security_contact">
89 <th>Security contact:</th>
90 <td>
91 <tal:none condition="not:securitycontact"
92 >None set</tal:none>
93 <a
94 tal:condition="securitycontact"
95 tal:replace="structure securitycontact/fmt:link"
96 >Billy Anderson</a>
97 </td>
98 <td>
99 <tal:edit-securitycontact
100 condition="context/menu:bugs/securitycontact|nothing">
101 <a tal:define="link context/menu:bugs/securitycontact"
102 tal:condition="link/enabled"
103 tal:attributes="href link/url; title link/text">
104 <img tal:attributes="alt link/text" src="/@@/edit" />
105 </a>
106 </tal:edit-securitycontact>
107 </td>
108 </tr>
109 </tbody>
110 </table>
111 <ul class="cross-reference">
112 <li id="bugtracker">
113 <strong>Bug tracker:</strong>
114 <tal:bugtracker replace="structure view/bugtracker" />
115 </li>
116 <li tal:define="fixed_elsewhere view/bugs_fixed_elsewhere_info">
117 <a tal:attributes="href fixed_elsewhere/url">
118 <strong tal:content="fixed_elsewhere/count">42</strong>
119 <tal:label
120 tal:replace="fixed_elsewhere/label">bugs</tal:label>
121 fixed elsewhere
122 </a>
123 </li>
124 <li tal:define="cve_bugs view/open_cve_bugs_info">
125 <a tal:attributes="href cve_bugs/url">
126 <strong tal:content="cve_bugs/count"></strong>
127 open CVE
128 <tal:label tal:replace="cve_bugs/label">bugs</tal:label>
129 </a>
130 <tal:cve-reports
131 condition="context/menu:bugs/cve|nothing">
132 -<a tal:define="link context/menu:bugs/cve"
133 tal:replace="structure link/render"
134 tal:condition="link/enabled">
135 CVE reports
136 </a>
137 </tal:cve-reports>
138 </li>
139 <li tal:define="pending_bugwatches view/pending_bugwatches_info"
140 tal:condition="pending_bugwatches">
141 <a tal:attributes="href pending_bugwatches/url">
142 <strong tal:content="pending_bugwatches/count"></strong>
143 <tal:label
144 tal:replace="pending_bugwatches/label">bugs</tal:label>
145 <tal:need-or-needs
146 define="count pending_bugwatches/count"
147 content="python:(count == 1) and 'needs' or 'need'" />
148 forwarding upstream
149 </a>
150 </li>
151 <li tal:define="expirable_bugs view/expirable_bugs_info"
152 tal:condition="expirable_bugs">
153 <a tal:attributes="href expirable_bugs/url">
154 <strong tal:content="expirable_bugs/count"></strong>
155 incomplete
156 <tal:label
157 tal:replace="expirable_bugs/label">bugs</tal:label>
158 can expire
159 </a>
160 </li>
161 <tal:review-nominations
162 condition="context/menu:bugs/nominations|nothing">
163 <li tal:define="link context/menu:bugs/nominations">
164 <a tal:attributes="href link/url"
165 tal:content="link/text" />
166 </li>
167 </tal:review-nominations>
168 <li style="font-weight: bold;">
169 <a href="+bugs">List all open bugs</a>
170 </li>
171 <li>
172 <tal:subscribe define="link context/menu:bugs/subscribe"
173 replace="structure link/render" />
174 </li>
175 </ul>
176 <ul class="rollover buttons">
177 <li>
178 <a href="+filebug">
179 <img
180 alt="Report a bug"
181 src="/+icing/but-sml-reportabug.gif"
182 />
183 </a>
184 </li>
185 <li tal:content="structure context/@@+ask-a-question-button" />
186 </ul>
187 </div><!-- two column right -->
188 </div><!-- columns -->
189 <div class="clear"></div>
190 <div class="left">
191 <tal:reported replace="structure context/@@+portlet-latestbugs" />
192 </div>
193 <div class="right">
194 <tal:touched replace="structure context/@@+portlet-recently-touched-bugs" />
195 </div>
196 </div><!-- main -->192 </div><!-- main -->
197 </body>193 </body>
198</html>194</html>
199195
=== modified file 'lib/lp/bugs/templates/bugtarget-macros-search.pt'
--- lib/lp/bugs/templates/bugtarget-macros-search.pt 2009-09-13 20:19:53 +0000
+++ lib/lp/bugs/templates/bugtarget-macros-search.pt 2009-09-18 14:43:52 +0000
@@ -73,6 +73,7 @@
73 <tal:widget replace="structure view/widgets/has_patch/hidden" />73 <tal:widget replace="structure view/widgets/has_patch/hidden" />
74 <tal:widget replace="structure view/widgets/component/hidden" />74 <tal:widget replace="structure view/widgets/component/hidden" />
75 <tal:widget replace="structure view/widgets/has_no_package/hidden" />75 <tal:widget replace="structure view/widgets/has_no_package/hidden" />
76 <br /><br />
76 <a tal:attributes="href advanced_search_url|string:?advanced=1"77 <a tal:attributes="href advanced_search_url|string:?advanced=1"
77 >Advanced search</a>78 >Advanced search</a>
78 <div metal:define-slot="extra-search-widgets">79 <div metal:define-slot="extra-search-widgets">
7980
=== modified file 'lib/lp/bugs/templates/bugtarget-portlet-tags-content.pt'
--- lib/lp/bugs/templates/bugtarget-portlet-tags-content.pt 2009-09-13 20:39:15 +0000
+++ lib/lp/bugs/templates/bugtarget-portlet-tags-content.pt 2009-09-18 14:43:52 +0000
@@ -1,36 +1,15 @@
1<div xmlns:tal="http://xml.zope.org/namespaces/tal"1<div xmlns:tal="http://xml.zope.org/namespaces/tal"
2 xmlns:metal="http://xml.zope.org/namespaces/metal"2 xmlns:metal="http://xml.zope.org/namespaces/metal"
3 xmlns:i18n="http://xml.zope.org/namespaces/i18n"3 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
4 tal:define="official_tags view/official_tags;4 class="portletBody">
5 other_tags view/other_tags"5 <div class="section">
6 tal:condition="python: official_tags or other_tags">6 <h2>Tags</h2>
7 <div class="section" tal:condition="official_tags">7 <div style="text-align: justify">
8 <h2>Official tags</h2>8 <a tal:repeat="tag_info view/tags_cloud_data"
9 <table width="100%">9 tal:content="tag_info/tag"
10 <tr tal:repeat="bug_tag_info official_tags">10 tal:attributes="href tag_info/url;
11 <td width="100%">11 style string:font-size: ${tag_info/factor}em" />
12 <a tal:content="bug_tag_info/tag"12 </div>
13 tal:attributes=" href bug_tag_info/url">
14 crash
15 </a>
16 </td>
17 <td tal:content="bug_tag_info/count">20</td>
18 </tr>
19 </table>
20 </div>
21 <div class="section" tal:condition="other_tags">
22 <h2 tal:condition="official_tags">Other tags</h2>
23 <h2 tal:condition="not: official_tags">Tags</h2>
24 <table width="100%">
25 <tr tal:repeat="bug_tag_info other_tags">
26 <td width="100%">
27 <a tal:content="bug_tag_info/tag"
28 tal:attributes=" href bug_tag_info/url">
29 crash
30 </a>
31 </td>
32 <td tal:content="bug_tag_info/count">20</td>
33 </tr>
34 </table>
35 </div>13 </div>
36</div>14</div>
15