Merge lp:~bac/launchpad/bug-652149 into lp:launchpad

Proposed by Brad Crittenden
Status: Merged
Approved by: Brad Crittenden
Approved revision: 11705
Merged at revision: 11789
Proposed branch: lp:~bac/launchpad/bug-652149
Merge into: lp:launchpad
Diff against target: 485 lines (+192/-55)
8 files modified
lib/lp/code/browser/branchlisting.py (+3/-1)
lib/lp/code/browser/branchvisibilitypolicy.py (+21/-14)
lib/lp/code/browser/tests/test_branchlisting.py (+77/-13)
lib/lp/code/stories/branches/xx-branch-visibility-policy.txt (+51/-15)
lib/lp/code/templates/branch-visibility.pt (+2/-2)
lib/lp/code/templates/project-branches.pt (+37/-8)
lib/lp/registry/browser/project.py (+1/-1)
lib/lp/testing/sampledata.py (+0/-1)
To merge this branch: bzr merge lp:~bac/launchpad/bug-652149
Reviewer Review Type Date Requested Status
Curtis Hovey (community) ui Approve
Henning Eggers (community) ui* Approve
Jeroen T. Vermeulen (community) code Approve
Review via email: mp+38705@code.launchpad.net

Commit message

Provide an indication of the default branch visibility rule for a project group and a link to 'Define branch visibility' for LP admins and commercial admins.

Description of the change

= Summary =

The code view for a project group did not show the default branch rules.
 It did have a link for 'Define branch visibility' but the permission on
it was wrong, so commercial admins did not see it.

== Proposed fix ==

Convert the template to main_side, add a portlet for the privacy setting
display and a portlet for the link to define branch visibility.

== Pre-implementation notes ==

Brief chat with Curtis.

== Implementation details ==

I included some drive-by fixes. Removed redundancy from
lp.testing.sampledata and cleaned up the page template for
product-branches to not use conditional paragraphs.

== Tests ==

bin/test -vvm lp.code -t TestProjectGroupBranchesPage

== Demo and Q/A ==

Visit a project group such as https://launchpad.dev/mozilla and
determine everything is in order.

= Launchpad lint =

Bah, I'll check to ensure the real lint issues are fixed.

Checking for conflicts and issues in changed files.

Linting changed files:
  lib/lp/code/templates/project-branches.pt
  lib/lp/code/templates/product-branches.pt
  lib/lp/code/browser/tests/test_branchlisting.py
  lib/lp/testing/sampledata.py
  lib/lp/code/stories/branches/xx-branch-visibility-policy.txt
  lib/lp/registry/browser/project.py
  lib/lp/code/browser/branchlisting.py

./lib/lp/code/stories/branches/xx-branch-visibility-policy.txt
       1: narrative uses a moin header.
      67: source exceeds 78 characters.
      94: narrative uses a moin header.
     104: source exceeds 78 characters.
     107: source exceeds 78 characters.
     125: source exceeds 78 characters.
     126: want exceeds 78 characters.
     134: source exceeds 78 characters.
     138: source exceeds 78 characters.
     146: narrative uses a moin header.
     198: narrative uses a moin header.
     231: source exceeds 78 characters.
     253: source exceeds 78 characters.
./lib/lp/code/browser/branchlisting.py
    1388: E302 expected 2 blank lines, found 1

To post a comment you must log in.
lp:~bac/launchpad/bug-652149 updated
11699. By Brad Crittenden

Fixed lint

11700. By Brad Crittenden

Fixed lint

Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Looks fine, apart from a few things we discussed on IRC:
 * Render & search views in your tests using BeautifulSoup(view())
 * Multi-line strings would be nicer than ("line" "line") in tests.
 * The view inherits from both LaunchpadFormView and, indirectly, LaunchpadView.

review: Approve (code)
Revision history for this message
Brad Crittenden (bac) wrote :

Thanks Jeroen. All of the issues you raised are fixed.

lp:~bac/launchpad/bug-652149 updated
11701. By Brad Crittenden

Do not use (expensive) browser in tests, refactor BranchVisiblityPolicyMixin, streamline expected output in tests.

Revision history for this message
Brad Crittenden (bac) wrote :

