Merge lp:~thumper/launchpad/inline-lifecycle-status-edit into lp:launchpad
- inline-lifecycle-status-edit
- Merge into devel
Proposed by
Tim Penhey
Status: | Merged |
---|---|
Merged at revision: | not available |
Proposed branch: | lp:~thumper/launchpad/inline-lifecycle-status-edit |
Merge into: | lp:launchpad |
Diff against target: |
317 lines 9 files modified
lib/canonical/launchpad/icing/style.css (+6/-6) lib/canonical/launchpad/javascript/code/branchstatus.js (+48/-0) lib/canonical/launchpad/windmill/testing/lpuser.py (+7/-0) lib/lp/code/browser/branch.py (+29/-2) lib/lp/code/browser/configure.zcml (+7/-0) lib/lp/code/stories/branches/xx-branch-edit.txt (+1/-1) lib/lp/code/templates/branch-index.pt (+16/-0) lib/lp/code/templates/branch-information.pt (+9/-4) lib/lp/code/windmill/tests/test_branch_index.py (+64/-0) |
To merge this branch: | bzr merge lp:~thumper/launchpad/inline-lifecycle-status-edit |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Deryck Hodge (community) | code js | Approve | |
Paul Hummer | Pending | ||
Review via email: mp+12707@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote : | # |
Revision history for this message
Deryck Hodge (deryck) wrote : | # |
Looks good. As we talked about together, drop the ending comma in the JS object literal, and you may not need to import node in the js file, but otherwise it looks very solid.
Cheers,
deryck
review:
Approve
(code js)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/icing/style.css' | |||
2 | --- lib/canonical/launchpad/icing/style.css 2009-10-06 17:45:46 +0000 | |||
3 | +++ lib/canonical/launchpad/icing/style.css 2009-10-10 23:06:17 +0000 | |||
4 | @@ -1851,12 +1851,12 @@ | |||
5 | 1851 | color: #d18b39; | 1851 | color: #d18b39; |
6 | 1852 | } | 1852 | } |
7 | 1853 | 1853 | ||
14 | 1854 | .branchstatusMATURE {color: #090;} | 1854 | .branchstatusMATURE, .branchstatusMATURE a {color: #090;} |
15 | 1855 | .branchstatusDEVELOPMENT {color: #900;} | 1855 | .branchstatusDEVELOPMENT, .branchstatusDEVELOPMENT a {color: #900;} |
16 | 1856 | .branchstatusEXPERIMENTAL {color: #930;} | 1856 | .branchstatusEXPERIMENTAL, .branchstatusEXPERIMENTAL a {color: #930;} |
17 | 1857 | .branchstatusMERGED {color: #666;} | 1857 | .branchstatusMERGED, .branchstatusMERGED a {color: #666;} |
18 | 1858 | .branchstatusABANDONED {color: #666;} | 1858 | .branchstatusABANDONED, .branchstatusABANDONED a {color: #666;} |
19 | 1859 | .branchstatusNEW {color: black;} | 1859 | .branchstatusNEW, .branchstatusNEW a {color: black;} |
20 | 1860 | 1860 | ||
21 | 1861 | .voteAPPROVE {color: green;} | 1861 | .voteAPPROVE {color: green;} |
22 | 1862 | .voteNEEDS_FIXING {color: #930;} | 1862 | .voteNEEDS_FIXING {color: #930;} |
23 | 1863 | 1863 | ||
24 | === added file 'lib/canonical/launchpad/javascript/code/branchstatus.js' | |||
25 | --- lib/canonical/launchpad/javascript/code/branchstatus.js 1970-01-01 00:00:00 +0000 | |||
26 | +++ lib/canonical/launchpad/javascript/code/branchstatus.js 2009-10-10 23:06:16 +0000 | |||
27 | @@ -0,0 +1,48 @@ | |||
28 | 1 | /** Copyright (c) 2009, Canonical Ltd. All rights reserved. | ||
29 | 2 | * | ||
30 | 3 | * Code for handling the update of the branch status. | ||
31 | 4 | * | ||
32 | 5 | * @module branchstatus | ||
33 | 6 | * @requires node, lazr.choiceedit, lp.client.plugins | ||
34 | 7 | */ | ||
35 | 8 | |||
36 | 9 | YUI.add('code.branchstatus', function(Y) { | ||
37 | 10 | |||
38 | 11 | Y.branchstatus = Y.namespace('code.branchstatus'); | ||
39 | 12 | |||
40 | 13 | /* | ||
41 | 14 | * Connect the branch status to the javascript events. | ||
42 | 15 | */ | ||
43 | 16 | Y.branchstatus.connect_status = function(conf) { | ||
44 | 17 | |||
45 | 18 | var status_content = Y.get('#branch-details-status-value'); | ||
46 | 19 | |||
47 | 20 | if | ||
48 | 21 | (conf.user_can_edit_status) { | ||
49 | 22 | var status_choice_edit = new Y.ChoiceSource({ | ||
50 | 23 | contentBox: status_content, | ||
51 | 24 | value: conf.status_value, | ||
52 | 25 | title: 'Change status to', | ||
53 | 26 | items: conf.status_widget_items}); | ||
54 | 27 | status_choice_edit.showError = function(err) { | ||
55 | 28 | display_error(null, err); | ||
56 | 29 | }; | ||
57 | 30 | status_choice_edit.on('save', function(e) { | ||
58 | 31 | var cb = status_choice_edit.get('contentBox'); | ||
59 | 32 | Y.Array.each(conf.status_widget_items, function(item) { | ||
60 | 33 | if (item.value == status_choice_edit.get('value')) { | ||
61 | 34 | cb.query('span').addClass(item.css_class); | ||
62 | 35 | } else { | ||
63 | 36 | cb.query('span').removeClass(item.css_class); | ||
64 | 37 | } | ||
65 | 38 | }); | ||
66 | 39 | }); | ||
67 | 40 | status_choice_edit.plug({ | ||
68 | 41 | fn: Y.lp.client.plugins.PATCHPlugin, cfg: { | ||
69 | 42 | patch: 'lifecycle_status', | ||
70 | 43 | resource: conf.branch_path}}); | ||
71 | 44 | status_choice_edit.render(); | ||
72 | 45 | } | ||
73 | 46 | }; | ||
74 | 47 | |||
75 | 48 | }, '0.1', {requires: ['node', 'lazr.choiceedit', 'lp.client.plugins']}); | ||
76 | 0 | 49 | ||
77 | === modified file 'lib/canonical/launchpad/windmill/testing/lpuser.py' | |||
78 | --- lib/canonical/launchpad/windmill/testing/lpuser.py 2009-08-19 11:13:26 +0000 | |||
79 | +++ lib/canonical/launchpad/windmill/testing/lpuser.py 2009-10-10 23:06:17 +0000 | |||
80 | @@ -53,6 +53,13 @@ | |||
81 | 53 | client.waits.forPageLoad(timeout=u'100000') | 53 | client.waits.forPageLoad(timeout=u'100000') |
82 | 54 | 54 | ||
83 | 55 | 55 | ||
84 | 56 | def login_person(person, password, client): | ||
85 | 57 | """Create a LaunchpadUser for a person and password.""" | ||
86 | 58 | user = LaunchpadUser( | ||
87 | 59 | person.displayname, person.preferredemail.email, password) | ||
88 | 60 | user.ensure_login(client) | ||
89 | 61 | |||
90 | 62 | |||
91 | 56 | # Well Known Users | 63 | # Well Known Users |
92 | 57 | ANONYMOUS = AnonymousUser() | 64 | ANONYMOUS = AnonymousUser() |
93 | 58 | 65 | ||
94 | 59 | 66 | ||
95 | === modified file 'lib/lp/code/browser/branch.py' | |||
96 | --- lib/lp/code/browser/branch.py 2009-10-09 15:44:36 +0000 | |||
97 | +++ lib/lp/code/browser/branch.py 2009-10-10 23:06:17 +0000 | |||
98 | @@ -9,6 +9,7 @@ | |||
99 | 9 | 'BranchAddView', | 9 | 'BranchAddView', |
100 | 10 | 'BranchContextMenu', | 10 | 'BranchContextMenu', |
101 | 11 | 'BranchDeletionView', | 11 | 'BranchDeletionView', |
102 | 12 | 'BranchEditStatusView', | ||
103 | 12 | 'BranchEditView', | 13 | 'BranchEditView', |
104 | 13 | 'BranchEditWhiteboardView', | 14 | 'BranchEditWhiteboardView', |
105 | 14 | 'BranchRequestImportView', | 15 | 'BranchRequestImportView', |
106 | @@ -71,10 +72,12 @@ | |||
107 | 71 | from canonical.lazr.utils import smartquote | 72 | from canonical.lazr.utils import smartquote |
108 | 72 | from canonical.widgets.branch import TargetBranchWidget | 73 | from canonical.widgets.branch import TargetBranchWidget |
109 | 73 | from canonical.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription | 74 | from canonical.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription |
110 | 75 | from canonical.widgets.lazrjs import vocabulary_to_choice_edit_items | ||
111 | 74 | 76 | ||
112 | 75 | from lp.bugs.interfaces.bug import IBug | 77 | from lp.bugs.interfaces.bug import IBug |
113 | 76 | from lp.code.browser.branchref import BranchRef | 78 | from lp.code.browser.branchref import BranchRef |
115 | 77 | from lp.code.enums import BranchType, UICreatableBranchType | 79 | from lp.code.enums import ( |
116 | 80 | BranchLifecycleStatus, BranchType, UICreatableBranchType) | ||
117 | 78 | from lp.code.interfaces.branch import ( | 81 | from lp.code.interfaces.branch import ( |
118 | 79 | BranchCreationForbidden, BranchExists, IBranch) | 82 | BranchCreationForbidden, BranchExists, IBranch) |
119 | 80 | from lp.code.interfaces.branchmergeproposal import ( | 83 | from lp.code.interfaces.branchmergeproposal import ( |
120 | @@ -223,7 +226,13 @@ | |||
121 | 223 | facet = 'branches' | 226 | facet = 'branches' |
122 | 224 | links = [ | 227 | links = [ |
123 | 225 | 'associations', 'add_subscriber', 'browse_revisions', 'link_bug', | 228 | 'associations', 'add_subscriber', 'browse_revisions', 'link_bug', |
125 | 226 | 'link_blueprint', 'register_merge', 'source', 'subscription'] | 229 | 'link_blueprint', 'register_merge', 'source', 'subscription', |
126 | 230 | 'edit_status'] | ||
127 | 231 | |||
128 | 232 | @enabled_with_permission('launchpad.Edit') | ||
129 | 233 | def edit_status(self): | ||
130 | 234 | text = 'Change branch status' | ||
131 | 235 | return Link('+edit-status', text, icon='edit') | ||
132 | 227 | 236 | ||
133 | 228 | def browse_revisions(self): | 237 | def browse_revisions(self): |
134 | 229 | """Return a link to the branch's revisions on codebrowse.""" | 238 | """Return a link to the branch's revisions on codebrowse.""" |
135 | @@ -558,6 +567,18 @@ | |||
136 | 558 | # Actually only ProductSeries currently do that. | 567 | # Actually only ProductSeries currently do that. |
137 | 559 | return list(self.context.getProductSeriesPushingTranslations()) | 568 | return list(self.context.getProductSeriesPushingTranslations()) |
138 | 560 | 569 | ||
139 | 570 | @property | ||
140 | 571 | def status_config(self): | ||
141 | 572 | """The config to configure the ChoiceSource JS widget.""" | ||
142 | 573 | return simplejson.dumps({ | ||
143 | 574 | 'status_widget_items': vocabulary_to_choice_edit_items( | ||
144 | 575 | BranchLifecycleStatus, | ||
145 | 576 | css_class_prefix='branchstatus'), | ||
146 | 577 | 'status_value': self.context.lifecycle_status.title, | ||
147 | 578 | 'user_can_edit_status': check_permission('launchpad.Edit', self.context), | ||
148 | 579 | 'branch_path': '/' + self.context.unique_name, | ||
149 | 580 | }) | ||
150 | 581 | |||
151 | 561 | 582 | ||
152 | 562 | class DecoratedMergeProposal: | 583 | class DecoratedMergeProposal: |
153 | 563 | """Provide some additional attributes to a normal branch merge proposal. | 584 | """Provide some additional attributes to a normal branch merge proposal. |
154 | @@ -701,6 +722,12 @@ | |||
155 | 701 | field_names = ['whiteboard'] | 722 | field_names = ['whiteboard'] |
156 | 702 | 723 | ||
157 | 703 | 724 | ||
158 | 725 | class BranchEditStatusView(BranchEditFormView): | ||
159 | 726 | """A view for editing the lifecycle status only.""" | ||
160 | 727 | |||
161 | 728 | field_names = ['lifecycle_status'] | ||
162 | 729 | |||
163 | 730 | |||
164 | 704 | class BranchMirrorStatusView(LaunchpadFormView): | 731 | class BranchMirrorStatusView(LaunchpadFormView): |
165 | 705 | """This view displays the mirror status of a branch. | 732 | """This view displays the mirror status of a branch. |
166 | 706 | 733 | ||
167 | 707 | 734 | ||
168 | === modified file 'lib/lp/code/browser/configure.zcml' | |||
169 | --- lib/lp/code/browser/configure.zcml 2009-09-22 18:45:02 +0000 | |||
170 | +++ lib/lp/code/browser/configure.zcml 2009-10-10 23:06:16 +0000 | |||
171 | @@ -444,6 +444,13 @@ | |||
172 | 444 | permission="launchpad.AnyPerson" | 444 | permission="launchpad.AnyPerson" |
173 | 445 | template="../../app/templates/generic-edit.pt"/> | 445 | template="../../app/templates/generic-edit.pt"/> |
174 | 446 | <browser:page | 446 | <browser:page |
175 | 447 | name="+edit-status" | ||
176 | 448 | for="lp.code.interfaces.branch.IBranch" | ||
177 | 449 | class="lp.code.browser.branch.BranchEditStatusView" | ||
178 | 450 | facet="branches" | ||
179 | 451 | permission="launchpad.Edit" | ||
180 | 452 | template="../../app/templates/generic-edit.pt"/> | ||
181 | 453 | <browser:page | ||
182 | 447 | name="+edit" | 454 | name="+edit" |
183 | 448 | for="lp.code.interfaces.branch.IBranch" | 455 | for="lp.code.interfaces.branch.IBranch" |
184 | 449 | class="lp.code.browser.branch.BranchEditView" | 456 | class="lp.code.browser.branch.BranchEditView" |
185 | 450 | 457 | ||
186 | === modified file 'lib/lp/code/stories/branches/xx-branch-edit.txt' | |||
187 | --- lib/lp/code/stories/branches/xx-branch-edit.txt 2009-09-22 19:04:02 +0000 | |||
188 | +++ lib/lp/code/stories/branches/xx-branch-edit.txt 2009-10-10 23:06:17 +0000 | |||
189 | @@ -107,7 +107,7 @@ | |||
190 | 107 | 'http://code.launchpad.dev/~name12/gnome-terminal/klingon' | 107 | 'http://code.launchpad.dev/~name12/gnome-terminal/klingon' |
191 | 108 | >>> contents = browser.contents | 108 | >>> contents = browser.contents |
192 | 109 | >>> status_tag = find_tag_by_id(contents, 'branch-details-status-value') | 109 | >>> status_tag = find_tag_by_id(contents, 'branch-details-status-value') |
194 | 110 | >>> print status_tag.renderContents() | 110 | >>> print extract_text(status_tag) |
195 | 111 | Merged | 111 | Merged |
196 | 112 | 112 | ||
197 | 113 | Set the branch status back to its initial state. | 113 | Set the branch status back to its initial state. |
198 | 114 | 114 | ||
199 | === modified file 'lib/lp/code/templates/branch-index.pt' | |||
200 | --- lib/lp/code/templates/branch-index.pt 2009-09-30 12:14:24 +0000 | |||
201 | +++ lib/lp/code/templates/branch-index.pt 2009-10-10 23:06:17 +0000 | |||
202 | @@ -37,6 +37,22 @@ | |||
203 | 37 | tal:define="lp_js string:${icingroot}/build" | 37 | tal:define="lp_js string:${icingroot}/build" |
204 | 38 | tal:attributes="src string:${lp_js}/code/branchlinks.js"> | 38 | tal:attributes="src string:${lp_js}/code/branchlinks.js"> |
205 | 39 | </script> | 39 | </script> |
206 | 40 | <script type="text/javascript" | ||
207 | 41 | tal:condition="devmode" | ||
208 | 42 | tal:define="lp_js string:${icingroot}/build" | ||
209 | 43 | tal:attributes="src string:${lp_js}/code/branchstatus.js"> | ||
210 | 44 | </script> | ||
211 | 45 | <script type="text/javascript" | ||
212 | 46 | tal:content="string: | ||
213 | 47 | YUI().use('node', 'event', 'widget', 'plugin', 'overlay', | ||
214 | 48 | 'lazr.choiceedit', 'code.branchstatus', function(Y) { | ||
215 | 49 | Y.on('load', | ||
216 | 50 | function(e) { | ||
217 | 51 | Y.branchstatus.connect_status(${view/status_config}); | ||
218 | 52 | }, | ||
219 | 53 | window); | ||
220 | 54 | }); | ||
221 | 55 | "/> | ||
222 | 40 | </metal:block> | 56 | </metal:block> |
223 | 41 | 57 | ||
224 | 42 | <body> | 58 | <body> |
225 | 43 | 59 | ||
226 | === modified file 'lib/lp/code/templates/branch-information.pt' | |||
227 | --- lib/lp/code/templates/branch-information.pt 2009-09-22 17:03:24 +0000 | |||
228 | +++ lib/lp/code/templates/branch-information.pt 2009-10-10 23:06:16 +0000 | |||
229 | @@ -22,10 +22,15 @@ | |||
230 | 22 | 22 | ||
231 | 23 | <dl id="status"> | 23 | <dl id="status"> |
232 | 24 | <dt>Status:</dt> | 24 | <dt>Status:</dt> |
237 | 25 | <dd | 25 | <dd> |
238 | 26 | id="branch-details-status-value" | 26 | <span id="branch-details-status-value"> |
239 | 27 | tal:attributes="class string:branchstatus${context/lifecycle_status/name}" | 27 | <span tal:attributes="class string:value branchstatus${context/lifecycle_status/name}" |
240 | 28 | tal:content="structure context/lifecycle_status/title" /> | 28 | tal:content="structure context/lifecycle_status/title" /> |
241 | 29 | <a href="+edit-status"> | ||
242 | 30 | <img class="editicon" src="/@@/edit"/> | ||
243 | 31 | </a> | ||
244 | 32 | </span> | ||
245 | 33 | </dd> | ||
246 | 29 | </dl> | 34 | </dl> |
247 | 30 | </div> | 35 | </div> |
248 | 31 | 36 | ||
249 | 32 | 37 | ||
250 | === added file 'lib/lp/code/windmill/tests/test_branch_index.py' | |||
251 | --- lib/lp/code/windmill/tests/test_branch_index.py 1970-01-01 00:00:00 +0000 | |||
252 | +++ lib/lp/code/windmill/tests/test_branch_index.py 2009-10-10 23:06:17 +0000 | |||
253 | @@ -0,0 +1,64 @@ | |||
254 | 1 | # Copyright 2009 Canonical Ltd. This software is licensed under the | ||
255 | 2 | # GNU Affero General Public License version 3 (see the file LICENSE). | ||
256 | 3 | |||
257 | 4 | """Test for the main branch page.""" | ||
258 | 5 | |||
259 | 6 | __metaclass__ = type | ||
260 | 7 | __all__ = [] | ||
261 | 8 | |||
262 | 9 | import transaction | ||
263 | 10 | import unittest | ||
264 | 11 | |||
265 | 12 | import windmill | ||
266 | 13 | from windmill.authoring import WindmillTestClient | ||
267 | 14 | |||
268 | 15 | from canonical.launchpad.windmill.testing.constants import ( | ||
269 | 16 | PAGE_LOAD, SLEEP) | ||
270 | 17 | from canonical.launchpad.windmill.testing.lpuser import login_person | ||
271 | 18 | from lp.code.windmill.testing import CodeWindmillLayer | ||
272 | 19 | from lp.testing import TestCaseWithFactory | ||
273 | 20 | |||
274 | 21 | |||
275 | 22 | class TestBranchStatus(TestCaseWithFactory): | ||
276 | 23 | |||
277 | 24 | layer = CodeWindmillLayer | ||
278 | 25 | |||
279 | 26 | def test_inline_branch_status_setting(self): | ||
280 | 27 | """Test branch bug links.""" | ||
281 | 28 | eric = self.factory.makePerson( | ||
282 | 29 | name="eric", displayname="Eric the Viking", password="test", | ||
283 | 30 | email="eric@example.com") | ||
284 | 31 | branch = self.factory.makeBranch(owner=eric) | ||
285 | 32 | transaction.commit() | ||
286 | 33 | |||
287 | 34 | client = WindmillTestClient("Branch status setting") | ||
288 | 35 | |||
289 | 36 | login_person(eric, "test", client) | ||
290 | 37 | |||
291 | 38 | start_url = ( | ||
292 | 39 | windmill.settings['TEST_URL'] + branch.unique_name) | ||
293 | 40 | client.open(url=start_url) | ||
294 | 41 | client.waits.forPageLoad(timeout=PAGE_LOAD) | ||
295 | 42 | |||
296 | 43 | # Click on the element containing the branch status. | ||
297 | 44 | client.click(id=u'branch-details-status-value') | ||
298 | 45 | client.waits.forElement( | ||
299 | 46 | xpath=u'//div[contains(@class, "yui-ichoicelist-content")]') | ||
300 | 47 | |||
301 | 48 | # Change the status to experimental. | ||
302 | 49 | client.click(link=u'Experimental') | ||
303 | 50 | client.waits.sleep(milliseconds=SLEEP) | ||
304 | 51 | |||
305 | 52 | client.asserts.assertText( | ||
306 | 53 | xpath=u'//span[@id="branch-details-status-value"]/span', | ||
307 | 54 | validator=u'Experimental') | ||
308 | 55 | |||
309 | 56 | # Reload the page and make sure the change sticks. | ||
310 | 57 | client.open(url=start_url) | ||
311 | 58 | client.asserts.assertText( | ||
312 | 59 | xpath=u'//span[@id="branch-details-status-value"]/span', | ||
313 | 60 | validator=u'Experimental') | ||
314 | 61 | |||
315 | 62 | |||
316 | 63 | def test_suite(): | ||
317 | 64 | return unittest.TestLoader().loadTestsFromName(__name__) |
This is the branch that adds the lazr.js popup chooser for the branch status.
Go for gold