Merge lp:~allenap/launchpad/update-project-group-page-bug-434764 into lp:launchpad
- update-project-group-page-bug-434764
- Merge into devel
Proposed by
Gavin Panella
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~allenap/launchpad/update-project-group-page-bug-434764 |
Merge into: | lp:launchpad |
Diff against target: |
1522 lines (+680/-579) 13 files modified
lib/lp/bugs/browser/bugtask.py (+178/-201) lib/lp/bugs/browser/configure.zcml (+10/-4) lib/lp/bugs/browser/tests/bugtask-search-views.txt (+0/-152) lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt (+39/-31) lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt (+2/-1) lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt (+1/-1) lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-authenticated.txt (+0/-19) lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-unauthenticated.txt (+0/-16) lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt (+334/-0) lib/lp/bugs/templates/bugtarget-bugs.pt (+1/-88) lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt (+64/-38) lib/lp/bugs/templates/bugtarget-portlet-bugfilters.pt (+46/-27) lib/lp/registry/browser/project.py (+5/-1) |
To merge this branch: | bzr merge lp:~allenap/launchpad/update-project-group-page-bug-434764 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Abel Deuring (community) | code | Approve | |
Review via email: mp+15322@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote : | # |
Revision history for this message
Abel Deuring (adeuring) wrote : | # |
Hi Gavin,
nice work. Just one nitpick: In xx-bugs.
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/browser/bugtask.py' |
2 | --- lib/lp/bugs/browser/bugtask.py 2009-11-17 02:33:27 +0000 |
3 | +++ lib/lp/bugs/browser/bugtask.py 2009-12-07 15:04:15 +0000 |
4 | @@ -8,7 +8,8 @@ |
5 | __all__ = [ |
6 | 'assignee_renderer', |
7 | 'BugListingBatchNavigator', |
8 | - 'BugListingPortletView', |
9 | + 'BugListingPortletInfoView', |
10 | + 'BugListingPortletStatsView', |
11 | 'BugNominationsView', |
12 | 'bugtarget_renderer', |
13 | 'BugTargetTraversalMixin', |
14 | @@ -56,7 +57,8 @@ |
15 | IInputWidget, IDisplayWidget, InputErrors, WidgetsError) |
16 | from zope.app.form.utility import setUpWidget, setUpWidgets |
17 | from zope.component import ( |
18 | - ComponentLookupError, getAdapter, getUtility, getMultiAdapter) |
19 | + ComponentLookupError, getAdapter, getMultiAdapter, getUtility, |
20 | + queryMultiAdapter) |
21 | from zope.event import notify |
22 | from zope import formlib |
23 | from zope.interface import implementer, implements, Interface, providedBy |
24 | @@ -107,8 +109,7 @@ |
25 | IDistroSeriesBugTask, IFrontPageBugTaskSearch, |
26 | INominationsReviewTableBatchNavigator, INullBugTask, IPersonBugTaskSearch, |
27 | IProductSeriesBugTask, IRemoveQuestionFromBugTaskForm, IUpstreamBugTask, |
28 | - IUpstreamProductBugTaskSearch, RESOLVED_BUGTASK_STATUSES, |
29 | - UNRESOLVED_BUGTASK_STATUSES) |
30 | + IUpstreamProductBugTaskSearch, UNRESOLVED_BUGTASK_STATUSES) |
31 | from lp.bugs.interfaces.bugtracker import BugTrackerType |
32 | from lp.bugs.interfaces.cve import ICveSet |
33 | from lp.registry.interfaces.distribution import IDistribution |
34 | @@ -292,6 +293,24 @@ |
35 | return ["-importance"] |
36 | |
37 | |
38 | +def get_default_search_params(user): |
39 | + """Return a BugTaskSearchParams instance with default values. |
40 | + |
41 | + By default, a search includes any bug that is unresolved and not a |
42 | + duplicate of another bug. |
43 | + |
44 | + If this search will be used to display a list of bugs to the user |
45 | + it may be a good idea to set the orderby attribute using |
46 | + get_sortorder_from_request(): |
47 | + |
48 | + params = get_default_search_params(user) |
49 | + params.orderby = get_sortorder_from_request(request) |
50 | + |
51 | + """ |
52 | + return BugTaskSearchParams( |
53 | + user=user, status=any(*UNRESOLVED_BUGTASK_STATUSES), omit_dupes=True) |
54 | + |
55 | + |
56 | OLD_BUGTASK_STATUS_MAP = { |
57 | 'Unconfirmed': 'New', |
58 | 'Needs Info': 'Incomplete', |
59 | @@ -1668,59 +1687,162 @@ |
60 | return u"" |
61 | |
62 | |
63 | -class BugListingPortletView(LaunchpadView): |
64 | - """Portlet containing all available bug listings.""" |
65 | - def getOpenBugsURL(self): |
66 | - """Return the URL for open bugs on this bug target.""" |
67 | - return get_buglisting_search_filter_url( |
68 | - status=[status.title for status in UNRESOLVED_BUGTASK_STATUSES]) |
69 | - |
70 | - def getBugsAssignedToMeURL(self): |
71 | - """Return the URL for bugs assigned to the current user on target.""" |
72 | - if self.user: |
73 | - return get_buglisting_search_filter_url(assignee=self.user.name) |
74 | +class BugsInfoMixin: |
75 | + """Contains properties giving URLs to bug information.""" |
76 | + |
77 | + @property |
78 | + def bugs_fixed_elsewhere_url(self): |
79 | + """A URL to a list of bugs fixed elsewhere.""" |
80 | + return "%s?field.status_upstream=resolved_upstream" % ( |
81 | + canonical_url(self.context, view_name='+bugs')) |
82 | + |
83 | + @property |
84 | + def open_cve_bugs_url(self): |
85 | + """A URL to a list of open bugs linked to CVEs.""" |
86 | + return "%s?field.has_cve=on" % ( |
87 | + canonical_url(self.context, view_name='+bugs')) |
88 | + |
89 | + @property |
90 | + def open_cve_bugs_has_report(self): |
91 | + """Whether or not the context has a CVE report page.""" |
92 | + return queryMultiAdapter( |
93 | + (self.context, self.request), name='+cve') is not None |
94 | + |
95 | + @property |
96 | + def pending_bugwatches_url(self): |
97 | + """A URL to a list of bugs that need a bugwatch. |
98 | + |
99 | + None is returned if the context is not an upstream product. |
100 | + """ |
101 | + if not IProduct.providedBy(self.context): |
102 | + return None |
103 | + if self.context.official_malone: |
104 | + return None |
105 | + return "%s?field.status_upstream=pending_bugwatch" % ( |
106 | + canonical_url(self.context, view_name='+bugs')) |
107 | + |
108 | + @property |
109 | + def expirable_bugs_url(self): |
110 | + """A URL to a list of bugs that can expire, or None. |
111 | + |
112 | + If the bugtarget is not a supported implementation, or its pillar |
113 | + does not have enable_bug_expiration set to True, None is returned. |
114 | + The bugtarget may be an `IDistribution`, `IDistroSeries`, `IProduct`, |
115 | + or `IProductSeries`. |
116 | + """ |
117 | + if target_has_expirable_bugs_listing(self.context): |
118 | + return canonical_url(self.context, view_name='+expirable-bugs') |
119 | else: |
120 | - return str(self.request.URL) + "/+login" |
121 | - |
122 | - def getBugsAssignedToMeCount(self): |
123 | - """Return the count of bugs assinged to the logged-in user.""" |
124 | - assert self.user, ( |
125 | - "Counting 'bugs assigned to me' requires a logged-in user") |
126 | - |
127 | - search_params = BugTaskSearchParams( |
128 | - user=self.user, assignee=self.user, |
129 | - status=any(*UNRESOLVED_BUGTASK_STATUSES), |
130 | - omit_dupes=True) |
131 | - |
132 | - return self.context.searchTasks(search_params).count() |
133 | - |
134 | - def getCriticalBugsURL(self): |
135 | - """Return the URL for critical bugs on this bug target.""" |
136 | + return None |
137 | + |
138 | + @property |
139 | + def new_bugs_url(self): |
140 | + """A URL to a page of new bugs.""" |
141 | + return get_buglisting_search_filter_url( |
142 | + status=BugTaskStatus.NEW.title) |
143 | + |
144 | + @property |
145 | + def open_bugs_url(self): |
146 | + """A URL to a list of open bugs.""" |
147 | + return canonical_url(self.context, view_name='+bugs') |
148 | + |
149 | + @property |
150 | + def critical_bugs_url(self): |
151 | + """A URL to a list of critical bugs.""" |
152 | return get_buglisting_search_filter_url( |
153 | status=[status.title for status in UNRESOLVED_BUGTASK_STATUSES], |
154 | importance=BugTaskImportance.CRITICAL.title) |
155 | |
156 | - def getUnassignedBugsURL(self): |
157 | - """Return the URL for critical bugs on this bug target.""" |
158 | - unresolved_tasks_query_string = get_buglisting_search_filter_url( |
159 | - status=[status.title for status in UNRESOLVED_BUGTASK_STATUSES]) |
160 | - |
161 | - return unresolved_tasks_query_string + "&assignee_option=none" |
162 | - |
163 | - def getNewBugsURL(self): |
164 | - """Return the URL for new bugs on this bug target.""" |
165 | - return get_buglisting_search_filter_url( |
166 | - status=BugTaskStatus.NEW.title) |
167 | - |
168 | - def getAllBugsEverReportedURL(self): |
169 | - """Return the URL to list all bugs reported.""" |
170 | - all_statuses = UNRESOLVED_BUGTASK_STATUSES + RESOLVED_BUGTASK_STATUSES |
171 | - all_status_query_string = get_buglisting_search_filter_url( |
172 | - status=[status.title for status in all_statuses]) |
173 | - |
174 | - # Add the bit that simulates the "omit dupes" checkbox |
175 | - # being unchecked. |
176 | - return all_status_query_string + "&field.omit_dupes.used=" |
177 | + @property |
178 | + def my_bugs_url(self): |
179 | + """A URL to a list of bugs assigned to the user, or None.""" |
180 | + if self.user is None: |
181 | + return None |
182 | + else: |
183 | + return get_buglisting_search_filter_url(assignee=self.user.name) |
184 | + |
185 | + |
186 | +class BugsStatsMixin(BugsInfoMixin): |
187 | + """Contains properties giving bug stats. |
188 | + |
189 | + These can be expensive to obtain. |
190 | + """ |
191 | + |
192 | + @property |
193 | + def bugs_fixed_elsewhere_count(self): |
194 | + """A count of bugs fixed elsewhere.""" |
195 | + params = get_default_search_params(self.user) |
196 | + params.resolved_upstream = True |
197 | + return self.context.searchTasks(params).count() |
198 | + |
199 | + @property |
200 | + def open_cve_bugs_count(self): |
201 | + """A count of open bugs linked to CVEs.""" |
202 | + params = get_default_search_params(self.user) |
203 | + params.has_cve = True |
204 | + return self.context.searchTasks(params).count() |
205 | + |
206 | + @property |
207 | + def pending_bugwatches_count(self): |
208 | + """A count of bugs that need a bugwatch. |
209 | + |
210 | + None is returned if the context is not an upstream product. |
211 | + """ |
212 | + if not IProduct.providedBy(self.context): |
213 | + return None |
214 | + if self.context.official_malone: |
215 | + return None |
216 | + params = get_default_search_params(self.user) |
217 | + params.pending_bugwatch_elsewhere = True |
218 | + return self.context.searchTasks(params).count() |
219 | + |
220 | + @property |
221 | + def expirable_bugs_count(self): |
222 | + """A count of bugs that can expire, or None. |
223 | + |
224 | + If the bugtarget is not a supported implementation, or its pillar |
225 | + does not have enable_bug_expiration set to True, None is returned. |
226 | + The bugtarget may be an `IDistribution`, `IDistroSeries`, `IProduct`, |
227 | + or `IProductSeries`. |
228 | + """ |
229 | + if target_has_expirable_bugs_listing(self.context): |
230 | + return getUtility(IBugTaskSet).findExpirableBugTasks( |
231 | + 0, user=self.user, target=self.context).count() |
232 | + else: |
233 | + return None |
234 | + |
235 | + @property |
236 | + def new_bugs_count(self): |
237 | + """A count of new bugs.""" |
238 | + return self.context.new_bugtasks.count() |
239 | + |
240 | + @property |
241 | + def open_bugs_count(self): |
242 | + """A count of open bugs.""" |
243 | + return self.context.open_bugtasks.count() |
244 | + |
245 | + @property |
246 | + def critical_bugs_count(self): |
247 | + """A count of critical bugs.""" |
248 | + return self.context.critical_bugtasks.count() |
249 | + |
250 | + @property |
251 | + def my_bugs_count(self): |
252 | + """A count of bugs assigned to the user, or None.""" |
253 | + if self.user is None: |
254 | + return None |
255 | + else: |
256 | + params = get_default_search_params(self.user) |
257 | + params.assignee = self.user |
258 | + return self.context.searchTasks(params).count() |
259 | + |
260 | + |
261 | +class BugListingPortletInfoView(LaunchpadView, BugsInfoMixin): |
262 | + """Portlet containing available bug listings without stats.""" |
263 | + |
264 | + |
265 | +class BugListingPortletStatsView(LaunchpadView, BugsStatsMixin): |
266 | + """Portlet containing available bug listings with stats.""" |
267 | |
268 | |
269 | def get_buglisting_search_filter_url( |
270 | @@ -1972,7 +2094,7 @@ |
271 | return Link('+nominations', 'Review nominations', icon='bug') |
272 | |
273 | |
274 | -class BugTaskSearchListingView(LaunchpadFormView, FeedsMixin): |
275 | +class BugTaskSearchListingView(LaunchpadFormView, FeedsMixin, BugsInfoMixin): |
276 | """View that renders a list of bugs for a given set of search criteria.""" |
277 | |
278 | implements(IBugTaskSearchListingMenu) |
279 | @@ -2131,18 +2253,6 @@ |
280 | # LaunchpadFormView's own validation. |
281 | pass |
282 | |
283 | - def _getDefaultSearchParams(self): |
284 | - """Return a BugTaskSearchParams instance with default values. |
285 | - |
286 | - By default, a search includes any bug that is unresolved and not |
287 | - a duplicate of another bug. |
288 | - """ |
289 | - search_params = BugTaskSearchParams( |
290 | - user=self.user, status=any(*UNRESOLVED_BUGTASK_STATUSES), |
291 | - omit_dupes=True) |
292 | - search_params.orderby = get_sortorder_from_request(self.request) |
293 | - return search_params |
294 | - |
295 | def buildSearchParams(self, searchtext=None, extra_params=None): |
296 | """Build the BugTaskSearchParams object for the given arguments and |
297 | values specified by the user on this form's widgets. |
298 | @@ -2213,7 +2323,8 @@ |
299 | else: |
300 | form_values['tag'] = tags |
301 | |
302 | - search_params = self._getDefaultSearchParams() |
303 | + search_params = get_default_search_params(self.user) |
304 | + search_params.orderby = get_sortorder_from_request(self.request) |
305 | for name, value in form_values.items(): |
306 | setattr(search_params, name, value) |
307 | return search_params |
308 | @@ -2602,140 +2713,6 @@ |
309 | """ |
310 | return IDistributionSourcePackage(self.context, None) |
311 | |
312 | - def _bugOrBugs(self, count): |
313 | - """Return 'bug' if the count is 1, otherwise return 'bugs'. |
314 | - |
315 | - zope.i18n does not support for ngettext-like functionality. |
316 | - """ |
317 | - if count == 1: |
318 | - return 'bug' |
319 | - else: |
320 | - return 'bugs' |
321 | - |
322 | - @property |
323 | - def bugs_fixed_elsewhere_info(self): |
324 | - """Return a dict with count and URL of bugs fixed elsewhere. |
325 | - |
326 | - The available keys are: |
327 | - * 'count' - The number of bugs. |
328 | - * 'url' - The URL of the search. |
329 | - * 'label' - Either 'bug' or 'bugs' depending on the count. |
330 | - """ |
331 | - params = self._getDefaultSearchParams() |
332 | - params.resolved_upstream = True |
333 | - fixed_elsewhere = self.context.searchTasks(params) |
334 | - count = fixed_elsewhere.count() |
335 | - label = self._bugOrBugs(count) |
336 | - search_url = ( |
337 | - "%s/+bugs?field.status_upstream=resolved_upstream" % |
338 | - canonical_url(self.context)) |
339 | - return dict(count=count, url=search_url, label=label) |
340 | - |
341 | - @property |
342 | - def open_cve_bugs_info(self): |
343 | - """Return a dict with count and URL of open bugs linked to CVEs. |
344 | - |
345 | - The available keys are: |
346 | - * 'count' - The number of bugs. |
347 | - * 'url' - The URL of the search. |
348 | - * 'label' - Either 'bug' or 'bugs' depending on the count. |
349 | - """ |
350 | - params = self._getDefaultSearchParams() |
351 | - params.has_cve = True |
352 | - open_cve_bugs = self.context.searchTasks(params) |
353 | - count = open_cve_bugs.count() |
354 | - label = self._bugOrBugs(count) |
355 | - search_url = ( |
356 | - "%s/+bugs?field.has_cve=on" % canonical_url(self.context)) |
357 | - return dict(count=count, url=search_url, label=label) |
358 | - |
359 | - @property |
360 | - def pending_bugwatches_info(self): |
361 | - """Return a dict with count and URL of bugs that need a bugwatch. |
362 | - |
363 | - None is returned if the context is not an upstream product. |
364 | - |
365 | - The available keys are: |
366 | - * 'count' - The number of bugs. |
367 | - * 'url' - The URL of the search. |
368 | - * 'label' - Either 'bug' or 'bugs' depending on the count. |
369 | - """ |
370 | - if not self.isUpstreamProduct: |
371 | - return None |
372 | - params = self._getDefaultSearchParams() |
373 | - params.pending_bugwatch_elsewhere = True |
374 | - pending_bugwatch_elsewhere = self.context.searchTasks(params) |
375 | - count = pending_bugwatch_elsewhere.count() |
376 | - label = self._bugOrBugs(count) |
377 | - search_url = ( |
378 | - "%s/+bugs?field.status_upstream=pending_bugwatch" % |
379 | - canonical_url(self.context)) |
380 | - return dict(count=count, url=search_url, label=label) |
381 | - |
382 | - @property |
383 | - def expirable_bugs_info(self): |
384 | - """Return a dict with count and url of bugs that can expire, or None. |
385 | - |
386 | - If the bugtarget is not a supported implementation, or its pillar |
387 | - does not have enable_bug_expiration set to True, None is returned. |
388 | - The bugtarget may be an `IDistribution`, `IDistroSeries`, `IProduct`, |
389 | - or `IProductSeries`. |
390 | - |
391 | - The available keys are: |
392 | - * 'count' - The number of bugs. |
393 | - * 'url' - The URL of the search, or None. |
394 | - * 'label' - Either 'bug' or 'bugs' depending on the count. |
395 | - """ |
396 | - if not target_has_expirable_bugs_listing(self.context): |
397 | - return None |
398 | - bugtaskset = getUtility(IBugTaskSet) |
399 | - expirable_bugtasks = bugtaskset.findExpirableBugTasks( |
400 | - 0, user=self.user, target=self.context) |
401 | - count = expirable_bugtasks.count() |
402 | - label = self._bugOrBugs(count) |
403 | - url = "%s/+expirable-bugs" % canonical_url(self.context) |
404 | - return dict(count=count, url=url, label=label) |
405 | - |
406 | - @property |
407 | - def new_bugs_info(self): |
408 | - """Return a dict with new bugs info.""" |
409 | - return dict( |
410 | - count=self.context.new_bugtasks.count, |
411 | - url=get_buglisting_search_filter_url( |
412 | - status=BugTaskStatus.NEW.title)) |
413 | - |
414 | - @property |
415 | - def open_bugs_info(self): |
416 | - """Return a dict with open bugs info.""" |
417 | - return dict( |
418 | - count=self.context.open_bugtasks.count, |
419 | - url=canonical_url( |
420 | - self.context, rootsite='bugs', view_name='+bugs')) |
421 | - |
422 | - @property |
423 | - def critical_bugs_info(self): |
424 | - """Return a dict with critical bugs info.""" |
425 | - return dict( |
426 | - count=self.context.critical_bugtasks.count, |
427 | - url=get_buglisting_search_filter_url( |
428 | - status=[status.title for status |
429 | - in UNRESOLVED_BUGTASK_STATUSES], |
430 | - importance=BugTaskImportance.CRITICAL.title)) |
431 | - |
432 | - @property |
433 | - def my_bugs_info(self): |
434 | - """Return a dict with info on bugs assigned to the user, or None.""" |
435 | - if self.user: |
436 | - return dict( |
437 | - count=self.context.searchTasks( |
438 | - BugTaskSearchParams( |
439 | - user=self.user, assignee=self.user, |
440 | - status=any(*UNRESOLVED_BUGTASK_STATUSES), |
441 | - omit_dupes=True)).count(), |
442 | - url=get_buglisting_search_filter_url(assignee=self.user.name)) |
443 | - else: |
444 | - return None |
445 | - |
446 | @property |
447 | def hot_bugtasks(self): |
448 | """Return the 10 most recently updated bugtasks for this target.""" |
449 | @@ -3689,7 +3666,7 @@ |
450 | # If the user does not have permission to view the bug for |
451 | # whatever reason, raise ComponentLookupError. |
452 | try: |
453 | - name = context.bug.displayname |
454 | + context.bug.displayname |
455 | except Unauthorized: |
456 | raise ComponentLookupError() |
457 | |
458 | |
459 | === modified file 'lib/lp/bugs/browser/configure.zcml' |
460 | --- lib/lp/bugs/browser/configure.zcml 2009-11-19 05:56:30 +0000 |
461 | +++ lib/lp/bugs/browser/configure.zcml 2009-12-07 15:04:15 +0000 |
462 | @@ -24,15 +24,21 @@ |
463 | template="../templates/bugtarget-portlet-recently-touched-bugs.pt"/> |
464 | <browser:page |
465 | for="lp.bugs.interfaces.bugtarget.IHasBugs" |
466 | - class="lp.bugs.browser.bugtask.BugListingPortletView" |
467 | + class="lp.bugs.browser.bugtask.BugListingPortletInfoView" |
468 | permission="zope.Public" |
469 | name="+portlet-bugfilters" |
470 | template="../templates/bugtarget-portlet-bugfilters.pt"/> |
471 | <browser:page |
472 | for="lp.bugs.interfaces.bugtarget.IHasBugs" |
473 | - class="lp.bugs.browser.bugtask.BugListingPortletView" |
474 | - permission="zope.Public" |
475 | - name="+bugtarget-portlet-bugfilters-content" |
476 | + class="lp.bugs.browser.bugtask.BugListingPortletInfoView" |
477 | + permission="zope.Public" |
478 | + name="+bugtarget-portlet-bugfilters-info" |
479 | + template="../templates/bugtarget-portlet-bugfilters-content.pt"/> |
480 | + <browser:page |
481 | + for="lp.bugs.interfaces.bugtarget.IHasBugs" |
482 | + class="lp.bugs.browser.bugtask.BugListingPortletStatsView" |
483 | + permission="zope.Public" |
484 | + name="+bugtarget-portlet-bugfilters-stats" |
485 | template="../templates/bugtarget-portlet-bugfilters-content.pt"/> |
486 | <browser:page |
487 | for="lp.bugs.interfaces.bugtarget.IHasBugs" |
488 | |
489 | === modified file 'lib/lp/bugs/browser/tests/bugtask-search-views.txt' |
490 | --- lib/lp/bugs/browser/tests/bugtask-search-views.txt 2009-08-13 15:12:16 +0000 |
491 | +++ lib/lp/bugs/browser/tests/bugtask-search-views.txt 2009-12-07 15:04:15 +0000 |
492 | @@ -350,158 +350,6 @@ |
493 | Mozilla Firefox 1.0 |
494 | |
495 | |
496 | -Bug Filters Portlet |
497 | -------------------- |
498 | - |
499 | -The bug filters portlet has links to various "canned" searches, and |
500 | -shows the number of bugs matching that filter beside each. The counts |
501 | -are (mostly) gotten from the context object itself. Since these URLs and |
502 | -counts are dependant on the current user, we will log in as Sample |
503 | -Person. |
504 | - |
505 | - >>> from canonical.launchpad.interfaces import IProductSet |
506 | - |
507 | - >>> login("test@canonical.com") |
508 | - |
509 | - >>> firefox = getUtility(IProductSet).get(4) |
510 | - >>> print firefox.name |
511 | - firefox |
512 | - |
513 | - >>> bugfilters_portlet_view = create_view(firefox, '+portlet-bugfilters') |
514 | - |
515 | - >>> print bugfilters_portlet_view.getOpenBugsURL() |
516 | - +bugs?search=Search&field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed |
517 | - >>> print bugfilters_portlet_view.context.open_bugtasks.count() |
518 | - 3 |
519 | - |
520 | - >>> print bugfilters_portlet_view.getBugsAssignedToMeURL() |
521 | - +bugs?search=Search&field.assignee=name12 |
522 | - |
523 | - >>> print bugfilters_portlet_view.getBugsAssignedToMeCount() |
524 | - 1 |
525 | - |
526 | -If Sample Person were assigned to second bug, but that bug was a dupe, |
527 | -it would not be included in the counts. |
528 | - |
529 | - >>> from canonical.launchpad.interfaces import IBugTaskSet |
530 | - |
531 | - >>> bug_six_in_firefox = getUtility(IBugTaskSet).get(15) |
532 | - >>> print bug_six_in_firefox.bug.duplicateof.id |
533 | - 5 |
534 | - >>> print bugfilters_portlet_view.user.displayname |
535 | - Sample Person |
536 | - |
537 | - >>> bug_six_in_firefox.transitionToAssignee( |
538 | - ... bugfilters_portlet_view.user) |
539 | - >>> flush_database_updates() |
540 | - |
541 | - >>> print bugfilters_portlet_view.getBugsAssignedToMeCount() |
542 | - 1 |
543 | - |
544 | -The critical bugs link and counts consider only unresolved bugs. |
545 | - |
546 | - >>> print bugfilters_portlet_view.getCriticalBugsURL() |
547 | - +bugs?search=Search&field.importance=Critical&field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed |
548 | - |
549 | - >>> bugfilters_portlet_view.context.critical_bugtasks.count() |
550 | - 1 |
551 | - |
552 | - >>> critical_task = bugfilters_portlet_view.context.critical_bugtasks[0] |
553 | - >>> prev_status = critical_task.status |
554 | - >>> critical_task.transitionToStatus( |
555 | - ... BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user) |
556 | - >>> flush_database_updates() |
557 | - |
558 | - >>> print bugfilters_portlet_view.context.critical_bugtasks.count() |
559 | - 0 |
560 | - |
561 | - >>> critical_task.transitionToStatus( |
562 | - ... prev_status, getUtility(ILaunchBag).user) |
563 | - >>> flush_database_updates() |
564 | - |
565 | -Moving along... |
566 | - |
567 | - >>> print bugfilters_portlet_view.getNewBugsURL() |
568 | - +bugs?search=Search&field.status=New |
569 | - |
570 | - >>> print bugfilters_portlet_view.context.new_bugtasks.count() |
571 | - 3 |
572 | - |
573 | - >>> print bugfilters_portlet_view.getUnassignedBugsURL() |
574 | - +bugs?search=Search&field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&assignee_option=none |
575 | - >>> print bugfilters_portlet_view.context.unassigned_bugtasks.count() |
576 | - 1 |
577 | - |
578 | -And finally, all bugs ever reported. |
579 | - |
580 | - >>> print bugfilters_portlet_view.getAllBugsEverReportedURL() |
581 | - +bugs?search=Search&field.status=New&field.status=Incomplete&field.status=Confirmed&field.status=Triaged&field.status=In+Progress&field.status=Fix+Committed&field.status=Fix+Released&field.status=Invalid&field.status=Won%27t+Fix&field.omit_dupes.used= |
582 | - |
583 | - >>> print bugfilters_portlet_view.context.all_bugtasks.count() |
584 | - 4 |
585 | - |
586 | -All counts ignore bugtasks with status Unknown. Let's set bug four's |
587 | -status in firefox to Unknown and note how the count is decremented by 1 |
588 | -for the open, new, unassigned, and all bugs ever reported |
589 | -counts. |
590 | - |
591 | - >>> bug_four_in_firefox = getUtility(IBugTaskSet).get(13) |
592 | - |
593 | - >>> print bug_four_in_firefox.bug.id |
594 | - 4 |
595 | - >>> print bug_four_in_firefox.product.name |
596 | - firefox |
597 | - |
598 | -We'll examine the counts once more, to verify they are what we think |
599 | -they are. |
600 | - |
601 | - >>> print bugfilters_portlet_view.context.open_bugtasks.count() |
602 | - 3 |
603 | - >>> print bugfilters_portlet_view.context.critical_bugtasks.count() |
604 | - 1 |
605 | - >>> print bugfilters_portlet_view.context.new_bugtasks.count() |
606 | - 3 |
607 | - >>> print bugfilters_portlet_view.context.unassigned_bugtasks.count() |
608 | - 1 |
609 | - >>> print bugfilters_portlet_view.context.all_bugtasks.count() |
610 | - 4 |
611 | - |
612 | -Then change the status. |
613 | - |
614 | - >>> bug_four_in_firefox.transitionToStatus( |
615 | - ... BugTaskStatus.UNKNOWN, getUtility(ILaunchBag).user) |
616 | - >>> flush_database_updates() |
617 | - |
618 | -And the affected counts have been decremented. |
619 | - |
620 | - >>> print bugfilters_portlet_view.context.open_bugtasks.count() |
621 | - 2 |
622 | - >>> print bugfilters_portlet_view.context.critical_bugtasks.count() |
623 | - 1 |
624 | - >>> print bugfilters_portlet_view.context.new_bugtasks.count() |
625 | - 2 |
626 | - >>> print bugfilters_portlet_view.context.unassigned_bugtasks.count() |
627 | - 0 |
628 | - >>> print bugfilters_portlet_view.context.all_bugtasks.count() |
629 | - 3 |
630 | - |
631 | -The unassigned bug counts consider only bugs with an unresolved status. |
632 | - |
633 | - >>> bug_four_in_firefox.transitionToStatus( |
634 | - ... BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user) |
635 | - >>> flush_database_updates() |
636 | - |
637 | - >>> print bugfilters_portlet_view.context.unassigned_bugtasks.count() |
638 | - 0 |
639 | - |
640 | - >>> bug_four_in_firefox.transitionToStatus( |
641 | - ... BugTaskStatus.FIXCOMMITTED, getUtility(ILaunchBag).user) |
642 | - >>> flush_database_updates() |
643 | - |
644 | - >>> print bugfilters_portlet_view.context.unassigned_bugtasks.count() |
645 | - 1 |
646 | - |
647 | - |
648 | == Constructing search filter urls == |
649 | |
650 | There is a helper method, get_buglisting_search_filter_url(), which can |
651 | |
652 | === modified file 'lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt' |
653 | --- lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt 2009-06-12 16:36:02 +0000 |
654 | +++ lib/lp/bugs/browser/tests/special/bugs-fixed-elsewhere.txt 2009-12-07 15:04:15 +0000 |
655 | @@ -1,21 +1,35 @@ |
656 | = Bugs Fixed Elsewhere = |
657 | |
658 | -The +bugs-index view for a distribution or product contains a method for |
659 | -getting information about bugs fixed in some other context. It includes |
660 | -both a count of how many bugs that are fixed elsewhere, as well as a |
661 | -URL to the full list. |
662 | +The +bugtarget-portlet-bugfilters-info view for a distribution or |
663 | +product contains a property for a URL to a list of bugs fixed |
664 | +elsewhere. |
665 | |
666 | >>> from zope.component import getMultiAdapter |
667 | >>> from canonical.launchpad.webapp.servers import LaunchpadTestRequest |
668 | - >>> view = getMultiAdapter( |
669 | - ... (bugtarget, LaunchpadTestRequest()), name='+bugs-index') |
670 | - >>> view.initialize() |
671 | - |
672 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
673 | - >>> bugs_fixed['count'] |
674 | + |
675 | + >>> view = getMultiAdapter( |
676 | + ... (bugtarget, LaunchpadTestRequest()), |
677 | + ... name='+bugtarget-portlet-bugfilters-info') |
678 | + >>> view.initialize() |
679 | + |
680 | + >>> view.bugs_fixed_elsewhere_url |
681 | + u'http://.../+bugs?field.status_upstream=resolved_upstream' |
682 | + |
683 | +The +bugtarget-portlet-bugfilters-stats view for a distribution or |
684 | +product contains the URL as above in addition to a count of how many |
685 | +bugs that are fixed elsewhere. This count can take a while to |
686 | +calculate, so it is put on this separate view which can be requested |
687 | +asyncronously. |
688 | + |
689 | + >>> view = getMultiAdapter( |
690 | + ... (bugtarget, LaunchpadTestRequest()), |
691 | + ... name='+bugtarget-portlet-bugfilters-stats') |
692 | + >>> view.initialize() |
693 | + |
694 | + >>> view.bugs_fixed_elsewhere_url |
695 | + u'http://.../+bugs?field.status_upstream=resolved_upstream' |
696 | + >>> view.bugs_fixed_elsewhere_count |
697 | 0 |
698 | - >>> bugs_fixed['url'] |
699 | - u'http://.../+bugs?field.status_upstream=resolved_upstream' |
700 | |
701 | Simply opening a bug elsewhere won't increase the count. |
702 | |
703 | @@ -29,8 +43,7 @@ |
704 | >>> from canonical.launchpad.interfaces import IBugTaskSet |
705 | >>> elsewhere = getUtility(IBugTaskSet).createTask( |
706 | ... bug, owner=getUtility(ILaunchBag).user, product=evolution) |
707 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
708 | - >>> bugs_fixed['count'] |
709 | + >>> view.bugs_fixed_elsewhere_count |
710 | 0 |
711 | |
712 | But if we mark the bug as fixed in the other, the count will increase |
713 | @@ -42,23 +55,22 @@ |
714 | ... BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user) |
715 | >>> syncUpdate(elsewhere) |
716 | |
717 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
718 | - >>> bugs_fixed['count'] |
719 | + >>> view.bugs_fixed_elsewhere_count |
720 | 1 |
721 | |
722 | Bugs fixed elsewhere also show up when we perform an advanced bug |
723 | search, using the appropriate query string parameter to ask for "bugs |
724 | resolved elsewhere": |
725 | |
726 | - >>> view = getMultiAdapter( |
727 | + >>> search_view = getMultiAdapter( |
728 | ... (bugtarget, |
729 | ... LaunchpadTestRequest( |
730 | ... form={'field.status_upstream': 'resolved_upstream'})), |
731 | ... name='+bugs') |
732 | - >>> view.initialize() |
733 | - >>> navigator = view.search() |
734 | + >>> search_view.initialize() |
735 | + >>> navigator = search_view.search() |
736 | |
737 | - >>> for task in view.search().batch: |
738 | + >>> for task in search_view.search().batch: |
739 | ... for related_task in task.related_tasks: |
740 | ... print related_task.target.name |
741 | ... print related_task.status.name |
742 | @@ -81,8 +93,7 @@ |
743 | ... BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user) |
744 | >>> syncUpdate(another_elsewhere) |
745 | |
746 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
747 | - >>> bugs_fixed['count'] |
748 | + >>> view.bugs_fixed_elsewhere_count |
749 | 2 |
750 | |
751 | This means that No Privileges Person will see that there is only one bug |
752 | @@ -90,11 +101,11 @@ |
753 | |
754 | >>> login('no-priv@canonical.com') |
755 | >>> view = getMultiAdapter( |
756 | - ... (bugtarget, LaunchpadTestRequest()), name='+bugs-index') |
757 | + ... (bugtarget, LaunchpadTestRequest()), |
758 | + ... name='+bugtarget-portlet-bugfilters-stats') |
759 | >>> view.initialize() |
760 | |
761 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
762 | - >>> bugs_fixed['count'] |
763 | + >>> view.bugs_fixed_elsewhere_count |
764 | 1 |
765 | |
766 | If the private bug is made public again, he will of course see that |
767 | @@ -106,8 +117,7 @@ |
768 | >>> syncUpdate(another_bug) |
769 | |
770 | >>> login('no-priv@canonical.com') |
771 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
772 | - >>> bugs_fixed['count'] |
773 | + >>> view.bugs_fixed_elsewhere_count |
774 | 2 |
775 | |
776 | |
777 | @@ -118,8 +128,7 @@ |
778 | >>> another_bug.duplicateof = bug |
779 | >>> syncUpdate(another_bug) |
780 | |
781 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
782 | - >>> bugs_fixed['count'] |
783 | + >>> view.bugs_fixed_elsewhere_count |
784 | 1 |
785 | |
786 | |
787 | @@ -136,6 +145,5 @@ |
788 | ... BugTaskStatus.FIXRELEASED, getUtility(ILaunchBag).user) |
789 | >>> syncUpdate(bugtask) |
790 | |
791 | - >>> bugs_fixed = view.bugs_fixed_elsewhere_info |
792 | - >>> bugs_fixed['count'] |
793 | + >>> view.bugs_fixed_elsewhere_count |
794 | 0 |
795 | |
796 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt' |
797 | --- lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt 2009-09-20 14:58:50 +0000 |
798 | +++ lib/lp/bugs/stories/bugtask-searches/xx-advanced-upstream-pending-bugwatch.txt 2009-12-07 15:04:15 +0000 |
799 | @@ -19,7 +19,8 @@ |
800 | 'Bugs in ALSA utilities' |
801 | |
802 | >>> pending_watches_link = user_browser.getLink( |
803 | - ... 'need forwarding upstream') |
804 | + ... 'Bugs fixed elsewhere') |
805 | + |
806 | |
807 | == Marking and searching for pending bugwatches == |
808 | |
809 | |
810 | === modified file 'lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt' |
811 | --- lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt 2009-09-11 14:03:37 +0000 |
812 | +++ lib/lp/bugs/stories/bugtask-searches/xx-listing-basics.txt 2009-12-07 15:04:15 +0000 |
813 | @@ -137,7 +137,7 @@ |
814 | request, issued by regular browsers via Javascript. |
815 | |
816 | >>> browser.open( |
817 | - ... "http://launchpad.dev/ubuntu/+bugtarget-portlet-bugfilters-content") |
818 | + ... "http://launchpad.dev/ubuntu/+bugtarget-portlet-bugfilters-info") |
819 | >>> browser.getLink("New").click() |
820 | |
821 | The result set is filtered to show only New bugs. |
822 | |
823 | === removed file 'lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-authenticated.txt' |
824 | --- lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-authenticated.txt 2009-06-12 16:36:02 +0000 |
825 | +++ lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-authenticated.txt 1970-01-01 00:00:00 +0000 |
826 | @@ -1,19 +0,0 @@ |
827 | -The distribution bug listing contains a portlet that shows bug |
828 | -statistics for the distro. Each statistic is a link to filter the |
829 | -listing to show just those bugs. This portlet is served in a separate |
830 | -request; the request is issued via Javascript from main bugs page |
831 | -of a distribution. |
832 | - |
833 | - >>> print http(r""" |
834 | - ... GET /debian/+bugtarget-portlet-bugfilters-content HTTP/1.1 |
835 | - ... Authorization: Basic dGVzdEBjYW5vbmljYWwuY29tOnRlc3Q= |
836 | - ... Accept-Language: en-ca,en-us;q=0.8,en;q=0.5,fr-ca;q=0.3 |
837 | - ... """) |
838 | - HTTP/1.1 200 Ok |
839 | - ...Open...3... |
840 | - ...Assigned to me...1... |
841 | - ...Critical...0... |
842 | - ...New...1... |
843 | - ...Unassigned...2... |
844 | - ...All bugs ever reported...4... |
845 | - ... |
846 | |
847 | === removed file 'lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-unauthenticated.txt' |
848 | --- lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-unauthenticated.txt 2009-06-12 16:36:02 +0000 |
849 | +++ lib/lp/bugs/stories/distribution/xx-distribution-bug-statistics-portlet-unauthenticated.txt 1970-01-01 00:00:00 +0000 |
850 | @@ -1,16 +0,0 @@ |
851 | -The distribution bug listing contains a portlet that shows bug |
852 | -statistics for the distro. Each statistic is a link to filter the |
853 | -listing to show just those bugs. This portlet is served in a separate |
854 | -request; the request is issued via Javascript from main bugs page |
855 | -of a distribution. |
856 | - |
857 | - >>> print http(r""" |
858 | - ... GET /debian/+bugtarget-portlet-bugfilters-content HTTP/1.1 |
859 | - ... """) |
860 | - HTTP/1.1 200 Ok |
861 | - ...Open...3... |
862 | - ...Critical...0... |
863 | - ...New...1... |
864 | - ...Unassigned...2... |
865 | - ...All bugs ever reported...4... |
866 | - ... |
867 | |
868 | === added file 'lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt' |
869 | --- lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt 1970-01-01 00:00:00 +0000 |
870 | +++ lib/lp/bugs/stories/xx-bugs-statistics-portlet.txt 2009-12-07 15:04:15 +0000 |
871 | @@ -0,0 +1,334 @@ |
872 | += Bug statistics portlet = |
873 | + |
874 | +The distribution, project group and project bug listings contain a |
875 | +portlet that shows bug statistics for the target. Each statistic is a |
876 | +link to filter the listing to show just those bugs. This portlet is |
877 | +served in a separate request; the request is issued via Javascript and |
878 | +inserted into the page later. |
879 | + |
880 | + >>> from BeautifulSoup import BeautifulSoup |
881 | + |
882 | + >>> def print_portlet(browser, path): |
883 | + ... browser.open( |
884 | + ... 'http://bugs.launchpad.dev/%s/+portlet-bugfilters' % path) |
885 | + ... table = BeautifulSoup(browser.contents).find('table', 'bug-links') |
886 | + ... tbody_info, tbody_links = table('tbody') |
887 | + ... print_table(tbody_info) |
888 | + ... for link in tbody_links('a'): |
889 | + ... text = extract_text(link) |
890 | + ... if len(text) > 0: |
891 | + ... print "%s\n --> %s" % (text, link['href']) |
892 | + |
893 | + >>> def print_portlet_contents(browser, path): |
894 | + ... browser.open( |
895 | + ... 'http://bugs.launchpad.dev' |
896 | + ... '/%s/+bugtarget-portlet-bugfilters-stats' % path) |
897 | + ... table = BeautifulSoup('<table>%s</table>' % browser.contents) |
898 | + ... print_table(table) |
899 | + |
900 | + |
901 | +== Distribution == |
902 | + |
903 | + >>> path = 'debian' |
904 | + |
905 | +If the user is not logged-in a subscribe link is shown along with some |
906 | +general stats. |
907 | + |
908 | + >>> print_portlet(anon_browser, path) |
909 | + Open bugs |
910 | + Critical bugs |
911 | + Bugs fixed elsewhere |
912 | + New bugs |
913 | + Open CVE bugs - CVE reports |
914 | + Subscribe to bug mail |
915 | + --> http://bugs.launchpad.dev/debian/+subscribe |
916 | + |
917 | + >>> print_portlet_contents(anon_browser, path) |
918 | + 3 Open bugs |
919 | + 0 Critical bugs |
920 | + 0 Bugs fixed elsewhere |
921 | + 1 New bugs |
922 | + 2 Open CVE bugs - CVE reports |
923 | + |
924 | +Once the user has identified him or herself, information on assigned |
925 | +bugs is also shown. |
926 | + |
927 | + >>> print_portlet(user_browser, path) |
928 | + Open bugs |
929 | + Bugs assigned to me |
930 | + Critical bugs |
931 | + Bugs fixed elsewhere |
932 | + New bugs |
933 | + Open CVE bugs - CVE reports |
934 | + Subscribe to bug mail |
935 | + --> http://bugs.launchpad.dev/debian/+subscribe |
936 | + |
937 | + >>> print_portlet_contents(user_browser, path) |
938 | + 3 Open bugs |
939 | + 0 Bugs assigned to me |
940 | + 0 Critical bugs |
941 | + 0 Bugs fixed elsewhere |
942 | + 1 New bugs |
943 | + 2 Open CVE bugs - CVE reports |
944 | + |
945 | +The content includes a link to the distribution CVE report. |
946 | + |
947 | + >>> print user_browser.getLink('CVE reports').url |
948 | + http://bugs.launchpad.dev/debian/+cve |
949 | + |
950 | + |
951 | +== Distribution Series == |
952 | + |
953 | + >>> path = 'debian/woody' |
954 | + |
955 | +If the user is not logged-in general stats are shown. There is also a |
956 | +link to review nominations. |
957 | + |
958 | + >>> print_portlet(anon_browser, path) |
959 | + Open bugs |
960 | + Critical bugs |
961 | + Bugs fixed elsewhere |
962 | + New bugs |
963 | + Open CVE bugs - CVE reports |
964 | + Subscribe to bug mail |
965 | + --> http://bugs.launchpad.dev/debian/woody/+subscribe |
966 | + Review nominations |
967 | + --> http://bugs.launchpad.dev/debian/woody/+nominations |
968 | + |
969 | + >>> print_portlet_contents(anon_browser, path) |
970 | + 2 Open bugs |
971 | + 0 Critical bugs |
972 | + 0 Bugs fixed elsewhere |
973 | + 2 New bugs |
974 | + 1 Open CVE bugs - CVE reports |
975 | + |
976 | +Once the user has identified him or herself, information on assigned |
977 | +bugs is also shown. |
978 | + |
979 | + >>> print_portlet(user_browser, path) |
980 | + Open bugs |
981 | + Bugs assigned to me |
982 | + Critical bugs |
983 | + Bugs fixed elsewhere |
984 | + New bugs |
985 | + Open CVE bugs - CVE reports |
986 | + Subscribe to bug mail |
987 | + --> http://bugs.launchpad.dev/debian/woody/+subscribe |
988 | + Review nominations |
989 | + --> http://bugs.launchpad.dev/debian/woody/+nominations |
990 | + |
991 | + >>> print_portlet_contents(user_browser, path) |
992 | + 2 Open bugs |
993 | + 0 Bugs assigned to me |
994 | + 0 Critical bugs |
995 | + 0 Bugs fixed elsewhere |
996 | + 2 New bugs |
997 | + 1 Open CVE bugs - CVE reports |
998 | + |
999 | +The content includes a link to the distribution CVE report. |
1000 | + |
1001 | + >>> print user_browser.getLink('CVE reports').url |
1002 | + http://bugs.launchpad.dev/debian/woody/+cve |
1003 | + |
1004 | + |
1005 | +== Distribution Source Package == |
1006 | + |
1007 | + >>> path = 'debian/+source/mozilla-firefox' |
1008 | + |
1009 | +If the user is not logged-in general stats are shown. |
1010 | + |
1011 | + >>> print_portlet(anon_browser, path) |
1012 | + Open bugs |
1013 | + Critical bugs |
1014 | + Bugs fixed elsewhere |
1015 | + New bugs |
1016 | + Open CVE bugs |
1017 | + Subscribe to bug mail |
1018 | + --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+subscribe |
1019 | + |
1020 | + >>> print_portlet_contents(anon_browser, path) |
1021 | + 3 Open bugs |
1022 | + 0 Critical bugs |
1023 | + 0 Bugs fixed elsewhere |
1024 | + 1 New bugs |
1025 | + 2 Open CVE bugs |
1026 | + |
1027 | +Once the user has identified him or herself, information on assigned |
1028 | +bugs is also shown. |
1029 | + |
1030 | + >>> print_portlet(user_browser, path) |
1031 | + Open bugs |
1032 | + Bugs assigned to me |
1033 | + Critical bugs |
1034 | + Bugs fixed elsewhere |
1035 | + New bugs |
1036 | + Open CVE bugs |
1037 | + Subscribe to bug mail |
1038 | + --> http://bugs.launchpad.dev/debian/+source/mozilla-firefox/+subscribe |
1039 | + |
1040 | + >>> print_portlet_contents(user_browser, path) |
1041 | + 3 Open bugs |
1042 | + 0 Bugs assigned to me |
1043 | + 0 Critical bugs |
1044 | + 0 Bugs fixed elsewhere |
1045 | + 1 New bugs |
1046 | + 2 Open CVE bugs |
1047 | + |
1048 | +Note that the "CVE reports" link is not shown above; distribution |
1049 | +source packages do not have a CVE reports page. |
1050 | + |
1051 | + >>> print user_browser.getLink('CVE reports').url |
1052 | + Traceback (most recent call last): |
1053 | + ... |
1054 | + LinkNotFoundError |
1055 | + |
1056 | + |
1057 | +== Source Package in Distribution Series == |
1058 | + |
1059 | + >>> path = 'debian/woody/+source/mozilla-firefox' |
1060 | + |
1061 | +If the user is not logged-in general stats are shown. There is no |
1062 | +option to subscribe to bug mail. |
1063 | + |
1064 | + >>> print_portlet(anon_browser, path) |
1065 | + Open bugs |
1066 | + Critical bugs |
1067 | + Bugs fixed elsewhere |
1068 | + New bugs |
1069 | + Open CVE bugs |
1070 | + |
1071 | + >>> print_portlet_contents(anon_browser, path) |
1072 | + 2 Open bugs |
1073 | + 0 Critical bugs |
1074 | + 0 Bugs fixed elsewhere |
1075 | + 2 New bugs |
1076 | + 1 Open CVE bugs |
1077 | + |
1078 | +Once the user has identified him or herself, information on assigned |
1079 | +bugs is also shown. |
1080 | + |
1081 | + >>> print_portlet(user_browser, path) |
1082 | + Open bugs |
1083 | + Bugs assigned to me |
1084 | + Critical bugs |
1085 | + Bugs fixed elsewhere |
1086 | + New bugs |
1087 | + Open CVE bugs |
1088 | + |
1089 | + >>> print_portlet_contents(user_browser, path) |
1090 | + 2 Open bugs |
1091 | + 0 Bugs assigned to me |
1092 | + 0 Critical bugs |
1093 | + 0 Bugs fixed elsewhere |
1094 | + 2 New bugs |
1095 | + 1 Open CVE bugs |
1096 | + |
1097 | +Note that the "CVE reports" link is not shown above; source packages |
1098 | +do not have a CVE reports page. |
1099 | + |
1100 | + >>> print user_browser.getLink('CVE reports').url |
1101 | + Traceback (most recent call last): |
1102 | + ... |
1103 | + LinkNotFoundError |
1104 | + |
1105 | + |
1106 | +== Project group == |
1107 | + |
1108 | + >>> path = 'mozilla' |
1109 | + |
1110 | +If the user is not logged-in general stats are shown. |
1111 | + |
1112 | + >>> print_portlet(anon_browser, path) |
1113 | + Open bugs |
1114 | + Critical bugs |
1115 | + Bugs fixed elsewhere |
1116 | + New bugs |
1117 | + Open CVE bugs |
1118 | + Subscribe to bug mail |
1119 | + --> http://bugs.launchpad.dev/mozilla/+subscribe |
1120 | + |
1121 | + >>> print_portlet_contents(anon_browser, path) |
1122 | + 4 Open bugs |
1123 | + 1 Critical bugs |
1124 | + 0 Bugs fixed elsewhere |
1125 | + 4 New bugs |
1126 | + 1 Open CVE bugs |
1127 | + |
1128 | +Once the user has identified him or herself, information on assigned |
1129 | +bugs is also shown. |
1130 | + |
1131 | + >>> print_portlet(user_browser, path) |
1132 | + Open bugs |
1133 | + Bugs assigned to me |
1134 | + Critical bugs |
1135 | + Bugs fixed elsewhere |
1136 | + New bugs |
1137 | + Open CVE bugs |
1138 | + Subscribe to bug mail |
1139 | + --> http://bugs.launchpad.dev/mozilla/+subscribe |
1140 | + |
1141 | + >>> print_portlet_contents(user_browser, path) |
1142 | + 4 Open bugs |
1143 | + 0 Bugs assigned to me |
1144 | + 1 Critical bugs |
1145 | + 0 Bugs fixed elsewhere |
1146 | + 4 New bugs |
1147 | + 1 Open CVE bugs |
1148 | + |
1149 | +Note that the "CVE reports" link is not shown above; project groups do |
1150 | +not have a CVE reports page. |
1151 | + |
1152 | + >>> print user_browser.getLink('CVE reports').url |
1153 | + Traceback (most recent call last): |
1154 | + ... |
1155 | + LinkNotFoundError |
1156 | + |
1157 | + |
1158 | +== Project == |
1159 | + |
1160 | + >>> path = 'firefox' |
1161 | + |
1162 | +If the user is not logged-in general stats are shown. |
1163 | + |
1164 | + >>> print_portlet(anon_browser, path) |
1165 | + Open bugs |
1166 | + Critical bugs |
1167 | + Bugs fixed elsewhere |
1168 | + New bugs |
1169 | + Open CVE bugs - CVE reports |
1170 | + Subscribe to bug mail |
1171 | + --> http://bugs.launchpad.dev/firefox/+subscribe |
1172 | + |
1173 | + >>> print_portlet_contents(anon_browser, path) |
1174 | + 3 Open bugs |
1175 | + 1 Critical bugs |
1176 | + 0 Bugs fixed elsewhere |
1177 | + 3 New bugs |
1178 | + 1 Open CVE bugs - CVE reports |
1179 | + |
1180 | +Once the user has identified him or herself, information on assigned |
1181 | +bugs is also shown. |
1182 | + |
1183 | + >>> print_portlet(user_browser, path) |
1184 | + Open bugs |
1185 | + Bugs assigned to me |
1186 | + Critical bugs |
1187 | + Bugs fixed elsewhere |
1188 | + New bugs |
1189 | + Open CVE bugs - CVE reports |
1190 | + Subscribe to bug mail |
1191 | + --> http://bugs.launchpad.dev/firefox/+subscribe |
1192 | + |
1193 | + >>> print_portlet_contents(user_browser, path) |
1194 | + 3 Open bugs |
1195 | + 0 Bugs assigned to me |
1196 | + 1 Critical bugs |
1197 | + 0 Bugs fixed elsewhere |
1198 | + 3 New bugs |
1199 | + 1 Open CVE bugs - CVE reports |
1200 | + |
1201 | + |
1202 | +The content includes a link to the distribution CVE report. |
1203 | + |
1204 | + >>> print user_browser.getLink('CVE reports').url |
1205 | + http://bugs.launchpad.dev/firefox/+cve |
1206 | |
1207 | === modified file 'lib/lp/bugs/templates/bugtarget-bugs.pt' |
1208 | --- lib/lp/bugs/templates/bugtarget-bugs.pt 2009-11-18 20:28:03 +0000 |
1209 | +++ lib/lp/bugs/templates/bugtarget-bugs.pt 2009-12-07 15:04:15 +0000 |
1210 | @@ -34,94 +34,7 @@ |
1211 | </li> |
1212 | </ul> |
1213 | </div> |
1214 | - <div class="portlet"> |
1215 | - <table class="bug-links"> |
1216 | - <tr tal:define="open_bugs_info view/open_bugs_info"> |
1217 | - <td class="bugs-count" tal:content="open_bugs_info/count" /> |
1218 | - <td class="bugs-link"> |
1219 | - <a tal:attributes="href open_bugs_info/url">Open bugs</a> |
1220 | - </td> |
1221 | - </tr> |
1222 | - <tr tal:condition="view/user" |
1223 | - tal:define="my_bugs_info view/my_bugs_info"> |
1224 | - <td class="bugs-count" tal:content="my_bugs_info/count" /> |
1225 | - <td class="bugs-link"> |
1226 | - <a tal:attributes="href my_bugs_info/url">Bugs assigned to me</a> |
1227 | - </td> |
1228 | - </tr> |
1229 | - <tr tal:define="critical_bugs_info view/critical_bugs_info"> |
1230 | - <td class="bugs-count" tal:content="critical_bugs_info/count" /> |
1231 | - <td class="bugs-link"> |
1232 | - <a tal:attributes="href critical_bugs_info/url">Critical bugs</a> |
1233 | - </td> |
1234 | - </tr> |
1235 | - <tr tal:define="fixed_elsewhere view/bugs_fixed_elsewhere_info"> |
1236 | - <td class="bugs-count" tal:content="fixed_elsewhere/count" /> |
1237 | - <td class="bugs-link"> |
1238 | - <a tal:attributes="href fixed_elsewhere/url"> |
1239 | - Bugs fixed elsewhere |
1240 | - </a> |
1241 | - </td> |
1242 | - </tr> |
1243 | - <tr tal:define="new_bugs_info view/new_bugs_info"> |
1244 | - <td class="bugs-count" tal:content="new_bugs_info/count" /> |
1245 | - <td class="bugs-link"> |
1246 | - <a tal:attributes="href new_bugs_info/url">New bugs</a> |
1247 | - </td> |
1248 | - </tr> |
1249 | - <tr tal:define="cve_bugs_info view/open_cve_bugs_info"> |
1250 | - <td class="bugs-count" tal:content="cve_bugs_info/count" /> |
1251 | - <td class="bugs-link"> |
1252 | - <a tal:attributes="href cve_bugs_info/url">Open CVE bugs</a> |
1253 | - - |
1254 | - <a href="+cve">CVE reports</a> |
1255 | - </td> |
1256 | - </tr> |
1257 | - <tr tal:define="expirable_bugs_info view/expirable_bugs_info" |
1258 | - tal:condition="expirable_bugs_info"> |
1259 | - <td class="bugs-count" tal:content="expirable_bugs_info/count" /> |
1260 | - <td class="bugs-link"> |
1261 | - <a tal:attributes="href expirable_bugs_info/url"> |
1262 | - Incomplete bugs |
1263 | - </a> |
1264 | - (can expire) |
1265 | - </td> |
1266 | - </tr> |
1267 | - <tr tal:define="pending_bugwatches view/pending_bugwatches_info" |
1268 | - tal:condition="pending_bugwatches"> |
1269 | - <td class="bugs-count" tal:content="pending_bugwatches/count" /> |
1270 | - <td class="bugs-link"> |
1271 | - <a tal:attributes="href pending_bugwatches/url"> |
1272 | - Bugs need forwarding upstream |
1273 | - </a> |
1274 | - </td> |
1275 | - </tr> |
1276 | - <tr tal:define="subscribe_link context/menu:bugs/subscribe"> |
1277 | - <td class="bugs-count" style="padding-top: 1em"> |
1278 | - <a tal:attributes="href subscribe_link/url"> |
1279 | - <img tal:attributes="src subscribe_link/icon_url" /> |
1280 | - </a> |
1281 | - </td> |
1282 | - <td class="bugs-link"> |
1283 | - <a tal:attributes="href subscribe_link/url" |
1284 | - tal:content="subscribe_link/escapedtext" /> |
1285 | - </td> |
1286 | - </tr> |
1287 | - <tr tal:define=" |
1288 | - review_nominations_link context/menu:bugs/nominations|nothing" |
1289 | - tal:condition="review_nominations_link"> |
1290 | - <td class="bugs-count" style="padding-top: 1em"> |
1291 | - <a tal:attributes="href review_nominations_link/url"> |
1292 | - <img tal:attributes="src review_nominations_link/icon_url" /> |
1293 | - </a> |
1294 | - </td> |
1295 | - <td class="bugs-link"> |
1296 | - <a tal:attributes="href review_nominations_link/url" |
1297 | - tal:content="review_nominations_link/escapedtext" /> |
1298 | - </td> |
1299 | - </tr> |
1300 | - </table> |
1301 | - </div> |
1302 | + <div tal:replace="structure context/@@+portlet-bugfilters" /> |
1303 | <div tal:replace="structure context/@@+portlet-bugtags" /> |
1304 | <tal:releasecriticalbugs |
1305 | tal:condition="view/shouldShowReleaseCriticalPortlet" |
1306 | |
1307 | === modified file 'lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt' |
1308 | --- lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt 2009-09-13 20:29:46 +0000 |
1309 | +++ lib/lp/bugs/templates/bugtarget-portlet-bugfilters-content.pt 2009-12-07 15:04:15 +0000 |
1310 | @@ -1,41 +1,67 @@ |
1311 | -<div xmlns:tal="http://xml.zope.org/namespaces/tal" |
1312 | - xmlns:metal="http://xml.zope.org/namespaces/metal"> |
1313 | -<table width="100%"> |
1314 | +<tal:portlet-bug-filters-content |
1315 | + xmlns:tal="http://xml.zope.org/namespaces/tal" |
1316 | + xmlns:metal="http://xml.zope.org/namespaces/metal"> |
1317 | + <tal:comment condition="nothing"> |
1318 | + The view/*_count|nothing expressions below are so that this |
1319 | + template can be rendered by a view that does not have count |
1320 | + information available. |
1321 | + </tal:comment> |
1322 | <tr> |
1323 | - <td><a tal:attributes="href view/getOpenBugsURL">Open</a></td> |
1324 | - <td tal:content="context/open_bugtasks/count">10</td> |
1325 | + <td class="bugs-count" tal:content="view/open_bugs_count|nothing" /> |
1326 | + <td class="bugs-link"> |
1327 | + <a tal:attributes="href view/open_bugs_url">Open bugs</a> |
1328 | + </td> |
1329 | </tr> |
1330 | <tr tal:condition="view/user"> |
1331 | - <td> |
1332 | - <a href="#" tal:attributes="href view/getBugsAssignedToMeURL"> |
1333 | - Assigned to me |
1334 | - </a> |
1335 | - </td> |
1336 | - <td tal:content="view/getBugsAssignedToMeCount">50</td> |
1337 | - </tr> |
1338 | - <tr> |
1339 | - <td><a tal:attributes="href view/getCriticalBugsURL">Critical</a></td> |
1340 | - <td tal:content="context/critical_bugtasks/count">42</td> |
1341 | - </tr> |
1342 | - <tr> |
1343 | - <td> |
1344 | - <a tal:attributes="href view/getNewBugsURL">New</a> |
1345 | - </td> |
1346 | - <td tal:content="context/new_bugtasks/count">42</td> |
1347 | - </tr> |
1348 | - <tr> |
1349 | - <td> |
1350 | - <a tal:attributes="href view/getUnassignedBugsURL">Unassigned</a> |
1351 | - </td> |
1352 | - <td tal:content="context/unassigned_bugtasks/count">42</td> |
1353 | - </tr> |
1354 | - <tr> |
1355 | - <td> |
1356 | - <a tal:attributes="href view/getAllBugsEverReportedURL"> |
1357 | - All bugs ever reported |
1358 | - </a> |
1359 | - </td> |
1360 | - <td tal:content="context/all_bugtasks/count">42</td> |
1361 | - </tr> |
1362 | -</table> |
1363 | -</div> |
1364 | + <td class="bugs-count" tal:content="view/my_bugs_count|nothing" /> |
1365 | + <td class="bugs-link"> |
1366 | + <a tal:attributes="href view/my_bugs_url">Bugs assigned to me</a> |
1367 | + </td> |
1368 | + </tr> |
1369 | + <tr> |
1370 | + <td class="bugs-count" tal:content="view/critical_bugs_count|nothing" /> |
1371 | + <td class="bugs-link"> |
1372 | + <a tal:attributes="href view/critical_bugs_url">Critical bugs</a> |
1373 | + </td> |
1374 | + </tr> |
1375 | + <tr> |
1376 | + <td class="bugs-count" tal:content="view/bugs_fixed_elsewhere_count|nothing" /> |
1377 | + <td class="bugs-link"> |
1378 | + <a tal:attributes="href view/bugs_fixed_elsewhere_url"> |
1379 | + Bugs fixed elsewhere |
1380 | + </a> |
1381 | + </td> |
1382 | + </tr> |
1383 | + <tr> |
1384 | + <td class="bugs-count" tal:content="view/new_bugs_count|nothing" /> |
1385 | + <td class="bugs-link"> |
1386 | + <a tal:attributes="href view/new_bugs_url">New bugs</a> |
1387 | + </td> |
1388 | + </tr> |
1389 | + <tr> |
1390 | + <td class="bugs-count" tal:content="view/open_cve_bugs_count|nothing" /> |
1391 | + <td class="bugs-link"> |
1392 | + <a tal:attributes="href view/open_cve_bugs_url">Open CVE bugs</a> |
1393 | + <span tal:condition="view/open_cve_bugs_has_report"> |
1394 | + - <a tal:attributes="href context/fmt:url/+cve">CVE reports</a> |
1395 | + </span> |
1396 | + </td> |
1397 | + </tr> |
1398 | + <tr tal:condition="view/expirable_bugs_url"> |
1399 | + <td class="bugs-count" tal:content="view/expirable_bugs_count|nothing" /> |
1400 | + <td class="bugs-link"> |
1401 | + <a tal:attributes="href view/expirable_bugs_url"> |
1402 | + Incomplete bugs |
1403 | + </a> |
1404 | + (can expire) |
1405 | + </td> |
1406 | + </tr> |
1407 | + <tr tal:condition="view/pending_bugwatches_url"> |
1408 | + <td class="bugs-count" tal:content="view/pending_bugwatches_count|nothing" /> |
1409 | + <td class="bugs-link"> |
1410 | + <a tal:attributes="href view/pending_bugwatches_url"> |
1411 | + Bugs need forwarding upstream |
1412 | + </a> |
1413 | + </td> |
1414 | + </tr> |
1415 | +</tal:portlet-bug-filters-content> |
1416 | |
1417 | === modified file 'lib/lp/bugs/templates/bugtarget-portlet-bugfilters.pt' |
1418 | --- lib/lp/bugs/templates/bugtarget-portlet-bugfilters.pt 2009-12-03 18:33:22 +0000 |
1419 | +++ lib/lp/bugs/templates/bugtarget-portlet-bugfilters.pt 2009-12-07 15:04:15 +0000 |
1420 | @@ -4,34 +4,53 @@ |
1421 | xmlns:i18n="http://xml.zope.org/namespaces/i18n" |
1422 | class="portlet" id="portlet-bugfilters"> |
1423 | <a id="bugtarget-bugfilters-link" |
1424 | - tal:attributes="href context/fmt:url/+bugtarget-portlet-bugfilters-content" > |
1425 | + tal:attributes="href context/fmt:url/+bugtarget-portlet-bugfilters-stats"> |
1426 | </a> |
1427 | - <h2>Filters</h2> |
1428 | - <div id="bugfilters-portlet-spinner" |
1429 | - style="text-align: center; display: none"> |
1430 | - <img src="/@@/spinner" /> |
1431 | - </div> |
1432 | - <script type="text/javascript"> |
1433 | + <table class="bug-links"> |
1434 | + <tbody id="bugfilters-portlet-content" |
1435 | + tal:content="structure context/@@+bugtarget-portlet-bugfilters-info" /> |
1436 | + <tbody tal:define="menu context/menu:bugs"> |
1437 | + <tr tal:define="subscribe_link menu/subscribe|nothing" |
1438 | + tal:condition="subscribe_link"> |
1439 | + <td class="bugs-count" style="padding-top: 1em"> |
1440 | + <a tal:attributes="href subscribe_link/url"> |
1441 | + <img tal:attributes="src subscribe_link/icon_url" /> |
1442 | + </a> |
1443 | + </td> |
1444 | + <td class="bugs-link"> |
1445 | + <a tal:attributes="href subscribe_link/url" |
1446 | + tal:content="subscribe_link/escapedtext" /> |
1447 | + </td> |
1448 | + </tr> |
1449 | + <tr tal:define="review_nominations_link context/menu:bugs/nominations|nothing" |
1450 | + tal:condition="review_nominations_link"> |
1451 | + <td class="bugs-count" style="padding-top: 1em"> |
1452 | + <a tal:attributes="href review_nominations_link/url"> |
1453 | + <img tal:attributes="src review_nominations_link/icon_url" /> |
1454 | + </a> |
1455 | + </td> |
1456 | + <td class="bugs-link"> |
1457 | + <a tal:attributes="href review_nominations_link/url" |
1458 | + tal:content="review_nominations_link/escapedtext" /> |
1459 | + </td> |
1460 | + </tr> |
1461 | + </tbody> |
1462 | + </table> |
1463 | + <script type="text/javascript"> |
1464 | LPS.use('io-base', 'node', function(Y) { |
1465 | - Y.on('domready', function() { |
1466 | - var portlet = Y.one('#portlet-bugfilters'); |
1467 | - Y.one('#bugfilters-portlet-spinner').setStyle('display', 'block'); |
1468 | - |
1469 | - function hide_spinner() { |
1470 | - Y.one('#bugfilters-portlet-spinner').setStyle('display', 'none'); |
1471 | - } |
1472 | - |
1473 | - function on_success(transactionid, response, arguments) { |
1474 | - hide_spinner(); |
1475 | - portlet.set('innerHTML', |
1476 | - portlet.get('innerHTML') + response.responseText); |
1477 | - } |
1478 | - |
1479 | - var config = {on: {success: on_success, |
1480 | - failure: hide_spinner}}; |
1481 | - var url = Y.one('#bugtarget-bugfilters-link').getAttribute('href'); |
1482 | - var request = Y.io(url, config); |
1483 | - }); |
1484 | + Y.on('domready', function() { |
1485 | + var url = Y.one('#bugtarget-bugfilters-link').getAttribute('href'); |
1486 | + var handlers = { |
1487 | + success: function(transactionid, response, arguments) { |
1488 | + Y.one('#bugfilters-portlet-content').set( |
1489 | + 'innerHTML', response.responseText); |
1490 | + }, |
1491 | + failure: function() { |
1492 | + Y.one('#bugfilters-portlet-content').set('innerHTML', ''); |
1493 | + } |
1494 | + }; |
1495 | + var request = Y.io(url, {on: handlers}); |
1496 | + }); |
1497 | }); |
1498 | - </script> |
1499 | + </script> |
1500 | </div> |
1501 | |
1502 | === modified file 'lib/lp/registry/browser/project.py' |
1503 | --- lib/lp/registry/browser/project.py 2009-11-13 21:55:42 +0000 |
1504 | +++ lib/lp/registry/browser/project.py 2009-12-07 15:04:15 +0000 |
1505 | @@ -292,12 +292,16 @@ |
1506 | |
1507 | usedfor = IProject |
1508 | facet = 'bugs' |
1509 | - links = ['new'] |
1510 | + links = ['new', 'subscribe'] |
1511 | |
1512 | def new(self): |
1513 | text = 'Report a Bug' |
1514 | return Link('+filebug', text, icon='add') |
1515 | |
1516 | + def subscribe(self): |
1517 | + text = 'Subscribe to bug mail' |
1518 | + return Link('+subscribe', text, icon='edit') |
1519 | + |
1520 | |
1521 | class ProjectView(HasAnnouncementsView, FeedsMixin): |
1522 | implements(IProjectActionMenu) |
This branch makes the bug search portlet consistent between the pages
for projects, project groups, distributions, distribution series,
source packages in distribution, and source packages in distribution
series. All of these pages now have a quick-to-load portlet that only
contains links to "canned" searches, and which makes an async request
to load the stats information.
It's a big branch, but most of it is refactoring or removal.
lib/lp/ bugs/browser/ bugtask. py
New function get_default_ search_ params( ), which is just the breaking chParams( ). Also, _getDefaultSear chParams( )
out of _getDefaultSear
applied an ordering to the parameters, but none of the call-sites
cared, so I dropped that.
Two new mixin classes: BugsInfoMixin and BugsStatsMixin. The latter bugwatches_ count. These properties are gsURL() and several
inherits from the former. These provide several properties, like
open_bugs_url and pending_
refactored from methods like getUnassignedBu
*_info properties that hung directly off the view. The *_info
properties returned dicts containing a count and url; the mixins now
provide two properties.
The BugsInfoMixin is mixed into views that need URLs the "canned"
searches it knows about. BugsStatsMixin is used when views need URLs
and counts. Because calculating the counts can take a long time,
this typically means that the latter views are fetched
asynchronously by the browser.
Two of these views are BugListingPortl etInfoView and tletStatsView.
BugListingPor
lib/lp/ bugs/browser/ configure. zcml
Replace the registration of +bugtarget- portlet- bugfilters- content
with two views, one for just the URLs and the other for URLs and
counts.
lib/lp/ bugs/browser/ tests/bugtask- search- views.txt
Remove some tests that are now in xx-bugs- statistics- portlet. In
fact, the tests removed were poor tests because a lot of the time
they were not testing the view at all.
lib/lp/ bugs/browser/ tests/special/ bugs-fixed- elsewhere. txt
Fix this up to work with the new properties in the mixins. Mostly
mechanical changes.
lib/lp/ bugs/stories/ bugtask- searches/ xx-advanced- upstream- pending- bugwatch. txt bugs/stories/ bugtask- searches/ xx-listing- basics. txt
lib/lp/
Small mechanical changes.
lib/lp/ bugs/stories/ distribution/ xx-distribution -bug-statistics -portlet- authenticated. txt bugs/stories/ distribution/ xx-distribution -bug-statistics -portlet- unauthenticated .txt
lib/lp/
Removed because it's now all in xx-bugs- statistics- portlet, and
these are very old style tests.
lib/lp/ bugs/stories/ xx-bugs- statistics- portlet. txt
New. Explains and demonstrates the new portlet views.
lib/lp/ bugs/templates/ bugtarget- bugs.pt
Bits moved to bugtarget- portlet- bugfilters- content. pt.
lib/lp/ bugs/templates/ bugtarget- portlet- bugfilters- content. pt
Originally from bugtarget-bugs.pt, but changed since. Pretty simple
table stuff. There's an comment in there to explain how the template
can be used for both the without-counts and the with-count views.
lib/lp/ bugs/templates/ bugtarget- portlet- bugfilters. pt
Clean up the portlet body and update the javascript to load the
stats.
lib/lp/ registry/ browser/ project. py
Add a subscrib...