Merge lp:~thumper/launchpad/inline-lifecycle-status-edit into lp:launchpad

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
Reviewer Review Type Date Requested Status
Deryck Hodge (community) code js Approve
Paul Hummer Pending
Review via email: mp+12707@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

This is the branch that adds the lazr.js popup chooser for the branch status.

Go for gold

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
=== modified file 'lib/canonical/launchpad/icing/style.css'
--- lib/canonical/launchpad/icing/style.css 2009-10-06 17:45:46 +0000
+++ lib/canonical/launchpad/icing/style.css 2009-10-10 23:06:17 +0000
@@ -1851,12 +1851,12 @@
1851 color: #d18b39;1851 color: #d18b39;
1852}1852}
18531853
1854.branchstatusMATURE {color: #090;}1854.branchstatusMATURE, .branchstatusMATURE a {color: #090;}
1855.branchstatusDEVELOPMENT {color: #900;}1855.branchstatusDEVELOPMENT, .branchstatusDEVELOPMENT a {color: #900;}
1856.branchstatusEXPERIMENTAL {color: #930;}1856.branchstatusEXPERIMENTAL, .branchstatusEXPERIMENTAL a {color: #930;}
1857.branchstatusMERGED {color: #666;}1857.branchstatusMERGED, .branchstatusMERGED a {color: #666;}
1858.branchstatusABANDONED {color: #666;}1858.branchstatusABANDONED, .branchstatusABANDONED a {color: #666;}
1859.branchstatusNEW {color: black;}1859.branchstatusNEW, .branchstatusNEW a {color: black;}
18601860
1861.voteAPPROVE {color: green;}1861.voteAPPROVE {color: green;}
1862.voteNEEDS_FIXING {color: #930;}1862.voteNEEDS_FIXING {color: #930;}
18631863
=== added file 'lib/canonical/launchpad/javascript/code/branchstatus.js'
--- lib/canonical/launchpad/javascript/code/branchstatus.js 1970-01-01 00:00:00 +0000
+++ lib/canonical/launchpad/javascript/code/branchstatus.js 2009-10-10 23:06:16 +0000
@@ -0,0 +1,48 @@
1/** Copyright (c) 2009, Canonical Ltd. All rights reserved.
2 *
3 * Code for handling the update of the branch status.
4 *
5 * @module branchstatus
6 * @requires node, lazr.choiceedit, lp.client.plugins
7 */
8
9YUI.add('code.branchstatus', function(Y) {
10
11Y.branchstatus = Y.namespace('code.branchstatus');
12
13/*
14 * Connect the branch status to the javascript events.
15 */
16Y.branchstatus.connect_status = function(conf) {
17
18 var status_content = Y.get('#branch-details-status-value');
19
20 if
21 (conf.user_can_edit_status) {
22 var status_choice_edit = new Y.ChoiceSource({
23 contentBox: status_content,
24 value: conf.status_value,
25 title: 'Change status to',
26 items: conf.status_widget_items});
27 status_choice_edit.showError = function(err) {
28 display_error(null, err);
29 };
30 status_choice_edit.on('save', function(e) {
31 var cb = status_choice_edit.get('contentBox');
32 Y.Array.each(conf.status_widget_items, function(item) {
33 if (item.value == status_choice_edit.get('value')) {
34 cb.query('span').addClass(item.css_class);
35 } else {
36 cb.query('span').removeClass(item.css_class);
37 }
38 });
39 });
40 status_choice_edit.plug({
41 fn: Y.lp.client.plugins.PATCHPlugin, cfg: {
42 patch: 'lifecycle_status',
43 resource: conf.branch_path}});
44 status_choice_edit.render();
45 }
46};
47
48}, '0.1', {requires: ['node', 'lazr.choiceedit', 'lp.client.plugins']});
049
=== modified file 'lib/canonical/launchpad/windmill/testing/lpuser.py'
--- lib/canonical/launchpad/windmill/testing/lpuser.py 2009-08-19 11:13:26 +0000
+++ lib/canonical/launchpad/windmill/testing/lpuser.py 2009-10-10 23:06:17 +0000
@@ -53,6 +53,13 @@
53 client.waits.forPageLoad(timeout=u'100000')53 client.waits.forPageLoad(timeout=u'100000')
5454
5555
56def login_person(person, password, client):
57 """Create a LaunchpadUser for a person and password."""
58 user = LaunchpadUser(
59 person.displayname, person.preferredemail.email, password)
60 user.ensure_login(client)
61
62
56# Well Known Users63# Well Known Users
57ANONYMOUS = AnonymousUser()64ANONYMOUS = AnonymousUser()
5865
5966
=== modified file 'lib/lp/code/browser/branch.py'
--- lib/lp/code/browser/branch.py 2009-10-09 15:44:36 +0000
+++ lib/lp/code/browser/branch.py 2009-10-10 23:06:17 +0000
@@ -9,6 +9,7 @@
9 'BranchAddView',9 'BranchAddView',
10 'BranchContextMenu',10 'BranchContextMenu',
11 'BranchDeletionView',11 'BranchDeletionView',
12 'BranchEditStatusView',
12 'BranchEditView',13 'BranchEditView',
13 'BranchEditWhiteboardView',14 'BranchEditWhiteboardView',
14 'BranchRequestImportView',15 'BranchRequestImportView',
@@ -71,10 +72,12 @@
71from canonical.lazr.utils import smartquote72from canonical.lazr.utils import smartquote
72from canonical.widgets.branch import TargetBranchWidget73from canonical.widgets.branch import TargetBranchWidget
73from canonical.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription74from canonical.widgets.itemswidgets import LaunchpadRadioWidgetWithDescription
75from canonical.widgets.lazrjs import vocabulary_to_choice_edit_items
7476
75from lp.bugs.interfaces.bug import IBug77from lp.bugs.interfaces.bug import IBug
76from lp.code.browser.branchref import BranchRef78from lp.code.browser.branchref import BranchRef
77from lp.code.enums import BranchType, UICreatableBranchType79from lp.code.enums import (
80 BranchLifecycleStatus, BranchType, UICreatableBranchType)
78from lp.code.interfaces.branch import (81from lp.code.interfaces.branch import (
79 BranchCreationForbidden, BranchExists, IBranch)82 BranchCreationForbidden, BranchExists, IBranch)
80from lp.code.interfaces.branchmergeproposal import (83from lp.code.interfaces.branchmergeproposal import (
@@ -223,7 +226,13 @@
223 facet = 'branches'226 facet = 'branches'
224 links = [227 links = [
225 'associations', 'add_subscriber', 'browse_revisions', 'link_bug',228 'associations', 'add_subscriber', 'browse_revisions', 'link_bug',
226 'link_blueprint', 'register_merge', 'source', 'subscription']229 'link_blueprint', 'register_merge', 'source', 'subscription',
230 'edit_status']
231
232 @enabled_with_permission('launchpad.Edit')
233 def edit_status(self):
234 text = 'Change branch status'
235 return Link('+edit-status', text, icon='edit')
227236
228 def browse_revisions(self):237 def browse_revisions(self):
229 """Return a link to the branch's revisions on codebrowse."""238 """Return a link to the branch's revisions on codebrowse."""
@@ -558,6 +567,18 @@
558 # Actually only ProductSeries currently do that.567 # Actually only ProductSeries currently do that.
559 return list(self.context.getProductSeriesPushingTranslations())568 return list(self.context.getProductSeriesPushingTranslations())
560569
570 @property
571 def status_config(self):
572 """The config to configure the ChoiceSource JS widget."""
573 return simplejson.dumps({
574 'status_widget_items': vocabulary_to_choice_edit_items(
575 BranchLifecycleStatus,
576 css_class_prefix='branchstatus'),
577 'status_value': self.context.lifecycle_status.title,
578 'user_can_edit_status': check_permission('launchpad.Edit', self.context),
579 'branch_path': '/' + self.context.unique_name,
580 })
581
561582
562class DecoratedMergeProposal:583class DecoratedMergeProposal:
563 """Provide some additional attributes to a normal branch merge proposal.584 """Provide some additional attributes to a normal branch merge proposal.
@@ -701,6 +722,12 @@
701 field_names = ['whiteboard']722 field_names = ['whiteboard']
702723
703724
725class BranchEditStatusView(BranchEditFormView):
726 """A view for editing the lifecycle status only."""
727
728 field_names = ['lifecycle_status']
729
730
704class BranchMirrorStatusView(LaunchpadFormView):731class BranchMirrorStatusView(LaunchpadFormView):
705 """This view displays the mirror status of a branch.732 """This view displays the mirror status of a branch.
706733
707734
=== modified file 'lib/lp/code/browser/configure.zcml'
--- lib/lp/code/browser/configure.zcml 2009-09-22 18:45:02 +0000
+++ lib/lp/code/browser/configure.zcml 2009-10-10 23:06:16 +0000
@@ -444,6 +444,13 @@
444 permission="launchpad.AnyPerson"444 permission="launchpad.AnyPerson"
445 template="../../app/templates/generic-edit.pt"/>445 template="../../app/templates/generic-edit.pt"/>
446 <browser:page446 <browser:page
447 name="+edit-status"
448 for="lp.code.interfaces.branch.IBranch"
449 class="lp.code.browser.branch.BranchEditStatusView"
450 facet="branches"
451 permission="launchpad.Edit"
452 template="../../app/templates/generic-edit.pt"/>
453 <browser:page
447 name="+edit"454 name="+edit"
448 for="lp.code.interfaces.branch.IBranch"455 for="lp.code.interfaces.branch.IBranch"
449 class="lp.code.browser.branch.BranchEditView"456 class="lp.code.browser.branch.BranchEditView"
450457
=== modified file 'lib/lp/code/stories/branches/xx-branch-edit.txt'
--- lib/lp/code/stories/branches/xx-branch-edit.txt 2009-09-22 19:04:02 +0000
+++ lib/lp/code/stories/branches/xx-branch-edit.txt 2009-10-10 23:06:17 +0000
@@ -107,7 +107,7 @@
107 'http://code.launchpad.dev/~name12/gnome-terminal/klingon'107 'http://code.launchpad.dev/~name12/gnome-terminal/klingon'
108 >>> contents = browser.contents108 >>> contents = browser.contents
109 >>> status_tag = find_tag_by_id(contents, 'branch-details-status-value')109 >>> status_tag = find_tag_by_id(contents, 'branch-details-status-value')
110 >>> print status_tag.renderContents()110 >>> print extract_text(status_tag)
111 Merged111 Merged
112112
113Set the branch status back to its initial state.113Set the branch status back to its initial state.
114114
=== modified file 'lib/lp/code/templates/branch-index.pt'
--- lib/lp/code/templates/branch-index.pt 2009-09-30 12:14:24 +0000
+++ lib/lp/code/templates/branch-index.pt 2009-10-10 23:06:17 +0000
@@ -37,6 +37,22 @@
37 tal:define="lp_js string:${icingroot}/build"37 tal:define="lp_js string:${icingroot}/build"
38 tal:attributes="src string:${lp_js}/code/branchlinks.js">38 tal:attributes="src string:${lp_js}/code/branchlinks.js">
39 </script>39 </script>
40 <script type="text/javascript"
41 tal:condition="devmode"
42 tal:define="lp_js string:${icingroot}/build"
43 tal:attributes="src string:${lp_js}/code/branchstatus.js">
44 </script>
45 <script type="text/javascript"
46 tal:content="string:
47 YUI().use('node', 'event', 'widget', 'plugin', 'overlay',
48 'lazr.choiceedit', 'code.branchstatus', function(Y) {
49 Y.on('load',
50 function(e) {
51 Y.branchstatus.connect_status(${view/status_config});
52 },
53 window);
54 });
55 "/>
40</metal:block>56</metal:block>
4157
42<body>58<body>
4359
=== modified file 'lib/lp/code/templates/branch-information.pt'
--- lib/lp/code/templates/branch-information.pt 2009-09-22 17:03:24 +0000
+++ lib/lp/code/templates/branch-information.pt 2009-10-10 23:06:16 +0000
@@ -22,10 +22,15 @@
2222
23 <dl id="status">23 <dl id="status">
24 <dt>Status:</dt>24 <dt>Status:</dt>
25 <dd25 <dd>
26 id="branch-details-status-value"26 <span id="branch-details-status-value">
27 tal:attributes="class string:branchstatus${context/lifecycle_status/name}"27 <span tal:attributes="class string:value branchstatus${context/lifecycle_status/name}"
28 tal:content="structure context/lifecycle_status/title" />28 tal:content="structure context/lifecycle_status/title" />&nbsp;
29 <a href="+edit-status">
30 <img class="editicon" src="/@@/edit"/>
31 </a>
32 </span>
33 </dd>
29 </dl>34 </dl>
30 </div>35 </div>
3136
3237
=== added file 'lib/lp/code/windmill/tests/test_branch_index.py'
--- lib/lp/code/windmill/tests/test_branch_index.py 1970-01-01 00:00:00 +0000
+++ lib/lp/code/windmill/tests/test_branch_index.py 2009-10-10 23:06:17 +0000
@@ -0,0 +1,64 @@
1# Copyright 2009 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).
3
4"""Test for the main branch page."""
5
6__metaclass__ = type
7__all__ = []
8
9import transaction
10import unittest
11
12import windmill
13from windmill.authoring import WindmillTestClient
14
15from canonical.launchpad.windmill.testing.constants import (
16 PAGE_LOAD, SLEEP)
17from canonical.launchpad.windmill.testing.lpuser import login_person
18from lp.code.windmill.testing import CodeWindmillLayer
19from lp.testing import TestCaseWithFactory
20
21
22class TestBranchStatus(TestCaseWithFactory):
23
24 layer = CodeWindmillLayer
25
26 def test_inline_branch_status_setting(self):
27 """Test branch bug links."""
28 eric = self.factory.makePerson(
29 name="eric", displayname="Eric the Viking", password="test",
30 email="eric@example.com")
31 branch = self.factory.makeBranch(owner=eric)
32 transaction.commit()
33
34 client = WindmillTestClient("Branch status setting")
35
36 login_person(eric, "test", client)
37
38 start_url = (
39 windmill.settings['TEST_URL'] + branch.unique_name)
40 client.open(url=start_url)
41 client.waits.forPageLoad(timeout=PAGE_LOAD)
42
43 # Click on the element containing the branch status.
44 client.click(id=u'branch-details-status-value')
45 client.waits.forElement(
46 xpath=u'//div[contains(@class, "yui-ichoicelist-content")]')
47
48 # Change the status to experimental.
49 client.click(link=u'Experimental')
50 client.waits.sleep(milliseconds=SLEEP)
51
52 client.asserts.assertText(
53 xpath=u'//span[@id="branch-details-status-value"]/span',
54 validator=u'Experimental')
55
56 # Reload the page and make sure the change sticks.
57 client.open(url=start_url)
58 client.asserts.assertText(
59 xpath=u'//span[@id="branch-details-status-value"]/span',
60 validator=u'Experimental')
61
62
63def test_suite():
64 return unittest.TestLoader().loadTestsFromName(__name__)