Hi Henning,

Could you do a UI review, please? Screenshots available at:
http://people.canonical.com/~bac/branchvis/

lp:~bac/launchpad/bug-652149 updated
11702. By Brad Crittenden

Changed display of inherited branch vis policy for projects. Reverted change to product-branches.pt.

Revision history for this message
Henning Eggers (henninge) wrote :

Hi Brad,
this looks very good, thank you. The icon misalignment I noticed must be related to other stuff. I see it all over Launchpad now.

I was about to make suggestions about avoiding adding the side portlets and thus losing horizontal space. Horizontal space is a little issue because the project group page has an extra column on the branch listing. The information could be placed in the top portlet but I don't know how long the list of teams might get. Having a long list of team exceptions before reaching the actual branches degrades the usefulness of the page. Maybe the list could have been placed under the branch listing.

But I realized that a project's code page already has that portlet about visibility in the same spot, so I guess this is consistent. IIRC 3.0 UI design removed side portlets from all pages expect project/application home pages?

So the only think I'd like you to think about is if the extra portlet for changing the visibilty. Could that not be integrated into the other portlet by adding an edit icon at the right place?

There is one little nitpick: forbidden-no-teams.png shows some whitespace at the bottom of the upper portlet. This appears on other similar portlets, too, and is owed to the text being in a <p> tag which has margin-bottom set to 0.3em or so. Could that be avoided somehow?

But there are no real stoppers here, seeing that the use of side portlets seems to be appropriate here. Thank you!

Henning

review: Approve (ui*)
Revision history for this message
Curtis Hovey (sinzui) wrote :

I agree with Henning.

review: Approve (ui)
Revision history for this message
Brad Crittenden (bac) wrote :

Thanks for the UI review Henning and Curtis.

I hadn't noticed the extra space at the bottom of the top portlet. I defeated it with a style="margin-bottom: 0;" and it looks nicer.

For consistency with the other code branchlisting pages I prefer to keep the "Define branch visibility" link in a second portlet.

lp:~bac/launchpad/bug-652149 updated
11703. By Brad Crittenden

Fixed portlet spacing

11704. By Brad Crittenden

Merge from devel. Encountered conflicts with branchlisting files.

11705. By Brad Crittenden

