Merge lp:~danilo/launchpad/kill-feedback-requests into lp:launchpad

Proposed by Данило Шеган on 2012-05-17
Status: Merged
Approved by: Jelmer Vernooij on 2012-05-18
Approved revision: no longer in the source branch.
Merged at revision: 15399
Proposed branch: lp:~danilo/launchpad/kill-feedback-requests
Merge into: lp:launchpad
Diff against target: 1100 lines (+4/-748)
23 files modified
lib/lp/blueprints/browser/configure.zcml (+0/-19)
lib/lp/blueprints/browser/specification.py (+1/-23)
lib/lp/blueprints/browser/specificationfeedback.py (+0/-116)
lib/lp/blueprints/browser/specificationtarget.py (+0/-2)
lib/lp/blueprints/configure.zcml (+0/-9)
lib/lp/blueprints/enums.py (+0/-7)
lib/lp/blueprints/interfaces/specification.py (+0/-16)
lib/lp/blueprints/interfaces/specificationfeedback.py (+0/-45)
lib/lp/blueprints/model/specification.py (+0/-35)
lib/lp/blueprints/model/specificationfeedback.py (+0/-39)
lib/lp/blueprints/stories/blueprints/xx-reviews.txt (+0/-150)
lib/lp/blueprints/stories/standalone/xx-personviews.txt (+0/-13)
lib/lp/blueprints/templates/person-specfeedback.pt (+0/-31)
lib/lp/blueprints/templates/specification-givefeedback.pt (+0/-42)
lib/lp/blueprints/templates/specification-index.pt (+0/-16)
lib/lp/blueprints/templates/specification-listing-detailed.pt (+0/-6)
lib/lp/blueprints/templates/specification-listing-feedback.pt (+0/-36)
lib/lp/blueprints/templates/specification-portlet-feedbackqueue.pt (+0/-28)
lib/lp/blueprints/templates/specification-requestfeedback.pt (+0/-32)
lib/lp/registry/browser/configure.zcml (+0/-7)
lib/lp/registry/browser/person.py (+1/-22)
lib/lp/registry/doc/person.txt (+2/-11)
lib/lp/registry/model/person.py (+0/-43)
To merge this branch: bzr merge lp:~danilo/launchpad/kill-feedback-requests
Reviewer Review Type Date Requested Status
Jelmer Vernooij (community) 2012-05-17 Approve on 2012-05-18
Review via email: mp+106119@code.launchpad.net

Commit Message

Remove all code related to 'Feedback requests' on blueprint pages.

Description of the Change

= Bug 1000642: kill 'request feedback' =

'Request feedback' feature (available from individual blueprint pages) has never been complete nor it did what users expected. As the major problem, it never emailed anything (neither when feedback was requested, nor when it was received).

It was also hard to find (feedback requests for you are available only from your blueprints homepage: https://blueprints.launchpad.net/people/+me/+specfeedback

== Proposed fix ==

Francis proposed killing the feature altogether: it never did what people expected it to do, and it's very much incomplete. There will be no resources to complete it, so it's better to remove it altogether.

== Pre-implementation notes ==

== LOC Rationale ==

This is being done by us to help us keep our relative LOC while working on the workitems project a net negative.

This is all strictly code removal.

== Tests ==

Full test suite.

== Demo and Q/A ==

- Browse to a blueprint page: no 'Feedback' section should appear there (before the whiteboard)
- Browse to https://blueprints.launchpad.net/people/+me: no link to 'Feedback requests' in the menu on the right side should be there
- https://blueprints.launchpad.net/people/+me/+specfeedback should not work

= Launchpad lint =

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/blueprints/configure.zcml
  lib/lp/blueprints/enums.py
  lib/lp/blueprints/browser/configure.zcml
  lib/lp/blueprints/browser/specification.py
  lib/lp/blueprints/browser/specificationtarget.py
  lib/lp/blueprints/interfaces/specification.py
  lib/lp/blueprints/model/specification.py
  lib/lp/blueprints/stories/standalone/xx-personviews.txt
  lib/lp/blueprints/templates/specification-index.pt
  lib/lp/blueprints/templates/specification-listing-detailed.pt
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/browser/person.py
  lib/lp/registry/doc/person.txt
  lib/lp/registry/model/person.py

To post a comment you must log in.
Данило Шеган (danilo) wrote :

As William suggested, this will have to wait for https://code.launchpad.net/~danilo/launchpad/bug-1000642-db/+merge/106343 to land and be rolled out.

Jelmer Vernooij (jelmer) wrote :

Another bit of dead code gone, thanks! :-)

