Merge lp:~gmb/launchpad/show-bwa-on-bw-pages-bug-558409 into lp:launchpad/db-devel

Proposed by Graham Binns
Status: Merged
Approved by: Graham Binns
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~gmb/launchpad/show-bwa-on-bw-pages-bug-558409
Merge into: lp:launchpad/db-devel
Diff against target: 259 lines (+182/-2)
6 files modified
lib/lp/bugs/browser/bugwatch.py (+30/-1)
lib/lp/bugs/browser/configure.zcml (+6/-0)
lib/lp/bugs/browser/tests/bugwatch-views.txt (+82/-1)
lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt (+43/-0)
lib/lp/bugs/templates/bugwatch-editform.pt (+4/-0)
lib/lp/bugs/templates/bugwatch-portlet-activity.pt (+17/-0)
To merge this branch: bzr merge lp:~gmb/launchpad/show-bwa-on-bw-pages-bug-558409
Reviewer Review Type Date Requested Status
Brad Crittenden (community) code Approve
Curtis Hovey (community) ui Approve
Eleanor Berger (community) ui* Approve
Review via email: mp+23308@code.launchpad.net

Commit message

The latest bug watch activity will now be displayed on the watch's +edit page.

Description of the change

This branch adds the recent activity for a bug watch to its +edit page.

To test this:

 1. Run cronscripts/garbo-hourly.py to schedule some watches
 2. Run cronscripts/checkwatches.py to check them
 3. Visit https://bugs.launchpad.dev/bugs/15/+watch/11/+edit to see
    the +edit page with activity data.

I genially stole the design for the activity list from the code guys
(see any ~vcs-imports branch).

No lint.

== lib/lp/bugs/browser/bugwatch.py ==

 - I've added a property to BugWatchView, recent_watch_activity, which
   will return a list of dicts containing data about recent activity
   which can then be TAL formatted. I did this rather than access the
   watch's activity property directly since this allowed me to avoid
   having to do things like python:view.getIconForActivityStatus() in
   the TAL, which is just hateful.
 - I've added a watch_has_activity property to BugWatchEditView. This is
   used to decide whether or not the activity portlet is shown.

== lib/lp/bugs/browser/configure.zcml ==

 - I've added the ZCML for the activity portlet.

== lib/lp/bugs/browser/tests/bugwatch-views.txt ==

 - I've added tests for BugWatchView.recent_watch_activity and
   BugWatchEditView.watch_has_activity.

== lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt ==

 - I've added tests for the displaying of activity data on the
   BugWatch +edit page.

== lib/lp/bugs/templates/bugwatch-editform.pt ==

 - I've updated the template to show the activity portlet if there's any
   activity on the watch.

== lib/lp/bugs/templates/bugwatch-portlet-activity.pt ==

 - I've added a template for displaying the bug watch activity.

To post a comment you must log in.
Revision history for this message
Eleanor Berger (intellectronica) wrote :

(14:17:06) intellectronica: gmb: i think it can be improved by highlighting the last (current) status, but since this design is identical to the code imports ui, i'm not sure if we should change it at all
(14:17:26) gmb: intellectronica, Yeah, I think that the general thinking is that we should keep the same design.
(14:17:57) intellectronica: gmb: did you discuss that already with anyone before doing it?
(14:18:38) gmb: intellectronica, When I talked to deryck yesterday he mentioned that someone (jml, I think) was keen to see the code design re-used, and this has been mentioned in previous discussions.
(14:19:24) intellectronica: gmb: yes, i think it makes sense, and in that case, assuming we're not going to change the design on code pages too, i agree that leaving it like this is the pragmatic choice.

review: Approve (ui*)
Revision history for this message
Eleanor Berger (intellectronica) wrote :
Revision history for this message
Curtis Hovey (sinzui) wrote :

Hi Graham.

Your changes are a fine addition.

I noted that the page is missing a heading and a breadcrumb. There is no obvious parent for these so the fix is not trivial. As this feature is rarely used by users, we agree to report a bug about this issue.

