Merge lp:~edwin-grubbs/launchpad/bug-412519-team-page into lp:launchpad

Proposed by Edwin Grubbs
Status: Merged
Merged at revision: not available
Proposed branch: lp:~edwin-grubbs/launchpad/bug-412519-team-page
Merge into: lp:launchpad
Diff against target: None lines
To merge this branch: bzr merge lp:~edwin-grubbs/launchpad/bug-412519-team-page
Reviewer Review Type Date Requested Status
Martin Albisetti (community) ui Approve
Guilherme Salgado (community) code Approve
Review via email: mp+10536@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (3.5 KiB)

Summary
-------

Convert the $team/+index page to LP3.0.

I've uploaded before and after screenshots here:
  https://dev.launchpad.net/TeamIndexPage

This branch does not address the following feedback items, which will be
taken care of in a followup branch:
 * List all members.
 * Show members' timezones.
 * Recently approved query shouldn't show users approved a long time ago
 * even if they are the most recent.
 * "Contact this team" link should be moved into the action menu.
 * Add portlet with info from the karmacache.

Implementation details
----------------------

Moved the contact-details and subteam-of portlets into macros
and moved the mailinglist and membership portlets into separate
templates to make reorganizing the portlets easier. I started off
making new templates, but then switched to macros which were quicker
to edit.
    lib/lp/registry/templates/person-macros.pt
    lib/lp/registry/templates/team-portlet-mailinglist.pt
    lib/lp/registry/templates/team-portlet-membership.pt
    lib/lp/registry/templates/team-index.pt

The map wouldn't load because the base layout wouldn't include the js
even when needs_gmap2 was set to True.
    lib/lp/app/templates/base-layout.pt

The $team/+index page now uses a subclass of PersonIndexView instead
of PersonIndexView directly, since that makes it possible to customize
the menu items in it. Also separated two portlets into their own files.
    lib/lp/registry/browser/configure.zcml

Moved a bunch of menu items up to CommonMenuLinks or TeamMenuMixin.
Added the 'team' attribute to the TeamMenuMixin, since some of the
menus have the view as the context object. Added TeamIndexView and
the TeamIndexMenu.
    lib/lp/registry/browser/person.py

Fixed tests.
    lib/lp/registry/browser/tests/team-views.txt
    lib/lp/registry/stories/foaf/xx-reassign-team.txt
    lib/lp/registry/stories/foaf/xx-team-claim.txt
    lib/lp/registry/stories/foaf/xx-team-home.txt
    lib/lp/registry/stories/teammembership/private-team.txt
    lib/lp/registry/stories/teammembership/xx-private-membership.txt
    lib/lp/soyuz/stories/ppa/xx-ppa-private-teams.txt

Removed the header for the map. I can't remember who wanted that.
    lib/lp/registry/templates/team-portlet-map.pt

Added info icon to link.
    lib/lp/registry/templates/person-portlet-related-projects.pt

Added maintained-packages link and reformatted.
    lib/lp/soyuz/templates/person-portlet-ppas.pt

Fixed font size of ppa names.
    lib/lp/soyuz/templates/person-ppas.pt

Tests
-----

./bin/test -vv -t 'team-views.txt|xx-reassign-team.txt|xx-team-claim.txt|xx-team-home.txt|private-team.txt|xx-private-membership.txt|xx-ppa-private-teams.txt'

Demo and Q/A
------------

SQL to insert test data for the ~guadalinux user on launchpad.dev:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    /* For homepage content and description at the top of the page. */
    UPDATE Person
    SET homepage_content = 'Homepage content. Testing.',
        teamdescription = 'Team description. Testing.'
    WHERE id = 32;

    /* For related projects portlet. */
    UPDATE Product SET owner = 32;

Q/A
~~~
* Open http://launchpad.dev/~guadamen
    * Verify al...

Read more...

Revision history for this message
Guilherme Salgado (salgado) wrote :

Hi Edwin,

This looks really nice and it's great to see team-index.pt shrinking. r=me with those few changes we discussed on IRC

review: Approve (code)
Revision history for this message
Martin Albisetti (beuno) wrote :

Hi Edwin,

This looks great, and I'm looking forward to seeing this land.

I have a few comments which I'd like to see if we can address:

- I feel the "Team details" portlet should always be on the top right. The related projects portlet is pushing it down when it exists
- All the "show all *" links should be on the top-right of each portlet (I can spot "view all members" and view all X related packages)
- Maybe in the same spirit, you should move the "view map and time zones" to the top right as well
- If the team is not a sub-team, can we just not expose that information?
- How about not mentioning the projects' name again in the polls area and just say "No polls created"? And maybe not offer the show link if there aren't any?
- The "created on" date and by whom should be on the top-right, like in bugs and every other object (see with Curtis for this)
- If there aren't any packages, maybe we shouldn't offer the "Maintained packages" link?

review: Needs Fixing (ui)
Revision history for this message
Martin Albisetti (beuno) wrote :

One more comment, the "Join team" is probably the most important action, so maybe it could be on the top, with the same format as the downloads for projects?

Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

I want to clarify a couple of the suggested changes.

On Mon, Aug 24, 2009 at 2:33 PM, Martin Albisetti<email address hidden> wrote:
> Review: Needs Fixing ui
> Hi Edwin,
>
> This looks great, and I'm looking forward to seeing this land.
>
> I have a few comments which I'd like to see if we can address:
>
> - I feel the "Team details" portlet should always be on the top right. The related projects portlet is pushing it down when it exists

I think I will move the Related Projects portlet to the top on the
left side, since there was a bug to make sure this is very prominent.

> - All the "show all *" links should be on the top-right of each portlet (I can spot "view all members" and view all X related packages)

I'm confused, since we discussed Martin Pool's complaint about the
"Show all" links being black and not being in the body with the other
links. Should it be blue in the top right corner or still black?

> - Maybe in the same spirit, you should move the "view map and time zones" to the top right as well
> - If the team is not a sub-team, can we just not expose that information?
> - How about not mentioning the projects' name again in the polls area and just say "No polls created"?  And maybe not offer the show link if there aren't any?
> - The "created on" date and by whom should be on the top-right, like in bugs and every other object (see with Curtis for this)
> - If there aren't any packages, maybe we shouldn't offer the "Maintained packages" link?
> --
> https://code.edge.launchpad.net/~edwin-grubbs/launchpad/bug-412519-team-page/+merge/10536
> You are the owner of lp:~edwin-grubbs/launchpad/bug-412519-team-page.
>

Revision history for this message
Martin Albisetti (beuno) wrote :

On Mon, Aug 24, 2009 at 4:57 PM, Edwin Grubbs<email address hidden> wrote:
> I think I will move the Related Projects portlet to the top on the
> left side, since there was a bug to make sure this is very prominent.

I think the team's information is more important.

> I'm confused, since we discussed Martin Pool's complaint about the
> "Show all" links being black and not being in the body with the other
> links. Should it be blue in the top right corner or still black?

Blue and on the top right, without the arrow, I'd say.

--
Martin

Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

New screenshots are available at https://dev.launchpad.net/TeamIndexPage#preview
One important comment below.

> Hi Edwin,
>
> This looks great, and I'm looking forward to seeing this land.
>
> I have a few comments which I'd like to see if we can address:
>
> - I feel the "Team details" portlet should always be on the top right. The
> related projects portlet is pushing it down when it exists

Fixed.

> - All the "show all *" links should be on the top-right of each portlet (I can
> spot "view all members" and view all X related packages)

Fixed.

> - Maybe in the same spirit, you should move the "view map and time zones" to
> the top right as well

Fixed.

> - If the team is not a sub-team, can we just not expose that information?

Fixed.

> - How about not mentioning the projects' name again in the polls area and just
> say "No polls created"? And maybe not offer the show link if there aren't
> any?

Fixed.

> - The "created on" date and by whom should be on the top-right, like in bugs
> and every other object (see with Curtis for this)

Curtis will work on this bug regarding the base template.

> - If there aren't any packages, maybe we shouldn't offer the "Maintained
> packages" link?

Fixed.

Revision history for this message
Martin Albisetti (beuno) wrote :

Thank you for your changes, the page is looking much better. Great job.

Fixing the major problems it had has, however, brought some of the "polish" issues to my attention I would like to solve on this page, so, if you can still invest a bit of time on this page, please try and address them.

- I'd drop mentoring from that page. The feature is broken.
- How about s/Recently applied/Pending approval?
- If there's no email set, we should probably say "set contact email" instead of edit
- If there is an email set, just have an edit icon next to it, no text
- The "join team" should be placed before the actions portlet, just like downloads
- If there's no mailing list, it should say "create a mailing list", with an add icon
- I'd move the "show members photos" link into +members, uncluttering that section
- "You are not a member of this team" should probably be preceded by "(+) Join it". I'd also add some spacing between this text and the rest (0.5-1em, see what feels right)
- s/Mailing list archive/View archive
- s/Mailing list subscribers/View subscribers
- s/You are not subscribed to the team mailing list. (Subscribe)/(+) Subscribe to mailing list

review: Needs Fixing (ui)
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Hi Martin,

Screenshots for revision 3 are available at
https://dev.launchpad.net/TeamIndexPage

-Edwin

Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :

Also, be sure to look at the screenshot of the project page whose black portlet links changed to blue because that change was done in the stylesheet.

> Hi Martin,
>
> Screenshots for revision 3 are available at
> https://dev.launchpad.net/TeamIndexPage
>
> -Edwin

Revision history for this message
Martin Albisetti (beuno) wrote :

Perfect.
Thank you :)

review: Approve (ui)
Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (17.3 KiB)

