Merge lp:~allenap/launchpad/sub-search-ui-bug-656823-2-devel into lp:launchpad

Proposed by Gavin Panella on 2010-11-04
Status: Merged
Approved by: Gavin Panella on 2010-11-04
Approved revision: no longer in the source branch.
Merged at revision: 11884
Proposed branch: lp:~allenap/launchpad/sub-search-ui-bug-656823-2-devel
Merge into: lp:launchpad
Diff against target: 335 lines (+213/-22)
5 files modified
lib/lp/registry/browser/configure.zcml (+6/-0)
lib/lp/registry/browser/person.py (+86/-17)
lib/lp/registry/stories/person/xx-person-subscriptions.txt (+60/-1)
lib/lp/registry/templates/person-structural-subscriptions.pt (+48/-0)
lib/lp/registry/templates/person-subscriptions.pt (+13/-4)
To merge this branch: bzr merge lp:~allenap/launchpad/sub-search-ui-bug-656823-2-devel
Reviewer Review Type Date Requested Status
Paul Hummer (community) ui 2010-11-04 Approve on 2010-11-04
Graham Binns (community) code 2010-11-04 Approve on 2010-11-04
Review via email: mp+40117@code.launchpad.net

Commit Message

New view, +structural-subscriptions, to display the structural subscriptions belonging to an individual user or team. Previously this was not possible.

Description of the Change

This adds a new view for IPerson, registered as
+structural-subscriptions, that displays the structures to which the
user has subscribed. This matches a similar page called +subscriptions
(which is live, but not linked to from anywhere) which shows direct
subscriptions (bugs only so far).

I didn't put this information on the +subscriptions page because that
has a batch navigator over the direct subscriptions. I've found having
a static data set on the same page as batched information to be
confusing in the past.

Instead each page links to the other using an info link at the
top. This looks okay, but there's probably a better way of doing it.

The structural subscriptions are shown in a list, not in tabular form,
because they will be extended later to include subordinate
information, namely bug subscription filters. There can be multiple
filters for each structural subscription. Nested lists seem to be an
obvious way to represent this.

Screenshots:

  http://people.canonical.com/~gavin/ui/sub-search-ui-bug-656823-2/+subscriptions.png

  http://people.canonical.com/~gavin/ui/sub-search-ui-bug-656823-2/+structural-subscriptions.png

To post a comment you must log in.
Graham Binns (gmb) :
review: Approve (code)
Paul Hummer (rockstar) wrote :

This looks good to me. I generally don't like pages that are just listings, but we already have a story for them. You might want to consider a javascripty inline solution for showing these listings on the main page.