review: Approve (ui)
Revision history for this message
Brad Crittenden (bac) wrote :

Nice branch Graham.

In your browser test I'd like to see the state of watch_has_activity before you add an activity to show that it does transition. Other than that it looks good.

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/bugs/browser/bugwatch.py'
2--- lib/lp/bugs/browser/bugwatch.py 2010-01-15 03:32:46 +0000
3+++ lib/lp/bugs/browser/bugwatch.py 2010-04-13 14:53:49 +0000
4@@ -21,7 +21,8 @@
5 from canonical.launchpad.fields import URIField
6 from canonical.launchpad.webapp.interfaces import ILaunchBag
7 from lp.bugs.interfaces.bugwatch import (
8- IBugWatch, IBugWatchSet, NoBugTrackerFound, UnrecognizedBugTrackerURL)
9+ BUG_WATCH_ACTIVITY_SUCCESS_STATUSES, IBugWatch, IBugWatchSet,
10+ NoBugTrackerFound, UnrecognizedBugTrackerURL)
11 from canonical.launchpad.webapp import (
12 action, canonical_url, custom_widget, GetitemNavigation,
13 LaunchpadFormView, LaunchpadView)
14@@ -68,6 +69,28 @@
15
16 return displayed_comments
17
18+ @property
19+ def recent_watch_activity(self):
20+ """Return a list of dicts representing recent watch activity."""
21+ activity_items = []
22+ for activity in self.context.activity:
23+ if activity.result in BUG_WATCH_ACTIVITY_SUCCESS_STATUSES:
24+ icon = "/@@/yes"
25+ completion_message = "completed successfully"
26+ else:
27+ icon = "/@@/no"
28+ completion_message = (
29+ "failed with error '%s'" % activity.result.title)
30+
31+ activity_items.append({
32+ 'icon': icon,
33+ 'date': activity.activity_date,
34+ 'completion_message': completion_message,
35+ 'result_text': activity.result.title,
36+ })
37+
38+ return activity_items
39+
40
41 class BugWatchEditForm(Interface):
42 """Form definition for the bug watch edit view."""
43@@ -99,6 +122,11 @@
44 """See `LaunchpadFormView.`"""
45 return {'url' : self.context.url}
46
47+ @property
48+ def watch_has_activity(self):
49+ """Return True if there has been activity on the bug watch."""
50+ return not self.context.activity.is_empty()
51+
52 def validate(self, data):
53 """See `LaunchpadFormView.`"""
54 if 'url' not in data:
55@@ -136,3 +164,4 @@
56 return canonical_url(getUtility(ILaunchBag).bug)
57
58 cancel_url = next_url
59+
60
61=== modified file 'lib/lp/bugs/browser/configure.zcml'
62--- lib/lp/bugs/browser/configure.zcml 2010-03-11 01:39:25 +0000
63+++ lib/lp/bugs/browser/configure.zcml 2010-04-13 14:53:49 +0000
64@@ -1103,6 +1103,12 @@
65 class="lp.bugs.browser.bugwatch.BugWatchEditView"
66 permission="launchpad.AnyPerson"
67 template="../templates/bugwatch-editform.pt"/>
68+ <browser:page
69+ for="lp.bugs.interfaces.bugwatch.IBugWatch"
70+ name="+portlet-activity"
71+ class="lp.bugs.browser.bugwatch.BugWatchView"
72+ permission="launchpad.AnyPerson"
73+ template="../templates/bugwatch-portlet-activity.pt"/>
74 <browser:pages
75 for="lp.bugs.interfaces.bugwatch.IBugWatch"
76 permission="launchpad.AnyPerson">
77
78=== modified file 'lib/lp/bugs/browser/tests/bugwatch-views.txt'
79--- lib/lp/bugs/browser/tests/bugwatch-views.txt 2009-10-22 11:55:51 +0000
80+++ lib/lp/bugs/browser/tests/bugwatch-views.txt 2010-04-13 14:53:49 +0000
81@@ -1,4 +1,5 @@
82-= Bug Watch Edit Page =
83+Bug Watch Edit Page
84+===================
85
86 It's possible to edit a bug watch on +edit, as well as deleting it.
87 Deleting a bug watch is only possible when the bug watch isn't linked to
88@@ -28,3 +29,83 @@
89 >>> [action.label for action in unlinked_bugwatch_view.actions
90 ... if action.available()]
91 ['Change', 'Delete Bug Watch']
92+
93+
94+Recent activity
95+---------------
96+
97+The Bug Watch +edit page displays a list of the recent activity for the
98+watch. This is provided by the BugWatch activity portlet view and can be
99+accessed via the recent_watch_activity property of BugWatchView.
100+
101+We'll create a new watch in order to demonstrate this.
102+
103+ >>> from canonical.launchpad.ftests import login
104+ >>> login('foo.bar@canonical.com')
105+ >>> new_watch = factory.makeBugWatch()
106+
107+The view for the new watch will have an empty recent_watch_activity list
108+since it hasn't been updated yet.
109+
110+ >>> new_watch_view = create_initialized_view(
111+ ... new_watch, '+portlet-activity')
112+ >>> len(new_watch_view.recent_watch_activity)
113+ 0
114+
115+The BugWatch +edit view has a watch_has_activity property, which is used
116+to determine whether the recent activity portlet should be displayed.
117+
118+ >>> new_watch_edit_view = create_initialized_view(
119+ ... new_watch, '+edit')
120+ >>> print new_watch_edit_view.watch_has_activity
121+ False
122+
123+Adding a successful activity entry for the watch will cause it to show
124+up on the BugWatchView's recent_watch_activity property.
125+
126+ >>> new_watch.addActivity()
127+ >>> len(new_watch_view.recent_watch_activity)
128+ 1
129+
130+The BugWatch +edit view's watch_has_activity property will also have
131+changed.
132+
133+ >>> new_watch_edit_view = create_initialized_view(
134+ ... new_watch, '+edit')
135+ >>> print new_watch_edit_view.watch_has_activity
136+ True
137+
138+Each entry in the recent_watch_activity list is a dict containing data
139+about the activity.
140+
141+ >>> from pprint import pprint
142+ >>> for activity_dict in new_watch_view.recent_watch_activity:
143+ ... pprint(activity_dict)
144+ {'completion_message': 'completed successfully',
145+ 'date': datetime.datetime(...tzinfo=<UTC>),
146+ 'icon': '/@@/yes',
147+ 'result_text': 'Synchronisation succeeded'}
148+
149+If an activity entry records a failure, the 'icon' entry in the dict
150+will point to the 'no' icon and the completion_message will explain the
151+failure.
152+
153+We'll commit the transaction to make sure that the two activities have
154+different dates.
155+
156+ >>> import transaction
157+ >>> transaction.commit()
158+
159+ >>> from lp.bugs.interfaces.bugwatch import BugWatchActivityStatus
160+ >>> new_watch.addActivity(result=BugWatchActivityStatus.BUG_NOT_FOUND)
161+ >>> for activity_dict in new_watch_view.recent_watch_activity:
162+ ... pprint(activity_dict)
163+ {'completion_message': "failed with error 'Bug Not Found'",
164+ 'date': datetime.datetime(...tzinfo=<UTC>),
165+ 'icon': '/@@/no',
166+ 'result_text': 'Bug Not Found'}
167+ {'completion_message': 'completed successfully',
168+ 'date': datetime.datetime(...tzinfo=<UTC>),
169+ 'icon': '/@@/yes',
170+ 'result_text': 'Synchronisation succeeded'}
171+
172
173=== modified file 'lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt'
174--- lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt 2010-04-09 12:00:54 +0000
175+++ lib/lp/bugs/stories/bugwatches/xx-edit-bugwatch.txt 2010-04-13 14:53:49 +0000
176@@ -77,3 +77,46 @@
177 ... admin_browser.contents, 'bugwatch-next_check')
178 >>> print extract_text(data_tag.renderContents())
179 Next check: 2010-04-08...
180+
181+
182+Recent activity
183+---------------
184+
185+Recent activity on a bug watch is shown on the page as a list of
186+activity entries. When a watch has not been checked, no activity is
187+shown.
188+
189+ >>> admin_browser.open('http://bugs.launchpad.dev/bugs/1/+watch/2')
190+ >>> recent_activity_list = find_tag_by_id(
191+ ... admin_browser.contents, 'recent-watch-activity')
192+ >>> print recent_activity_list
193+ None
194+
195+Adding some activity to the watch will cause it to show up in the recent
196+activity list.
197+
198+ >>> login('foo.bar@canonical.com')
199+ >>> watch = getUtility(IBugWatchSet).get(2)
200+ >>> watch.addActivity()
201+ >>> logout()
202+
203+ >>> admin_browser.open('http://bugs.launchpad.dev/bugs/1/+watch/2')
204+ >>> recent_activity_list = find_tag_by_id(
205+ ... admin_browser.contents, 'recent-watch-activity')
206+ >>> print extract_text(recent_activity_list)
207+ Update completed successfully ... ago
208+
209+If an update fails, that too will be reflected in the list.
210+
211+ >>> from lp.bugs.interfaces.bugwatch import BugWatchActivityStatus
212+ >>> login('foo.bar@canonical.com')
213+ >>> watch = getUtility(IBugWatchSet).get(2)
214+ >>> watch.addActivity(result=BugWatchActivityStatus.BUG_NOT_FOUND)
215+ >>> logout()
216+
217+ >>> admin_browser.open('http://bugs.launchpad.dev/bugs/1/+watch/2')
218+ >>> recent_activity_list = find_tag_by_id(
219+ ... admin_browser.contents, 'recent-watch-activity')
220+ >>> print extract_text(recent_activity_list)
221+ Update failed with error 'Bug Not Found' ... ago
222+ Update completed successfully ... ago
223
224=== modified file 'lib/lp/bugs/templates/bugwatch-editform.pt'
225--- lib/lp/bugs/templates/bugwatch-editform.pt 2009-09-03 12:43:53 +0000
226+++ lib/lp/bugs/templates/bugwatch-editform.pt 2010-04-13 14:53:49 +0000
227@@ -21,6 +21,10 @@
228 </div>
229 </div>
230
231+ <div class="yui-g" tal:condition="view/watch_has_activity">
232+ <div tal:replace="structure context/@@+portlet-activity" />
233+ </div>
234+
235 <div class="yui-g">
236 <div metal:use-macro="context/@@launchpad_form/form"/>
237 </div>
238
239=== added file 'lib/lp/bugs/templates/bugwatch-portlet-activity.pt'
240--- lib/lp/bugs/templates/bugwatch-portlet-activity.pt 1970-01-01 00:00:00 +0000
241+++ lib/lp/bugs/templates/bugwatch-portlet-activity.pt 2010-04-13 14:53:49 +0000
242@@ -0,0 +1,17 @@
243+<div
244+ xmlns:tal="http://xml.zope.org/namespaces/tal"
245+ xmlns:metal="http://xml.zope.org/namespaces/metal"
246+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
247+ class="portlet" id="portlet-watches">
248+ <h2>Recent activity</h2>
249+ <div id="recent-watch-activity">
250+ <tal:activity repeat="activity view/recent_watch_activity">
251+ <div>
252+ <img tal:attributes="src activity/icon; title activity/result_text" />
253+ Update
254+ <tal:message replace="activity/completion_message" />
255+ <tal:time replace="activity/date/fmt:displaydate" />
256+ </div>
257+ </tal:activity>
258+ </div>
259+</div>

Subscribers

People subscribed via source and target branches

to status/vote changes: