Merge lp:~sinzui/launchpad/edit-question-bug-210312 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Approved by: Aaron Bentley
Approved revision: not available
Merged at revision: not available
Proposed branch: lp:~sinzui/launchpad/edit-question-bug-210312
Merge into: lp:launchpad
Diff against target: 333 lines (+86/-60)
7 files modified
lib/lp/answers/browser/question.py (+11/-12)
lib/lp/answers/browser/tests/views.txt (+31/-12)
lib/lp/answers/interfaces/faq.py (+2/-2)
lib/lp/answers/interfaces/question.py (+1/-1)
lib/lp/answers/stories/question-subscriptions.txt (+24/-24)
lib/lp/answers/stories/this-is-a-faq.txt (+6/-2)
lib/lp/answers/templates/question-subscription.pt (+11/-7)
To merge this branch: bzr merge lp:~sinzui/launchpad/edit-question-bug-210312
Reviewer Review Type Date Requested Status
Aaron Bentley (community) Approve
Review via email: mp+15695@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Curtis Hovey (sinzui) wrote :
Download full text (4.6 KiB)

This is my branch to fix some simple issues with Launchpad Answers.

    lp:~sinzui/launchpad/edit-question-bug-210312
    Diff size: 334
    Launchpad bug: https://bugs.launchpad.net/bugs/210312
                   https://bugs.launchpad.net/bugs/275475
                   https://bugs.launchpad.net/bugs/386158
    Test command: ./bin/test -vv \
        -t answers.*views.txt
        -t question-subscriptions
        -t this-is-a-faq
    Pre-implementation: no one
    Target release: 3.1.12

= Fix some simple issues with Launchpad Answers =

Bug 210312 [cannot edit the language of the question]
    The question +edit page only shows the user's preferred languages. It
    must show all languages so that the user can fix the language.

Bug 275475 [launchpad displays the hint for subscribing when i click on
    unsubscribe]
    The paragraph talks about subscribing, but the action is unsubscribing.

Bug 386158 [confusingly redundant fields in create faq page]
    There are two textareas, each of which seems to want the answer to the faq.

== Rules ==

Bug 210312 [cannot edit the language of the question]
    * Remove the QuestionSupportLanguageMixin and use the interface's
      language

Bug 275475 [launchpad displays the hint for subscribing when i click on
    unsubscribe]
    * Add a condition to the template to select the right paragraph to show.

Bug 386158 [confusingly redundant fields in create faq page]
    * Revise the field labels and hints to distinguish between the FAQ and
      the question the user is answering.

== QA ==

Bug 210312 [cannot edit the language of the question]
    * Edit a question on edge.
    * Verify the language choice contains every language registered in
      Launchpad.

Bug 275475 [launchpad displays the hint for subscribing when i click on
    unsubscribe]
    * Choose the subscribe link on a a question.
    * Verify the link to your subscriptions page actually goes to your
      subscription page.
    * Choose the Subscribe button
    * Choose the Unsubscribe link
    * Verify that the paragraph talks about the consequence of unsubscribing.

Bug 386158 [confusingly redundant fields in create faq page]
    * Choose create a new FAQ link from any question.
    * Verify the FAQ field speak of "this FAQ".
    * Verify the last field labeled "Additional comment for question #..."

== Lint ==

Linting changed files:
  lib/lp/answers/browser/question.py
  lib/lp/answers/browser/tests/views.txt
  lib/lp/answers/interfaces/faq.py
  lib/lp/answers/interfaces/question.py
  lib/lp/answers/stories/question-subscriptions.txt
  lib/lp/answers/stories/this-is-a-faq.txt
  lib/lp/answers/templates/question-subscription.pt

== Test ==

    * lib/lp/answers/browser/tests/views.txt
      * Modernised part of the test--they predated LaunchpadFormView
      * Added label and page_title tests to verify that sane fragments
        for subscribe/unsubscribe were created for the automated rules.
      * Verified that the QuestionEdit form uses the LanguageVocabulary.
    * lib/lp/answers/stories/question-subscriptions.txt
      * Removed some cruft from the story.
      * Revised the story to verify the links in the subscr...

Read more...