review: Approve (ui)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/registry/browser/configure.zcml'
2--- lib/lp/registry/browser/configure.zcml 2010-10-21 03:22:06 +0000
3+++ lib/lp/registry/browser/configure.zcml 2010-11-05 12:07:18 +0000
4@@ -1067,6 +1067,12 @@
5 name="+subscriptions"
6 template="../templates/person-subscriptions.pt"/>
7 <browser:page
8+ for="lp.registry.interfaces.person.IPerson"
9+ permission="zope.Public"
10+ class="lp.registry.browser.person.PersonStructuralSubscriptionsView"
11+ name="+structural-subscriptions"
12+ template="../templates/person-structural-subscriptions.pt"/>
13+ <browser:page
14 for="lp.registry.interfaces.person.ITeam"
15 permission="zope.Public"
16 class="lp.registry.browser.person.TeamIndexView"
17
18=== modified file 'lib/lp/registry/browser/person.py'
19--- lib/lp/registry/browser/person.py 2010-11-02 11:31:17 +0000
20+++ lib/lp/registry/browser/person.py 2010-11-05 12:07:18 +0000
21@@ -52,6 +52,7 @@
22 'PersonSpecWorkloadTableView',
23 'PersonSpecWorkloadView',
24 'PersonSpecsMenu',
25+ 'PersonStructuralSubscriptionsView',
26 'PersonSubscribedBugTaskSearchListingView',
27 'PersonSubscriptionsView',
28 'PersonView',
29@@ -73,8 +74,8 @@
30 'TeamMembershipView',
31 'TeamMugshotView',
32 'TeamNavigation',
33+ 'TeamOverviewMenu',
34 'TeamOverviewNavigationMenu',
35- 'TeamOverviewMenu',
36 'TeamReassignmentView',
37 'archive_to_person',
38 ]
39@@ -990,6 +991,16 @@
40 enabled = bool(self.person.getOwnedOrDrivenPillars())
41 return Link(target, text, enabled=enabled, icon='info')
42
43+ def subscriptions(self):
44+ target = '+subscriptions'
45+ text = 'Direct subscriptions'
46+ return Link(target, text, icon='info')
47+
48+ def structural_subscriptions(self):
49+ target = '+structural-subscriptions'
50+ text = 'Structural subscriptions'
51+ return Link(target, text, icon='info')
52+
53
54 class PersonMenuMixin(CommonMenuLinks):
55
56@@ -1023,14 +1034,34 @@
57
58 usedfor = IPerson
59 facet = 'overview'
60- links = ['edit', 'branding', 'common_edithomepage',
61- 'editemailaddresses', 'editlanguages', 'editwikinames',
62- 'editircnicknames', 'editjabberids',
63- 'editsshkeys', 'editpgpkeys', 'editlocation', 'memberships',
64- 'codesofconduct', 'karma', 'administer', 'administer_account',
65- 'projects', 'activate_ppa', 'maintained',
66- 'view_ppa_subscriptions', 'ppa', 'oauth_tokens',
67- 'related_software_summary', 'view_recipes']
68+ links = [
69+ 'edit',
70+ 'branding',
71+ 'common_edithomepage',
72+ 'editemailaddresses',
73+ 'editlanguages',
74+ 'editwikinames',
75+ 'editircnicknames',
76+ 'editjabberids',
77+ 'editsshkeys',
78+ 'editpgpkeys',
79+ 'editlocation',
80+ 'memberships',
81+ 'codesofconduct',
82+ 'karma',
83+ 'administer',
84+ 'administer_account',
85+ 'projects',
86+ 'activate_ppa',
87+ 'maintained',
88+ 'view_ppa_subscriptions',
89+ 'ppa',
90+ 'oauth_tokens',
91+ 'related_software_summary',
92+ 'view_recipes',
93+ 'subscriptions',
94+ 'structural_subscriptions',
95+ ]
96
97 def related_software_summary(self):
98 target = '+related-software'
99@@ -1370,14 +1401,36 @@
100
101 usedfor = ITeam
102 facet = 'overview'
103- links = ['edit', 'branding', 'common_edithomepage', 'members', 'mugshots',
104- 'add_member', 'proposed_members',
105- 'memberships', 'received_invitations',
106- 'editemail', 'configure_mailing_list', 'moderate_mailing_list',
107- 'editlanguages', 'map', 'polls',
108- 'add_poll', 'join', 'leave', 'add_my_teams',
109- 'reassign', 'projects', 'activate_ppa', 'maintained', 'ppa',
110- 'related_software_summary', 'view_recipes']
111+ links = [
112+ 'edit',
113+ 'branding',
114+ 'common_edithomepage',
115+ 'members',
116+ 'mugshots',
117+ 'add_member',
118+ 'proposed_members',
119+ 'memberships',
120+ 'received_invitations',
121+ 'editemail',
122+ 'configure_mailing_list',
123+ 'moderate_mailing_list',
124+ 'editlanguages',
125+ 'map',
126+ 'polls',
127+ 'add_poll',
128+ 'join',
129+ 'leave',
130+ 'add_my_teams',
131+ 'reassign',
132+ 'projects',
133+ 'activate_ppa',
134+ 'maintained',
135+ 'ppa',
136+ 'related_software_summary',
137+ 'view_recipes',
138+ 'subscriptions',
139+ 'structural_subscriptions',
140+ ]
141
142
143 class TeamOverviewNavigationMenu(NavigationMenu, TeamMenuMixin):
144@@ -2398,6 +2451,22 @@
145 return "Subscriptions for %s" % self.context.displayname
146
147
148+class PersonStructuralSubscriptionsView(LaunchpadView):
149+ """All the structural subscriptions for a person."""
150+
151+ page_title = 'Structural subscriptions'
152+
153+ def canUnsubscribeFromBugTasks(self):
154+ """Can the current user modify subscriptions for the context?"""
155+ return (self.user is not None and
156+ self.user.inTeam(self.context))
157+
158+ @property
159+ def label(self):
160+ """The header for the structural subscriptions page."""
161+ return "Structural subscriptions for %s" % self.context.displayname
162+
163+
164 class PersonVouchersView(LaunchpadFormView):
165 """Form for displaying and redeeming commercial subscription vouchers."""
166
167
168=== modified file 'lib/lp/registry/stories/person/xx-person-subscriptions.txt'
169--- lib/lp/registry/stories/person/xx-person-subscriptions.txt 2010-10-14 20:20:47 +0000
170+++ lib/lp/registry/stories/person/xx-person-subscriptions.txt 2010-11-05 12:07:18 +0000
171@@ -1,5 +1,5 @@
172 Subscriptions View
173-==================
174+------------------
175
176 XXX: bdmurray 2010-09-24 bug=628411 This story is complete until we publish
177 the link that leads to the +subscriptions page.
178@@ -144,3 +144,62 @@
179 ... find_main_content(subscriber_browser.contents))
180 >>> "does not have any direct bug subscriptions" in page_text
181 True
182+
183+
184+Structural subscriptions
185+========================
186+
187+Leading from the subscriptions view is an overview page of all
188+structural subscriptions.
189+
190+ >>> admin_browser.open("http://launchpad.dev/people/+me/+subscriptions")
191+ >>> admin_browser.getLink("Structural subscriptions").click()
192+ >>> admin_browser.url
193+ 'http://launchpad.dev/~name16/+structural-subscriptions'
194+ >>> admin_browser.title
195+ 'Structural subscriptions : Foo Bar'
196+
197+The structures to which the user is subscribed are displayed in a
198+list. The title of the structure links to the structure itself, and is
199+followed by a link to edit the subscription.
200+
201+ >>> subscriptions = find_tag_by_id(
202+ ... admin_browser.contents, 'structural-subscriptions')
203+ >>> for subscription in subscriptions.findAll("li"):
204+ ... structure_link, modify_link = subscription.findAll("a")
205+ ... print "%s <%s>" % (
206+ ... extract_text(structure_link), structure_link.get("href"))
207+ ... print "--> %s" % modify_link.get("href")
208+ mozilla-firefox in ubuntu </ubuntu/+source/mozilla-firefox>
209+ --> /ubuntu/+source/mozilla-firefox/+subscribe
210+ pmount in ubuntu </ubuntu/+source/pmount>
211+ --> /ubuntu/+source/pmount/+subscribe
212+
213+The links to modify subscriptions are only shown when the user has
214+permission to modify those subscriptions.
215+
216+ >>> subscriber_browser.open(
217+ ... "http://launchpad.dev/~name16/+structural-subscriptions")
218+ >>> subscriptions = find_tag_by_id(
219+ ... subscriber_browser.contents, 'structural-subscriptions')
220+ >>> for subscription in subscriptions.findAll("li"):
221+ ... [structure_link] = subscription.findAll("a")
222+ ... print "%s <%s>" % (
223+ ... extract_text(structure_link), structure_link.get("href"))
224+ mozilla-firefox in ubuntu </ubuntu/+source/mozilla-firefox>
225+ pmount in ubuntu </ubuntu/+source/pmount>
226+
227+The structural subscriptions page links back to the direct
228+subscriptions page.
229+
230+ >>> admin_browser.getLink("Direct subscriptions").url
231+ 'http://launchpad.dev/~name16/+subscriptions'
232+
233+A simple explanatory message is shown when the user doesn't have any
234+structural subscriptions.
235+
236+ >>> subscriber_browser.open(
237+ ... "http://launchpad.dev/people/+me/+structural-subscriptions")
238+ >>> print extract_text(find_tag_by_id(
239+ ... subscriber_browser.contents, "structural-subscriptions"))
240+ Webster does not have any structural subscriptions.
241
242=== added file 'lib/lp/registry/templates/person-structural-subscriptions.pt'
243--- lib/lp/registry/templates/person-structural-subscriptions.pt 1970-01-01 00:00:00 +0000
244+++ lib/lp/registry/templates/person-structural-subscriptions.pt 2010-11-05 12:07:18 +0000
245@@ -0,0 +1,48 @@
246+<html
247+ xmlns="http://www.w3.org/1999/xhtml"
248+ xmlns:tal="http://xml.zope.org/namespaces/tal"
249+ xmlns:metal="http://xml.zope.org/namespaces/metal"
250+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
251+ xml:lang="en"
252+ lang="en"
253+ dir="ltr"
254+ metal:use-macro="view/macro:page/main_only"
255+ i18n:domain="launchpad">
256+ <body>
257+
258+ <div metal:fill-slot="main"
259+ tal:define="structural_subscriptions context/structural_subscriptions">
260+
261+ <ul class="horizontal">
262+ <li
263+ tal:define="link context/menu:overview/subscriptions"
264+ tal:condition="link/enabled"
265+ tal:content="structure link/fmt:link" />
266+ </ul>
267+
268+ <div class="yui-g">
269+ <div class="portlet" id="structural-subscriptions">
270+
271+ <ul tal:condition="structural_subscriptions">
272+ <li tal:repeat="subscription structural_subscriptions">
273+ <span tal:replace="structure subscription/target/fmt:link" />
274+ <a tal:condition="view/canUnsubscribeFromBugTasks"
275+ tal:attributes="href subscription/target/fmt:url/+subscribe;
276+ title string:Modify subscription to ${subscription/target/title};">
277+ <img src="/@@/edit" />
278+ </a>
279+ </li>
280+ </ul>
281+
282+ <p tal:condition="not: structural_subscriptions">
283+ <tal:person content="context/fmt:displayname" /> does not
284+ have any structural subscriptions.
285+ </p>
286+
287+ </div>
288+ </div>
289+
290+ </div>
291+
292+ </body>
293+</html>
294
295=== modified file 'lib/lp/registry/templates/person-subscriptions.pt'
296--- lib/lp/registry/templates/person-subscriptions.pt 2010-10-08 15:43:12 +0000
297+++ lib/lp/registry/templates/person-subscriptions.pt 2010-11-05 12:07:18 +0000
298@@ -15,6 +15,16 @@
299 sub_bugs view/subscribedBugTasks;
300 sub_bug_batch sub_bugs/currentBatch">
301
302+ <ul class="horizontal">
303+ <li
304+ tal:define="link context/menu:overview/structural_subscriptions"
305+ tal:condition="link/enabled"
306+ tal:content="structure link/fmt:link" />
307+ </ul>
308+
309+ <div class="yui-g">
310+ <div class="portlet">
311+
312 <tal:no_subscribed_bugs condition="not: sub_bug_batch|nothing">
313 <p>
314 <tal:person content="display_name">Sample
315@@ -23,10 +33,6 @@
316 </tal:no_subscribed_bugs>
317
318 <tal:subscribed_bugs condition="sub_bug_batch|nothing">
319- <p>
320- Direct bug subscriptions for
321- <tal:person content="display_name">Sample Person</tal:person>
322- </p>
323 <tal:multipage condition="sub_bugs/has_multiple_pages">
324 <tal:navigation
325 replace="structure sub_bugs/@@+navigation-links-upper"/>
326@@ -72,6 +78,9 @@
327 </tal:multipage>
328 </tal:subscribed_bugs>
329
330+ </div>
331+ </div>
332+
333 </div>
334 </body>
335 </html>