The changes look reasonable and complete to me.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/blueprints/browser/configure.zcml'
2--- lib/lp/blueprints/browser/configure.zcml 2012-03-28 18:43:36 +0000
3+++ lib/lp/blueprints/browser/configure.zcml 2012-06-12 12:14:35 +0000
4@@ -274,9 +274,6 @@
5 <browser:page
6 name="+portlet-blocked"
7 template="../templates/specification-portlet-blocked.pt"/>
8- <browser:page
9- name="+portlet-feedbackqueue"
10- template="../templates/specification-portlet-feedbackqueue.pt"/>
11 </browser:pages>
12 <browser:page
13 for="lp.blueprints.interfaces.specification.ISpecification"
14@@ -314,9 +311,6 @@
15 <browser:page
16 name="+listing-detailed"
17 template="../templates/specification-listing-detailed.pt"/>
18- <browser:page
19- name="+listing-feedback"
20- template="../templates/specification-listing-feedback.pt"/>
21 </browser:pages>
22 <browser:page
23 for="lp.blueprints.interfaces.specification.ISpecification"
24@@ -337,12 +331,6 @@
25 permission="launchpad.Edit"
26 template="../templates/specification-subscription-delete.pt"/>
27 <browser:page
28- for="lp.blueprints.interfaces.specification.ISpecification"
29- name="+givefeedback"
30- class="lp.blueprints.browser.specificationfeedback.SpecificationFeedbackClearingView"
31- permission="launchpad.AnyPerson"
32- template="../templates/specification-givefeedback.pt"/>
33- <browser:page
34 name="+addsubscriber"
35 for="lp.blueprints.interfaces.specification.ISpecification"
36 class="lp.blueprints.browser.specificationsubscription.SpecificationSubscriptionAddSubscriberView"
37@@ -424,13 +412,6 @@
38 permission="launchpad.Edit"
39 template="../templates/specification-edit.pt"/>
40 <browser:page
41- name="+requestfeedback"
42- for="lp.blueprints.interfaces.specification.ISpecification"
43- class="lp.blueprints.browser.specificationfeedback.SpecificationFeedbackAddView"
44- permission="launchpad.AnyPerson"
45- template="../templates/specification-requestfeedback.pt">
46- </browser:page>
47- <browser:page
48 name="+linkbug"
49 for="lp.blueprints.interfaces.specification.ISpecification"
50 class="lp.bugs.browser.buglinktarget.BugLinkView"
51
52=== modified file 'lib/lp/blueprints/browser/specification.py'
53--- lib/lp/blueprints/browser/specification.py 2012-03-26 14:23:39 +0000
54+++ lib/lp/blueprints/browser/specification.py 2012-06-12 12:14:35 +0000
55@@ -418,19 +418,13 @@
56 usedfor = ISpecification
57 links = ['edit', 'people', 'status', 'priority',
58 'whiteboard', 'proposegoal', 'workitems',
59- 'milestone', 'requestfeedback', 'givefeedback', 'subscription',
60+ 'milestone', 'subscription',
61 'addsubscriber',
62 'linkbug', 'unlinkbug', 'linkbranch',
63 'adddependency', 'removedependency',
64 'dependencytree', 'linksprint', 'supersede',
65 'retarget']
66
67- def givefeedback(self):
68- text = 'Give feedback'
69- enabled = (self.user is not None and
70- bool(self.context.getFeedbackRequests(self.user)))
71- return Link('+givefeedback', text, icon='edit', enabled=enabled)
72-
73 @enabled_with_permission('launchpad.Edit')
74 def milestone(self):
75 text = 'Target milestone'
76@@ -447,11 +441,6 @@
77 return Link('+priority', text, icon='edit')
78
79 @enabled_with_permission('launchpad.AnyPerson')
80- def requestfeedback(self):
81- text = 'Request feedback'
82- return Link('+requestfeedback', text, icon='add')
83-
84- @enabled_with_permission('launchpad.AnyPerson')
85 def proposegoal(self):
86 text = 'Propose as goal'
87 if self.context.goal is not None:
88@@ -544,12 +533,6 @@
89 """Used to render portlets and listing items that need browser code."""
90
91 @cachedproperty
92- def feedbackrequests(self):
93- if self.user is None:
94- return []
95- return list(self.context.getFeedbackRequests(self.user))
96-
97- @cachedproperty
98 def has_dep_tree(self):
99 return self.context.dependencies or self.context.blocked_specs
100
101@@ -585,11 +568,6 @@
102 if not self.user:
103 return
104
105- if self.feedbackrequests:
106- msg = "You have %d feedback request(s) on this blueprint."
107- msg %= len(self.feedbackrequests)
108- self.notices.append(msg)
109-
110 @property
111 def approver_widget(self):
112 return InlinePersonEditPickerWidget(
113
114=== removed file 'lib/lp/blueprints/browser/specificationfeedback.py'
115--- lib/lp/blueprints/browser/specificationfeedback.py 2012-01-01 02:58:52 +0000
116+++ lib/lp/blueprints/browser/specificationfeedback.py 1970-01-01 00:00:00 +0000
117@@ -1,116 +0,0 @@
118-# Copyright 2009 Canonical Ltd. This software is licensed under the
119-# GNU Affero General Public License version 3 (see the file LICENSE).
120-
121-"""Views for SpecificationFeedback."""
122-
123-__metaclass__ = type
124-
125-from zope.app.form.browser import TextAreaWidget
126-from zope.component import getUtility
127-from zope.interface import Interface
128-
129-from lp import _
130-from lp.app.browser.launchpadform import (
131- action,
132- custom_widget,
133- LaunchpadFormView,
134- )
135-from lp.blueprints.interfaces.specificationfeedback import (
136- ISpecificationFeedback,
137- )
138-from lp.registry.interfaces.person import IPersonSet
139-from lp.services.helpers import english_list
140-from lp.services.webapp import canonical_url
141-
142-
143-__all__ = [
144- 'SpecificationFeedbackAddView',
145- 'SpecificationFeedbackClearingView',
146- ]
147-
148-
149-class SpecificationFeedbackAddView(LaunchpadFormView):
150-
151- schema = ISpecificationFeedback
152-
153- field_names = [
154- 'reviewer', 'queuemsg',
155- ]
156-
157- custom_widget('queuemsg', TextAreaWidget, height=5)
158-
159- @property
160- def label(self):
161- return "Request feedback on specification"
162-
163- @property
164- def page_title(self):
165- return self.label
166-
167- def validate(self, data):
168- reviewer = data.get('reviewer')
169- requester = self.user
170- for request in self.context.getFeedbackRequests(reviewer):
171- if request.requester == requester:
172- self.addError("You've already requested feedback from %s"
173- % reviewer.displayname)
174- if reviewer == requester:
175- self.addError("You can't request feedback from yourself")
176-
177- @action(_("Add"), name="create")
178- def create_action(self, action, data):
179- reviewer = data.get('reviewer')
180- requester = self.user
181- queuemsg = data.get('queuemsg')
182- return self.context.queue(reviewer, requester, queuemsg)
183-
184- @property
185- def next_url(self):
186- return canonical_url(self.context)
187-
188- @property
189- def cancel_url(self):
190- return self.next_url
191-
192-
193-class SpecificationFeedbackClearingView(LaunchpadFormView):
194-
195- schema = Interface
196- field_names = []
197-
198- @property
199- def label(self):
200- return _('Give feedback on this blueprint')
201-
202- @property
203- def requests(self):
204- """Return the feedback requests made of this user."""
205- if self.user is None:
206- return None
207- return self.context.getFeedbackRequests(self.user)
208-
209- @action(_('Save changes'), name='save')
210- def save_action(self, action, data):
211- names = self.request.form_ng.getAll('name')
212- if len(names) == 0:
213- self.request.response.addNotification(
214- 'Please select feedback queue items to clear.')
215- else:
216- cleared_from = []
217- for name in names:
218- requester = getUtility(IPersonSet).getByName(name)
219- if requester is not None:
220- self.context.unqueue(self.user, requester)
221- cleared_from.append(requester.displayname)
222- self.request.response.addNotification(
223- 'Cleared requests from: %s' % english_list(cleared_from))
224-
225- @property
226- def next_url(self):
227- if self.context.getFeedbackRequests(self.user).count() == 0:
228- # No more queue items to process; return to the spec.
229- return canonical_url(self.context)
230-
231- @property
232- def cancel_url(self):
233- return canonical_url(self.context)
234
235=== modified file 'lib/lp/blueprints/browser/specificationtarget.py'
236--- lib/lp/blueprints/browser/specificationtarget.py 2012-02-17 04:09:06 +0000
237+++ lib/lp/blueprints/browser/specificationtarget.py 2012-06-12 12:14:35 +0000
238@@ -328,8 +328,6 @@
239 filter.append(SpecificationFilter.DRAFTER)
240 elif role == 'approver':
241 filter.append(SpecificationFilter.APPROVER)
242- elif role == 'feedback':
243- filter.append(SpecificationFilter.FEEDBACK)
244 elif role == 'subscriber':
245 filter.append(SpecificationFilter.SUBSCRIBER)
246
247
248=== modified file 'lib/lp/blueprints/configure.zcml'
249--- lib/lp/blueprints/configure.zcml 2012-02-22 21:34:15 +0000
250+++ lib/lp/blueprints/configure.zcml 2012-06-12 12:14:35 +0000
251@@ -115,15 +115,6 @@
252 lazr.lifecycle.interfaces.IObjectModifiedEvent"
253 handler="lp.blueprints.mail.notifications.notify_specification_subscription_modified"/>
254
255- <!-- SpecificationFeedback -->
256-
257- <class class="lp.blueprints.model.specificationfeedback.SpecificationFeedback">
258- <allow interface="lp.blueprints.interfaces.specificationfeedback.ISpecificationFeedback"/>
259- <require
260- permission="zope.Public"
261- set_schema="lp.blueprints.interfaces.specificationfeedback.ISpecificationFeedback"/>
262- </class>
263-
264 <!-- SprintAttendance -->
265
266 <class class="lp.blueprints.model.sprintattendance.SprintAttendance">
267
268=== modified file 'lib/lp/blueprints/enums.py'
269--- lib/lp/blueprints/enums.py 2012-02-15 21:36:02 +0000
270+++ lib/lp/blueprints/enums.py 2012-06-12 12:14:35 +0000
271@@ -334,13 +334,6 @@
272 to which the person has subscribed.
273 """)
274
275- FEEDBACK = DBItem(110, """
276- Feedback
277-
278- This indicates that the list should include all the specifications
279- which the person has been asked to provide specific feedback on.
280- """)
281-
282
283 class SpecificationSort(EnumeratedType):
284 """The scheme to sort the results of a specifications query.
285
286=== modified file 'lib/lp/blueprints/interfaces/specification.py'
287--- lib/lp/blueprints/interfaces/specification.py 2012-04-03 22:12:29 +0000
288+++ lib/lp/blueprints/interfaces/specification.py 2012-06-12 12:14:35 +0000
289@@ -379,7 +379,6 @@
290 subscribers = Attribute('The set of subscribers to this spec.')
291 sprints = Attribute('The sprints at which this spec is discussed.')
292 sprint_links = Attribute('The entries that link this spec to sprints.')
293- feedbackrequests = Attribute('The set of feedback requests queued.')
294 dependencies = exported(
295 CollectionField(
296 title=_('Specs on which this one depends.'),
297@@ -442,11 +441,6 @@
298 def getSprintSpecification(sprintname):
299 """Get the record that links this spec to the named sprint."""
300
301- def getFeedbackRequests(person):
302- """Return the requests for feedback for a given person on this
303- specification.
304- """
305-
306 def notificationRecipientAddresses():
307 """Return the list of email addresses that receive notifications."""
308
309@@ -523,16 +517,6 @@
310 If person is None, the return value is always False.
311 """
312
313- # queue-related methods
314- def queue(provider, requester, queuemsg=None):
315- """Put this specification into the feedback queue of the given person,
316- with an optional message."""
317-
318- def unqueue(provider, requester):
319- """Remove the feedback request by the requester for this spec, from
320- the provider's feedback queue.
321- """
322-
323 # sprints
324 def linkSprint(sprint, user):
325 """Put this spec on the agenda of the sprint."""
326
327=== removed file 'lib/lp/blueprints/interfaces/specificationfeedback.py'
328--- lib/lp/blueprints/interfaces/specificationfeedback.py 2011-12-24 16:54:44 +0000
329+++ lib/lp/blueprints/interfaces/specificationfeedback.py 1970-01-01 00:00:00 +0000
330@@ -1,45 +0,0 @@
331-# Copyright 2009 Canonical Ltd. This software is licensed under the
332-# GNU Affero General Public License version 3 (see the file LICENSE).
333-
334-# pylint: disable-msg=E0211,E0213
335-
336-"""Specification queueing interfaces. It is possible to put a specification
337-into somebody's queue, along with a message telling that person what they
338-are supposed to do with that spec."""
339-
340-__metaclass__ = type
341-
342-__all__ = [
343- 'ISpecificationFeedback',
344- ]
345-
346-from zope.interface import Interface
347-from zope.schema import (
348- Int,
349- Text,
350- )
351-
352-from lp import _
353-from lp.services.fields import PublicPersonChoice
354-
355-
356-class ISpecificationFeedback(Interface):
357- """The queue entry for a specification on a person, including a message
358- from the person who put it in their queue."""
359-
360- reviewer = PublicPersonChoice(
361- title=_('Feedback From'), required=True,
362- vocabulary='ValidPersonOrTeam', readonly=False,
363- description=_("Select the person who you would like to give you "
364- "some feedback on this specification."))
365- requester = PublicPersonChoice(
366- title=_("The person who requested this feedback."),
367- vocabulary='ValidPersonOrTeam', required=True)
368- specification = Int(title=_('Specification ID'), required=True,
369- readonly=True)
370- queuemsg = Text(title=_("Message"), required=False,
371- description=_("A brief message for the person that you are "
372- "asking to look at this spec. Tell them why you are putting this "
373- "specification in their queue."))
374-
375-
376
377=== modified file 'lib/lp/blueprints/model/specification.py'
378--- lib/lp/blueprints/model/specification.py 2012-03-26 14:23:39 +0000
379+++ lib/lp/blueprints/model/specification.py 2012-06-12 12:14:35 +0000
380@@ -57,7 +57,6 @@
381 from lp.blueprints.model.specificationdependency import (
382 SpecificationDependency,
383 )
384-from lp.blueprints.model.specificationfeedback import SpecificationFeedback
385 from lp.blueprints.model.specificationsubscription import (
386 SpecificationSubscription,
387 )
388@@ -191,8 +190,6 @@
389 joinColumn='specification', otherColumn='person',
390 intermediateTable='SpecificationSubscription',
391 orderBy=['displayname', 'name'])
392- feedbackrequests = SQLMultipleJoin('SpecificationFeedback',
393- joinColumn='specification', orderBy='id')
394 sprint_links = SQLMultipleJoin('SprintSpecification', orderBy='id',
395 joinColumn='specification')
396 sprints = SQLRelatedJoin('Sprint', orderBy='name',
397@@ -435,12 +432,6 @@
398 return sprintspecification
399 return None
400
401- def getFeedbackRequests(self, person):
402- """See ISpecification."""
403- fb = SpecificationFeedback.selectBy(
404- specification=self, reviewer=person)
405- return fb.prejoin(['requester'])
406-
407 def notificationRecipientAddresses(self):
408 """See ISpecification."""
409 related_people = [
410@@ -699,32 +690,6 @@
411
412 return bool(self.subscription(person))
413
414- # queueing
415- def queue(self, reviewer, requester, queuemsg=None):
416- """See ISpecification."""
417- for fbreq in self.feedbackrequests:
418- if (fbreq.reviewer.id == reviewer.id and
419- fbreq.requester == requester.id):
420- # we have a relevant request already, update it
421- fbreq.queuemsg = queuemsg
422- return fbreq
423- # since no previous feedback request existed for this person,
424- # create a new one
425- return SpecificationFeedback(
426- specification=self,
427- reviewer=reviewer,
428- requester=requester,
429- queuemsg=queuemsg)
430-
431- def unqueue(self, reviewer, requester):
432- """See ISpecification."""
433- # see if a relevant queue entry exists, and if so, delete it
434- for fbreq in self.feedbackrequests:
435- if (fbreq.reviewer.id == reviewer.id and
436- fbreq.requester.id == requester.id):
437- SpecificationFeedback.delete(fbreq.id)
438- return
439-
440 # Template methods for BugLinkTargetMixin
441 buglinkClass = SpecificationBug
442
443
444=== removed file 'lib/lp/blueprints/model/specificationfeedback.py'
445--- lib/lp/blueprints/model/specificationfeedback.py 2011-12-30 06:14:56 +0000
446+++ lib/lp/blueprints/model/specificationfeedback.py 1970-01-01 00:00:00 +0000
447@@ -1,39 +0,0 @@
448-# Copyright 2009 Canonical Ltd. This software is licensed under the
449-# GNU Affero General Public License version 3 (see the file LICENSE).
450-
451-# pylint: disable-msg=E0611,W0212
452-
453-__metaclass__ = type
454-
455-__all__ = ['SpecificationFeedback']
456-
457-from sqlobject import (
458- ForeignKey,
459- StringCol,
460- )
461-from zope.interface import implements
462-
463-from lp.blueprints.interfaces.specificationfeedback import (
464- ISpecificationFeedback,
465- )
466-from lp.registry.interfaces.person import validate_public_person
467-from lp.services.database.sqlbase import SQLBase
468-
469-
470-class SpecificationFeedback(SQLBase):
471- """A subscription for person to a spec."""
472-
473- implements(ISpecificationFeedback)
474-
475- _table = 'SpecificationFeedback'
476- specification = ForeignKey(dbName='specification',
477- foreignKey='Specification', notNull=True)
478- reviewer = ForeignKey(
479- dbName='reviewer', foreignKey='Person',
480- storm_validator=validate_public_person, notNull=True)
481- requester = ForeignKey(
482- dbName='requester', foreignKey='Person',
483- storm_validator=validate_public_person, notNull=True)
484- queuemsg = StringCol(notNull=False, default=None)
485-
486-
487
488=== removed file 'lib/lp/blueprints/stories/blueprints/xx-reviews.txt'
489--- lib/lp/blueprints/stories/blueprints/xx-reviews.txt 2011-03-04 19:21:54 +0000
490+++ lib/lp/blueprints/stories/blueprints/xx-reviews.txt 1970-01-01 00:00:00 +0000
491@@ -1,150 +0,0 @@
492-
493-Specification Reviews
494-=====================
495-
496-Now, we'll ask someone to review the spec. Let's ask Carlos! We'll pass
497-him a message.
498-
499-First, we load the review request page.
500-
501- >>> browser.addHeader('Authorization', 'Basic test@canonical.com:test')
502- >>> browser.open(
503- ... 'http://blueprints.launchpad.dev/firefox/+spec/canvas')
504- >>> browser.getLink('Request feedback').click()
505- >>> browser.url
506- 'http://blueprints.launchpad.dev/firefox/+spec/canvas/+requestfeedback'
507-
508-This page contains a cancellation link back to the blueprint page, in case you
509-change your mind.
510-
511- >>> print browser.getLink('Cancel').url
512- http://blueprints.launchpad.dev/firefox/+spec/canvas
513-
514-Now we try to POST to the form behind it. We expect to be redirected to the
515-spec home page.
516-
517- >>> browser.getControl(name="field.reviewer").value = "mark"
518- >>> browser.getControl(
519- ... name="field.queuemsg").value = "specification, review thyself"
520- >>> browser.getControl("Add").click()
521- >>> print browser.url
522- http://blueprints.launchpad.dev/firefox/+spec/canvas
523-
524-If we try to request feedback to the same person to the same specification,
525-we'll get a nice error message
526-
527- >>> browser.open(
528- ... 'http://blueprints.launchpad.dev/firefox/+spec/canvas/'
529- ... '+requestfeedback')
530- >>> browser.getControl(name="field.reviewer").value = "mark"
531- >>> browser.getControl(
532- ... name="field.queuemsg").value = "specification, review thyself"
533- >>> browser.getControl("Add").click()
534- >>> print browser.url
535- http://blueprints.launchpad.dev/firefox/+spec/canvas/+requestfeedback
536-
537- >>> for error in get_feedback_messages(browser.contents):
538- ... print error
539- There is 1 error.
540- You've already requested feedback from Mark Shuttleworth
541-
542-I can't request feedback from myself.
543-
544- >>> browser.getControl(name="field.reviewer").value = "name12"
545- >>> browser.getControl(
546- ... name="field.queuemsg").value = "test spec request"
547- >>> browser.getControl("Add").click()
548- >>> print browser.url
549- http://blueprints.launchpad.dev/firefox/+spec/canvas/+requestfeedback
550- >>> for error in get_feedback_messages(browser.contents):
551- ... print error
552- There is 1 error.
553- You can't request feedback from yourself
554-
555-We will see that review request message on the spec page.
556-
557- >>> browser.open('http://blueprints.launchpad.dev/firefox/+spec/canvas')
558- >>> print extract_text(
559- ... find_tag_by_id(browser.contents, 'feedback-requests'))
560- Feedback requests
561- Sample Person requested feedback from Mark Shuttleworth:
562- specification, review thyself
563- ...
564-
565-We will do another 2 feedback requests for mark with different logged in
566-users, first with Carlos.
567-
568- >>> carlos_browser = setupBrowser(auth='Basic carlos@canonical.com:test')
569- >>> carlos_browser.open(
570- ... 'http://blueprints.launchpad.dev/firefox/+spec/canvas/'
571- ... '+requestfeedback')
572- >>> carlos_browser.getControl(name="field.reviewer").value = "mark"
573- >>> carlos_browser.getControl(
574- ... name="field.queuemsg").value = (
575- ... "do we really want to maintain compatibility with windows?")
576- >>> carlos_browser.getControl("Add").click()
577-
578-And then with Foo Bar
579-
580- >>> admin_browser.open(
581- ... 'http://blueprints.launchpad.dev/firefox/+spec/canvas/'
582- ... '+requestfeedback')
583- >>> admin_browser.getControl(name="field.reviewer").value = "mark"
584- >>> admin_browser.getControl(
585- ... name="field.queuemsg").value = (
586- ... "please check my grammer and speling")
587- >>> admin_browser.getControl("Add").click()
588-
589-Now, let's go and clear a review request. Mark has been asked to review spec
590-"canvas". Let's view the page, and tell it that we have completed the review.
591-First, on the spec home page we see an alert reminding us that we have been
592-asked to review this page in particular.
593-
594- >>> mark_browser = setupBrowser(auth='Basic mark@example.com:test')
595- >>> mark_browser.open(
596- ... 'http://blueprints.launchpad.dev/firefox/+spec/canvas/')
597- >>> for message in get_feedback_messages(mark_browser.contents):
598- ... print message
599- You have 3 feedback request(s)...
600-
601-We also see our name in the "feedback requests" portlet.
602-
603- >>> print extract_text(
604- ... find_tag_by_id(browser.contents, 'feedback-requests'))
605- Feedback requests
606- ...
607- Mark Shuttleworth:
608- ...
609-
610-And we see the "Give Feedback" menu item.
611-
612- >>> give_feedback = mark_browser.getLink("Give feedback")
613-
614-Let's load the "+givefeedback" page, to tell the system that our work is
615-complete. Note that the form posts back to the main spec home page.
616-
617- >>> give_feedback.click()
618- >>> print mark_browser.url
619- http://blueprints.launchpad.dev/firefox/+spec/canvas/+givefeedback
620-
621-Now we POST this page back to itself. First, we clear a single item.
622-
623- >>> mark_browser.getControl("Carlos Perelló Marín").selected = True
624- >>> mark_browser.getControl("Save changes").click()
625- >>> print mark_browser.url
626- http://blueprints.launchpad.dev/firefox/+spec/canvas/+givefeedback
627-
628- >>> for message in get_feedback_messages(mark_browser.contents):
629- ... print extract_text(message)
630- Cleared requests from: Carlos ...
631-
632-And now, the remaining two. This time we expect to be redirected.
633-
634- >>> mark_browser.getControl("Sample Person").selected = True
635- >>> mark_browser.getControl("Foo Bar").selected = True
636- >>> mark_browser.getControl("Save changes").click()
637-
638- >>> print mark_browser.url
639- http://blueprints.launchpad.dev/firefox/+spec/canvas
640-
641-
642
643=== modified file 'lib/lp/blueprints/stories/standalone/xx-personviews.txt'
644--- lib/lp/blueprints/stories/standalone/xx-personviews.txt 2011-12-23 23:44:59 +0000
645+++ lib/lp/blueprints/stories/standalone/xx-personviews.txt 2012-06-12 12:14:35 +0000
646@@ -87,16 +87,3 @@
647 Team member workload...
648 Andrew Bennetts's specifications:...
649 Daniel Silverstone has no outstanding specifications...
650-
651-The 'Feedback requests' link displays a list of the specifications that
652-the person was asked to review.
653-
654- >>> browser.open('http://blueprints.launchpad.dev/~name16')
655- >>> browser.getLink('Feedback request').click()
656- >>> browser.url
657- '.../~name16/+specfeedback'
658- >>> print browser.title
659- Feature feedback requests...
660- >>> soup = find_main_content(browser.contents)
661- >>> soup('p')
662- [... 1 specification(s) listed...]
663
664=== removed file 'lib/lp/blueprints/templates/person-specfeedback.pt'
665--- lib/lp/blueprints/templates/person-specfeedback.pt 2009-09-14 22:45:13 +0000
666+++ lib/lp/blueprints/templates/person-specfeedback.pt 1970-01-01 00:00:00 +0000
667@@ -1,31 +0,0 @@
668-<html
669- xmlns="http://www.w3.org/1999/xhtml"
670- xmlns:tal="http://xml.zope.org/namespaces/tal"
671- xmlns:metal="http://xml.zope.org/namespaces/metal"
672- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
673- metal:use-macro="view/macro:page/main_only"
674- i18n:domain="launchpad"
675->
676-
677-<body>
678-
679-<div metal:fill-slot="main" tal:define="specs view/feedback_specs">
680- <p>
681- <tal:no_specs condition="not: specs">
682- No feedback requests to list.
683- </tal:no_specs>
684- <tal:has_specs condition="specs">
685- <span tal:replace="specs/count">7</span> specification(s) listed.
686- Select the specification then choose "Give Feedback" to clear this
687- request from your queue.
688- </tal:has_specs>
689- Anybody can request feedback from anyone else on a particular
690- specification.
691- </p>
692-
693- <tal:per_spec repeat="spec specs">
694- <div tal:replace="structure spec/@@+listing-feedback" />
695- </tal:per_spec>
696-</div>
697-</body>
698-</html>
699
700=== removed file 'lib/lp/blueprints/templates/specification-givefeedback.pt'
701--- lib/lp/blueprints/templates/specification-givefeedback.pt 2009-09-22 09:19:45 +0000
702+++ lib/lp/blueprints/templates/specification-givefeedback.pt 1970-01-01 00:00:00 +0000
703@@ -1,42 +0,0 @@
704-<specification-give-feedback
705- xmlns="http://www.w3.org/1999/xhtml"
706- xmlns:tal="http://xml.zope.org/namespaces/tal"
707- xmlns:metal="http://xml.zope.org/namespaces/metal"
708- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
709- metal:use-macro="view/macro:page/main_only"
710- i18n:domain="launchpad">
711-
712- <div metal:fill-slot="main">
713- <div class="top-portlet">
714- <h2>Select the requests which you wish to remove from your queue</h2>
715- <div metal:use-macro="context/@@launchpad_form/form">
716- <div metal:fill-slot="extra_info">
717- <p>
718- Select the items that you have addressed in this
719- blueprint, and click "Save changes" to clear those
720- feedback requests from your queue.
721- </p>
722- </div>
723- <div metal:fill-slot="widgets">
724- <table class="form">
725- <tbody>
726- <tr tal:repeat="request view/requests">
727- <td colspan="2">
728- <input type="checkbox" name="name"
729- tal:attributes="value request/requester/name;
730- id string:req_${request/requester/name}" />
731- <label tal:content="request/requester/displayname"
732- tal:attributes="for string:req_${request/requester/name}" />
733- <div tal:condition="request/queuemsg"
734- tal:content="request/queuemsg"
735- class="lesser" />
736- </td>
737- </tr>
738- </tbody>
739- </table>
740- </div>
741- </div>
742- </div>
743- </div>
744-
745-</specification-give-feedback>
746
747=== modified file 'lib/lp/blueprints/templates/specification-index.pt'
748--- lib/lp/blueprints/templates/specification-index.pt 2012-06-04 11:41:47 +0000
749+++ lib/lp/blueprints/templates/specification-index.pt 2012-06-12 12:14:35 +0000
750@@ -260,22 +260,6 @@
751 </div>
752 </div>
753
754- <div id="feedback-requests">
755- <h3 tal:condition="not:context/feedbackrequests">Feedback requests</h3>
756-
757- <div tal:replace="structure context/@@+portlet-feedbackqueue" />
758-
759- <ul class="horizontal">
760- <li tal:define="link context_menu/givefeedback"
761- tal:condition="link/enabled">
762- <a tal:replace="structure link/fmt:link" />
763- </li>
764- <li tal:define="link context_menu/requestfeedback"
765- tal:condition="link/enabled">
766- <a tal:replace="structure link/fmt:link" />
767- </li>
768- </ul>
769- </div>
770 </div>
771 </div>
772
773
774=== modified file 'lib/lp/blueprints/templates/specification-listing-detailed.pt'
775--- lib/lp/blueprints/templates/specification-listing-detailed.pt 2009-07-17 17:59:07 +0000
776+++ lib/lp/blueprints/templates/specification-listing-detailed.pt 2012-06-12 12:14:35 +0000
777@@ -46,12 +46,6 @@
778 </tal:block>
779 <i tal:condition="context/whiteboard"
780 tal:content="context/whiteboard">white board goes here</i>
781- <tal:fbreqs repeat="fbreq view/feedbackrequests">
782- <b>Your feedback requested</b> by
783- <span tal:replace="fbreq/requester/displayname">Foo Bar</span>.
784- <i tal:content="fbreq/queuemsg"
785- tal:condition="fbreq/queuemsg">Msg goes here</i>
786- </tal:fbreqs>
787 <tal:sprints condition="context/sprints">
788 <br />
789 <b>Sprints</b>:
790
791=== removed file 'lib/lp/blueprints/templates/specification-listing-feedback.pt'
792--- lib/lp/blueprints/templates/specification-listing-feedback.pt 2009-09-14 22:45:13 +0000
793+++ lib/lp/blueprints/templates/specification-listing-feedback.pt 1970-01-01 00:00:00 +0000
794@@ -1,36 +0,0 @@
795-<tal:root
796- xmlns:tal="http://xml.zope.org/namespaces/tal"
797- xmlns:metal="http://xml.zope.org/namespaces/metal"
798- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
799- omit-tag="">
800-
801-<table class="narrow-listing" style="margin-bottom: 1em;">
802- <tr>
803- <td width="80%">
804- <a tal:replace="structure context/fmt:link" />
805- <img src="/@@/info" alt="Informational"
806- title="Informational specification"
807- tal:condition="context/informational" />
808- </td>
809- <td>
810- <a class="sprite external-link"
811- tal:attributes="href context/specurl"
812- tal:condition="context/specurl">Spec</a>
813- </td>
814- </tr>
815- <tr>
816- <td colspan="2">
817- <span tal:replace="context/summary/fmt:shorten/500">summary</span>.
818- </td>
819- </tr>
820- <tr class="lesser" tal:repeat="fbreq view/feedbackrequests">
821- <td colspan="2">
822- <a tal:replace="structure fbreq/requester/fmt:link">Foo Bar</a>
823- wants your feedback:<br />
824- <span tal:replace="fbreq/queuemsg">
825- Feedback queue message
826- </span>
827- </td>
828- </tr>
829-</table>
830-</tal:root>
831
832=== removed file 'lib/lp/blueprints/templates/specification-portlet-feedbackqueue.pt'
833--- lib/lp/blueprints/templates/specification-portlet-feedbackqueue.pt 2011-03-03 23:45:45 +0000
834+++ lib/lp/blueprints/templates/specification-portlet-feedbackqueue.pt 1970-01-01 00:00:00 +0000
835@@ -1,28 +0,0 @@
836-<tal:root
837- xmlns:tal="http://xml.zope.org/namespaces/tal"
838- xmlns:metal="http://xml.zope.org/namespaces/metal"
839- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
840- omit-tag="">
841-<div
842- tal:define="fbreqs context/feedbackrequests"
843- tal:condition="fbreqs"
844- id="portlet-feedback"
845->
846- <h3>Feedback requests</h3>
847- <div>
848- <ul style="list-style: none; padding-left: 0;">
849- <li tal:repeat="fbreq fbreqs">
850- <tal:requester replace="structure fbreq/requester/fmt:link" />
851- requested feedback from
852- <strong tal:content="structure fbreq/reviewer/fmt:link" />:
853- <span
854- tal:condition="fbreq/queuemsg"
855- tal:content="structure fbreq/queuemsg/fmt:text-to-html"
856- style="font-style:italic; text-indent:2em;"
857- />
858- </li>
859- </ul>
860- </div>
861-
862-</div>
863-</tal:root>
864
865=== removed file 'lib/lp/blueprints/templates/specification-requestfeedback.pt'
866--- lib/lp/blueprints/templates/specification-requestfeedback.pt 2009-09-22 10:48:09 +0000
867+++ lib/lp/blueprints/templates/specification-requestfeedback.pt 1970-01-01 00:00:00 +0000
868@@ -1,32 +0,0 @@
869-<html
870- xmlns="http://www.w3.org/1999/xhtml"
871- xmlns:tal="http://xml.zope.org/namespaces/tal"
872- xmlns:metal="http://xml.zope.org/namespaces/metal"
873- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
874- metal:use-macro="view/macro:page/main_side"
875- i18n:domain="launchpad"
876->
877-
878-<body>
879-
880-<div metal:fill-slot="side">
881- <div class="portlet"
882- tal:content="structure context/@@+portlet-feedbackqueue" />
883-</div>
884-
885-<div metal:fill-slot="main">
886-
887- <div metal:use-macro="context/@@launchpad_form/form">
888-
889- <p metal:fill-slot="extra_info" class="documentDescription">
890- You can request feedback from a specific person,
891- including a brief message to explain what you need them to look at or
892- consider.
893- </p>
894-
895- </div>
896-
897-</div>
898-
899-</body>
900-</html>
901
902=== modified file 'lib/lp/registry/browser/configure.zcml'
903--- lib/lp/registry/browser/configure.zcml 2012-04-06 15:57:35 +0000
904+++ lib/lp/registry/browser/configure.zcml 2012-06-12 12:14:35 +0000
905@@ -981,13 +981,6 @@
906 template="../../blueprints/templates/person-table-specworkload.pt"/>
907 <browser:page
908 for="lp.registry.interfaces.person.IPerson"
909- name="+specfeedback"
910- facet="specifications"
911- class="lp.registry.browser.person.PersonSpecFeedbackView"
912- permission="zope.Public"
913- template="../../blueprints/templates/person-specfeedback.pt"/>
914- <browser:page
915- for="lp.registry.interfaces.person.IPerson"
916 name="+specworkload"
917 facet="specifications"
918 class="lp.registry.browser.person.PersonSpecWorkloadView"
919
920=== modified file 'lib/lp/registry/browser/person.py'
921--- lib/lp/registry/browser/person.py 2012-05-24 12:05:42 +0000
922+++ lib/lp/registry/browser/person.py 2012-06-12 12:14:35 +0000
923@@ -43,7 +43,6 @@
924 'PersonSetActionNavigationMenu',
925 'PersonSetContextMenu',
926 'PersonSetNavigation',
927- 'PersonSpecFeedbackView',
928 'PersonSpecWorkloadTableView',
929 'PersonSpecWorkloadView',
930 'PersonSpecsMenu',
931@@ -148,9 +147,7 @@
932 LaunchpadRadioWidget,
933 LaunchpadRadioWidgetWithDescription,
934 )
935-from lp.blueprints.browser.specificationtarget import HasSpecificationsView
936 from lp.blueprints.enums import (
937- SpecificationFilter,
938 SpecificationWorkItemStatus,
939 )
940 from lp.bugs.interfaces.bugtask import (
941@@ -602,8 +599,7 @@
942 usedfor = IPerson
943 facet = 'specifications'
944 links = ['assignee', 'drafter', 'approver',
945- 'subscriber', 'registrant', 'feedback',
946- 'workload']
947+ 'subscriber', 'registrant', 'workload']
948
949 def registrant(self):
950 text = 'Registrant'
951@@ -631,12 +627,6 @@
952 text = 'Subscriber'
953 return Link('+specs?role=subscriber', text, icon='blueprint')
954
955- def feedback(self):
956- text = 'Feedback requests'
957- summary = 'List specs where feedback has been requested from %s' % (
958- self.context.displayname)
959- return Link('+specfeedback', text, summary, icon='info')
960-
961 def workload(self):
962 text = 'Workload'
963 summary = 'Show all specification work assigned'
964@@ -1356,17 +1346,6 @@
965 for spec in self.context.specifications()]
966
967
968-class PersonSpecFeedbackView(HasSpecificationsView):
969-
970- label = 'Feature feedback requests'
971- page_title = label
972-
973- @cachedproperty
974- def feedback_specs(self):
975- filter = [SpecificationFilter.FEEDBACK]
976- return self.context.specifications(filter=filter)
977-
978-
979 class PersonVouchersView(LaunchpadFormView):
980 """Form for displaying and redeeming commercial subscription vouchers."""
981
982
983=== modified file 'lib/lp/registry/doc/person.txt'
984--- lib/lp/registry/doc/person.txt 2012-04-16 15:35:47 +0000
985+++ lib/lp/registry/doc/person.txt 2012-06-12 12:14:35 +0000
986@@ -93,7 +93,6 @@
987 ... 'randomuser@randomhost.com', PersonCreationRationale.POFILEIMPORT,
988 ... comment='when importing the Portuguese translation of firefox',
989 ... hide_email_addresses=True)
990- >>> import transaction
991 >>> transaction.commit()
992 >>> p.teamowner is None
993 True
994@@ -1194,16 +1193,15 @@
995 ... SpecificationFilter.COMPLETE]).count()
996 0
997
998-Next, Carlos has three incomplete specs *related* to him:
999+Next, Carlos has two incomplete specs *related* to him:
1000
1001 >>> filter = []
1002 >>> for spec in carlos.specifications(filter=filter):
1003 ... print spec.name, spec.is_complete, spec.informational
1004 svg-support False False
1005 extension-manager-upgrades False True
1006- media-integrity-check False False
1007
1008-Carlos has 2 specifications assigned to him:
1009+These 2 specifications are assigned to Carlos:
1010
1011 >>> for spec in carlos.assigned_specs:
1012 ... print spec.name
1013@@ -1225,13 +1223,6 @@
1014 ... print spec.name
1015 extension-manager-upgrades
1016
1017-The Foo Bar person has a single spec which has feedback requested:
1018-
1019- >>> filter = [SpecificationFilter.FEEDBACK]
1020- >>> for spec in foobar.specifications(filter=filter):
1021- ... print spec.name
1022- e4x
1023-
1024 But has registered 5 of them:
1025
1026 >>> filter = [SpecificationFilter.CREATOR]
1027
1028=== modified file 'lib/lp/registry/model/person.py'
1029--- lib/lp/registry/model/person.py 2012-06-11 09:17:44 +0000
1030+++ lib/lp/registry/model/person.py 2012-06-12 12:14:35 +0000
1031@@ -844,7 +844,6 @@
1032 SpecificationFilter.ASSIGNEE,
1033 SpecificationFilter.DRAFTER,
1034 SpecificationFilter.APPROVER,
1035- SpecificationFilter.FEEDBACK,
1036 SpecificationFilter.SUBSCRIBER])
1037 for role in roles:
1038 if role in filter:
1039@@ -884,10 +883,6 @@
1040 base += """ OR Specification.id in
1041 (SELECT specification FROM SpecificationSubscription
1042 WHERE person = %(my_id)d)"""
1043- if SpecificationFilter.FEEDBACK in filter:
1044- base += """ OR Specification.id in
1045- (SELECT specification FROM SpecificationFeedback
1046- WHERE reviewer = %(my_id)d)"""
1047 base += ') '
1048
1049 # filter out specs on inactive products
1050@@ -3904,40 +3899,6 @@
1051 DELETE FROM StructuralSubscription WHERE subscriber=%(from_id)d
1052 ''' % vars())
1053
1054- def _mergeSpecificationFeedback(self, cur, from_id, to_id):
1055- # Update the SpecificationFeedback entries that will not conflict
1056- # and trash the rest.
1057-
1058- # First we handle the reviewer.
1059- cur.execute('''
1060- UPDATE SpecificationFeedback
1061- SET reviewer=%(to_id)d
1062- WHERE reviewer=%(from_id)d AND specification NOT IN
1063- (
1064- SELECT specification
1065- FROM SpecificationFeedback
1066- WHERE reviewer = %(to_id)d
1067- )
1068- ''' % vars())
1069- cur.execute('''
1070- DELETE FROM SpecificationFeedback WHERE reviewer=%(from_id)d
1071- ''' % vars())
1072-
1073- # And now we handle the requester.
1074- cur.execute('''
1075- UPDATE SpecificationFeedback
1076- SET requester=%(to_id)d
1077- WHERE requester=%(from_id)d AND specification NOT IN
1078- (
1079- SELECT specification
1080- FROM SpecificationFeedback
1081- WHERE requester = %(to_id)d
1082- )
1083- ''' % vars())
1084- cur.execute('''
1085- DELETE FROM SpecificationFeedback WHERE requester=%(from_id)d
1086- ''' % vars())
1087-
1088 def _mergeSpecificationSubscription(self, cur, from_id, to_id):
1089 # Update the SpecificationSubscription entries that will not conflict
1090 # and trash the rest
1091@@ -4334,10 +4295,6 @@
1092 self._mergeStructuralSubscriptions(cur, from_id, to_id)
1093 skip.append(('structuralsubscription', 'subscriber'))
1094
1095- self._mergeSpecificationFeedback(cur, from_id, to_id)
1096- skip.append(('specificationfeedback', 'reviewer'))
1097- skip.append(('specificationfeedback', 'requester'))
1098-
1099 self._mergeSpecificationSubscription(cur, from_id, to_id)
1100 skip.append(('specificationsubscription', 'person'))
1101