Revision history for this message
Aaron Bentley (abentley) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/answers/browser/question.py'
--- lib/lp/answers/browser/question.py 2009-11-11 22:17:17 +0000
+++ lib/lp/answers/browser/question.py 2009-12-05 17:20:55 +0000
@@ -46,6 +46,7 @@
4646
47from lazr.lifecycle.event import ObjectModifiedEvent47from lazr.lifecycle.event import ObjectModifiedEvent
48from lazr.lifecycle.snapshot import Snapshot48from lazr.lifecycle.snapshot import Snapshot
49from lazr.restful.interface import copy_field
4950
50from canonical.cachedproperty import cachedproperty51from canonical.cachedproperty import cachedproperty
51from canonical.launchpad import _52from canonical.launchpad import _
@@ -321,7 +322,7 @@
321322
322 @property323 @property
323 def page_title(self):324 def page_title(self):
324 return 'Subscription to question #%s' % self.context.id325 return 'Subscription'
325326
326 @property327 @property
327 def label(self):328 def label(self):
@@ -452,8 +453,7 @@
452 "The language in which this question is written. "453 "The language in which this question is written. "
453 "The languages marked with a star (*) are the "454 "The languages marked with a star (*) are the "
454 "languages spoken by at least one answer contact in "455 "languages spoken by at least one answer contact in "
455 "the community."456 "the community.")),
456 )),
457 render_context=self.render_context)457 render_context=self.render_context)
458458
459 def shouldWarnAboutUnsupportedLanguage(self):459 def shouldWarnAboutUnsupportedLanguage(self):
@@ -659,11 +659,12 @@
659 cancel_url = next_url659 cancel_url = next_url
660660
661661
662class QuestionEditView(QuestionSupportLanguageMixin, LaunchpadEditFormView):662class QuestionEditView(LaunchpadEditFormView):
663 """View for editing a Question."""663 """View for editing a Question."""
664 schema = IQuestion664 schema = IQuestion
665 label = 'Edit question'665 label = 'Edit question'
666 field_names = ["title", "description", "target", "assignee", "whiteboard"]666 field_names = [
667 "language", "title", "description", "target", "assignee", "whiteboard"]
667668
668 custom_widget('title', TextWidget, displayWidth=40)669 custom_widget('title', TextWidget, displayWidth=40)
669 custom_widget('whiteboard', TextAreaWidget, height=5)670 custom_widget('whiteboard', TextAreaWidget, height=5)
@@ -685,10 +686,6 @@
685 self.form_fields = self.form_fields.omit("distribution",686 self.form_fields = self.form_fields.omit("distribution",
686 "sourcepackagename", "product")687 "sourcepackagename", "product")
687688
688 # Add the language field with a vocabulary specialized for display
689 # purpose.
690 self.form_fields = self.createLanguageField() + self.form_fields
691
692 editable_fields = []689 editable_fields = []
693 for field in self.form_fields:690 for field in self.form_fields:
694 if zope.security.canWrite(self.context, field.__name__):691 if zope.security.canWrite(self.context, field.__name__):
@@ -764,7 +761,6 @@
764 return '%s suggests this article as an answer to your question:' % (761 return '%s suggests this article as an answer to your question:' % (
765 self.user.displayname)762 self.user.displayname)
766763
767
768 def getFAQMessageReference(self, faq):764 def getFAQMessageReference(self, faq):
769 """Return the reference for the FAQ to use in the linking message."""765 """Return the reference for the FAQ to use in the linking message."""
770 return smartquote('FAQ #%s: "%s".' % (faq.id, faq.title))766 return smartquote('FAQ #%s: "%s".' % (faq.id, faq.title))
@@ -991,7 +987,7 @@
991 def original_bug(self):987 def original_bug(self):
992 """Return the bug that the question was created from or None."""988 """Return the bug that the question was created from or None."""
993 for buglink in self.context.bug_links:989 for buglink in self.context.bug_links:
994 if (check_permission('launchpad.View', buglink.bug)990 if (check_permission('launchpad.View', buglink.bug)
995 and buglink.bug.owner == self.context.owner991 and buglink.bug.owner == self.context.owner
996 and buglink.bug.datecreated == self.context.datecreated):992 and buglink.bug.datecreated == self.context.datecreated):
997 return buglink.bug993 return buglink.bug
@@ -1140,7 +1136,10 @@
1140 Adds a message field to the form.1136 Adds a message field to the form.
1141 """1137 """
1142 super(QuestionCreateFAQView, self).setUpFields()1138 super(QuestionCreateFAQView, self).setUpFields()
1143 self.form_fields += form.Fields(IQuestionLinkFAQForm['message'])1139 self.form_fields += form.Fields(
1140 copy_field(IQuestionLinkFAQForm['message']))
1141 self.form_fields['message'].field.title = _(
1142 'Additional comment for question #%s' % self.context.id)
1144 self.form_fields['message'].custom_widget = (1143 self.form_fields['message'].custom_widget = (
1145 self.custom_widgets['message'])1144 self.custom_widgets['message'])
11461145
11471146
=== modified file 'lib/lp/answers/browser/tests/views.txt'
--- lib/lp/answers/browser/tests/views.txt 2009-09-28 09:11:17 +0000
+++ lib/lp/answers/browser/tests/views.txt 2009-12-05 17:20:55 +0000
@@ -38,34 +38,46 @@
38This view is used to subscribe and unsubscribe from a question.38This view is used to subscribe and unsubscribe from a question.
39Subscription is done when the user click on the 'Subscribe' button.39Subscription is done when the user click on the 'Subscribe' button.
4040
41 >>> request = LaunchpadTestRequest(form={'subscribe': 'Subscribe'})41 >>> view = create_initialized_view(question_three, name='+subscribe')
42 >>> request.method = 'POST'42 >>> print view.label
43 >>> view = getMultiAdapter((question_three, request), name='+subscribe')43 Subscribe to question
44 >>> view.initialize()44
45 >>> print view.page_title
46 Subscription
47
48 >>> form = {'subscribe': 'Subscribe'}
49 >>> view = create_initialized_view(
50 ... question_three, name='+subscribe', form=form)
45 >>> question_three.isSubscribed(getUtility(ILaunchBag).user)51 >>> question_three.isSubscribed(getUtility(ILaunchBag).user)
46 True52 True
4753
48A notification message is displayed and the view redirect to the question54A notification message is displayed and the view redirect to the question
49view page.55view page.
5056
51 >>> for notice in request.notifications:57 >>> for notice in view.request.notifications:
52 ... print notice.message58 ... print notice.message
53 You have subscribed to this question.59 You have subscribed to this question.
54 >>> request.response.getHeader('Location')60
61 >>> view.request.response.getHeader('Location')
55 '.../+question/3'62 '.../+question/3'
5663
57Unsubscription works in a similar manner.64Unsubscription works in a similar manner.
5865
59 >>> request = LaunchpadTestRequest(form={'subscribe': 'Unsubscribe'})66 >>> view = create_initialized_view(question_three, name='+subscribe')
60 >>> request.method = 'POST'67 >>> print view.label
61 >>> view = getMultiAdapter((question_three, request), name='+subscribe')68 Unsubscribe from question
62 >>> view.initialize()69
70 >>> form = {'subscribe': 'Unsubscribe'}
71 >>> view = create_initialized_view(
72 ... question_three, name='+subscribe', form=form)
63 >>> question_three.isSubscribed(getUtility(ILaunchBag).user)73 >>> question_three.isSubscribed(getUtility(ILaunchBag).user)
64 False74 False
65 >>> for notice in request.notifications:75
76 >>> for notice in view.request.notifications:
66 ... print notice.message77 ... print notice.message
67 You have unsubscribed from this question.78 You have unsubscribed from this question.
68 >>> request.response.getHeader('Location')79
80 >>> view.request.response.getHeader('Location')
69 '.../+question/3'81 '.../+question/3'
7082
71These two actions didn't generate any notification mails:83These two actions didn't generate any notification mails:
@@ -503,6 +515,13 @@
503 >>> print question_three.whiteboard515 >>> print question_three.whiteboard
504 Some note516 Some note
505517
518The question language can be set to any language registered with
519Launchpad--it is not restricted to the user's preferred languages.
520
521 >>> view = create_initialized_view(question_three, name='+edit')
522 >>> view.widgets['language'].vocabulary
523 <canonical.launchpad.vocabularies.dbobjects.LanguageVocabulary ...>
524
506In a similar manner, the sourcepackagename field can only be updated on525In a similar manner, the sourcepackagename field can only be updated on
507a distribution question:526a distribution question:
508527
509528
=== modified file 'lib/lp/answers/interfaces/faq.py'
--- lib/lp/answers/interfaces/faq.py 2009-07-17 00:26:05 +0000
+++ lib/lp/answers/interfaces/faq.py 2009-12-05 17:20:55 +0000
@@ -38,7 +38,7 @@
3838
39 title = Title(39 title = Title(
40 title=_('Title'),40 title=_('Title'),
41 description=_('The title describing the FAQ, often a question.'),41 description=_('The title describing this FAQ, often a question.'),
42 required=True)42 required=True)
4343
44 keywords = TextLine(44 keywords = TextLine(
@@ -49,7 +49,7 @@
49 content = Text(49 content = Text(
50 title=_('Content'),50 title=_('Content'),
51 description=_(51 description=_(
52 'The answer to the question in plain text. You may choose to '52 'The answer for this FAQ in plain text. You may choose to '
53 'include a URL to an external FAQ.'),53 'include a URL to an external FAQ.'),
54 required=True)54 required=True)
5555
5656
=== modified file 'lib/lp/answers/interfaces/question.py'
--- lib/lp/answers/interfaces/question.py 2009-07-17 00:26:05 +0000
+++ lib/lp/answers/interfaces/question.py 2009-12-05 17:20:55 +0000
@@ -486,7 +486,7 @@
486 message = Text(486 message = Text(
487 title=_('Answer Message'),487 title=_('Answer Message'),
488 description=_(488 description=_(
489 'Enter a message that will be added as the question answer. '489 'Enter a comment that will be added as the question comments. '
490 'The title of the FAQ will be automatically appended to this '490 'The title of the FAQ will be automatically appended to this '
491 'message.'),491 'message.'),
492 required=True)492 required=True)
493493
=== modified file 'lib/lp/answers/stories/question-subscriptions.txt'
--- lib/lp/answers/stories/question-subscriptions.txt 2009-09-25 08:39:54 +0000
+++ lib/lp/answers/stories/question-subscriptions.txt 2009-12-05 17:20:55 +0000
@@ -7,16 +7,18 @@
7== Subscribing ==7== Subscribing ==
88
9To subscribe, users use the 'Subscribe' link and then confirm that9To subscribe, users use the 'Subscribe' link and then confirm that
10they want to subscribe by clicking on the 'Subscribe' button.10they want to subscribe by clicking on the 'Subscribe' button. The user
11sees a link to his subscribed questions.
1112
12 >>> user_browser.open(13 >>> user_browser.open(
13 ... 'http://launchpad.dev/firefox/+question/2')14 ... 'http://launchpad.dev/firefox/+question/2')
14 >>> link = user_browser.getLink('Subscribe')15 >>> user_browser.getLink('Subscribe').click()
15 >>> link.url
16 '.../+question/2/+subscribe'
17 >>> link.click()
18 >>> print user_browser.title16 >>> print user_browser.title
19 Subscription to question...17 Subscription : Question #2 ...
18
19 >>> print user_browser.getLink('your subscribed questions page')
20 <Link ...'http://answers.launchpad.dev/~no-priv/+subscribedquestions'>
21
20 >>> user_browser.getControl('Subscribe').click()22 >>> user_browser.getControl('Subscribe').click()
2123
22A message confirming that he was subscribed is displayed and the user24A message confirming that he was subscribed is displayed and the user
@@ -26,11 +28,10 @@
26 ... print message28 ... print message
27 You have subscribed to this question.29 You have subscribed to this question.
2830
29 >>> portlet = find_tag_by_id(user_browser.contents, 'subscribers')31 >>> print extract_text(find_tag_by_id(
30 >>> portlet.first('h2')32 ... user_browser.contents, 'subscribers'))
31 <h2>Subscribers</h2>33 Subscribers
32 >>> portlet.first('ul')34 No Privileges Person
33 <ul> ...No Privileges Person...
3435
3536
36== Unsubscribing ==37== Unsubscribing ==
@@ -39,14 +40,14 @@
39becomes an 'Unsubscribe' link. To unsubscribe, the user follows that40becomes an 'Unsubscribe' link. To unsubscribe, the user follows that
40link and then click on the 'Unsubscribe' button.41link and then click on the 'Unsubscribe' button.
4142
42 >>> link = user_browser.getLink('Unsubscribe')43 >>> link = user_browser.getLink('Unsubscribe').click()
43 >>> link.url44 >>> print user_browser.title
44 '.../+question/2/+subscribe'45 Subscription : Question #2 ...
45 >>> link.click()46
4647 >>> print extract_text(
47 >>> soup = find_main_content(user_browser.contents)48 ... find_tag_by_id(user_browser.contents, 'unsubscribe'))
48 >>> soup.first('h1')49 Unsubscribing from this question ...
49 <h1>Unsubscribe from question</h1>50
50 >>> user_browser.getControl('Unsubscribe').click()51 >>> user_browser.getControl('Unsubscribe').click()
5152
52A confirmation is displayed and the user, which was unsubscribed from53A confirmation is displayed and the user, which was unsubscribed from
@@ -56,11 +57,10 @@
56 ... print message57 ... print message
57 You have unsubscribed from this question.58 You have unsubscribed from this question.
5859
59 >>> portlet = find_tag_by_id(user_browser.contents, 'subscribers')60 >>> print extract_text(find_tag_by_id(
60 >>> portlet.first('p')61 ... user_browser.contents, 'subscribers'))
61 <p>62 Subscribers
62 <i>No subscribers.</i>63 No subscribers.
63 </p>
6464
6565
66== Subscribing While Posting A Message ==66== Subscribing While Posting A Message ==
6767
=== modified file 'lib/lp/answers/stories/this-is-a-faq.txt'
--- lib/lp/answers/stories/this-is-a-faq.txt 2009-11-14 16:30:47 +0000
+++ lib/lp/answers/stories/this-is-a-faq.txt 2009-12-05 17:20:55 +0000
@@ -244,9 +244,13 @@
244There is a 'Message' field that will be used to answer the question.244There is a 'Message' field that will be used to answer the question.
245It is pre-filled, but he can change its value:245It is pre-filled, but he can change its value:
246246
247 >>> print owner_browser.getControl('Message').value247 >>> print owner_browser.getControl(
248 ... 'Additional comment for question #2').value
248 Sample Person suggests this article as an answer to your question:249 Sample Person suggests this article as an answer to your question:
249 >>> owner_browser.getControl('Message').value = 'Read the Fine Answer:'250
251 >>> owner_browser.getControl(
252 ... 'Additional comment for question #2').value = (
253 ... 'Read the Fine Answer:')
250254
251After clicking the 'Create' button, the FAQ is created and the user is255After clicking the 'Create' button, the FAQ is created and the user is
252returned to the question page.256returned to the question page.
253257
=== modified file 'lib/lp/answers/templates/question-subscription.pt'
--- lib/lp/answers/templates/question-subscription.pt 2009-08-12 19:54:50 +0000
+++ lib/lp/answers/templates/question-subscription.pt 2009-12-05 17:20:55 +0000
@@ -9,16 +9,20 @@
99
10<body>10<body>
1111
12<tal:heading metal:fill-slot="heading">
13 <h1 tal:content="view/label">Subscribe to question</h1>
14</tal:heading>
15
16<div metal:fill-slot="main">12<div metal:fill-slot="main">
1713
18 <p>14 <p id="subscribe"
15 tal:condition="not: view/subscription">
19 Subscribing to a question makes it show up on16 Subscribing to a question makes it show up on
20 <a tal:attributes="href string:/~${request/lp:person/name}/+questions"17 <a tal:attributes="href view/user/menu:navigation/subscribed/fmt:url"
21 >your Answers page</a>.18 >your subscribed questions page</a>. You will receive email notifications
19 about updates to this question.
20 </p>
21
22 <p id="unsubscribe"
23 tal:condition="view/subscription">
24 Unsubscribing from this question will stop email notifications
25 about updates to this question.
22 </p>26 </p>
2327
24 <form action="."28 <form action="."