Merge lp:~allenap/launchpad/just-comment-on-question-bug-114710 into lp:launchpad

Proposed by Gavin Panella
Status: Merged
Approved by: Barry Warsaw
Approved revision: no longer in the source branch.
Merged at revision: not available
Proposed branch: lp:~allenap/launchpad/just-comment-on-question-bug-114710
Merge into: lp:launchpad
Diff against target: 498 lines
8 files modified
lib/lp/answers/browser/question.py (+31/-17)
lib/lp/answers/browser/tests/views.txt (+16/-15)
lib/lp/answers/stories/question-edit.txt (+13/-8)
lib/lp/answers/stories/question-obfuscation.txt (+1/-1)
lib/lp/answers/stories/question-reject-and-change-status.txt (+11/-0)
lib/lp/answers/stories/question-workflow.txt (+41/-21)
lib/lp/answers/stories/this-is-a-faq.txt (+6/-6)
lib/lp/answers/templates/question-index.pt (+1/-1)
To merge this branch: bzr merge lp:~allenap/launchpad/just-comment-on-question-bug-114710
Reviewer Review Type Date Requested Status
Barry Warsaw (community) code ui* Approve
Review via email: mp+12405@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

The first change in this branch is to make the "Add comment" button
always appear. I just followed sinzui's patch in the bug report and
then updated tests. I've done other stuff in this branch, so I've
broken out just the changes that account for this fix here:

  http://pastebin.ubuntu.com/277696/

The other stuff was adding a few cancel links, changing some of the
form action wordings, and fixing a bit of lint:

  http://pastebin.ubuntu.com/277724/

To test:
  bin/test -vvt lp/answers

The only lint reported is bogus.

Revision history for this message
Barry Warsaw (barry) wrote :
Download full text (4.4 KiB)

Wow, I am so psyched you are adding this. It's a huge annoyance every time
I'm CHR. Thanks!

We talked about the order of the buttons and since we want to encourage people
to answer the question, it seems like a better order would be "Add Answer"
"Add Information Request" "Add Comment".

We also discussed possible confusion that users may have as to what the
different actions mean. We agreed that it might be nice to add a (?) help
pop up but also that that's outside the scope of this branch.

I have only minor comments on style, but otherwise the code looks great.
merge-conditional, r=me with their consideration.

=== modified file 'lib/lp/answers/browser/question.py'
--- lib/lp/answers/browser/question.py 2009-09-22 15:43:52 +0000
+++ lib/lp/answers/browser/question.py 2009-09-25 09:01:14 +0000
> @@ -678,11 +683,16 @@
> editable_fields.append(field.__name__)
> self.form_fields = self.form_fields.select(*editable_fields)
>
> - @action(u"Continue", name="change")
> + @action(u"Save Changes", name="change")

Why do you use a u-string here but everywhere else you use the translation
marker _()? I think for consistency you should change this to
_('Save Changes')

> @@ -810,12 +823,10 @@
> def canAddComment(self, action):
> """Return whether the comment action should be displayed.
>
> - Comments (message without a status change) can be added when the
> - question is solved or invalid
> + Comments (message without a status change) can be added at any
> + time by any logged-in user.
> """
> - return (self.user is not None and
> - self.context.status in [
> - QuestionStatus.SOLVED, QuestionStatus.INVALID])
> + return (self.user is not None)

You don't need the parentheses any more.

=== modified file 'lib/lp/answers/stories/question-edit.txt'
--- lib/lp/answers/stories/question-edit.txt 2009-08-25 21:30:02 +0000
+++ lib/lp/answers/stories/question-edit.txt 2009-09-25 09:01:14 +0000
> @@ -14,6 +14,11 @@
> >>> user_browser.url
> '.../firefox/+question/2/+edit'
>
> +There is a cancel link should the user decide otherwise:
> +
> + >>> user_browser.getLink('Cancel').url
> + '.../firefox/+question/2'

You should print the url here and elsewhere to avoid the quote noise.