Merged new tests from devel

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/code/browser/branchlisting.py'
--- lib/lp/code/browser/branchlisting.py 2010-10-20 16:04:58 +0000
+++ lib/lp/code/browser/branchlisting.py 2010-10-23 04:44:50 +0000
@@ -94,6 +94,7 @@
94 PersonActiveReviewsView,94 PersonActiveReviewsView,
95 PersonProductActiveReviewsView,95 PersonProductActiveReviewsView,
96 )96 )
97from lp.code.browser.branchvisibilitypolicy import BranchVisibilityPolicyMixin
97from lp.code.browser.summary import BranchCountSummaryView98from lp.code.browser.summary import BranchCountSummaryView
98from lp.code.enums import (99from lp.code.enums import (
99 BranchLifecycleStatus,100 BranchLifecycleStatus,
@@ -532,7 +533,8 @@
532 return "listing sortable"533 return "listing sortable"
533534
534535
535class BranchListingView(LaunchpadFormView, FeedsMixin):536class BranchListingView(LaunchpadFormView, FeedsMixin,
537 BranchVisibilityPolicyMixin):
536 """A base class for views of branch listings."""538 """A base class for views of branch listings."""
537 schema = IBranchListingFilter539 schema = IBranchListingFilter
538 field_names = ['lifecycle', 'sort_by']540 field_names = ['lifecycle', 'sort_by']
539541
=== modified file 'lib/lp/code/browser/branchvisibilitypolicy.py'
--- lib/lp/code/browser/branchvisibilitypolicy.py 2010-08-31 11:11:09 +0000
+++ lib/lp/code/browser/branchvisibilitypolicy.py 2010-10-23 04:44:50 +0000
@@ -8,6 +8,7 @@
8__all__ = [8__all__ = [
9 'AddBranchVisibilityTeamPolicyView',9 'AddBranchVisibilityTeamPolicyView',
10 'RemoveBranchVisibilityTeamPolicyView',10 'RemoveBranchVisibilityTeamPolicyView',
11 'BranchVisibilityPolicyMixin',
11 'BranchVisibilityPolicyView',12 'BranchVisibilityPolicyView',
12 ]13 ]
1314
@@ -38,6 +39,8 @@
38 BranchVisibilityRule,39 BranchVisibilityRule,
39 TeamBranchVisibilityRule,40 TeamBranchVisibilityRule,
40 )41 )
42from lp.code.interfaces.branchnamespace import IBranchNamespacePolicy
43from lp.code.interfaces.branchtarget import IBranchTarget
41from lp.code.interfaces.branchvisibilitypolicy import (44from lp.code.interfaces.branchvisibilitypolicy import (
42 IBranchVisibilityTeamPolicy,45 IBranchVisibilityTeamPolicy,
43 )46 )
@@ -155,7 +158,24 @@
155 self.context.removeTeamFromBranchVisibilityPolicy(item.team)158 self.context.removeTeamFromBranchVisibilityPolicy(item.team)
156159
157160
158class BranchVisibilityPolicyView(LaunchpadView):161class BranchVisibilityPolicyMixin:
162 """Mixin class providing visibility rules."""
163 @property
164 def base_visibility_rule(self):
165 return self.context.getBaseBranchVisibilityRule()
166
167 @property
168 def team_policies(self):
169 """The policy items that have a valid team."""
170 return [item for item in self.items if item.team is not None]
171
172 @cachedproperty
173 def items(self):
174 return self.context.getBranchVisibilityTeamPolicies()
175
176
177class BranchVisibilityPolicyView(LaunchpadView,
178 BranchVisibilityPolicyMixin):
159 """Simple view for displaying branch visibility policies."""179 """Simple view for displaying branch visibility policies."""
160180
161 @property181 @property
@@ -163,14 +183,6 @@
163 name = self.context.displayname183 name = self.context.displayname
164 return 'Set branch visibility policy for %s' % name184 return 'Set branch visibility policy for %s' % name
165185
166 @cachedproperty
167 def items(self):
168 return self.context.getBranchVisibilityTeamPolicies()
169
170 @property
171 def base_visibility_rule(self):
172 return self.context.getBaseBranchVisibilityRule()
173
174 @property186 @property
175 def can_remove_items(self):187 def can_remove_items(self):
176 """You cannot remove items if using inherited policy or188 """You cannot remove items if using inherited policy or
@@ -178,8 +190,3 @@
178 """190 """
179 return (len(self.items) > 0 and191 return (len(self.items) > 0 and
180 not self.context.isUsingInheritedBranchVisibilityPolicy())192 not self.context.isUsingInheritedBranchVisibilityPolicy())
181
182 @property
183 def team_policies(self):
184 """The policy items that have a valid team."""
185 return [item for item in self.items if item.team is not None]
186193
=== modified file 'lib/lp/code/browser/tests/test_branchlisting.py'
--- lib/lp/code/browser/tests/test_branchlisting.py 2010-10-20 13:53:15 +0000
+++ lib/lp/code/browser/tests/test_branchlisting.py 2010-10-23 04:44:50 +0000
@@ -33,11 +33,15 @@
33 GroupedDistributionSourcePackageBranchesView,33 GroupedDistributionSourcePackageBranchesView,
34 SourcePackageBranchesView,34 SourcePackageBranchesView,
35 )35 )
36from lp.code.enums import BranchVisibilityRule
36from lp.code.interfaces.seriessourcepackagebranch import (37from lp.code.interfaces.seriessourcepackagebranch import (
37 IMakeOfficialBranchLinks,38 IMakeOfficialBranchLinks,
38 )39 )
39from lp.code.model.branch import Branch40from lp.code.model.branch import Branch
40from lp.registry.interfaces.person import PersonVisibility41from lp.registry.interfaces.person import (
42 IPersonSet,
43 PersonVisibility,
44 )
41from lp.registry.interfaces.pocket import PackagePublishingPocket45from lp.registry.interfaces.pocket import PackagePublishingPocket
42from lp.registry.model.person import Owner46from lp.registry.model.person import Owner
43from lp.registry.model.product import Product47from lp.registry.model.product import Product
@@ -51,6 +55,10 @@
51 time_counter,55 time_counter,
52 )56 )
53from lp.testing.factory import remove_security_proxy_and_shout_at_engineer57from lp.testing.factory import remove_security_proxy_and_shout_at_engineer
58from lp.testing.sampledata import (
59 ADMIN_EMAIL,
60 COMMERCIAL_ADMIN_EMAIL,
61 )
54from lp.testing.views import create_initialized_view62from lp.testing.views import create_initialized_view
5563
5664
@@ -422,35 +430,91 @@
422 self.assertIs(None, branches)430 self.assertIs(None, branches)
423431
424432
425class TestProjectBranchListing(TestCaseWithFactory):433class TestProjectGroupBranches(TestCaseWithFactory):
434 """Test for the project group branches page."""
426435
427 layer = DatabaseFunctionalLayer436 layer = DatabaseFunctionalLayer
428437
429 def setUp(self):438 def setUp(self):
430 super(TestProjectBranchListing, self).setUp()439 TestCaseWithFactory.setUp(self)
431 self.project = self.factory.makeProject()440 self.project = self.factory.makeProject()
432 self.product = self.factory.makeProduct(project=self.project)441
442 def test_project_with_no_branch_visibility_rule(self):
443 view = create_initialized_view(
444 self.project, name="+branches", rootsite='code')
445 privacy_portlet = find_tag_by_id(view(), 'privacy')
446 text = extract_text(privacy_portlet)
447 expected = """
448 Inherited branch visibility for all projects in .* is Public.
449 """
450 self.assertTextMatchesExpressionIgnoreWhitespace(
451 expected, text)
452
453 def test_project_with_private_branch_visibility_rule(self):
454 self.project.setBranchVisibilityTeamPolicy(
455 None, BranchVisibilityRule.FORBIDDEN)
456 view = create_initialized_view(
457 self.project, name="+branches", rootsite='code')
458 privacy_portlet = find_tag_by_id(view(), 'privacy')
459 text = extract_text(privacy_portlet)
460 expected = """
461 Inherited branch visibility for all projects in .* is Forbidden.
462 """
463 self.assertTextMatchesExpressionIgnoreWhitespace(
464 expected, text)
465
466 def _testBranchVisibilityLink(self, user):
467 login_person(user)
468 view = create_initialized_view(
469 self.project, name="+branches", rootsite='code',
470 principal=user)
471 action_portlet = find_tag_by_id(view(), 'action-portlet')
472 text = extract_text(action_portlet)
473 expected = '.*Define branch visibility.*'
474 self.assertTextMatchesExpressionIgnoreWhitespace(
475 expected, text)
476
477 def test_branch_visibility_link_admin(self):
478 # An admin will be displayed a link to define branch visibility in the
479 # action portlet.
480 admin = getUtility(IPersonSet).getByEmail(ADMIN_EMAIL)
481 self._testBranchVisibilityLink(admin)
482
483 def test_branch_visibility_link_commercial_admin(self):
484 # A commercial admin will be displayed a link to define branch
485 # visibility in the action portlet.
486 admin = getUtility(IPersonSet).getByEmail(COMMERCIAL_ADMIN_EMAIL)
487 self._testBranchVisibilityLink(admin)
488
489 def test_branch_visibility_link_non_admin(self):
490 # A non-admin will not see the action portlet.
491 view = create_initialized_view(
492 self.project, name="+branches", rootsite='code')
493 action_portlet = find_tag_by_id(view(), 'action-portlet')
494 self.assertIs(None, action_portlet)
433495
434 def test_no_branches_gets_message_not_listing(self):496 def test_no_branches_gets_message_not_listing(self):
435 # If there are no product branches on the project's products, then497 # If there are no product branches on the project's products, then
436 # the view shows the no code hosting message instead of a listing.498 # the view shows the no code hosting message instead of a listing.
437 browser = self.getUserBrowser(499 self.factory.makeProduct(project=self.project)
438 canonical_url(self.project, rootsite='code'))500 view = create_initialized_view(
501 self.project, name='+branches', rootsite='code')
439 displayname = self.project.displayname502 displayname = self.project.displayname
440 expected_text = normalize_whitespace(503 expected_text = normalize_whitespace(
441 ("Launchpad does not know where any of %s's "504 ("Launchpad does not know where any of %s's "
442 "projects host their code." % displayname))505 "projects host their code." % displayname))
443 no_branch_div = find_tag_by_id(browser.contents, "no-branchtable")506 no_branch_div = find_tag_by_id(view(), "no-branchtable")
444 text = normalize_whitespace(extract_text(no_branch_div))507 text = normalize_whitespace(extract_text(no_branch_div))
445 self.assertEqual(expected_text, text)508 self.assertEqual(expected_text, text)
446509
447 def test_branches_get_listing(self):510 def test_branches_get_listing(self):
448 # If a product has a branch, then the project view has a branch511 # If a product has a branch, then the project view has a branch
449 # listing.512 # listing.
450 branch = self.factory.makeProductBranch(product=self.product)513 product = self.factory.makeProduct(project=self.project)
451 browser = self.getUserBrowser(514 self.factory.makeProductBranch(product=product)
452 canonical_url(self.project, rootsite='code'))515 view = create_initialized_view(
453 table = find_tag_by_id(browser.contents, "branchtable")516 self.project, name='+branches', rootsite='code')
517 table = find_tag_by_id(view(), "branchtable")
454 self.assertIsNot(None, table)518 self.assertIsNot(None, table)
455519
456520
457521
=== modified file 'lib/lp/code/stories/branches/xx-branch-visibility-policy.txt'
--- lib/lp/code/stories/branches/xx-branch-visibility-policy.txt 2009-07-20 18:22:54 +0000
+++ lib/lp/code/stories/branches/xx-branch-visibility-policy.txt 2010-10-23 04:44:50 +0000
@@ -1,7 +1,8 @@
1= Branch Visibility Policy Pages =1Branch Visibility Policy Pages
2==============================
23
3Controlling the branch visibility policies for products and projects is only4Controlling the branch visibility policies for products and projects is only
4available to launchpad admins and launchpad commercial admins.5available to Launchpad admins and Launchpad commercial admins.
56
6Not to anonymous people.7Not to anonymous people.
78
@@ -64,12 +65,36 @@
64 >>> print commercial_browser.url65 >>> print commercial_browser.url
65 http://launchpad.dev/firefox/+branchvisibility66 http://launchpad.dev/firefox/+branchvisibility
6667
67 >>> commercial_browser.getLink('Customise policy for Mozilla Firefox').click()68 >>> commercial_browser.getLink(
69 ... 'Customise policy for Mozilla Firefox').click()
68 >>> print commercial_browser.url70 >>> print commercial_browser.url
69 http://launchpad.dev/firefox/+addbranchvisibilitypolicy71 http://launchpad.dev/firefox/+addbranchvisibilitypolicy
7072
7173Admins can define branch visibility on projects, too.
72== Default policies ==74
75 >>> admin_browser.open('http://code.launchpad.dev/mozilla')
76 >>> admin_browser.getLink('Define branch visibility').click()
77 >>> print admin_browser.url
78 http://launchpad.dev/mozilla/+branchvisibility
79
80 >>> admin_browser.getLink('Set policy for a team').click()
81 >>> print admin_browser.url
82 http://launchpad.dev/mozilla/+addbranchvisibilitypolicy
83
84As can commercial admins.
85
86 >>> commercial_browser.open('http://code.launchpad.dev/mozilla')
87 >>> commercial_browser.getLink('Define branch visibility').click()
88 >>> print commercial_browser.url
89 http://launchpad.dev/mozilla/+branchvisibility
90
91 >>> commercial_browser.getLink('Set policy for a team').click()
92 >>> print commercial_browser.url
93 http://launchpad.dev/mozilla/+addbranchvisibilitypolicy
94
95
96Default policies
97----------------
7398
74The default policies are to have all branches public. When the branch policy99The default policies are to have all branches public. When the branch policy
75objects are created for products they are constructed with the branch policy100objects are created for products they are constructed with the branch policy
@@ -79,10 +104,12 @@
79104
80 >>> admin_browser.open('http://launchpad.dev/firefox/+branchvisibility')105 >>> admin_browser.open('http://launchpad.dev/firefox/+branchvisibility')
81106
82 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'inherited'))107 >>> print extract_text(
108 ... find_tag_by_id(admin_browser.contents, 'inherited'))
83 Using inherited policy from the Mozilla Project.109 Using inherited policy from the Mozilla Project.
84110
85 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'default-policy'))111 >>> print extract_text(
112 ... find_tag_by_id(admin_browser.contents, 'default-policy'))
86 Default branch visibility for all branches in Mozilla Firefox is Public.113 Default branch visibility for all branches in Mozilla Firefox is Public.
87114
88When the project is using the inherited policy, the user can either115When the project is using the inherited policy, the user can either
@@ -100,8 +127,11 @@
100 >>> admin_browser.getLink('Edit inherited policy').click()127 >>> admin_browser.getLink('Edit inherited policy').click()
101 >>> print find_tag_by_id(admin_browser.contents, 'inherited')128 >>> print find_tag_by_id(admin_browser.contents, 'inherited')
102 None129 None
103 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'default-policy'))130 >>> print extract_text(
104 Default branch visibility for all branches in the Mozilla Project is Public.131 ... find_tag_by_id(admin_browser.contents, 'default-policy'))
132 Default branch visibility for all branches
133 in the Mozilla Project is Public.
134
105 >>> actions = find_tag_by_id(admin_browser.contents, 'policy-actions')135 >>> actions = find_tag_by_id(admin_browser.contents, 'policy-actions')
106 >>> for anchor in actions.fetch('a'):136 >>> for anchor in actions.fetch('a'):
107 ... print '%s -> %s' % (anchor.renderContents(), anchor['href'])137 ... print '%s -> %s' % (anchor.renderContents(), anchor['href'])
@@ -109,11 +139,13 @@
109139
110Products that don't have an associated project look similar to projects.140Products that don't have an associated project look similar to projects.
111141
112 >>> admin_browser.open('http://launchpad.dev/alsa-utils/+branchvisibility')142 >>> admin_browser.open(
143 ... 'http://launchpad.dev/alsa-utils/+branchvisibility')
113144
114 >>> print find_tag_by_id(admin_browser.contents, 'inherited')145 >>> print find_tag_by_id(admin_browser.contents, 'inherited')
115 None146 None
116 >>> print extract_text(find_tag_by_id(admin_browser.contents, 'default-policy'))147 >>> print extract_text(
148 ... find_tag_by_id(admin_browser.contents, 'default-policy'))
117 Default branch visibility for all branches in alsa-utils is Public.149 Default branch visibility for all branches in alsa-utils is Public.
118 >>> actions = find_tag_by_id(admin_browser.contents, 'policy-actions')150 >>> actions = find_tag_by_id(admin_browser.contents, 'policy-actions')
119 >>> for anchor in actions.fetch('a'):151 >>> for anchor in actions.fetch('a'):
@@ -121,7 +153,8 @@
121 Set policy for a team -> +addbranchvisibilitypolicy153 Set policy for a team -> +addbranchvisibilitypolicy
122154
123155
124== Overriding the inherited policy ==156Overriding the inherited policy
157-------------------------------
125158
126Setting any policy item overrides the use of an inherited policy, even if159Setting any policy item overrides the use of an inherited policy, even if
127it new policy item just specifies public branches for everyone.160it new policy item just specifies public branches for everyone.
@@ -173,7 +206,8 @@
173 Ubuntu Gnome Team: Private206 Ubuntu Gnome Team: Private
174207
175208
176== Removing policy items ==209Removing policy items
210---------------------
177211
178When removing the policy items, the defined items are shown as a list212When removing the policy items, the defined items are shown as a list
179of checkboxes. Any number of these can be selected, and when the213of checkboxes. Any number of these can be selected, and when the
@@ -206,7 +240,8 @@
206Before we remove them, let's ensure that the commercial admins can see240Before we remove them, let's ensure that the commercial admins can see
207the removal page.241the removal page.
208242
209 >>> commercial_browser.open('http://launchpad.dev/firefox/+branchvisibility')243 >>> commercial_browser.open(
244 ... 'http://launchpad.dev/firefox/+branchvisibility')
210 >>> commercial_browser.getLink('Remove policy items').click()245 >>> commercial_browser.getLink('Remove policy items').click()
211 >>> print commercial_browser.url246 >>> print commercial_browser.url
212 http://launchpad.dev/firefox/+removebranchvisibilitypolicy247 http://launchpad.dev/firefox/+removebranchvisibilitypolicy
@@ -228,7 +263,8 @@
228Firefox will go back to inheriting the polices of Mozilla. Let's let263Firefox will go back to inheriting the polices of Mozilla. Let's let
229the commercial admin do the removal to ensure he has the permission.264the commercial admin do the removal to ensure he has the permission.
230265
231 >>> commercial_browser.open('http://launchpad.dev/firefox/+branchvisibility')266 >>> commercial_browser.open(
267 ... 'http://launchpad.dev/firefox/+branchvisibility')
232 >>> commercial_browser.getLink('Remove policy items').click()268 >>> commercial_browser.getLink('Remove policy items').click()
233 >>> commercial_browser.getControl('Ubuntu Gnome Team: Private').click()269 >>> commercial_browser.getControl('Ubuntu Gnome Team: Private').click()
234 >>> commercial_browser.getControl('Remove Selected Policy Items').click()270 >>> commercial_browser.getControl('Remove Selected Policy Items').click()
235271
=== modified file 'lib/lp/code/templates/branch-visibility.pt'
--- lib/lp/code/templates/branch-visibility.pt 2009-08-24 02:09:05 +0000
+++ lib/lp/code/templates/branch-visibility.pt 2010-10-23 04:44:50 +0000
@@ -41,7 +41,7 @@
41 </div>41 </div>
4242
43 <div style="padding-left: 1em" id="policy-actions">43 <div style="padding-left: 1em" id="policy-actions">
44 <tal:using-inhertied-policy condition="context/isUsingInheritedBranchVisibilityPolicy">44 <tal:using-inherited-policy condition="context/isUsingInheritedBranchVisibilityPolicy">
45 <p>45 <p>
46 <img src="/@@/edit" alt="edit" />46 <img src="/@@/edit" alt="edit" />
47 <a tal:define="inherited_url context/project/fmt:url"47 <a tal:define="inherited_url context/project/fmt:url"
@@ -56,7 +56,7 @@
56 </tal:displayname>56 </tal:displayname>
57 </a>57 </a>
58 </p>58 </p>
59 </tal:using-inhertied-policy>59 </tal:using-inherited-policy>
6060
61 <tal:no-inhertied-policy condition="not: context/isUsingInheritedBranchVisibilityPolicy">61 <tal:no-inhertied-policy condition="not: context/isUsingInheritedBranchVisibilityPolicy">
62 <p>62 <p>
6363
=== modified file 'lib/lp/code/templates/project-branches.pt'
--- lib/lp/code/templates/project-branches.pt 2010-10-18 21:32:32 +0000
+++ lib/lp/code/templates/project-branches.pt 2010-10-23 04:44:50 +0000
@@ -3,20 +3,49 @@
3 xmlns:tal="http://xml.zope.org/namespaces/tal"3 xmlns:tal="http://xml.zope.org/namespaces/tal"
4 xmlns:metal="http://xml.zope.org/namespaces/metal"4 xmlns:metal="http://xml.zope.org/namespaces/metal"
5 xmlns:i18n="http://xml.zope.org/namespaces/i18n"5 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
6 metal:use-macro="view/macro:page/main_only"6 metal:use-macro="view/macro:page/main_side"
7 i18n:domain="launchpad">7 i18n:domain="launchpad">
88
9 <body>9 <body>
1010
11 <metal:side fill-slot="side"
12 tal:define="context_menu context/menu:context"
13 tal:condition="not:
14 context/codehosting_usage/enumvalue:UNKNOWN">
15 <div id="privacy"
16 tal:define="priv not:view/base_visibility_rule/enumvalue:PUBLIC"
17 tal:attributes="class python: priv and 'first portlet private' or 'first portlet public'">
18 <p id="default-policy" style="margin-bottom: 0;">
19 Inherited branch visibility for all projects in
20 <strong tal:content="context/displayname">Project</strong> is
21 <strong tal:content="view/base_visibility_rule/title">Public</strong>.
22 </p>
23
24 <tal:has-policies condition="view/team_policies">
25 <p>Except for the following teams:</p>
26 <ul id="team-policies">
27 <li tal:repeat="item view/team_policies">
28 <tal:team replace="structure item/team/fmt:link:mainsite"
29 condition="item/team">Team Name</tal:team>:
30 <tal:team condition="not: item/team">Everyone</tal:team>
31 <tal:policy replace="item/rule/title">Public</tal:policy>
32 </li>
33 </ul>
34 </tal:has-policies>
35 </div>
36
37 <div id="action-portlet"
38 class="portlet"
39 tal:define="menu context/menu:overview;
40 link menu/branch_visibility"
41 tal:condition="link/enabled">
42 <div tal:content="structure link/render" />
43 </div>
44 </metal:side>
45
11 <div metal:fill-slot="main"46 <div metal:fill-slot="main"
12 tal:define="branches view/branches">47 tal:define="branches view/branches">
1348
14 <div style="float:right" id="floating-links"
15 tal:define="menu context/menu:overview">
16 <div tal:define="link menu/branch_visibility"
17 tal:condition="link/enabled"
18 tal:content="structure link/render" />
19 </div>
20 <tal:no-branches49 <tal:no-branches
21 condition="not:context/has_branches">50 condition="not:context/has_branches">
22 <div id="no-branchtable">51 <div id="no-branchtable">
@@ -35,7 +64,7 @@
35 <li>64 <li>
36 <a tal:attributes="href product/@@+code-index/configure_codehosting/fmt:url"65 <a tal:attributes="href product/@@+code-index/configure_codehosting/fmt:url"
37 tal:content="product/title" />66 tal:content="product/title" />
38 </li> 67 </li>
39 </ul>68 </ul>
40 </div>69 </div>
41 </div>70 </div>
4271
=== modified file 'lib/lp/registry/browser/project.py'
--- lib/lp/registry/browser/project.py 2010-09-23 03:17:10 +0000
+++ lib/lp/registry/browser/project.py 2010-10-23 04:44:50 +0000
@@ -254,7 +254,7 @@
254 'RDF</abbr> metadata')254 'RDF</abbr> metadata')
255 return Link('+rdf', text, icon='download-icon')255 return Link('+rdf', text, icon='download-icon')
256256
257 @enabled_with_permission('launchpad.Admin')257 @enabled_with_permission('launchpad.Commercial')
258 def branch_visibility(self):258 def branch_visibility(self):
259 text = 'Define branch visibility'259 text = 'Define branch visibility'
260 return Link('+branchvisibility', text, icon='edit', site='mainsite')260 return Link('+branchvisibility', text, icon='edit', site='mainsite')
261261
=== modified file 'lib/lp/testing/sampledata.py'
--- lib/lp/testing/sampledata.py 2010-08-30 17:05:49 +0000
+++ lib/lp/testing/sampledata.py 2010-10-23 04:44:50 +0000
@@ -58,7 +58,6 @@
58USER_EMAIL = 'test@canonical.com'58USER_EMAIL = 'test@canonical.com'
59VCS_IMPORTS_MEMBER_EMAIL = 'david.allouche@canonical.com'59VCS_IMPORTS_MEMBER_EMAIL = 'david.allouche@canonical.com'
60COMMERCIAL_ADMIN_EMAIL = 'commercial-member@canonical.com'60COMMERCIAL_ADMIN_EMAIL = 'commercial-member@canonical.com'
61ADMIN_EMAIL = 'foo.bar@canonical.com'
62SAMPLE_PERSON_EMAIL = USER_EMAIL61SAMPLE_PERSON_EMAIL = USER_EMAIL
63# A user that is an admin of ubuntu-team, which has upload rights62# A user that is an admin of ubuntu-team, which has upload rights
64# to Ubuntu.63# to Ubuntu.