Merge lp:~sinzui/launchpad/wax-and-wane into lp:launchpad
- wax-and-wane
- Merge into devel
Status: | Merged | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Merged at revision: | not available | ||||||||||||||||
Proposed branch: | lp:~sinzui/launchpad/wax-and-wane | ||||||||||||||||
Merge into: | lp:launchpad | ||||||||||||||||
Diff against target: |
296 lines (+110/-63) 8 files modified
lib/canonical/launchpad/icing/style-3-0.css (+3/-0) lib/lp/registry/browser/mailinglists.py (+13/-4) lib/lp/registry/browser/milestone.py (+1/-1) lib/lp/registry/browser/tests/mailinglist-message-views.txt (+74/-0) lib/lp/registry/browser/tests/milestone-views.txt (+15/-2) lib/lp/registry/browser/tests/test_views.py (+1/-0) lib/lp/registry/doc/message-holds.txt (+0/-52) lib/lp/registry/templates/milestone-index.pt (+3/-4) |
||||||||||||||||
To merge this branch: | bzr merge lp:~sinzui/launchpad/wax-and-wane | ||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brad Crittenden (community) | code | Approve | |
Review via email:
|
Commit message
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Curtis Hovey (sinzui) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Brad Crittenden (bac) wrote : | # |
Hi Curtis,
Thanks for these changes. Everything looks really good. I would suggest you put a test into _append_paragraph to ensure current_paragraph is not empty. This could happen if you closed the paragraph right before you hit line 20. It's not big deal but we shouldn't generate an empty <p></p> if we can easily help it.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Curtis Hovey (sinzui) wrote : | # |
Hi Brad.
On Tue, 2010-01-12 at 14:18 +0000, Brad Crittenden wrote:
> Review: Approve code
> Hi Curtis,
>
> Thanks for these changes. Everything looks really good. I would
> suggest you put a test into _append_paragraph to ensure
> current_paragraph is not empty. This could happen if you closed the
> paragraph right before you hit line 20. It's not big deal but we
> shouldn't generate an empty <p></p> if we can easily help it.
Thanks for your insight. I discounted the end case because leading and
trailing white space are stripped before the paragraphs are formatted.
But putting the rule in the helper method makes the rule clear and
universal. So I moved it.
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -158,7 +158,7 @@
for lineno, line in enumerate(
if lineno > 20:
- if len(line.strip()) == 0 and len(current_
+ if len(line.strip()) == 0:
else:
@@ -167,6 +167,10 @@
def _append_
+ if len(current_
+ # There is nothing to append. The message has multiple
+ # blank lines.
+ return
--
__Curtis C. Hovey_________
http://
Preview Diff
1 | === modified file 'lib/canonical/launchpad/icing/style-3-0.css' | |||
2 | --- lib/canonical/launchpad/icing/style-3-0.css 2010-01-06 02:02:18 +0000 | |||
3 | +++ lib/canonical/launchpad/icing/style-3-0.css 2010-01-13 14:18:16 +0000 | |||
4 | @@ -276,6 +276,9 @@ | |||
5 | 276 | display: inline; | 276 | display: inline; |
6 | 277 | padding: 0 1.5em 0 0; | 277 | padding: 0 1.5em 0 0; |
7 | 278 | } | 278 | } |
8 | 279 | .pre { | ||
9 | 280 | white-space: pre; | ||
10 | 281 | } | ||
11 | 279 | .table-actions:nth-child(2) { | 282 | .table-actions:nth-child(2) { |
12 | 280 | /* text-align only works here because the <li> also has the | 283 | /* text-align only works here because the <li> also has the |
13 | 281 | style display:inline. | 284 | style display:inline. |
14 | 282 | 285 | ||
15 | === modified file 'lib/lp/registry/browser/mailinglists.py' | |||
16 | --- lib/lp/registry/browser/mailinglists.py 2009-08-16 17:21:54 +0000 | |||
17 | +++ lib/lp/registry/browser/mailinglists.py 2010-01-13 14:18:16 +0000 | |||
18 | @@ -130,7 +130,8 @@ | |||
19 | 130 | # The author field is very close to what the details has, except that | 130 | # The author field is very close to what the details has, except that |
20 | 131 | # the view wants to include a link to the person's overview page. | 131 | # the view wants to include a link to the person's overview page. |
21 | 132 | self.author = '<a href="%s">%s</a>' % ( | 132 | self.author = '<a href="%s">%s</a>' % ( |
23 | 133 | canonical_url(self.details.author), self.details.sender) | 133 | canonical_url(self.details.author), |
24 | 134 | escape(self.details.sender)) | ||
25 | 134 | 135 | ||
26 | 135 | def initialize(self): | 136 | def initialize(self): |
27 | 136 | """See `LaunchpadView`.""" | 137 | """See `LaunchpadView`.""" |
28 | @@ -158,13 +159,21 @@ | |||
29 | 158 | if lineno > 20: | 159 | if lineno > 20: |
30 | 159 | break | 160 | break |
31 | 160 | if len(line.strip()) == 0: | 161 | if len(line.strip()) == 0: |
34 | 161 | paragraphs.append(u'\n'.join(current_paragraph)) | 162 | self._append_paragraph(paragraphs, current_paragraph) |
33 | 162 | paragraphs.append('\n<p>\n') | ||
35 | 163 | current_paragraph = [] | 163 | current_paragraph = [] |
36 | 164 | else: | 164 | else: |
37 | 165 | current_paragraph.append(line) | 165 | current_paragraph.append(line) |
38 | 166 | self._append_paragraph(paragraphs, current_paragraph) | ||
39 | 167 | self.body_details = u''.join(paragraphs) | ||
40 | 168 | |||
41 | 169 | def _append_paragraph(self, paragraphs, current_paragraph): | ||
42 | 170 | if len(current_paragraph) == 0: | ||
43 | 171 | # There is nothing to append. The message has multiple | ||
44 | 172 | # blank lines. | ||
45 | 173 | return | ||
46 | 174 | paragraphs.append(u'\n<p>\n') | ||
47 | 166 | paragraphs.append(u'\n'.join(current_paragraph)) | 175 | paragraphs.append(u'\n'.join(current_paragraph)) |
49 | 167 | self.body_details = u''.join(paragraphs) | 176 | paragraphs.append(u'\n</p>\n') |
50 | 168 | 177 | ||
51 | 169 | def _remove_leading_blank_lines(self): | 178 | def _remove_leading_blank_lines(self): |
52 | 170 | """Strip off any leading blank lines. | 179 | """Strip off any leading blank lines. |
53 | 171 | 180 | ||
54 | === modified file 'lib/lp/registry/browser/milestone.py' | |||
55 | --- lib/lp/registry/browser/milestone.py 2009-12-05 18:37:28 +0000 | |||
56 | +++ lib/lp/registry/browser/milestone.py 2010-01-13 14:18:16 +0000 | |||
57 | @@ -214,7 +214,7 @@ | |||
58 | 214 | """The list of non-conjoined bugtasks targeted to this milestone.""" | 214 | """The list of non-conjoined bugtasks targeted to this milestone.""" |
59 | 215 | user = getUtility(ILaunchBag).user | 215 | user = getUtility(ILaunchBag).user |
60 | 216 | params = BugTaskSearchParams(user, milestone=self.context, | 216 | params = BugTaskSearchParams(user, milestone=self.context, |
62 | 217 | orderby=['-importance', 'datecreated', 'id'], | 217 | orderby=['status', '-importance', 'id'], |
63 | 218 | omit_dupes=True) | 218 | omit_dupes=True) |
64 | 219 | tasks = getUtility(IBugTaskSet).search(params) | 219 | tasks = getUtility(IBugTaskSet).search(params) |
65 | 220 | # We could replace all the code below with a simple | 220 | # We could replace all the code below with a simple |
66 | 221 | 221 | ||
67 | === added file 'lib/lp/registry/browser/tests/mailinglist-message-views.txt' | |||
68 | --- lib/lp/registry/browser/tests/mailinglist-message-views.txt 1970-01-01 00:00:00 +0000 | |||
69 | +++ lib/lp/registry/browser/tests/mailinglist-message-views.txt 2010-01-13 14:18:16 +0000 | |||
70 | @@ -0,0 +1,74 @@ | |||
71 | 1 | Held message view | ||
72 | 2 | ----------------- | ||
73 | 3 | |||
74 | 4 | The HeldMessageView formats a held message so that it can be moderated by | ||
75 | 5 | the mailing list administrator. | ||
76 | 6 | |||
77 | 7 | >>> from canonical.launchpad.interfaces import IMessageSet | ||
78 | 8 | |||
79 | 9 | >>> team, mlist = factory.makeTeamAndMailingList('parrot', 'owner') | ||
80 | 10 | |||
81 | 11 | >>> login('admin@canonical.com') | ||
82 | 12 | >>> message_set = getUtility(IMessageSet) | ||
83 | 13 | >>> message = message_set.fromEmail("""\ | ||
84 | 14 | ... From: Carlos <carlos@canonical.com> | ||
85 | 15 | ... To: parrot@lists.launchpad.dev | ||
86 | 16 | ... Subject: monkey | ||
87 | 17 | ... Message-ID: <monkey> | ||
88 | 18 | ... Date: Fri, 01 Aug 2000 01:09:00 -0000 | ||
89 | 19 | ... | ||
90 | 20 | ... First paragraph. | ||
91 | 21 | ... | ||
92 | 22 | ... Second paragraph. | ||
93 | 23 | ... | ||
94 | 24 | ... Third paragraph. | ||
95 | 25 | ... """) | ||
96 | 26 | >>> held_message = mlist.holdMessage(message) | ||
97 | 27 | >>> transaction.commit() | ||
98 | 28 | |||
99 | 29 | >>> login_person(team.teamowner) | ||
100 | 30 | >>> view = create_initialized_view( | ||
101 | 31 | ... held_message, name='+moderation', principal=team.teamowner) | ||
102 | 32 | >>> print view.widget_name | ||
103 | 33 | field.%3Cmonkey%3E | ||
104 | 34 | >>> print view.message_id | ||
105 | 35 | <monkey> | ||
106 | 36 | >>> print view.subject | ||
107 | 37 | monkey | ||
108 | 38 | >>> print view.date | ||
109 | 39 | 2000-08-01 01:09:00+00:00 | ||
110 | 40 | >>> print view.author | ||
111 | 41 | <a href="http://launchpad.dev/~carlos">Carlos <carlos@canonical.com></a> | ||
112 | 42 | >>> print view.body_summary | ||
113 | 43 | First paragraph. | ||
114 | 44 | >>> print view.body_details | ||
115 | 45 | <p> | ||
116 | 46 | Second paragraph. | ||
117 | 47 | </p> | ||
118 | 48 | <p> | ||
119 | 49 | Third paragraph. | ||
120 | 50 | </p> | ||
121 | 51 | |||
122 | 52 | |||
123 | 53 | View helpers | ||
124 | 54 | ------------ | ||
125 | 55 | |||
126 | 56 | The view uses a helper method to format the paragraphs. | ||
127 | 57 | |||
128 | 58 | >>> paragraphs = [] | ||
129 | 59 | >>> current_paragraph = ['line 1', 'line 2'] | ||
130 | 60 | >>> view._append_paragraph(paragraphs, current_paragraph) | ||
131 | 61 | >>> for line in paragraphs: | ||
132 | 62 | ... print line | ||
133 | 63 | <p> | ||
134 | 64 | line 1 | ||
135 | 65 | line 2 | ||
136 | 66 | </p> | ||
137 | 67 | |||
138 | 68 | The _append_paragraph method ignores empty paragraphs. | ||
139 | 69 | |||
140 | 70 | >>> paragraphs = [] | ||
141 | 71 | >>> current_paragraph = [] | ||
142 | 72 | >>> view._append_paragraph(paragraphs, current_paragraph) | ||
143 | 73 | >>> len(paragraphs) | ||
144 | 74 | 0 | ||
145 | 0 | 75 | ||
146 | === modified file 'lib/lp/registry/browser/tests/milestone-views.txt' | |||
147 | --- lib/lp/registry/browser/tests/milestone-views.txt 2009-12-02 15:18:08 +0000 | |||
148 | +++ lib/lp/registry/browser/tests/milestone-views.txt 2010-01-13 14:18:16 +0000 | |||
149 | @@ -72,11 +72,14 @@ | |||
150 | 72 | The has_bugs_or_specs boolean property can be used to verify if the | 72 | The has_bugs_or_specs boolean property can be used to verify if the |
151 | 73 | milestone has any bugs or specifications. | 73 | milestone has any bugs or specifications. |
152 | 74 | 74 | ||
153 | 75 | >>> from lp.bugs.interfaces.bugtask import BugTaskStatus | ||
154 | 76 | |||
155 | 75 | >>> view.has_bugs_or_specs | 77 | >>> view.has_bugs_or_specs |
156 | 76 | False | 78 | False |
157 | 77 | 79 | ||
158 | 78 | >>> bug = factory.makeBug(title="kiwi") | 80 | >>> bug = factory.makeBug(title="kiwi") |
159 | 79 | >>> bugtask = factory.makeBugTask(bug=bug, target=milestone.product) | 81 | >>> bugtask = factory.makeBugTask(bug=bug, target=milestone.product) |
160 | 82 | >>> bugtask.transitionToStatus(BugTaskStatus.FIXCOMMITTED, person) | ||
161 | 80 | >>> bugtask.transitionToAssignee(person) | 83 | >>> bugtask.transitionToAssignee(person) |
162 | 81 | >>> bugtask.milestone = milestone | 84 | >>> bugtask.milestone = milestone |
163 | 82 | >>> spec = factory.makeSpecification( | 85 | >>> spec = factory.makeSpecification( |
164 | @@ -142,6 +145,7 @@ | |||
165 | 142 | 145 | ||
166 | 143 | >>> bug = factory.makeBug(title="emo") | 146 | >>> bug = factory.makeBug(title="emo") |
167 | 144 | >>> bugtask = factory.makeBugTask(bug=bug, target=milestone.product) | 147 | >>> bugtask = factory.makeBugTask(bug=bug, target=milestone.product) |
168 | 148 | >>> bugtask.transitionToAssignee(person) | ||
169 | 145 | >>> bugtask.milestone = milestone | 149 | >>> bugtask.milestone = milestone |
170 | 146 | >>> spec = factory.makeSpecification( | 150 | >>> spec = factory.makeSpecification( |
171 | 147 | ... product=milestone.product, title='ostrich') | 151 | ... product=milestone.product, title='ostrich') |
172 | @@ -154,6 +158,15 @@ | |||
173 | 154 | >>> print view.specification_count_text | 158 | >>> print view.specification_count_text |
174 | 155 | <strong>2 blueprints</strong> | 159 | <strong>2 blueprints</strong> |
175 | 156 | 160 | ||
176 | 161 | Bugtasks are ordered by status (fix released last), and importance | ||
177 | 162 | (critical first). | ||
178 | 163 | |||
179 | 164 | >>> for bugtask in view.bugtasks: | ||
180 | 165 | ... assignee = bugtask.assignee | ||
181 | 166 | ... print bugtask.bug.title, assignee.name, bugtask.status.title | ||
182 | 167 | emo puffin-owner New | ||
183 | 168 | kiwi puffin-owner Fix Committed | ||
184 | 169 | |||
185 | 157 | The view provides a list of StatusCounts that summarise the targeted | 170 | The view provides a list of StatusCounts that summarise the targeted |
186 | 158 | specifications and bugtasks. | 171 | specifications and bugtasks. |
187 | 159 | 172 | ||
188 | @@ -174,7 +187,8 @@ | |||
189 | 174 | 187 | ||
190 | 175 | >>> for status_count in view.bugtask_status_counts: | 188 | >>> for status_count in view.bugtask_status_counts: |
191 | 176 | ... print '%s: %s' % (status_count.status.title, status_count.count) | 189 | ... print '%s: %s' % (status_count.status.title, status_count.count) |
193 | 177 | New: 2 | 190 | New: 1 |
194 | 191 | Fix Committed: 1 | ||
195 | 178 | 192 | ||
196 | 179 | The assignment_counts property returns all the users and count of bugs and | 193 | The assignment_counts property returns all the users and count of bugs and |
197 | 180 | specifications assigned to them. | 194 | specifications assigned to them. |
198 | @@ -711,4 +725,3 @@ | |||
199 | 711 | >>> view = create_initialized_view(milestone, '+delete') | 725 | >>> view = create_initialized_view(milestone, '+delete') |
200 | 712 | >>> check_permission('launchpad.Edit', view) | 726 | >>> check_permission('launchpad.Edit', view) |
201 | 713 | False | 727 | False |
202 | 714 | |||
203 | 715 | 728 | ||
204 | === modified file 'lib/lp/registry/browser/tests/test_views.py' | |||
205 | --- lib/lp/registry/browser/tests/test_views.py 2009-08-18 02:00:17 +0000 | |||
206 | +++ lib/lp/registry/browser/tests/test_views.py 2010-01-13 14:18:16 +0000 | |||
207 | @@ -21,6 +21,7 @@ | |||
208 | 21 | # that require something special like the librarian or mailman must run | 21 | # that require something special like the librarian or mailman must run |
209 | 22 | # on a layer that sets those services up. | 22 | # on a layer that sets those services up. |
210 | 23 | special_test_layer = { | 23 | special_test_layer = { |
211 | 24 | 'mailinglist-message-views.txt': LaunchpadFunctionalLayer, | ||
212 | 24 | 'milestone-views.txt': LaunchpadFunctionalLayer, | 25 | 'milestone-views.txt': LaunchpadFunctionalLayer, |
213 | 25 | 'person-views.txt': LaunchpadFunctionalLayer, | 26 | 'person-views.txt': LaunchpadFunctionalLayer, |
214 | 26 | 'user-to-user-views.txt': LaunchpadFunctionalLayer, | 27 | 'user-to-user-views.txt': LaunchpadFunctionalLayer, |
215 | 27 | 28 | ||
216 | === modified file 'lib/lp/registry/doc/message-holds.txt' | |||
217 | --- lib/lp/registry/doc/message-holds.txt 2009-05-12 21:39:35 +0000 | |||
218 | +++ lib/lp/registry/doc/message-holds.txt 2010-01-13 14:18:16 +0000 | |||
219 | @@ -377,58 +377,6 @@ | |||
220 | 377 | ---------------------------------------- | 377 | ---------------------------------------- |
221 | 378 | 378 | ||
222 | 379 | 379 | ||
223 | 380 | == Held message formatting == | ||
224 | 381 | |||
225 | 382 | When held messages are displayed in the u/i, they will be formatted in such a | ||
226 | 383 | way that we can show the body summary with an ellipsis to review more body | ||
227 | 384 | details. Because formatting email messages for the web can get tricky, we | ||
228 | 385 | take a fairly conservative 80/20 approach. | ||
229 | 386 | |||
230 | 387 | >>> from lp.registry.browser.mailinglists import HeldMessageView | ||
231 | 388 | >>> from canonical.launchpad.interfaces import ( | ||
232 | 389 | ... IHeldMessageDetails, IPersonSet) | ||
233 | 390 | >>> from zope.component import getUtility | ||
234 | 391 | >>> from zope.interface import implements | ||
235 | 392 | |||
236 | 393 | First, we craft an object like what the view expects. | ||
237 | 394 | |||
238 | 395 | >>> person = getUtility(IPersonSet).getByName('name12') | ||
239 | 396 | >>> class FakeHeldMessageDetails: | ||
240 | 397 | ... implements(IHeldMessageDetails) | ||
241 | 398 | ... message_id = '<zebra>' | ||
242 | 399 | ... subject = 'A subject' | ||
243 | 400 | ... date = 'Today' | ||
244 | 401 | ... author = person | ||
245 | 402 | ... sender = 'test@example.com' | ||
246 | 403 | ... body = """\ | ||
247 | 404 | ... What are the Guadamen? I think I might want to be come one | ||
248 | 405 | ... but I'm not sure. Are they men who like guacamole? Or are | ||
249 | 406 | ... they men who live on Gauadalcanal? I used to live on Guadalcanal | ||
250 | 407 | ... and boy, do I sure like avocados! | ||
251 | 408 | ... | ||
252 | 409 | ... Please consider me for Guadamanhood. | ||
253 | 410 | ... | ||
254 | 411 | ... -Guy | ||
255 | 412 | ... """ | ||
256 | 413 | |||
257 | 414 | >>> view = HeldMessageView(FakeHeldMessageDetails(), None) | ||
258 | 415 | >>> view.initialize() | ||
259 | 416 | >>> view.widget_name | ||
260 | 417 | 'field.%3Czebra%3E' | ||
261 | 418 | >>> view.author | ||
262 | 419 | u'<a href="http://launchpad.dev/~name12">test@example.com</a>' | ||
263 | 420 | >>> view.body_summary | ||
264 | 421 | 'What are the Guadamen? I think I might want to be come one' | ||
265 | 422 | >>> print view.body_details | ||
266 | 423 | but I'm not sure. Are they men who like guacamole? Or are | ||
267 | 424 | they men who live on Gauadalcanal? I used to live on Guadalcanal | ||
268 | 425 | and boy, do I sure like avocados! | ||
269 | 426 | <p> | ||
270 | 427 | Please consider me for Guadamanhood. | ||
271 | 428 | <p> | ||
272 | 429 | -Guy | ||
273 | 430 | |||
274 | 431 | |||
275 | 432 | == Posting privileges == | 380 | == Posting privileges == |
276 | 433 | 381 | ||
277 | 434 | Message approvals are also used to derived posting privileges for non-team | 382 | Message approvals are also used to derived posting privileges for non-team |
278 | 435 | 383 | ||
279 | === modified file 'lib/lp/registry/templates/milestone-index.pt' | |||
280 | --- lib/lp/registry/templates/milestone-index.pt 2009-12-11 19:54:04 +0000 | |||
281 | +++ lib/lp/registry/templates/milestone-index.pt 2010-01-13 14:18:16 +0000 | |||
282 | @@ -147,11 +147,10 @@ | |||
283 | 147 | <dl> | 147 | <dl> |
284 | 148 | <dt>Assignees:</dt> | 148 | <dt>Assignees:</dt> |
285 | 149 | <dd tal:define="count_statuses view/assignment_counts"> | 149 | <dd tal:define="count_statuses view/assignment_counts"> |
288 | 150 | <tal:statuses repeat="count_status count_statuses"> | 150 | <span class="pre" |
289 | 151 | <strong tal:content="count_status/count">2</strong> <a | 151 | tal:repeat="count_status count_statuses"><strong tal:content="count_status/count">2</strong> <a |
290 | 152 | tal:replace="structure count_status/status/fmt:link" /><tal:comma | 152 | tal:replace="structure count_status/status/fmt:link" /><tal:comma |
293 | 153 | condition="not: repeat/count_status/end">,</tal:comma> | 153 | condition="not: repeat/count_status/end">,</tal:comma></span> |
292 | 154 | </tal:statuses> | ||
294 | 155 | <tal:no-statuses condition="not: count_statuses"> | 154 | <tal:no-statuses condition="not: count_statuses"> |
295 | 156 | No users assigned to blueprints and bugs. | 155 | No users assigned to blueprints and bugs. |
296 | 157 | </tal:no-statuses> | 156 | </tal:no-statuses> |
This is my branch to fix from simple nuisances in launchpad.
lp:~sinzui/launchpad/wax-and-wane /bugs.launchpad .net/bugs/ wax-and- wane message- views implementation: no one
Diff size: 206
Launchpad bug: https:/
Test command: ./bin/test -vv \
-t mailinglist-
-t milestone-views
Pre-
Target release: 10.01
Fix from simple nuisances in launchpad ------- ------- ------- ------- ------- ------- ------- ------- -----
-------
Bug #504024 [invalid list moderation markup breaks webkit] moderation. pt create ill-formed markup
The HeldMessageView and message-
that makes the message moderation page unusable in webkit browsers. I
have observed two issues:
1) The template uses `structure view/author`, but the author field is not
HTML. The angle brackets are not escaped, creating an unclosed tag.
2) The view's initialize() method is using `paragraphs. append( '\n<p>\ n')`
which creates an unclosed paragraph. (this markup was deprecated in 1994
and it invalid XHTML which the page claims to be).
Both of these errors can cause form submittal errors.
Bug #505919 [milestones assignees wrap poorly]
The assignee name wraps to the next line and it is difficult to see
understand that the number belongs to the next name.
Bug #505917 [Sort milestone bugs by status by default]
People working the bugs need to see status, then importance.
Rules
-----
Bug #504024 [invalid list moderation markup breaks webkit]
* Add a <p> before each added paragraph and change the markup added
afterwards to </p>
* Remove the `structure` command
Bug #505919 [milestones assignees wrap poorly]
* Add a CSS class to prevent the count and name from wrapping.
* ADDENDUM: white-space: nowrap does not work because the comma is
allowed to wrap. The pre value works if the markup is has no line breaks
Bug #505917 [Sort milestone bugs by status by default]
* Change the sort order in the view.
QA
--
Bug #504024 [invalid list moderation markup breaks webkit] /edge.launchpad .net/~launchpad -users/ +mailinglist- moderate
* Visit https:/
* Verify the From address shows the real address in the VIAGRA messages.
* Expand a real message (not an empty spam)
* Verify the paragraphs are shown as paragraphs.
Bug #505919 [milestones assignees wrap poorly] /edge.launchpad .net/launchpad- registry/ +milestone/ 10.01
* Visit https:/
* Verify assignee names do not wrap in activities portlet.
Bug #505917 [Sort milestone bugs by status by default] /edge.launchpad .net/launchpad- registry/ +milestone/ 10.01
* Visit https:/
* Verify that the bugs are listed from triaged, in progress, fix committed
to fix released.
Lint
----
Linting changed files: /launchpad/ icing/style- 3-0.css registry/ browser/ mailinglists. py registry/ browser/ milestone. py registry/ browser/ tests/mailingli st-message- views.txt registry/ browser/ tests/milestone -views. txt registry/ browser/ tests/test_ views.py registry/ templates/ milestone- index.pt
lib/canonical
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
Test
----
* lib/lp/ registry/ browser/ tests/test_ views.py message- views.tx. ..
* Registered mailinglist-