Hi Salgado,

Can you do a followup review on the changes I made for Martin? BTW, it is understood that the changes to the see-all css also affect the project page and any other portlets.

-Edwin

{{{
=== modified file 'lib/canonical/launchpad/icing/style-3-0.css'
--- lib/canonical/launchpad/icing/style-3-0.css 2009-08-23 01:55:48 +0000
+++ lib/canonical/launchpad/icing/style-3-0.css 2009-08-28 02:04:01 +0000
@@ -369,9 +369,8 @@
     }
 .see-all a {
     padding-left: 8px;
- background: url(/@@/link-grey-arrow.png) left center no-repeat;
+ background: inherit;
     font-size: 72%;
- color: #484848;
     text-decoration: underline;
     }
 .rss-right {
@@ -576,6 +575,30 @@
     text-align: right;
     }

+ul.super-add-action {
+ margin: 0 auto 1em;
+}
+
+ul.super-add-action li {
+ padding: 0;
+}
+
+ul.super-add-action li a {
+ display: block;
+ border: 1px solid black;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ -khtml-border-radius: 3px;
+ background: #4f843c url(/@@/bg-action-add) center left no-repeat;
+ border-radius: 3px;
+ padding: 6%;
+ padding-left: 45px;
+ color: #fff;
+ font-size: 108%;
+ font-weight: bold;
+ text-decoration: underline;
+ }
+
 .involvement ul {
     border-top: 1px solid #d0d0d0;
     }

=== added file 'lib/canonical/launchpad/images/bg-action-add.png'
Binary files lib/canonical/launchpad/images/bg-action-add.png 1970-01-01 00:00:00 +0000 and lib/canonical/launchpad/images/bg-action-add.png 2009-08-26 19:07:10 +0000 differ
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2009-08-24 19:14:38 +0000
+++ lib/lp/registry/browser/person.py 2009-08-27 22:12:31 +0000
@@ -877,7 +877,8 @@
     def maintained(self):
         target = '+maintained-packages'
         text = 'Maintained Packages'
- return Link(target, text, icon='info')
+ enabled = bool(self.team.getLatestMaintainedPackages())
+ return Link(target, text, enabled=enabled, icon='info')

     def uploaded(self):
         target = '+uploaded-packages'
@@ -1078,7 +1079,7 @@
         return Link(target, text)

-class PersonRelatedSoftwareNavigationMenu(NavigationMenu):
+class PersonRelatedSoftwareNavigationMenu(NavigationMenu, CommonMenuLinks):

     usedfor = IPersonRelatedSoftwareMenu
     facet = 'overview'
@@ -1226,7 +1227,7 @@
     @enabled_with_permission('launchpad.Edit')
     def editemail(self):
         target = '+contactaddress'
- text = 'Change contact address'
+ text = 'Set contact address'
         summary = (
             'The address Launchpad uses to contact %s' %
             self.team.displayname)
@@ -1235,10 +1236,16 @@
     @enabled_with_permission('launchpad.MailingListManager')
     def configure_mailing_list(self):
         target = '+mailinglist'
- text = 'Configure mailing list'
+ mailing_list = self.team.mailing_list
+ if mailing_list is not None and mailing_list.is_usable:
+ text = 'Configure mailing list'
+ icon = 'edit'
+ else:
+ text = 'Create a mailing list'
+ icon = 'add'
         summary = (
             'The mail...

Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (11.2 KiB)

Hi Salgado,

Here are the tests that you asked me to add. I will add another comment with a diff of all the boring test fixes needed for the changing names of links.

-Edwin

{{{
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2009-08-31 12:01:46 +0000
+++ lib/lp/registry/browser/person.py 2009-09-01 00:11:08 +0000
@@ -3126,6 +3126,21 @@
     """

     @property
+ def can_show_subteam_portlet(self):
+ """Only show the subteam portlet if there is info to display.
+
+ Either the team is a member of another team, or there are
+ invitations to join a team, and the owner needs to see the
+ link so that the invitation can be accepted.
+ """
+ try:
+ return (self.context.super_teams.count() > 0
+ or (self.context.open_membership_invitations
+ and check_permission('launchpad.Edit', self.context)))
+ except AttributeError, e:
+ raise AssertionError(e)
+
+ @property
     def visibility(self):
         return self.context.visibility.title + ' Team'

=== modified file 'lib/lp/registry/stories/foaf/xx-team-home.txt'
--- lib/lp/registry/stories/foaf/xx-team-home.txt 2009-08-29 03:14:48 +0000
+++ lib/lp/registry/stories/foaf/xx-team-home.txt 2009-09-01 00:48:09 +0000
@@ -51,11 +51,41 @@
     English
     Set preferred languages

+The polls portlet only shows a link to view all polls if current
+polls exist.
+
+ >>> print extract_text(find_tag_by_id(browser.contents, 'polls'))
+ Polls
+ A random poll that never closes...
+ Show polls
+
+ >>> browser.open('http://launchpad.dev/~launchpad')
+ >>> print extract_text(find_tag_by_id(browser.contents, 'polls'))
+ Polls
+ No polls created.
+
+The subteam-of portlet is not shown if the team is not a subteam.
+
+ >>> browser.open('http://launchpad.dev/~ubuntu-team')
     >>> print extract_text(
     ... find_tag_by_id(browser.contents, 'subteam-of'))
     Subteam of
     &#8220;Ubuntu Team&#8221; is a member of these teams: GuadaMen...

+ >>> browser.open('http://launchpad.dev/~launchpad')
+ >>> print find_tag_by_id(browser.contents, 'subteam-of')
+ None
+
+Unless the user is the owner of the team and there are invitations to
+join a team.
+
+ >>> admin_browser.open('http://launchpad.dev/~launchpad')
+ >>> print extract_text(
+ ... find_tag_by_id(admin_browser.contents, 'subteam-of'))
+ Subteam of...
+ itself is not a member of any other team.
+ Show received invitations
+
 If the team does not have any recently approved or proposed members,
 the recent members sections are not displayed:

=== modified file 'lib/lp/registry/templates/person-macros.pt'
--- lib/lp/registry/templates/person-macros.pt 2009-08-28 00:57:32 +0000
+++ lib/lp/registry/templates/person-macros.pt 2009-09-01 00:06:13 +0000
@@ -79,8 +79,8 @@
 <metal:macro define-macro="subteam-of">
   <div class="portlet"
        id="subteam-of"
- tal:condition="
- python: context.super_teams or context.open_membership_invitations">
+ tal:condition="view/can_show_subteam_portlet"
+ >
     <h2>Subteam of</h2>

     <...

Revision history for this message
Edwin Grubbs (edwin-grubbs) wrote :
Download full text (20.6 KiB)

Incremental diff of boring test fixes.

{{{
=== modified file 'lib/lp/registry/browser/tests/person-views.txt'
--- lib/lp/registry/browser/tests/person-views.txt 2009-08-13 19:03:36 +0000
+++ lib/lp/registry/browser/tests/person-views.txt 2009-08-29 03:14:48 +0000
@@ -587,7 +587,7 @@
     >>> login('<email address hidden>')
     >>> view = create_initialized_view(landscape_developers, '+index')
     >>> print view.contact_link_title
- Send an email to your team through Launchpad
+ Send an email to your team's members through Launchpad

 The EmailToPersonView can be used by members to contact their team.

=== modified file 'lib/lp/registry/stories/foaf/xx-person-projects.txt'
--- lib/lp/registry/stories/foaf/xx-person-projects.txt 2009-08-13 15:12:16 +0000
+++ lib/lp/registry/stories/foaf/xx-person-projects.txt 2009-08-29 03:14:48 +0000
@@ -11,7 +11,6 @@
     Ubuntu Linux
     Ubuntu Test
     Tomcat
- &raquo; Show related projects

 The +related-software page displays a table with links to open bugs,
 unimplemented specs and open questions.

=== modified file 'lib/lp/registry/stories/foaf/xx-team-add-my-teams.txt'
--- lib/lp/registry/stories/foaf/xx-team-add-my-teams.txt 2009-06-16 20:17:00 +0000
+++ lib/lp/registry/stories/foaf/xx-team-add-my-teams.txt 2009-08-29 03:14:48 +0000
@@ -33,7 +33,7 @@
     [u'Launchpad Administrators has been proposed to this team.']
     >>> print extract_text(
     ... find_tag_by_id(browser.contents, 'recently-applied'))
- Recently applied
+ Pending approval
     Launchpad Administrators
     ...

=== modified file 'lib/lp/registry/stories/foaf/xx-team-contactemail.txt'
--- lib/lp/registry/stories/foaf/xx-team-contactemail.txt 2009-05-12 01:39:29 +0000
+++ lib/lp/registry/stories/foaf/xx-team-contactemail.txt 2009-08-29 03:14:48 +0000
@@ -17,7 +17,7 @@

     >>> browser = setupBrowser(auth='Basic <email address hidden>:test')
     >>> browser.open('http://launchpad.dev/~landscape-developers')
- >>> browser.getLink('Change contact address').click()
+ >>> browser.getLink(url='+contactaddress').click()
     >>> browser.title
     'Landscape Developers contact address'

@@ -73,7 +73,7 @@
     ... print msg
     Email address successfully confirmed.

- >>> browser.getLink('Change contact address').click()
+ >>> browser.getLink(url='+contactaddress').click()
     >>> browser.title
     'Landscape Developers contact address'
     >>> control = browser.getControl(name='field.contact_method')

=== modified file 'lib/lp/registry/stories/foaf/xx-team-edit.txt'
--- lib/lp/registry/stories/foaf/xx-team-edit.txt 2009-08-13 19:03:36 +0000
+++ lib/lp/registry/stories/foaf/xx-team-edit.txt 2009-08-29 03:14:48 +0000
@@ -88,7 +88,7 @@
 such team pages read-only.

     >>> browser.open('http://launchpad.dev/~landscape-developers')
- >>> browser.getLink('Configure mailing list').click()
+ >>> browser.getLink(url='+mailinglist').click()
     >>> browser.getControl('Apply for Mailing List').click()

     # Approval of mailing lists is not yet exposed through the web.

=== modified file 'lib/lp/registry/stories/foaf/xx-team-home.txt'
--- lib/lp/registry/stories/foaf/xx-team-home.txt 2009-08-...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/app/templates/base-layout.pt'
2--- lib/lp/app/templates/base-layout.pt 2009-08-20 07:58:58 +0000
3+++ lib/lp/app/templates/base-layout.pt 2009-08-21 13:48:43 +0000
4@@ -70,6 +70,8 @@
5
6 <metal:load-javascript
7 use-macro="context/@@+base-layout-macros/load-javascript" />
8+ <metal:page-javascript
9+ use-macro="context/@@+base-layout-macros/page-javascript" />
10 <metal:block define-slot="head_epilogue"></metal:block>
11 </head>
12
13
14=== modified file 'lib/lp/registry/browser/configure.zcml'
15--- lib/lp/registry/browser/configure.zcml 2009-08-20 14:01:26 +0000
16+++ lib/lp/registry/browser/configure.zcml 2009-08-21 13:48:43 +0000
17@@ -782,6 +782,7 @@
18 PersonSpecsMenu
19 TeamBugsMenu
20 TeamEditMenu
21+ TeamIndexMenu
22 TeamOverviewMenu
23 TeamOverviewNavigationMenu
24 TeamSpecsMenu
25@@ -1067,13 +1068,13 @@
26 <browser:page
27 for="lp.registry.interfaces.person.ITeam"
28 permission="zope.Public"
29- class="lp.registry.browser.person.PersonIndexView"
30+ class="lp.registry.browser.person.TeamIndexView"
31 name="+index"
32 template="../templates/team-index.pt"/>
33 <browser:page
34 for="lp.registry.interfaces.person.ITeam"
35 permission="zope.Public"
36- class="canonical.launchpad.browser.TeamMapView"
37+ class="lp.registry.browser.team.TeamMapView"
38 name="+map"
39 template="../templates/team-map.pt"/>
40 <browser:page
41@@ -1112,6 +1113,18 @@
42 template="../templates/team-portlet-map.pt"/>
43 <browser:page
44 for="lp.registry.interfaces.person.ITeam"
45+ class="lp.registry.browser.person.PersonIndexView"
46+ permission="zope.Public"
47+ name="+portlet-membership"
48+ template="../templates/team-portlet-membership.pt"/>
49+ <browser:page
50+ for="lp.registry.interfaces.person.ITeam"
51+ class="lp.registry.browser.person.PersonIndexView"
52+ permission="zope.Public"
53+ name="+portlet-mailinglist"
54+ template="../templates/team-portlet-mailinglist.pt"/>
55+ <browser:page
56+ for="lp.registry.interfaces.person.ITeam"
57 permission="launchpad.Edit"
58 class="canonical.launchpad.browser.TeamContactAddressView"
59 name="+contactaddress"
60
61=== modified file 'lib/lp/registry/browser/person.py'
62--- lib/lp/registry/browser/person.py 2009-08-20 16:13:15 +0000
63+++ lib/lp/registry/browser/person.py 2009-08-21 14:42:54 +0000
64@@ -42,6 +42,7 @@
65 'PersonLatestQuestionsView',
66 'PersonNavigation',
67 'PersonOAuthTokensView',
68+ 'PersonOverviewNavigationMenu',
69 'PersonOverviewMenu',
70 'PersonRdfContentsView',
71 'PersonRdfView',
72@@ -71,11 +72,13 @@
73 'TeamBreadcrumbBuilder',
74 'TeamEditLocationView',
75 'TeamEditMenu',
76+ 'TeamIndexMenu',
77 'TeamJoinView',
78 'TeamLeaveView',
79 'TeamMembershipView',
80 'TeamMugshotView',
81 'TeamNavigation',
82+ 'TeamOverviewNavigationMenu',
83 'TeamOverviewMenu',
84 'TeamReassignmentView',
85 'TeamSpecsMenu',
86@@ -866,6 +869,32 @@
87 'Package Archive and create a new PPA.')
88 return Link(target, text, summary, icon='add')
89
90+ def summary(self):
91+ target = '+related-software'
92+ text = 'Summary'
93+ return Link(target, text)
94+
95+ def maintained(self):
96+ target = '+maintained-packages'
97+ text = 'Maintained Packages'
98+ return Link(target, text, icon='info')
99+
100+ def uploaded(self):
101+ target = '+uploaded-packages'
102+ text = 'Uploaded Packages'
103+ return Link(target, text)
104+
105+ def ppa(self):
106+ target = '+ppa-packages'
107+ text = 'PPA Packages'
108+ return Link(target, text)
109+
110+ def projects(self):
111+ target = '+related-projects'
112+ text = 'Related Projects'
113+ return Link(target, text)
114+
115+
116
117 class PersonOverviewMenu(ApplicationMenu, CommonMenuLinks):
118
119@@ -876,7 +905,7 @@
120 'editircnicknames', 'editjabberids', 'editpassword',
121 'editsshkeys', 'editpgpkeys', 'editlocation', 'memberships',
122 'mentoringoffers', 'codesofconduct', 'karma',
123- 'administer', 'related_projects', 'activate_ppa',
124+ 'administer', 'related_projects', 'activate_ppa', 'maintained',
125 'view_ppa_subscriptions']
126
127 @enabled_with_permission('launchpad.Edit')
128@@ -1055,31 +1084,6 @@
129 facet = 'overview'
130 links = ('summary', 'maintained', 'uploaded', 'ppa', 'projects')
131
132- def summary(self):
133- target = '+related-software'
134- text = 'Summary'
135- return Link(target, text)
136-
137- def maintained(self):
138- target = '+maintained-packages'
139- text = 'Maintained Packages'
140- return Link(target, text)
141-
142- def uploaded(self):
143- target = '+uploaded-packages'
144- text = 'Uploaded Packages'
145- return Link(target, text)
146-
147- def ppa(self):
148- target = '+ppa-packages'
149- text = 'PPA Packages'
150- return Link(target, text)
151-
152- def projects(self):
153- target = '+related-projects'
154- text = 'Related Projects'
155- return Link(target, text)
156-
157
158 class PersonEditNavigationMenu(NavigationMenu):
159 """A sub-menu for different aspects of editing a Person's profile."""
160@@ -1117,6 +1121,17 @@
161
162
163 class TeamMenuMixin(PPANavigationMenuMixIn, CommonMenuLinks):
164+ """Base class of team menus.
165+
166+ You will need to override the team attribute if your menu subclass
167+ has the view as its context object.
168+ """
169+
170+ @property
171+ def team(self):
172+ """Allow subclasses that use the view as the context."""
173+ return self.context
174+
175 def profile(self):
176 target = ''
177 text = 'Overview'
178@@ -1175,8 +1190,7 @@
179 target = '+add-my-teams'
180 text = 'Add one of my teams'
181 enabled = True
182- team = self.context
183- if team.subscriptionpolicy == TeamSubscriptionPolicy.RESTRICTED:
184+ if self.team.subscriptionpolicy == TeamSubscriptionPolicy.RESTRICTED:
185 # This is a restricted team; users can't join.
186 enabled = False
187 return Link(target, text, icon='add', enabled=enabled)
188@@ -1218,11 +1232,6 @@
189 self.team.displayname)
190 return Link(target, text, summary, icon='edit')
191
192- @property
193- def team(self):
194- """Allow subclasses that use the view as the context."""
195- return self.context
196-
197 @enabled_with_permission('launchpad.MailingListManager')
198 def configure_mailing_list(self):
199 target = '+mailinglist'
200@@ -1247,17 +1256,17 @@
201 return Link(target, text, icon='edit')
202
203 def joinleave(self):
204- team = self.context
205 enabled = True
206- if userIsActiveTeamMember(team):
207- if team.teamowner == self.user:
208+ if userIsActiveTeamMember(self.team):
209+ if self.team.teamowner == self.user:
210 # The owner cannot leave his team
211 enabled = False
212 target = '+leave'
213 text = 'Leave the Team' # &#8230;
214 icon = 'remove'
215 else:
216- if team.subscriptionpolicy == TeamSubscriptionPolicy.RESTRICTED:
217+ if (self.team.subscriptionpolicy
218+ == TeamSubscriptionPolicy.RESTRICTED):
219 # This is a restricted team; users can't join.
220 enabled = False
221 target = '+join'
222@@ -1277,7 +1286,7 @@
223 'editlanguages', 'map', 'polls',
224 'add_poll', 'joinleave', 'add_my_teams', 'mentorships',
225 'reassign', 'related_projects',
226- 'activate_ppa']
227+ 'activate_ppa', 'maintained']
228
229
230 class TeamOverviewNavigationMenu(NavigationMenu, TeamMenuMixin):
231@@ -2578,18 +2587,17 @@
232 @property
233 def subscription_policy_description(self):
234 """Return the description of this team's subscription policy."""
235- team = self.context
236- assert team.isTeam(), (
237+ assert self.team.isTeam(), (
238 'This method can only be called when the context is a team.')
239- if team.subscriptionpolicy == TeamSubscriptionPolicy.RESTRICTED:
240+ if self.team.subscriptionpolicy == TeamSubscriptionPolicy.RESTRICTED:
241 description = _(
242 "This is a restricted team; new members can only be added "
243 "by one of the team's administrators.")
244- elif team.subscriptionpolicy == TeamSubscriptionPolicy.MODERATED:
245+ elif self.team.subscriptionpolicy == TeamSubscriptionPolicy.MODERATED:
246 description = _(
247 "This is a moderated team; all subscriptions are subjected "
248 "to approval by one of the team's administrators.")
249- elif team.subscriptionpolicy == TeamSubscriptionPolicy.OPEN:
250+ elif self.team.subscriptionpolicy == TeamSubscriptionPolicy.OPEN:
251 description = _(
252 "This is an open team; any user can join and no approval "
253 "is required.")
254@@ -2696,7 +2704,7 @@
255 def specific_contact_text(self):
256 """Return the appropriate link text."""
257 if self.context.is_team:
258- return 'Contact this team'
259+ return "Contact this team's administrators"
260 else:
261 # Note that we explicitly do not change the text to "Contact
262 # yourself" when viewing your own page.
263@@ -3066,6 +3074,27 @@
264 return check_permission('launchpad.View', self.context.location)
265
266
267+class TeamIndexView(PersonIndexView):
268+ """The view class for the +index page.
269+
270+ This class is needed, so an action menu that only applies to
271+ teams can be displayed without showing up on the person index page.
272+ """
273+
274+ @property
275+ def visibility(self):
276+ return self.context.visibility.title + ' Team'
277+
278+ @property
279+ def visibility_info(self):
280+ if self.context.visibility == PersonVisibility.PRIVATE:
281+ return 'Viewable by team members.'
282+ elif self.context.visibility == PersonVisibility.PRIVATE_MEMBERSHIP:
283+ return 'Team membership is viewable by team members.'
284+ else:
285+ return ''
286+
287+
288 class PersonCodeOfConductEditView(LaunchpadView):
289
290 def performCoCChanges(self):
291@@ -5447,11 +5476,32 @@
292 return 'Contact this user'
293
294
295+class ITeamIndexMenu(Interface):
296+ """A marker interface for the +index navigation menu."""
297+
298+
299 class ITeamEditMenu(Interface):
300 """A marker interface for the edit navigation menu."""
301
302
303-class TeamEditMenu(NavigationMenu, TeamMenuMixin):
304+class TeamNavigationMenuBase(NavigationMenu, TeamMenuMixin):
305+
306+ @property
307+ def team(self):
308+ """Override TeamOverviewMenu since the view is the context."""
309+ return self.context.context
310+
311+
312+class TeamIndexMenu(TeamNavigationMenuBase):
313+ """A menu for different aspects of editing a team."""
314+
315+ usedfor = ITeamIndexMenu
316+ facet = 'overview'
317+ title = 'Change team'
318+ links = ('edit', 'joinleave', 'add_member', 'add_my_teams')
319+
320+
321+class TeamEditMenu(TeamNavigationMenuBase):
322 """A menu for different aspects of editing a team."""
323
324 usedfor = ITeamEditMenu
325@@ -5460,10 +5510,6 @@
326 links = ('branding', 'common_edithomepage', 'editlanguages', 'reassign',
327 'editemail')
328
329- @property
330- def team(self):
331- """Override TeamOverviewMenu since the view is the context."""
332- return self.context.context
333-
334-
335+
336+classImplements(TeamIndexView, ITeamIndexMenu)
337 classImplements(TeamEditView, ITeamEditMenu)
338
339=== modified file 'lib/lp/registry/browser/tests/team-views.txt'
340--- lib/lp/registry/browser/tests/team-views.txt 2009-08-13 15:12:16 +0000
341+++ lib/lp/registry/browser/tests/team-views.txt 2009-08-21 13:48:43 +0000
342@@ -229,4 +229,4 @@
343 >>> print view.contact_link_title
344 Send an email to this team's owner through Launchpad
345 >>> print view.specific_contact_text
346- Contact this team
347+ Contact this team's administrators
348
349=== modified file 'lib/lp/registry/stories/foaf/xx-reassign-team.txt'
350--- lib/lp/registry/stories/foaf/xx-reassign-team.txt 2009-08-13 20:28:35 +0000
351+++ lib/lp/registry/stories/foaf/xx-reassign-team.txt 2009-08-21 13:48:43 +0000
352@@ -27,8 +27,9 @@
353 >>> browser.url
354 'http://launchpad.dev/~landscape-developers'
355 >>> print extract_text(
356- ... find_tag_by_id(browser.contents, 'team-details'))
357- Team owned by Celso Providelo, created on 2006-07-12
358+ ... find_tag_by_id(browser.contents, 'team-owner'))
359+ Owner:
360+ Celso Providelo
361
362 >>> browser.open('http://launchpad.dev/~landscape-developers/+members')
363 >>> print extract_text(find_tag_by_id(browser.contents, 'activemembers'))
364@@ -63,8 +64,9 @@
365 >>> browser.url
366 'http://launchpad.dev/~landscape-developers'
367 >>> print extract_text(
368- ... find_tag_by_id(browser.contents, 'team-details'))
369- Team owned by Ubuntu Team...
370+ ... find_tag_by_id(browser.contents, 'team-owner'))
371+ Owner:
372+ Ubuntu Team
373
374 >>> browser.open('http://launchpad.dev/~landscape-developers/+members')
375 >>> print extract_text(find_tag_by_id(browser.contents, 'activemembers'))
376
377=== modified file 'lib/lp/registry/stories/foaf/xx-team-claim.txt'
378--- lib/lp/registry/stories/foaf/xx-team-claim.txt 2009-07-23 13:44:13 +0000
379+++ lib/lp/registry/stories/foaf/xx-team-claim.txt 2009-08-21 13:48:43 +0000
380@@ -106,8 +106,9 @@
381 Team claimed successfully
382
383 >>> print extract_text(
384- ... find_tag_by_id(user_browser.contents, 'team-details'))
385- Team owned by No Privileges Person, ...
386+ ... find_tag_by_id(user_browser.contents, 'team-owner'))
387+ Owner:
388+ No Privileges Person
389
390
391 Trying to access +claimteam for an already active team 404s as you would
392
393=== modified file 'lib/lp/registry/stories/foaf/xx-team-home.txt'
394--- lib/lp/registry/stories/foaf/xx-team-home.txt 2009-08-13 19:03:36 +0000
395+++ lib/lp/registry/stories/foaf/xx-team-home.txt 2009-08-21 13:48:43 +0000
396@@ -6,10 +6,8 @@
397 >>> print browser.title
398 Ubuntu Team in Launchpad
399 >>> privacy_info = find_tag_by_id(browser.contents, 'privacy')
400- >>> print privacy_info['class']
401- aside public
402 >>> print extract_text(privacy_info)
403- This team is public
404+ Public Team
405
406 The page contains a few interesting details about team membership.
407
408@@ -28,18 +26,27 @@
409 Andrew Bennetts
410
411 >>> print extract_text(
412- ... find_tag_by_id(browser.contents, 'team-details'))
413- Team owned by Mark Shuttleworth, created on 2005-06-06
414+ ... find_tag_by_id(browser.contents, 'team-owner'))
415+ Owner:
416+ Mark Shuttleworth
417+
418+ >>> print extract_text(
419+ ... find_tag_by_id(browser.contents, 'team-datecreated'))
420+ Created on:
421+ 2005-06-06
422
423 >>> print extract_text(
424 ... find_tag_by_id(browser.contents, 'membership-summary'))
425- This team has: 10 active members, 1 invited members,
426- 2 proposed members and is a Moderated Team...
427+ This is a Moderated Team.
428+ 10 active members, 1 invited members, 2 proposed members...
429
430 >>> print extract_text(
431- ... find_tag_by_id(browser.contents, 'contact-details'))
432- Contact details
433+ ... find_tag_by_id(browser.contents, 'contact-email'))
434+ Email:
435 Log in for email information.
436+
437+ >>> print extract_text(
438+ ... find_tag_by_id(browser.contents, 'contact-languages'))
439 Languages:
440 English
441 Set preferred languages
442@@ -88,14 +95,11 @@
443
444 >>> browser.open('http://launchpad.dev/~ubuntu-team')
445 >>> print extract_text(
446- ... find_tag_by_id(browser.contents, 'contact-details'))
447- Contact details
448+ ... find_tag_by_id(browser.contents, 'contact-email'))
449+ Email:
450+ Contact this team's administrators
451 support@ubuntu.com
452- Contact this team
453 Change contact address
454- Languages:
455- English
456- Set preferred languages
457
458 Member can contact their team even if the team does not have a contact
459 address:
460@@ -103,16 +107,13 @@
461 >>> sample_browser = setupBrowser(auth='Basic test@canonical.com:test')
462 >>> sample_browser.open('http://launchpad.dev/~landscape-developers')
463 >>> print extract_text(
464- ... find_tag_by_id(sample_browser.contents, 'contact-details'))
465- Contact details
466+ ... find_tag_by_id(sample_browser.contents, 'contact-email'))
467+ Email:
468 No contact email
469- Contact this team
470- (Launchpad notifications are sent to all
471- team members)
472 Change contact address
473- Languages:
474- English
475- Set preferred languages
476+ Contact this team's administrators
477+ (Launchpad notifications are sent to all
478+ team members)
479
480 As teams do not have OpenID Logins, there is not link in the Contact
481 details section for help.
482@@ -143,7 +144,7 @@
483
484 Team owners and admins can see a link to approve and decline applicants.
485
486- >>> owner_browser = setupBrowser(auth="Basic mark@example.com:test")
487+ >>> owner_browser = setupBrowser(auth="Basic foo.bar@canonical.com:test")
488 >>> owner_browser.open('http://launchpad.dev/~ubuntu-team')
489 >>> print extract_text(
490 ... find_tag_by_id(owner_browser.contents, 'recently-applied'))
491@@ -165,17 +166,14 @@
492 ... find_tag_by_id(user_browser.contents, 'your-involvement'))
493 You are not a member of this team...
494
495-He can see the contact address, but the link's title explains the email
496-will actually go to the team's owner.
497+He can see the contact address, and the link explains the email
498+will actually go to the team's administrators.
499
500- >>> content = find_tag_by_id(user_browser.contents, 'contact-details')
501+ >>> content = find_tag_by_id(user_browser.contents, 'contact-email')
502 >>> print extract_text(content)
503- Contact details
504+ Email:
505+ Contact this team's administrators
506 support@ubuntu.com
507- Contact this team
508- Languages:
509- English
510- Set preferred languages
511
512 >>> content.a
513 <a href="+contactuser"
514
515=== modified file 'lib/lp/registry/stories/teammembership/private-team.txt'
516--- lib/lp/registry/stories/teammembership/private-team.txt 2009-05-09 20:04:39 +0000
517+++ lib/lp/registry/stories/teammembership/private-team.txt 2009-08-21 13:48:43 +0000
518@@ -34,10 +34,9 @@
519 The page states that the team is private.
520
521 >>> privacy_info = find_tag_by_id(cprov_browser.contents, 'privacy')
522- >>> print privacy_info['class']
523- aside private
524 >>> print extract_text(privacy_info)
525- This team is private
526+ Private Team
527+ Viewable by team members.
528
529 A normal user cannot see the team.
530
531
532=== modified file 'lib/lp/registry/stories/teammembership/xx-private-membership.txt'
533--- lib/lp/registry/stories/teammembership/xx-private-membership.txt 2009-08-20 12:24:29 +0000
534+++ lib/lp/registry/stories/teammembership/xx-private-membership.txt 2009-08-21 13:48:43 +0000
535@@ -34,10 +34,9 @@
536
537 >>> browser.open('http://launchpad.dev/~myteam')
538 >>> privacy_info = find_tag_by_id(browser.contents, 'privacy')
539- >>> print privacy_info['class']
540- aside private
541 >>> print extract_text(privacy_info)
542- This team is private
543+ Private Membership Team
544+ Team membership is viewable by team members.
545
546 A team member will be able to see these parts of the team page.
547
548@@ -50,7 +49,8 @@
549
550 >>> print extract_text(
551 ... find_tag_by_id(browser.contents, 'membership-summary'))
552- This team has: 2 active members, 1 proposed members ...
553+ This is a Moderated Team.
554+ 2 active members, 1 proposed members...
555
556
557 == Team Participation ==
558
559=== modified file 'lib/lp/registry/templates/person-macros.pt'
560--- lib/lp/registry/templates/person-macros.pt 2009-07-17 17:59:07 +0000
561+++ lib/lp/registry/templates/person-macros.pt 2009-08-21 15:54:04 +0000
562@@ -3,6 +3,113 @@
563 xmlns:metal="http://xml.zope.org/namespaces/metal"
564 omit-tag="">
565
566+<!-- contact-details macro. -->
567+<metal:macro define-macro="contact-details">
568+ <div class="portlet"
569+ id="contact-details">
570+ <h2 tal:condition="context/is_team">Team details</h2>
571+
572+ <dl id="contact-email">
573+ <dt>Email:</dt>
574+
575+ <dd>
576+ <tal:not_logged_in
577+ condition="view/email_address_visibility/is_login_required">
578+ <a href="+login">Log in</a> for email information.
579+ </tal:not_logged_in>
580+
581+ <tal:no_preferredemail
582+ condition="view/email_address_visibility/are_none_available">
583+ No contact email
584+ </tal:no_preferredemail>
585+
586+ <div tal:condition="view/can_contact">
587+ <img src="/@@/mail" alt="email"/>
588+ <a href="+contactuser"
589+ tal:attributes="title view/contact_link_title"
590+ tal:content="view/specific_contact_text"
591+ >Contact this person</a>
592+ <tal:no_preferredemail
593+ condition="view/email_address_visibility/are_none_available">
594+ <br /><small>(Launchpad notifications are sent to all
595+ team members)</small>
596+ </tal:no_preferredemail>
597+ </div>
598+
599+ <tal:emails repeat="email view/visible_email_addresses">
600+ <div style="white-space: nowrap">
601+ <img src="/@@/mail" alt="mail" />
602+ <tal:email replace="email">foo2@bar.com</tal:email>
603+ </div>
604+ </tal:emails>
605+ <a tal:replace="structure overview_menu/editemail/fmt:link" />
606+ </dd>
607+ </dl>
608+
609+ <div class="two-column-list">
610+ <dl id="team-owner">
611+ <dt>Owner:</dt>
612+ <dd>
613+ <tal:owner replace="structure context/teamowner/fmt:link"/>
614+ </dd>
615+ </dl>
616+
617+ <dl id="team-datecreated">
618+ <dt>Created on:</dt>
619+ <dd>
620+ <span id="created-date"
621+ tal:attributes="title context/datecreated/fmt:datetime"
622+ tal:content="context/datecreated/fmt:date" />
623+ </dd>
624+ </dl>
625+
626+ <dl id="contact-languages">
627+ <dt>Languages:</dt>
628+ <dd>
629+ <tal:languages content="view/languages">English</tal:languages>
630+ <a tal:attributes="href overview_menu/editlanguages/fmt:url"
631+ class="sprite edit">
632+ <span class="invisible-link">Set preferred languages</span></a>
633+ </dd>
634+ </dl>
635+
636+ </div>
637+ </div>
638+</metal:macro>
639+
640+<!-- subteam-of macro. -->
641+<metal:macro define-macro="subteam-of">
642+ <div class="portlet"
643+ id="subteam-of">
644+ <h2>Subteam of</h2>
645+
646+ <p tal:condition="not: context/super_teams">
647+ &#8220;<span tal:replace="context/displayname"/>&#8221;
648+ itself is not a member of any other team.
649+ </p>
650+
651+ <tal:is-a-subteam condition="context/super_teams">
652+ <p>
653+ &#8220;<span tal:replace="context/displayname"/>&#8221;
654+ is a member of these teams:
655+ </p>
656+ <ul class="iconed">
657+ <li tal:repeat="team context/super_teams">
658+ <tal:block replace="structure team/fmt:link" />
659+ </li>
660+ </ul>
661+ </tal:is-a-subteam>
662+
663+ <p>
664+ <tal:memberships
665+ replace="structure overview_menu/memberships/fmt:link" />
666+ &nbsp;
667+ <tal:received_invitations
668+ replace="structure overview_menu/received_invitations/fmt:link" />
669+ </p>
670+ </div>
671+</metal:macro>
672+
673 <metal:macro define-macro="sourcepackagerelease-rows">
674
675 <tal:comment replace="nothing">
676
677=== modified file 'lib/lp/registry/templates/person-portlet-related-projects.pt'
678--- lib/lp/registry/templates/person-portlet-related-projects.pt 2009-07-17 17:59:07 +0000
679+++ lib/lp/registry/templates/person-portlet-related-projects.pt 2009-08-21 14:51:31 +0000
680@@ -22,14 +22,14 @@
681 <tfoot>
682 <tr>
683 <td style="padding-top: .5em;">
684- <a href="+projects"
685- tal:condition="view/has_more_related_projects">
686- &raquo; Show all
687+ <a class="sprite info" href="+projects"
688+ tal:condition="view/has_more_related_projects">
689+ Show all
690 <tal:count content="view/related_projects_count">8</tal:count>
691 related projects</a>
692- <a href="+projects"
693- tal:condition="not: view/has_more_related_projects">
694- &raquo; Show related projects</a>
695+ <a class="sprite info" href="+projects"
696+ tal:condition="not: view/has_more_related_projects">
697+ Show related projects</a>
698 </td>
699 </tr>
700 </tfoot>
701
702=== modified file 'lib/lp/registry/templates/team-index.pt'
703--- lib/lp/registry/templates/team-index.pt 2009-08-07 23:55:37 +0000
704+++ lib/lp/registry/templates/team-index.pt 2009-08-21 14:12:07 +0000
705@@ -6,7 +6,7 @@
706 xml:lang="en"
707 lang="en"
708 dir="ltr"
709- metal:use-macro="view/macro:page/onecolumn"
710+ metal:use-macro="view/macro:page/main_side"
711 i18n:domain="launchpad"
712 >
713
714@@ -22,312 +22,113 @@
715
716 <body>
717
718-<div metal:fill-slot="before_nav_menu">
719- <div id="team-details" style="text-align:right">
720- Team owned
721- by <tal:reporter replace="structure context/teamowner/fmt:link" />,
722- created on <span id="created-date"
723- tal:attributes="title context/datecreated/fmt:datetime"
724- tal:content="context/datecreated/fmt:date" />
725- </div>
726-</div>
727-
728-<div metal:fill-slot="main" class="pillar"
729- tal:define="overview_menu context/menu:overview">
730-
731- <div style="float:right; margin:0">
732- <div id="privacy" tal:attributes="class view/public_private_css">
733- <div id="privacy-text">
734- This team is
735- <tal:public condition="not: context/private">public</tal:public>
736- <tal:private condition="context/private">private</tal:private>
737- </div>
738- </div>
739-
740- <div class="actions" style="text-align:right;"
741- tal:condition="overview_menu/edit/enabled"
742- tal:content="structure overview_menu/edit/fmt:link-icon">
743- </div>
744- </div>
745-
746- <tal:icon replace="structure context/image:mugshot" />
747-
748- <h1 tal:content="context/displayname" />
749-
750- <div
751- class="description"
752- tal:condition="context/homepage_content"
753- tal:content="structure context/homepage_content/fmt:text-to-html"
754- />
755-
756- <div
757- class="description"
758- tal:content="structure context/teamdescription/fmt:text-to-html"
759- />
760-
761- <div class="portletBody portletContent" style="margin-bottom: 1em;"
762- tal:define="can_view_membership context/@@+restricted-membership/userCanViewMembership">
763- <div tal:content="structure context/@@+portlet-map" />
764- </div>
765-
766- <div class="portlet" id="contact-details">
767- <h2 tal:condition="context/is_team">Contact details</h2>
768-
769- <div class="portletContent portletBody">
770- <tal:not_logged_in
771- condition="view/email_address_visibility/is_login_required">
772- <a href="+login">Log in</a> for email information.
773- </tal:not_logged_in>
774-
775- <tal:no_preferredemail
776- condition="view/email_address_visibility/are_none_available">
777- No contact email
778- <metal:define metal:define-macro="contact">
779- <tal:can-contact condition="view/can_contact">
780- &nbsp; <img src="/@@/mail" alt="email"/>
781- <a href="+contactuser"
782- tal:attributes="title view/contact_link_title"
783- tal:content="view/specific_contact_text">Contact this person</a>
784- <tal:no_preferredemail
785- condition="view/email_address_visibility/are_none_available">
786- <br /><small>(Launchpad notifications are sent to all
787- team members)</small>
788- </tal:no_preferredemail>
789- </tal:can-contact>
790- </metal:define>
791- </tal:no_preferredemail>
792- <tal:emails repeat="email view/visible_email_addresses">
793- <span style="white-space: nowrap">
794- <img src="/@@/mail" alt="mail" />
795- <tal:email replace="email">foo2@bar.com</tal:email>
796- <tal:contact condition="repeat/email/start">
797- <tal:contact metal:use-macro="template/macros/contact" />
798- </tal:contact>
799- <br tal:omit-tag="repeat/email/end" />
800- </span>
801- </tal:emails>
802- <a tal:replace="structure overview_menu/editemail/fmt:icon" />
803- <br /><strong>Languages:</strong>
804- <tal:languages content="view/languages">English</tal:languages>
805- <a tal:attributes="href overview_menu/editlanguages/fmt:url" class="sprite edit">
806- <span class="invisible-link">Set preferred languages</span></a>
807-
808- </div>
809- </div>
810-
811- <div tal:replace="structure context/@@+portlet-ppas"/>
812-
813- <div tal:content="structure context/@@+portlet-related-projects" />
814-
815- <div id="mailing-lists" class="portlet">
816- <h2>Mailing list</h2>
817-
818- <div class="portletBody portletContent">
819- <div
820- tal:define="archive_url view/archive_url"
821- tal:condition="archive_url">
822- <img src="/@@/mail" alt="mail" />
823- <a id="mailing-list-posting-address"
824- tal:attributes="href string:mailto:${context/mailing_list/address}"
825- tal:content="context/mailing_list/address">team@example.com</a>
826- <br />
827- <strong>Policy:</strong>
828- You must be a team member to subscribe to the team mailing list.
829- <br /><img src="/@@/mail" alt="email" /> <a id="mailing-list-archive"
830- tal:attributes="href archive_url">Mailing list archive</a>
831- <br /><img src="/@@/team" alt="team" /> <a id="mailing-list-subscribers"
832- tal:attributes="href context/fmt:url/+mailing-list-subscribers"
833- >Mailing list subscribers</a>
834- </div>
835- <div tal:condition="not: view/archive_url">
836- This team does not have a mailing list.
837- </div>
838- <div tal:condition="overview_menu/configure_mailing_list/enabled">
839- <tal:configure_mailing_list
840- replace="structure overview_menu/configure_mailing_list/fmt:link-icon" />
841- &nbsp;
842- <tal:moderate_mailing_list
843- replace="structure overview_menu/moderate_mailing_list/fmt:link-icon" />
844- </div>
845- <tal:block condition="view/userIsParticipant">
846- <div id="mailing-list-involvement"
847- tal:condition="view/team_has_mailing_list">
848- <tal:subscribed-to-list
849- condition="view/user_is_subscribed_to_list">
850- <form class="actions" id="form.list.unsubscribe" name="unsubscribe"
851- action="" method="post">
852- You are subscribed to the team mailing list.
853- <input type="submit" name="unsubscribe" value="Unsubscribe" />
854- </form>
855- </tal:subscribed-to-list>
856- <tal:can-subscribe-to-list
857- condition="view/user_can_subscribe_to_list">
858- You are not subscribed to the team mailing list.
859- (<a href="/people/+me/+editemails">Subscribe</a>)
860- </tal:can-subscribe-to-list>
861- </div>
862- </tal:block>
863- </div>
864- </div>
865-
866- <div id="membership" class="portlet">
867- <h2>Members</h2>
868-
869- <div id="membership-summary" class="portletBody portletContent"
870- style="margin-bottom: 1.5em;">
871- <div id="membership-summary">
872- This team has: <img src="/@@/team" alt="team" />
873- <strong><tal:active content="context/all_member_count" /></strong>
874- <a tal:attributes="href string:${context/fmt:url/+members}#active"
875- >active members</a><tal:invited
876- define="invited_member_count context/invited_member_count"
877- condition="invited_member_count">,
878- <strong><tal:invited_count content="context/invited_member_count" /></strong>
879- <a tal:attributes="href string:${context/fmt:url/+members}#invited"
880- >invited members</a></tal:invited><tal:proposed
881- define="proposed_member_count context/proposed_member_count"
882- condition="proposed_member_count">,
883- <strong><tal:proposed_count content="proposed_member_count" /></strong>
884- <a tal:attributes="href string:${context/fmt:url/+members}#proposed"
885- >proposed members</a>
886- </tal:proposed>
887- and is a
888- <span id="subscription-policy">
889- <strong><tal:policy replace="context/subscriptionpolicy/title" /></strong>
890- <img src="/@@/maybe"
891- tal:attributes="title context/subscriptionpolicy/description" />
892- </span>
893- <br />
894- <tal:members
895- replace="structure overview_menu/members/fmt:link" />
896- &nbsp;
897- <tal:mugshots
898- replace="structure overview_menu/mugshots/fmt:link" />
899- </div>
900-
901- <p id="your-involvement" tal:condition="not: request/lp:person">
902- You must <a href="+login">log in</a>
903- to join or leave this team.
904- </p>
905-
906- <p id="your-involvement" tal:condition="request/lp:person">
907- <tal:is-owner condition="view/userIsOwner">
908- <tal:team condition="context/teamowner/is_team">
909- You are a member of the team that owns this team.
910- </tal:team>
911- <tal:user condition="not: context/teamowner/is_team">
912- You are the owner of this team.
913- </tal:user>
914- <tal:absentee-owner condition="not: view/userIsActiveMember">
915- You are not currently an active member.
916- </tal:absentee-owner>
917- </tal:is-owner>
918-
919- <tal:not-owner condition="not: view/userIsOwner">
920- <tal:active-member tal:condition="view/userIsActiveMember">
921- <tal:can-leave condition="view/userCanRequestToLeave">
922- You are a member of this team.
923- </tal:can-leave>
924- </tal:active-member>
925- <tal:not-active-member tal:condition="not: view/userIsActiveMember">
926- <tal:not-member condition="not: view/userIsParticipant">
927- You are not a member of this team.
928- </tal:not-member>
929- <tal:participant condition="view/userIsParticipant">
930- You are an indirect member of this team:
931- <br />
932- <a tal:replace="structure view/user/fmt:link"
933- >Guilherme Salgado</a>
934- <tal:path repeat="team view/findUserPathToTeam">
935- &rarr;
936- <a tal:replace="structure team/fmt:link"
937- >Launchpad Developers</a>
938- </tal:path>
939- </tal:participant>
940- </tal:not-active-member>
941- </tal:not-owner>
942- <tal:join-leave
943- replace="structure overview_menu/joinleave/fmt:link" />
944- <a tal:replace="structure overview_menu/reassign/fmt:icon">
945- Change owner</a>
946- <br />
947- &nbsp;
948- <tal:add_member
949- condition="overview_menu/add_member/enabled">
950- <a tal:replace="structure overview_menu/add_member/fmt:link" />
951- &nbsp;
952- </tal:add_member>
953- <tal:add_my_teams
954- condition="overview_menu/add_my_teams/enabled">
955- <a tal:replace="structure overview_menu/add_my_teams/fmt:link" />
956- &nbsp;
957- </tal:add_my_teams>
958- </p>
959- </div>
960-
961- <tal:can-view condition="context/@@+restricted-membership/userCanViewMembership">
962- <table style="margin: 0px 0px .5em 0px;"
963- tal:condition="view/has_recent_approved_or_proposed_members">
964- <tr>
965- <td style="padding: 0px 3em 0px 0px" id="recently-approved"
966- tal:condition="view/recently_approved_members">
967- <h3 style="color:black; font-weight:bold; margin: 0px">Recently approved</h3>
968- <ul tal:condition="view/recently_approved_members">
969- <li tal:repeat="person view/recently_approved_members"
970- tal:content="structure person/fmt:link" />
971- </ul>
972- <div style="margin-top: 3px;">
973- <tal:mentorships
974- replace="structure overview_menu/mentorships/fmt:link" />
975- </div>
976- </td>
977- <td style="padding: 0px;" id="recently-applied"
978- tal:condition="view/recently_proposed_members">
979- <h3 style="color:black; font-weight:bold; margin: 0px">Recently applied</h3>
980- <ul>
981- <li tal:repeat="person view/recently_proposed_members"
982- tal:content="structure person/fmt:link" />
983- </ul>
984- <div style="margin-top: 3px;"
985- tal:condition="overview_menu/proposed_members/enabled"
986- tal:content="structure overview_menu/proposed_members/fmt:icon-link">
987- </div>
988- </td>
989- </tr>
990- </table>
991- </tal:can-view>
992- <div>
993-
994- </div>
995- </div>
996- <div class="portlet" id="subteam-of">
997- <h2>Subteam of</h2>
998-
999- <p tal:condition="not: context/super_teams">
1000- &#8220;<span tal:replace="context/displayname"/>&#8221;
1001- itself is not a member of any other team.
1002- </p>
1003-
1004- <tal:is-a-subteam condition="context/super_teams">
1005- <p>
1006- &#8220;<span tal:replace="context/displayname"/>&#8221;
1007- is a member of these teams:
1008- </p>
1009- <ul class="iconed">
1010- <li tal:repeat="team context/super_teams">
1011- <tal:block replace="structure team/fmt:link" />
1012- </li>
1013- </ul>
1014- </tal:is-a-subteam>
1015-
1016- <p>
1017- <tal:memberships
1018- replace="structure overview_menu/memberships/fmt:link" />
1019- &nbsp;
1020- <tal:received_invitations
1021- replace="structure overview_menu/received_invitations/fmt:link" />
1022- </p>
1023- </div>
1024- </div>
1025+<!-- side slot -->
1026+<div metal:fill-slot="side"
1027+ tal:define="overview_menu context/menu:overview">
1028+
1029+ <div id="privacy" class="portlet">
1030+ <h2 tal:content="view/visibility">Public Team</h2>
1031+ <span tal:content="view/visibility_info">Viewable by team members.</span>
1032+ </div>
1033+
1034+ <tal:menu replace="structure view/@@+global-actions" />
1035+
1036+ <div id="polls" class="portlet">
1037+ <h2>Current polls for
1038+ &#8220;<span tal:replace="context/displayname" />&#8221;
1039+ </h2>
1040+
1041+ <p tal:condition="not: view/hasCurrentPolls">
1042+ This team has no open polls nor polls that are not yet opened.
1043+ </p>
1044+
1045+ <ul tal:condition="view/hasCurrentPolls">
1046+ <li tal:repeat="poll view/openpolls">
1047+ <a tal:attributes="href poll/fmt:url">
1048+ <span tal:replace="poll/title" />
1049+ </a> - closes
1050+ <span
1051+ tal:attributes="title poll/datecloses/fmt:datetime"
1052+ tal:content="poll/datecloses/fmt:displaydate" />.
1053+
1054+ <tal:block define="user request/lp:person" condition="user">
1055+ <tal:block condition="python: poll.personVoted(user)">
1056+ You have
1057+ <span tal:replace="poll/closesIn/fmt:approximateduration" />
1058+ to change your vote if you wish.
1059+ </tal:block>
1060+
1061+ <tal:block condition="python: not poll.personVoted(user)">
1062+ You have
1063+ <span tal:replace="poll/closesIn/fmt:approximateduration" />
1064+ left to vote in this poll.
1065+ </tal:block>
1066+ </tal:block>
1067+
1068+ </li>
1069+
1070+ <li tal:condition="view/userIsOwner"
1071+ tal:repeat="poll view/notyetopenedpolls">
1072+ <a tal:attributes="href poll/fmt:url">
1073+ <span tal:replace="poll/title" />
1074+ </a> - opens
1075+ <span
1076+ tal:attributes="title poll/dateopens/fmt:datetime"
1077+ tal:content="poll/dateopens/fmt:displaydate" />
1078+ </li>
1079+ </ul>
1080+
1081+ <a tal:replace="structure overview_menu/polls/fmt:link" />
1082+ <a tal:replace="structure overview_menu/add_poll/fmt:link" />
1083+
1084+ </div>
1085+</div>
1086+
1087+<!-- heading slot. -->
1088+<div metal:fill-slot="heading">
1089+ <div tal:attributes="class view/public_private_css">
1090+ <tal:comment condition="nothing">
1091+ Display striped image.
1092+ </tal:comment>
1093+ </div>
1094+
1095+ <h1 style="margin: 0"
1096+ tal:content="context/displayname"/>
1097+
1098+ <div
1099+ class="description"
1100+ tal:condition="context/homepage_content"
1101+ tal:content="structure context/homepage_content/fmt:text-to-html"
1102+ />
1103+
1104+ <div
1105+ class="description"
1106+ tal:content="structure context/teamdescription/fmt:text-to-html"
1107+ />
1108+</div>
1109+
1110+<!-- main slot. -->
1111+<div metal:fill-slot="main"
1112+ tal:define="overview_menu context/menu:overview">
1113+
1114+ <div class="yui-g">
1115+ <!-- First portlet column. -->
1116+ <div class="first yui-u">
1117+ <div tal:content="structure context/@@+portlet-membership" />
1118+ <div tal:content="structure context/@@+portlet-ppas" />
1119+ <metal:subteam-of use-macro="context/@@+person-macros/subteam-of" />
1120+ </div>
1121+
1122+ <!-- Second portlet column. -->
1123+ <div class="yui-u">
1124+ <div tal:content="structure context/@@+portlet-related-projects" />
1125+ <metal:details use-macro="context/@@+person-macros/contact-details" />
1126+ <div tal:content="structure context/@@+portlet-mailinglist" />
1127+ </div>
1128+ </div>
1129+
1130+ <div tal:content="structure context/@@+portlet-map" />
1131+
1132+</div>
1133 </body>
1134 </html>
1135
1136=== added file 'lib/lp/registry/templates/team-portlet-mailinglist.pt'
1137--- lib/lp/registry/templates/team-portlet-mailinglist.pt 1970-01-01 00:00:00 +0000
1138+++ lib/lp/registry/templates/team-portlet-mailinglist.pt 2009-08-21 13:48:43 +0000
1139@@ -0,0 +1,57 @@
1140+<tal:root
1141+ xmlns:tal="http://xml.zope.org/namespaces/tal"
1142+ xmlns:metal="http://xml.zope.org/namespaces/metal"
1143+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
1144+ omit-tag="">
1145+
1146+<div id="mailing-lists" class="portlet">
1147+ <h2>Mailing list</h2>
1148+
1149+ <div class="portletBody portletContent">
1150+ <div
1151+ tal:define="archive_url view/archive_url"
1152+ tal:condition="archive_url">
1153+ <img src="/@@/mail" alt="mail" />
1154+ <a id="mailing-list-posting-address"
1155+ tal:attributes="href string:mailto:${context/mailing_list/address}"
1156+ tal:content="context/mailing_list/address">team@example.com</a>
1157+ <br />
1158+ <strong>Policy:</strong>
1159+ You must be a team member to subscribe to the team mailing list.
1160+ <br /><img src="/@@/mail" alt="email" /> <a id="mailing-list-archive"
1161+ tal:attributes="href archive_url">Mailing list archive</a>
1162+ <br /><img src="/@@/team" alt="team" /> <a id="mailing-list-subscribers"
1163+ tal:attributes="href context/fmt:url/+mailing-list-subscribers"
1164+ >Mailing list subscribers</a>
1165+ </div>
1166+ <div tal:condition="not: view/archive_url">
1167+ This team does not have a mailing list.
1168+ </div>
1169+ <div tal:condition="context/menu:overview/configure_mailing_list/enabled">
1170+ <tal:configure_mailing_list
1171+ replace="structure context/menu:overview/configure_mailing_list/fmt:link-icon" />
1172+ &nbsp;
1173+ <tal:moderate_mailing_list
1174+ replace="structure context/menu:overview/moderate_mailing_list/fmt:link-icon" />
1175+ </div>
1176+ <tal:block condition="view/userIsParticipant">
1177+ <div id="mailing-list-involvement"
1178+ tal:condition="view/team_has_mailing_list">
1179+ <tal:subscribed-to-list
1180+ condition="view/user_is_subscribed_to_list">
1181+ <form class="actions" id="form.list.unsubscribe" name="unsubscribe"
1182+ action="" method="post">
1183+ You are subscribed to the team mailing list.
1184+ <input type="submit" name="unsubscribe" value="Unsubscribe" />
1185+ </form>
1186+ </tal:subscribed-to-list>
1187+ <tal:can-subscribe-to-list
1188+ condition="view/user_can_subscribe_to_list">
1189+ You are not subscribed to the team mailing list.
1190+ (<a href="/people/+me/+editemails">Subscribe</a>)
1191+ </tal:can-subscribe-to-list>
1192+ </div>
1193+ </tal:block>
1194+ </div>
1195+</div>
1196+</tal:root>
1197
1198=== modified file 'lib/lp/registry/templates/team-portlet-map.pt'
1199--- lib/lp/registry/templates/team-portlet-map.pt 2009-07-17 17:59:07 +0000
1200+++ lib/lp/registry/templates/team-portlet-map.pt 2009-08-21 13:48:43 +0000
1201@@ -5,16 +5,10 @@
1202 omit-tag="">
1203
1204 <div class="portlet" id="portlet-map" style="margin-bottom: 0px;">
1205+ <h2>Location</h2>
1206
1207 <tal:can_view condition="context/required:launchpad.View"
1208 define="link context/menu:overview/map">
1209- <div
1210- tal:define="unmapped_count view/unmapped_participants_count"
1211- tal:condition="unmapped_count">
1212- <strong><tal:count replace="unmapped_count" /> member(s)</strong>
1213- have not set their location. <a tal:attributes="href link/target">Do
1214- it for them!</a>
1215- </div>
1216 <div style="width: 400px;" tal:condition="view/has_mapped_participants">
1217 <div id="team_map_actions"
1218 style="position:relative; z-index: 9999;
1219
1220=== added file 'lib/lp/registry/templates/team-portlet-membership.pt'
1221--- lib/lp/registry/templates/team-portlet-membership.pt 1970-01-01 00:00:00 +0000
1222+++ lib/lp/registry/templates/team-portlet-membership.pt 2009-08-21 13:48:43 +0000
1223@@ -0,0 +1,127 @@
1224+<tal:root
1225+ xmlns:tal="http://xml.zope.org/namespaces/tal"
1226+ xmlns:metal="http://xml.zope.org/namespaces/metal"
1227+ xmlns:i18n="http://xml.zope.org/namespaces/i18n"
1228+ omit-tag="">
1229+
1230+<div id="membership" class="portlet">
1231+ <h2>Members</h2>
1232+
1233+ <div id="membership-summary" class="portletBody portletContent"
1234+ style="margin-bottom: 1.5em;">
1235+ <div id="membership-summary">
1236+ This is a
1237+ <span>
1238+ <strong id="subscription-policy"
1239+ tal:content="context/subscriptionpolicy/title" />.
1240+ <img src="/@@/maybe"
1241+ tal:attributes="title context/subscriptionpolicy/description" />
1242+ </span>
1243+ <div>
1244+ <img src="/@@/team" alt="team" />
1245+ <strong><tal:active content="context/all_member_count" /></strong>
1246+ <a tal:attributes="href string:${context/fmt:url/+members}#active"
1247+ >active members</a><tal:invited
1248+ define="invited_member_count context/invited_member_count"
1249+ condition="invited_member_count">,
1250+ <strong>
1251+ <tal:invited_count content="context/invited_member_count" />
1252+ </strong>
1253+ <a tal:attributes="href string:${context/fmt:url/+members}#invited"
1254+ >invited members</a></tal:invited><tal:proposed
1255+ define="proposed_member_count context/proposed_member_count"
1256+ condition="proposed_member_count">,
1257+ <strong>
1258+ <tal:proposed_count content="proposed_member_count" />
1259+ </strong>
1260+ <a tal:attributes="href string:${context/fmt:url/+members}#proposed"
1261+ >proposed members</a>
1262+ </tal:proposed>
1263+ </div>
1264+ <tal:members
1265+ replace="structure context/menu:overview/members/fmt:link" />
1266+ &nbsp;
1267+ <tal:mugshots replace="structure context/menu:overview/mugshots/fmt:link" />
1268+ </div>
1269+
1270+ <p id="your-involvement" tal:condition="not: request/lp:person">
1271+ You must <a href="+login">log in</a>
1272+ to join or leave this team.
1273+ </p>
1274+
1275+ <div id="your-involvement" tal:condition="request/lp:person">
1276+ <tal:is-owner condition="view/userIsOwner">
1277+ <tal:team condition="context/teamowner/is_team">
1278+ You are a member of the team that owns this team.
1279+ </tal:team>
1280+ <tal:user condition="not: context/teamowner/is_team">
1281+ You are the owner of this team.
1282+ </tal:user>
1283+ <tal:absentee-owner condition="not: view/userIsActiveMember">
1284+ You are not currently an active member.
1285+ </tal:absentee-owner>
1286+ </tal:is-owner>
1287+
1288+ <tal:not-owner condition="not: view/userIsOwner">
1289+ <tal:active-member tal:condition="view/userIsActiveMember">
1290+ <tal:can-leave condition="view/userCanRequestToLeave">
1291+ You are a member of this team.
1292+ </tal:can-leave>
1293+ </tal:active-member>
1294+ <tal:not-active-member tal:condition="not: view/userIsActiveMember">
1295+ <tal:not-member condition="not: view/userIsParticipant">
1296+ You are not a member of this team.
1297+ </tal:not-member>
1298+ <tal:participant condition="view/userIsParticipant">
1299+ You are an indirect member of this team:
1300+ <br />
1301+ <a tal:replace="structure view/user/fmt:link"
1302+ >Guilherme Salgado</a>
1303+ <tal:path repeat="team view/findUserPathToTeam">
1304+ &rarr;
1305+ <a tal:replace="structure team/fmt:link"
1306+ >Launchpad Developers</a>
1307+ </tal:path>
1308+ </tal:participant>
1309+ </tal:not-active-member>
1310+ </tal:not-owner>
1311+ </div>
1312+ </div>
1313+ <tal:can-view
1314+ condition="context/@@+restricted-membership/userCanViewMembership"
1315+ define="overview_menu context/menu:overview">
1316+ <table style="margin: 0px 0px .5em 0px;"
1317+ tal:condition="view/has_recent_approved_or_proposed_members">
1318+ <tr>
1319+ <td style="padding: 0px 3em 0px 0px" id="recently-approved"
1320+ tal:condition="view/recently_approved_members">
1321+ <h3 style="color:black; font-weight:bold; margin: 0px">
1322+ Recently approved
1323+ </h3>
1324+ <ul tal:condition="view/recently_approved_members">
1325+ <li tal:repeat="person view/recently_approved_members"
1326+ tal:content="structure person/fmt:link" />
1327+ </ul>
1328+ <div style="margin-top: 3px;">
1329+ <tal:mentorships
1330+ replace="structure overview_menu/mentorships/fmt:link" />
1331+ </div>
1332+ </td>
1333+ <td style="padding: 0px;" id="recently-applied"
1334+ tal:condition="view/recently_proposed_members">
1335+ <h3 style="color:black; font-weight:bold; margin: 0px">
1336+ Recently applied
1337+ </h3>
1338+ <ul>
1339+ <li tal:repeat="person view/recently_proposed_members"
1340+ tal:content="structure person/fmt:link" />
1341+ </ul>
1342+ <div style="margin-top: 3px;"
1343+ tal:condition="overview_menu/proposed_members/enabled"
1344+ tal:content="structure overview_menu/proposed_members/fmt:icon-link">
1345+ </div>
1346+ </td>
1347+ </tr>
1348+ </table>
1349+ </tal:can-view>
1350+</tal:root>
1351
1352=== modified file 'lib/lp/soyuz/stories/ppa/xx-ppa-private-teams.txt'
1353--- lib/lp/soyuz/stories/ppa/xx-ppa-private-teams.txt 2009-05-15 19:33:57 +0000
1354+++ lib/lp/soyuz/stories/ppa/xx-ppa-private-teams.txt 2009-08-21 13:48:43 +0000
1355@@ -29,6 +29,7 @@
1356 >>> print_tag_with_id(browser.contents, 'ppas')
1357 Personal package archives
1358 Create a new PPA
1359+ Maintained Packages
1360
1361 The form looks almost identical to that for a public team.
1362
1363
1364=== modified file 'lib/lp/soyuz/templates/person-portlet-ppas.pt'
1365--- lib/lp/soyuz/templates/person-portlet-ppas.pt 2009-07-17 17:59:07 +0000
1366+++ lib/lp/soyuz/templates/person-portlet-ppas.pt 2009-08-21 15:16:48 +0000
1367@@ -10,20 +10,22 @@
1368
1369 <div tal:replace="structure context/@@+ppas-list"/>
1370
1371- <div class="actions">
1372- <p><tal:activate_ppa
1373- define="link context/menu:overview/activate_ppa"
1374- condition="link/enabled"
1375- replace="structure link/fmt:icon-link" />
1376- </p>
1377- <p><tal:is-person condition="not: context/is_team">
1378- <tal:view_p3a_subscriptions
1379- define="link context/menu:overview/view_ppa_subscriptions"
1380- condition="link/enabled"
1381- replace="structure link/fmt:icon-link" />
1382- </tal:is-person>
1383- </p>
1384- </div>
1385+ <ul class="horizontal">
1386+ <li tal:define="link context/menu:overview/activate_ppa"
1387+ tal:condition="link/enabled"
1388+ tal:content="structure link/fmt:icon-link" />
1389+
1390+ <li tal:define="link context/menu:overview/maintained"
1391+ tal:condition="link/enabled"
1392+ tal:replace="structure link/fmt:icon-link" />
1393+
1394+ <tal:is-person condition="not: context/is_team">
1395+ <li tal:define="link context/menu:overview/view_ppa_subscriptions"
1396+ tal:condition="link/enabled"
1397+ tal:replace="structure link/fmt:icon-link" />
1398+ </tal:is-person>
1399+
1400+ </ul>
1401 </div>
1402 </div>
1403 </div>
1404
1405=== modified file 'lib/lp/soyuz/templates/person-ppas.pt'
1406--- lib/lp/soyuz/templates/person-ppas.pt 2009-07-30 02:26:46 +0000
1407+++ lib/lp/soyuz/templates/person-ppas.pt 2009-08-21 13:48:43 +0000
1408@@ -4,7 +4,7 @@
1409 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
1410 omit-tag="">
1411 <div tal:define="ppas context/ppas" tal:condition="ppas">
1412- <table class="summary">
1413+ <table>
1414 <tal:ppa_line tal:repeat="ppa ppas">
1415 <tr>
1416 <td tal:define="ppa_link ppa/fmt:link"