=== modified file 'lib/lp/answers/stories/question-reject-and-change-status.txt'
--- lib/lp/answers/stories/question-reject-and-change-status.txt 2009-08-25 21:30:02 +0000
+++ lib/lp/answers/stories/question-reject-and-change-status.txt 2009-09-25 09:01:14 +0000
> @@ -35,6 +35,12 @@
> There is 1 error.
> You must provide an explanation message.
>
> +At this point the user might decide this is a bad idea, so there is a
> +cancel link to take him back to the question:
> +
> + >>> admin_browser.getLink('Cancel').url
> + '.../firefox/+question/2'

print

> +
> Entering an explanation message and clicking the 'Reject' button,
> will reject the question.
>
> @@ -108,6 +114,11 @@
> >>> admin_browser.getControl('Status', index=0).displayValue
> ['Invalid']
>
> +There is also a cancel link should the user decid...

Read more...

review: Approve (code ui*)

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-09-24 11:10:26 +0000
+++ lib/lp/answers/browser/question.py 2009-09-29 15:26:13 +0000
@@ -639,7 +639,12 @@
639 self.context.setStatus(self.user, data['status'], data['message'])639 self.context.setStatus(self.user, data['status'], data['message'])
640 self.request.response.addNotification(640 self.request.response.addNotification(
641 _('Question status updated.'))641 _('Question status updated.'))
642 self.request.response.redirect(canonical_url(self.context))642
643 @property
644 def next_url(self):
645 return canonical_url(self.context)
646
647 cancel_url = next_url
643648
644649
645class QuestionEditView(QuestionSupportLanguageMixin, LaunchpadEditFormView):650class QuestionEditView(QuestionSupportLanguageMixin, LaunchpadEditFormView):
@@ -678,11 +683,16 @@
678 editable_fields.append(field.__name__)683 editable_fields.append(field.__name__)
679 self.form_fields = self.form_fields.select(*editable_fields)684 self.form_fields = self.form_fields.select(*editable_fields)
680685
681 @action(u"Continue", name="change")686 @action(_("Save Changes"), name="change")
682 def change_action(self, action, data):687 def change_action(self, action, data):
683 """Update the Question from the request form data."""688 """Update the Question from the request form data."""
684 self.updateContextFromData(data)689 self.updateContextFromData(data)
685 self.request.response.redirect(canonical_url(self.context))690
691 @property
692 def next_url(self):
693 return canonical_url(self.context)
694
695 cancel_url = next_url
686696
687697
688class QuestionRejectView(LaunchpadFormView):698class QuestionRejectView(LaunchpadFormView):
@@ -701,15 +711,12 @@
701 self.setFieldError(711 self.setFieldError(
702 'message', _('You must provide an explanation message.'))712 'message', _('You must provide an explanation message.'))
703713
704 @action(_('Reject'))714 @action(_('Reject Question'), name="reject")
705 def reject_action(self, action, data):715 def reject_action(self, action, data):
706 """Reject the Question."""716 """Reject the Question."""
707 self.context.reject(self.user, data['message'])717 self.context.reject(self.user, data['message'])
708 self.request.response.addNotification(718 self.request.response.addNotification(
709 _('You have rejected this question.'))719 _('You have rejected this question.'))
710 self.request.response.redirect(canonical_url(self.context))
711 return ''
712
713720
714 def initialize(self):721 def initialize(self):
715 """See `LaunchpadFormView`.722 """See `LaunchpadFormView`.
@@ -724,6 +731,12 @@
724731
725 LaunchpadFormView.initialize(self)732 LaunchpadFormView.initialize(self)
726733
734 @property
735 def next_url(self):
736 return canonical_url(self.context)
737
738 cancel_url = next_url
739
727740
728class LinkFAQMixin:741class LinkFAQMixin:
729 """Mixin that contains common functionality for views linking a FAQ."""742 """Mixin that contains common functionality for views linking a FAQ."""
@@ -814,12 +827,10 @@
814 def canAddComment(self, action):827 def canAddComment(self, action):
815 """Return whether the comment action should be displayed.828 """Return whether the comment action should be displayed.
816829
817 Comments (message without a status change) can be added when the830 Comments (message without a status change) can be added at any
818 question is solved or invalid831 time by any logged-in user.
819 """832 """
820 return (self.user is not None and833 return self.user is not None
821 self.context.status in [
822 QuestionStatus.SOLVED, QuestionStatus.INVALID])
823834
824 @action(_('Add Comment'), name='comment', condition=canAddComment)835 @action(_('Add Comment'), name='comment', condition=canAddComment)
825 def comment_action(self, action, data):836 def comment_action(self, action, data):
@@ -1090,9 +1101,7 @@
1090 """View to create a new FAQ."""1101 """View to create a new FAQ."""
10911102
1092 schema = IFAQ1103 schema = IFAQ
10931104 label = _('Create a new FAQ')
1094 page_title = _('Create a new FAQ')
1095 label = page_title
10961105
1097 @property1106 @property
1098 def page_title(self):1107 def page_title(self):
@@ -1303,10 +1312,15 @@
1303 if self.context.faq == data.get('faq'):1312 if self.context.faq == data.get('faq'):
1304 self.setFieldError('faq', _("You didn't modify the linked FAQ."))1313 self.setFieldError('faq', _("You didn't modify the linked FAQ."))
13051314
1306 @action(_('Link FAQ'), name="link")1315 @action(_('Link to FAQ'), name="link")
1307 def link_action(self, action, data):1316 def link_action(self, action, data):
1308 """Link the selected FAQ to the question."""1317 """Link the selected FAQ to the question."""
1309 if data['faq'] is not None:1318 if data['faq'] is not None:
1310 data['message'] += '\n' + self.getFAQMessageReference(data['faq'])1319 data['message'] += '\n' + self.getFAQMessageReference(data['faq'])
1311 self.context.linkFAQ(self.user, data['faq'], data['message'])1320 self.context.linkFAQ(self.user, data['faq'], data['message'])
1312 self.next_url = canonical_url(self.context)1321
1322 @property
1323 def next_url(self):
1324 return canonical_url(self.context)
1325
1326 cancel_url = next_url
13131327
=== modified file 'lib/lp/answers/browser/tests/views.txt'
--- lib/lp/answers/browser/tests/views.txt 2009-09-19 14:36:11 +0000
+++ lib/lp/answers/browser/tests/views.txt 2009-09-29 15:26:13 +0000
@@ -102,21 +102,21 @@
102 >>> getAvailableActionNames(workflow_harness.view)102 >>> getAvailableActionNames(workflow_harness.view)
103 []103 []
104104
105When question is in the OPEN state, the owner can either answer his own105When question is in the OPEN state, the owner can comment, answer his
106question or provide more information.106own question or provide more information.
107107
108 >>> login('test@canonical.com')108 >>> login('test@canonical.com')
109 >>> workflow_harness.submit('', {})109 >>> workflow_harness.submit('', {})
110 >>> getAvailableActionNames(workflow_harness.view)110 >>> getAvailableActionNames(workflow_harness.view)
111 ['giveinfo', 'selfanswer']111 ['comment', 'giveinfo', 'selfanswer']
112112
113But when another user sees the question, he can provide an answer or113But when another user sees the question, he can comment, provide an
114request for more information.114answer or request more information.
115115
116 >>> login('no-priv@canonical.com')116 >>> login('no-priv@canonical.com')
117 >>> workflow_harness.submit('', {})117 >>> workflow_harness.submit('', {})
118 >>> getAvailableActionNames(workflow_harness.view)118 >>> getAvailableActionNames(workflow_harness.view)
119 ['answer', 'requestinfo']119 ['answer', 'comment', 'requestinfo']
120120
121When the other user requests for more information, a confirmation is121When the other user requests for more information, a confirmation is
122displayed, the question status is changed to NEEDSINFO and the user is122displayed, the question status is changed to NEEDSINFO and the user is
@@ -141,18 +141,18 @@
141 >>> len(pop_notifications())141 >>> len(pop_notifications())
142 1142 1
143143
144The available actions for that other user are still between giving an144The available actions for that other user are still comment, give an
145answer or requesting for more information:145answer or request more information:
146146
147 >>> getAvailableActionNames(workflow_harness.view)147 >>> getAvailableActionNames(workflow_harness.view)
148 ['answer', 'requestinfo']148 ['answer', 'comment', 'requestinfo']
149149
150And the question owner still has the same possibilities then initially:150And the question owner still has the same possibilities as at first:
151151
152 >>> login('test@canonical.com')152 >>> login('test@canonical.com')
153 >>> workflow_harness.submit('', {})153 >>> workflow_harness.submit('', {})
154 >>> getAvailableActionNames(workflow_harness.view)154 >>> getAvailableActionNames(workflow_harness.view)
155 ['giveinfo', 'selfanswer']155 ['comment', 'giveinfo', 'selfanswer']
156156
157If he replies with the requested information, the question is moved back157If he replies with the requested information, the question is moved back
158to the OPEN state.158to the OPEN state.
@@ -185,14 +185,15 @@
185 >>> workflow_harness.redirectionTarget()185 >>> workflow_harness.redirectionTarget()
186 '.../+question/2'186 '.../+question/2'
187187
188Once the question is answered, the set of possible actions for the question188Once the question is answered, the set of possible actions for the
189owner changes. He can now either confirm the answer, answer the problem189question owner changes. He can now either comment, confirm the answer,
190himself, or reopen the request because that answer isn't working.190answer the problem himself, or reopen the request because that answer
191isn't working.
191192
192 >>> login('test@canonical.com')193 >>> login('test@canonical.com')
193 >>> workflow_harness.submit('', {})194 >>> workflow_harness.submit('', {})
194 >>> getAvailableActionNames(workflow_harness.view)195 >>> getAvailableActionNames(workflow_harness.view)
195 ['confirm', 'reopen', 'selfanswer']196 ['comment', 'confirm', 'reopen', 'selfanswer']
196197
197Let's say he confirms the previous answer, in this case, the question will198Let's say he confirms the previous answer, in this case, the question will
198move to the 'SOLVED' state. Note that the UI doesn't enable the user to199move to the 'SOLVED' state. Note that the UI doesn't enable the user to
199200
=== modified file 'lib/lp/answers/stories/question-edit.txt'
--- lib/lp/answers/stories/question-edit.txt 2009-09-24 13:45:05 +0000
+++ lib/lp/answers/stories/question-edit.txt 2009-09-29 15:26:13 +0000
@@ -11,8 +11,13 @@
1111
12 >>> user_browser.open('http://launchpad.dev/firefox/+question/2')12 >>> user_browser.open('http://launchpad.dev/firefox/+question/2')
13 >>> user_browser.getLink('Edit question').click()13 >>> user_browser.getLink('Edit question').click()
14 >>> user_browser.url14 >>> print user_browser.url
15 '.../firefox/+question/2/+edit'15 http://answers.launchpad.dev/firefox/+question/2/+edit
16
17There is a cancel link should the user decide otherwise:
18
19 >>> print user_browser.getLink('Cancel').url
20 http://answers.launchpad.dev/firefox/+question/2
1621
17When we post the form, we should be redirected back to the question page.22When we post the form, we should be redirected back to the question page.
1823
@@ -22,10 +27,10 @@
22 >>> user_browser.getControl('Description').value = description27 >>> user_browser.getControl('Description').value = description
23 >>> summary = "Problem showing the SVG demo on W3C web site"28 >>> summary = "Problem showing the SVG demo on W3C web site"
24 >>> user_browser.getControl('Summary').value = summary29 >>> user_browser.getControl('Summary').value = summary
25 >>> user_browser.getControl('Continue').click()30 >>> user_browser.getControl('Save Changes').click()
2631
27 >>> user_browser.url32 >>> print user_browser.url
28 '.../firefox/+question/2'33 http://answers.launchpad.dev/firefox/+question/2
2934
30And viewing that page should show the updated information.35And viewing that page should show the updated information.
3136
@@ -61,7 +66,7 @@
61 >>> user_browser.getLink('Edit question').click()66 >>> user_browser.getLink('Edit question').click()
62 >>> user_browser.getControl(67 >>> user_browser.getControl(
63 ... name='field.target.package').value = 'linux-source-2.6.15'68 ... name='field.target.package').value = 'linux-source-2.6.15'
64 >>> user_browser.getControl('Continue').click()69 >>> user_browser.getControl('Save Changes').click()
6570
66Product questions ignore sourcepackage information if it is submitted:71Product questions ignore sourcepackage information if it is submitted:
6772
@@ -69,7 +74,7 @@
69 >>> user_browser.getLink('Edit question').click()74 >>> user_browser.getLink('Edit question').click()
70 >>> user_browser.getControl(75 >>> user_browser.getControl(
71 ... name='field.target.package').value = 'linux-source-2.6.15'76 ... name='field.target.package').value = 'linux-source-2.6.15'
72 >>> user_browser.getControl('Continue').click()77 >>> user_browser.getControl('Save Changes').click()
7378
7479
75== Changing Other Metadata ==80== Changing Other Metadata ==
@@ -85,7 +90,7 @@
8590
86 >>> browser.getControl('Assignee').value = 'name16'91 >>> browser.getControl('Assignee').value = 'name16'
87 >>> browser.getControl('Status Whiteboard').value = 'Some note'92 >>> browser.getControl('Status Whiteboard').value = 'Some note'
88 >>> browser.getControl('Continue').click()93 >>> browser.getControl('Save Changes').click()
8994
90 >>> soup = find_main_content(browser.contents)95 >>> soup = find_main_content(browser.contents)
91 >>> print soup.first('b', text='Whiteboard:').findNext('td').renderContents()96 >>> print soup.first('b', text='Whiteboard:').findNext('td').renderContents()
9297
=== modified file 'lib/lp/answers/stories/question-obfuscation.txt'
--- lib/lp/answers/stories/question-obfuscation.txt 2009-09-23 14:40:53 +0000
+++ lib/lp/answers/stories/question-obfuscation.txt 2009-09-29 15:26:13 +0000
@@ -51,7 +51,7 @@
51 >>> user_browser.getControl(name='field.faq-query').value = 'voip'51 >>> user_browser.getControl(name='field.faq-query').value = 'voip'
52 >>> user_browser.getControl('Search', index=0).click()52 >>> user_browser.getControl('Search', index=0).click()
53 >>> user_browser.getControl('4').selected = True53 >>> user_browser.getControl('4').selected = True
54 >>> user_browser.getControl('Link FAQ').click()54 >>> user_browser.getControl('Link to FAQ').click()
55 >>> user_browser.getLink('How can I make VOIP calls?').click()55 >>> user_browser.getLink('How can I make VOIP calls?').click()
56 >>> print user_browser.title56 >>> print user_browser.title
57 Questions : Ubuntu57 Questions : Ubuntu
5858
=== modified file 'lib/lp/answers/stories/question-reject-and-change-status.txt'
--- lib/lp/answers/stories/question-reject-and-change-status.txt 2009-09-24 13:45:05 +0000
+++ lib/lp/answers/stories/question-reject-and-change-status.txt 2009-09-29 15:26:13 +0000
@@ -35,6 +35,12 @@
35 There is 1 error.35 There is 1 error.
36 You must provide an explanation message.36 You must provide an explanation message.
3737
38At this point the user might decide this is a bad idea, so there is a
39cancel link to take him back to the question:
40
41 >>> print admin_browser.getLink('Cancel').url
42 http://answers.launchpad.dev/firefox/+question/2
43
38Entering an explanation message and clicking the 'Reject' button,44Entering an explanation message and clicking the 'Reject' button,
39will reject the question.45will reject the question.
4046
@@ -108,6 +114,11 @@
108 >>> admin_browser.getControl('Status', index=0).displayValue114 >>> admin_browser.getControl('Status', index=0).displayValue
109 ['Invalid']115 ['Invalid']
110116
117There is also a cancel link should the user decide otherwise:
118
119 >>> print admin_browser.getLink('Cancel').url
120 http://answers.launchpad.dev/firefox/+question/2
121
111The user needs to select a status and enter a message explaining the122The user needs to select a status and enter a message explaining the
112status change:123status change:
113124
114125
=== modified file 'lib/lp/answers/stories/question-workflow.txt'
--- lib/lp/answers/stories/question-workflow.txt 2009-09-24 13:45:05 +0000
+++ lib/lp/answers/stories/question-workflow.txt 2009-09-29 15:26:13 +0000
@@ -17,11 +17,13 @@
17 ... print extract_text(17 ... print extract_text(
18 ... find_tag_by_id(contents, 'registration'))18 ... find_tag_by_id(contents, 'registration'))
1919
20
21 >>> def find_last_comment(contents):20 >>> def find_last_comment(contents):
22 ... soup = find_main_content(contents)21 ... soup = find_main_content(contents)
23 ... return soup.fetch('div', 'boardCommentBody')[-1]22 ... return soup.fetch('div', 'boardCommentBody')[-1]
2423
24 >>> def print_last_comment(contents):
25 ... print extract_text(find_last_comment(contents))
26
2527
26== Logging In ==28== Logging In ==
2729
@@ -69,9 +71,8 @@
6971
70 >>> find_request_status(support_browser.contents)72 >>> find_request_status(support_browser.contents)
71 Needs information...73 Needs information...
72 >>> print find_last_comment(74 >>> print_last_comment(support_browser.contents)
73 ... support_browser.contents).renderContents()75 Can you provide an example of an URL displaying the problem?
74 <p>Can you provide an example of an URL displaying the problem?</p>
7576
76Of course, if you don't add a message, clicking on the button will give77Of course, if you don't add a message, clicking on the button will give
77you an error.78you an error.
@@ -82,6 +83,25 @@
82 Please enter a message.83 Please enter a message.
8384
8485
86== Adding a Comment ==
87
88A comment can be added at any point without altering the status. The
89user simply enters the comment in the 'Message' box and clicks the
90'Add Comment' button.
91
92 >>> support_browser.getControl('Message').value = (
93 ... "I forgot to mention, in the meantime here is a workaround...")
94 >>> support_browser.getControl('Add Comment').click()
95
96This appends the comment to the question and it doesn't change its
97status:
98
99 >>> print find_request_status(support_browser.contents)
100 Needs information...
101 >>> print_last_comment(support_browser.contents)
102 I forgot to mention, in the meantime here is a workaround...
103
104
85== Answering with More Information ==105== Answering with More Information ==
86106
87When the question is in the 'Needs information' state, it means that107When the question is in the 'Needs information' state, it means that
@@ -109,9 +129,9 @@
109129
110 >>> print find_request_status(owner_browser.contents)130 >>> print find_request_status(owner_browser.contents)
111 Open...131 Open...
112 >>> print find_last_comment(owner_browser.contents).renderContents()132 >>> print_last_comment(owner_browser.contents)
113 <p>The following SVG doesn't display properly:<br />133 The following SVG doesn't display properly:
114 <a rel="nofollow" href="http://www.w3.org/2001/08/rdfweb/rdfweb-chaals-and-dan.svg">...</a></p>134 http://www.w3.org/2001/08/rdfweb/rdfweb-chaals-and-dan.svg
115135
116136
117== Giving an Answer ==137== Giving an Answer ==
@@ -132,10 +152,9 @@
132152
133 >>> print find_request_status(support_browser.contents)153 >>> print find_request_status(support_browser.contents)
134 Answered...154 Answered...
135 >>> print find_last_comment(155 >>> print_last_comment(support_browser.contents)
136 ... support_browser.contents).renderContents()156 New version of the firefox package are available with SVG support
137 <p>New version of the firefox package are available with SVG support157 enabled. You can use apt-get or adept to upgrade.
138 enabled. You can use apt-get or adept to upgrade.</p>
139158
140159
141== Confirming an Answer ==160== Confirming an Answer ==
@@ -175,8 +194,8 @@
175Since no message can be provided when that button is clicked. A default194Since no message can be provided when that button is clicked. A default
176confirmation message was appended to the question discussion:195confirmation message was appended to the question discussion:
177196
178 >>> print find_last_comment(owner_browser.contents).renderContents()197 >>> print_last_comment(owner_browser.contents)
179 <p>Thanks No Privileges Person, that solved my question.</p>198 Thanks No Privileges Person, that solved my question.
180199
181The confirmed answer is also highlighted.200The confirmed answer is also highlighted.
182201
@@ -199,7 +218,7 @@
199 Link to a FAQ218 Link to a FAQ
200219
201220
202== Adding a Comment ==221== Adding another Comment ==
203222
204When the question is Solved, it is still possible to add comments to it.223When the question is Solved, it is still possible to add comments to it.
205The user simply enters the comment in the 'Message' box and clicks the224The user simply enters the comment in the 'Message' box and clicks the
@@ -214,8 +233,8 @@
214233
215 >>> print find_request_status(owner_browser.contents)234 >>> print find_request_status(owner_browser.contents)
216 Solved...235 Solved...
217 >>> print find_last_comment(owner_browser.contents).renderContents()236 >>> print_last_comment(owner_browser.contents)
218 <p>The example now displays correctly. Thanks.</p>237 The example now displays correctly. Thanks.
219238
220239
221== Reopening ==240== Reopening ==
@@ -237,11 +256,11 @@
237256
238 >>> print find_request_status(owner_browser.contents)257 >>> print find_request_status(owner_browser.contents)
239 Open...258 Open...
240 >>> print find_last_comment(owner_browser.contents).renderContents()259 >>> print_last_comment(owner_browser.contents)
241 <p>Actually, there are still SVGs that do not display correctly.260 Actually, there are still SVGs that do not display correctly.
242 For example, the following<br />261 For example, the following
243 <a rel="nofollow" href="http://people.w3.org/maxf/ChessGML/immortal.svg">...</a> doesn't262 http://people.w3.org/maxf/ChessGML/immortal.svg doesn't
244 display correctly.</p>263 display correctly.
245264
246This also removes the highlighting from the previous answer and sets265This also removes the highlighting from the previous answer and sets
247the answerer back to None.266the answerer back to None.
@@ -346,6 +365,7 @@
346 ... new_status = cells[3].renderContents()365 ... new_status = cells[3].renderContents()
347 ... print who.lstrip('&nbsp;'), action, new_status366 ... print who.lstrip('&nbsp;'), action, new_status
348 No Privileges Person Request for more information Needs information367 No Privileges Person Request for more information Needs information
368 No Privileges Person Comment Needs information
349 Sample Person Give more information Open369 Sample Person Give more information Open
350 No Privileges Person Answer Answered370 No Privileges Person Answer Answered
351 Sample Person Confirm Solved371 Sample Person Confirm Solved
352372
=== modified file 'lib/lp/answers/stories/this-is-a-faq.txt'
--- lib/lp/answers/stories/this-is-a-faq.txt 2009-09-24 13:45:05 +0000
+++ lib/lp/answers/stories/this-is-a-faq.txt 2009-09-29 15:26:13 +0000
@@ -92,11 +92,11 @@
92 >>> print user_browser.getControl('Message').value92 >>> print user_browser.getControl('Message').value
93 No Privileges Person suggests this article as an answer to your question:93 No Privileges Person suggests this article as an answer to your question:
9494
95He can then click 'Link FAQ' to answer the question with the selected95He can then click 'Link to FAQ' to answer the question with the selected
96FAQ. After clicking the button, the user is redirected to the question96FAQ. After clicking the button, the user is redirected to the question
97page.97page.
9898
99 >>> user_browser.getControl('Link FAQ').click()99 >>> user_browser.getControl('Link to FAQ').click()
100 >>> print user_browser.url100 >>> print user_browser.url
101 http://answers.launchpad.dev/firefox/+question/2101 http://answers.launchpad.dev/firefox/+question/2
102102
@@ -145,11 +145,11 @@
145 ( ) 9: How do I troubleshoot problems with extensions/themes?145 ( ) 9: How do I troubleshoot problems with extensions/themes?
146 ( ) 7: How do I install Java?146 ( ) 7: How do I install Java?
147147
148He changes the message and click 'Link FAQ'.148He changes the message and click 'Link to FAQ'.
149149
150 >>> user_browser.getControl('Message').value = (150 >>> user_browser.getControl('Message').value = (
151 ... "Sorry, this document doesn't really answer your question.")151 ... "Sorry, this document doesn't really answer your question.")
152 >>> user_browser.getControl('Link FAQ').click()152 >>> user_browser.getControl('Link to FAQ').click()
153153
154But since, he forgot to change the link, the form is displayed again154But since, he forgot to change the link, the form is displayed again
155with an error message.155with an error message.
@@ -165,7 +165,7 @@
165submit the form again.165submit the form again.
166166
167 >>> user_browser.getControl('No existing FAQs').selected = True167 >>> user_browser.getControl('No existing FAQs').selected = True
168 >>> user_browser.getControl('Link FAQ').click()168 >>> user_browser.getControl('Link to FAQ').click()
169169
170The new message was added to the question:170The new message was added to the question:
171171
@@ -359,7 +359,7 @@
359 >>> user_browser.getControl('Search', index=0).click()359 >>> user_browser.getControl('Search', index=0).click()
360 >>> user_browser.getControl('6').selected = True360 >>> user_browser.getControl('6').selected = True
361 >>> user_browser.getControl('Message').value = "The FAQ mentions this:"361 >>> user_browser.getControl('Message').value = "The FAQ mentions this:"
362 >>> user_browser.getControl('Link FAQ').click()362 >>> user_browser.getControl('Link to FAQ').click()
363363
364The question is still solved. No Privileges Person sees the FAQ was364The question is still solved. No Privileges Person sees the FAQ was
365added to the question, and his message was added to the question's365added to the question, and his message was added to the question's
366366
=== modified file 'lib/lp/answers/templates/question-index.pt'
--- lib/lp/answers/templates/question-index.pt 2009-09-24 11:10:26 +0000
+++ lib/lp/answers/templates/question-index.pt 2009-09-29 15:26:13 +0000
@@ -143,12 +143,12 @@
143 </tal:comment>143 </tal:comment>
144 <div class="actions" metal:fill-slot="buttons">144 <div class="actions" metal:fill-slot="buttons">
145 <div>145 <div>
146 <input tal:replace="structure view/comment_action/render" />
147 <input tal:replace="structure view/answer_action/render" />146 <input tal:replace="structure view/answer_action/render" />
148 <input tal:replace="structure view/selfanswer_action/render" />147 <input tal:replace="structure view/selfanswer_action/render" />
149 <input tal:replace="structure view/requestinfo_action/render" />148 <input tal:replace="structure view/requestinfo_action/render" />
150 <input tal:replace="structure view/giveinfo_action/render" />149 <input tal:replace="structure view/giveinfo_action/render" />
151 <input tal:replace="structure view/reopen_action/render" />150 <input tal:replace="structure view/reopen_action/render" />
151 <input tal:replace="structure view/comment_action/render" />
152 </div>152 </div>
153 <p id="answer-button-hint"153 <p id="answer-button-hint"
154 tal:condition="view/confirm_action/available">154 tal:condition="view/confirm_action/available">