Merge lp:~sinzui/launchpad/disable-gmaps-0 into lp:launchpad

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 11470
Proposed branch: lp:~sinzui/launchpad/disable-gmaps-0
Merge into: lp:launchpad
Diff against target: 560 lines (+149/-111)
11 files modified
lib/lp/registry/browser/__init__.py (+18/-0)
lib/lp/registry/browser/person.py (+4/-2)
lib/lp/registry/browser/team.py (+3/-2)
lib/lp/registry/browser/tests/mailinglist-views.txt (+0/-54)
lib/lp/registry/browser/tests/person-views.txt (+5/-0)
lib/lp/registry/browser/tests/team-views.txt (+5/-0)
lib/lp/registry/stories/location/personlocation.txt (+28/-7)
lib/lp/registry/stories/location/team-map.txt (+34/-5)
lib/lp/registry/stories/person/xx-person-home.txt (+46/-40)
lib/lp/registry/templates/person-portlet-map.pt (+4/-0)
lib/lp/registry/templates/team-portlet-map.pt (+2/-1)
To merge this branch: bzr merge lp:~sinzui/launchpad/disable-gmaps-0
Reviewer Review Type Date Requested Status
Robert Collins (community) Approve
Review via email: mp+33971@code.launchpad.net

Description of the change

This is my branch to disable Google maps.

    lp:~sinzui/launchpad/disable-gmaps-0
    Diff size: 467
    Launchpad bug:
          https://bugs.launchpad.net/bugs/624981
    Test command: ./bin/test -vv \
          -t personlocation, -t team-map -t xx-person-home
    Pre-implementation: Edwin
    Target release: 10.09

Disable Google maps
-------------------

Launchpad users who have enabled maps are seeing a popup stating that "the
Google Maps API server rejected your request". Google recognises this as a
problem with their service:
http://www.google.com/support/forum/p/base/thread?hl=en&tid=462f63cbd84b4464

Launchpad users can avoid the message by unchecking the "[X] Display map"
checkbox. If this problem persists, we will consider removing maps from
Launchpad until the issue is addresses.

Rules
-----

The small maps shown on user and team pages is governed in the view by
    self.request.needs_gmap2
This value is set by person visibility and the user's choice to enable/disable
maps. We can add a third condition that we can control per environment to
enable maps.

    * Add a switch to enable/disable Google maps
      * The switch should be easy to re-enable in any environment--
        Sounds like a feature-flag.

QA
--

    * Visit your profile page.
    * Verify maps are not displayed, but you can visit the page to
      set your timezone..

Lint
----

Linting changed files:
  lib/lp/registry/browser/__init__.py
  lib/lp/registry/browser/person.py
  lib/lp/registry/browser/team.py
  lib/lp/registry/stories/location/personlocation.txt
  lib/lp/registry/stories/location/team-map.txt
  lib/lp/registry/stories/person/xx-person-home.txt
  lib/lp/registry/templates/person-portlet-map.pt
  lib/lp/registry/templates/team-portlet-map.pt

Test
----

    * lib/lp/registry/stories/location/personlocation.txt
      * Added a test to verify the map is not shown when the gmap2 feature
        flag is not on. Revised a test to enable gmap2 so the test could
        continue verifying the maps users see.
      * Fixed long lines and headers.
    * lib/lp/registry/stories/location/team-map.txt
      * Added a test to verify the map is not shown when the gmap2 feature
        flag is not on. Revised a test to enable gmap2 so the test could
        continue verifying the maps users see.
      * Fixed long lines and headers.
    * lib/lp/registry/stories/person/xx-person-home.txt
      * Removed team test from person story...the team has its own story.
      * Fixed long lines and headers.

Implementation
--------------

    * lib/lp/registry/browser/__init__.py
      * Added MapMixin that provides access to the rudimentary feature flag.
        This method can be refactored to use the real feature when it is
        ready.
    * lib/lp/registry/browser/person.py
      * Use MapMixin in PersonIndexView.
    * lib/lp/registry/browser/team.py
      * Use MapMixin in TeamMapView.
    * lib/lp/registry/templates/person-portlet-map.pt
      * Added an edit icon so that the user can always edit his timezone.
      * Do not show the map if gmap2 is not enabled.
    * lib/lp/registry/templates/team-portlet-map.pt
      * Do not show the map if gmap2 is not enabled.

To post a comment you must log in.
Revision history for this message
Robert Collins (lifeless) wrote :

439
440 +
441 + <tal:gmap2 condition="view/gmap2_enabled">

Looks like 2 lines of VWS there which isn't really needed - one would be plenty in the template.

You have my ok to merge & CP; ec2 land will bitch about this, so I'm going to not mark this as 'production-change', and request that you self-tag that, to make the automation work.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/registry/browser/__init__.py'
--- lib/lp/registry/browser/__init__.py 2010-08-20 20:31:18 +0000
+++ lib/lp/registry/browser/__init__.py 2010-08-28 23:07:46 +0000
@@ -7,6 +7,7 @@
77
8__all__ = [8__all__ = [
9 'get_status_counts',9 'get_status_counts',
10 'MapMixin',
10 'MilestoneOverlayMixin',11 'MilestoneOverlayMixin',
11 'RegistryEditFormView',12 'RegistryEditFormView',
12 'RegistryDeleteViewMixin',13 'RegistryDeleteViewMixin',
@@ -19,6 +20,7 @@
19from storm.store import Store20from storm.store import Store
20from zope.component import getUtility21from zope.component import getUtility
2122
23from canonical.cachedproperty import cachedproperty
22from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities24from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
23from canonical.launchpad.webapp.launchpadform import (25from canonical.launchpad.webapp.launchpadform import (
24 action,26 action,
@@ -256,3 +258,19 @@
256 @action("Change", name='change')258 @action("Change", name='change')
257 def change_action(self, action, data):259 def change_action(self, action, data):
258 self.updateContextFromData(data)260 self.updateContextFromData(data)
261
262
263class MapMixin:
264
265 @cachedproperty
266 def gmap2_enabled(self):
267 # XXX sinzui 2010-08-27 bug=625556: This is a hack to use
268 # feature flags, which are not ready for general use in the production
269 # code, but has just enough to support this use case:
270 # Do not enable gmap2 if Google's service is not operational.
271 from lp.services.features.flags import FeatureController
272
273 def in_scope(value):
274 return True
275
276 return FeatureController(in_scope).getFlag('gmap2') == 'on'
259277
=== modified file 'lib/lp/registry/browser/person.py'
--- lib/lp/registry/browser/person.py 2010-08-26 22:44:30 +0000
+++ lib/lp/registry/browser/person.py 2010-08-28 23:07:46 +0000
@@ -244,6 +244,7 @@
244from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin244from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
245from lp.code.errors import InvalidNamespace245from lp.code.errors import InvalidNamespace
246from lp.code.interfaces.branchnamespace import IBranchNamespaceSet246from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
247from lp.registry.browser import MapMixin
247from lp.registry.browser.branding import BrandingChangeView248from lp.registry.browser.branding import BrandingChangeView
248from lp.registry.browser.mailinglists import enabled_with_active_mailing_list249from lp.registry.browser.mailinglists import enabled_with_active_mailing_list
249from lp.registry.browser.menu import (250from lp.registry.browser.menu import (
@@ -3324,7 +3325,7 @@
3324 return self.state is EmailAddressVisibleState.ALLOWED3325 return self.state is EmailAddressVisibleState.ALLOWED
33253326
33263327
3327class PersonIndexView(XRDSContentNegotiationMixin, PersonView):3328class PersonIndexView(XRDSContentNegotiationMixin, MapMixin, PersonView):
3328 """View class for person +index and +xrds pages."""3329 """View class for person +index and +xrds pages."""
33293330
3330 xrds_template = ViewPageTemplateFile(3331 xrds_template = ViewPageTemplateFile(
@@ -3337,7 +3338,8 @@
3337 # the location is set, visible, and the viewing user wants to see it.3338 # the location is set, visible, and the viewing user wants to see it.
3338 launchpad_views = get_launchpad_views(self.request.cookies)3339 launchpad_views = get_launchpad_views(self.request.cookies)
3339 self._small_map = launchpad_views['small_maps']3340 self._small_map = launchpad_views['small_maps']
3340 if (self.has_visible_location and self._small_map):3341 if (self.gmap2_enabled
3342 and self.has_visible_location and self._small_map):
3341 self.request.needs_gmap2 = True3343 self.request.needs_gmap2 = True
3342 if self.request.method == "POST":3344 if self.request.method == "POST":
3343 self.processForm()3345 self.processForm()
33443346
=== modified file 'lib/lp/registry/browser/team.py'
--- lib/lp/registry/browser/team.py 2010-08-22 19:14:23 +0000
+++ lib/lp/registry/browser/team.py 2010-08-28 23:07:46 +0000
@@ -69,6 +69,7 @@
69 LaunchpadRadioWidget,69 LaunchpadRadioWidget,
70 )70 )
71from lp.app.errors import UnexpectedFormData71from lp.app.errors import UnexpectedFormData
72from lp.registry.browser import MapMixin
72from lp.registry.browser.branding import BrandingChangeView73from lp.registry.browser.branding import BrandingChangeView
73from lp.registry.interfaces.mailinglist import (74from lp.registry.interfaces.mailinglist import (
74 IMailingList,75 IMailingList,
@@ -1031,7 +1032,7 @@
1031 self.request.response.addInfoNotification(msg)1032 self.request.response.addInfoNotification(msg)
10321033
10331034
1034class TeamMapView(LaunchpadView):1035class TeamMapView(MapMixin, LaunchpadView):
1035 """Show all people with known locations on a map.1036 """Show all people with known locations on a map.
10361037
1037 Also provides links to edit the locations of people in the team without1038 Also provides links to edit the locations of people in the team without
@@ -1044,7 +1045,7 @@
1044 def initialize(self):1045 def initialize(self):
1045 # Tell our base-layout to include Google's gmap2 javascript so that1046 # Tell our base-layout to include Google's gmap2 javascript so that
1046 # we can render the map.1047 # we can render the map.
1047 if self.mapped_participants_count > 0:1048 if self.gmap2_enabled and self.mapped_participants_count > 0:
1048 self.request.needs_gmap2 = True1049 self.request.needs_gmap2 = True
10491050
1050 @cachedproperty1051 @cachedproperty
10511052
=== modified file 'lib/lp/registry/browser/tests/mailinglist-views.txt'
--- lib/lp/registry/browser/tests/mailinglist-views.txt 2010-07-27 22:13:36 +0000
+++ lib/lp/registry/browser/tests/mailinglist-views.txt 2010-08-28 23:07:46 +0000
@@ -175,57 +175,3 @@
175 >>> view = create_view(an_expert)175 >>> view = create_view(an_expert)
176 >>> view.list_can_be_purged176 >>> view.list_can_be_purged
177 False177 False
178
179
180Privacy and mailing lists
181=========================
182
183If a private team has a mailing list the information cannot be seen
184by non-members. Access to the team index page is forbidden and the
185stanza for the mailing list is not shown. NB: the view class
186generates an Unauthorized exception which is turned into a NotFound in
187publication so as to fool the wily hackers.
188
189 >>> # Create a private team.
190 >>> owner = person_set.getByEmail('owner@canonical.com')
191 >>> login('foo.bar@canonical.com')
192 >>> from lp.registry.interfaces.person import PersonVisibility
193 >>> private_team, private_team_list = factory.makeTeamAndMailingList(
194 ... owner_name='owner',
195 ... team_name='private-team',
196 ... visibility=PersonVisibility.PRIVATE)
197 >>> login(ANONYMOUS)
198 >>> view = create_initialized_view(private_team, '+index')
199 Traceback (most recent call last):
200 ...
201 Unauthorized: (<Person at ...
202
203The owner of a team can see information about the mailing list.
204
205 >>> login('owner@canonical.com')
206 >>> view = create_initialized_view(private_team, '+index')
207 >>> print view.archive_url
208 http://lists.launchpad.dev/private-team
209
210A non-owner member can see information about the mailing list.
211
212 >>> ignored = private_team.addMember(sample_person, owner)
213 >>> login('test@canonical.com')
214 >>> view = create_initialized_view(private_team, '+index')
215 >>> print view.archive_url
216 http://lists.launchpad.dev/private-team
217
218An unprivileged non-member cannot see information about the mailing list.
219
220 >>> login('no-priv@canonical.com')
221 >>> view = create_initialized_view(private_team, '+index')
222 Traceback (most recent call last):
223 ...
224 Unauthorized: (<Person at ...
225
226An administrator may see the mailing list information.
227
228 >>> login('foo.bar@canonical.com')
229 >>> view = create_initialized_view(private_team, '+index')
230 >>> print view.archive_url
231 http://lists.launchpad.dev/private-team
232178
=== modified file 'lib/lp/registry/browser/tests/person-views.txt'
--- lib/lp/registry/browser/tests/person-views.txt 2010-08-02 17:48:13 +0000
+++ lib/lp/registry/browser/tests/person-views.txt 2010-08-28 23:07:46 +0000
@@ -347,6 +347,11 @@
347When the user set's his visibility to True, needs_gmap2 will be true and347When the user set's his visibility to True, needs_gmap2 will be true and
348the map_portlet_html can be called.348the map_portlet_html can be called.
349349
350 >>> from lp.services.features.model import FeatureFlag, getFeatureStore
351 >>> ignore = getFeatureStore().add(FeatureFlag(
352 ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
353 >>> transaction.commit()
354
350 >>> login_person(sample_person)355 >>> login_person(sample_person)
351 >>> sample_person.setLocationVisibility(True)356 >>> sample_person.setLocationVisibility(True)
352357
353358
=== modified file 'lib/lp/registry/browser/tests/team-views.txt'
--- lib/lp/registry/browser/tests/team-views.txt 2010-07-12 16:29:33 +0000
+++ lib/lp/registry/browser/tests/team-views.txt 2010-08-28 23:07:46 +0000
@@ -72,6 +72,11 @@
72state of the request's needs_gmap2 attribute to true if there are72state of the request's needs_gmap2 attribute to true if there are
73members who have set their location.73members who have set their location.
7474
75 >>> from lp.services.features.model import FeatureFlag, getFeatureStore
76 >>> ignore = getFeatureStore().add(FeatureFlag(
77 ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
78 >>> transaction.commit()
79
75 >>> team_view = create_initialized_view(ubuntu_team, '+index')80 >>> team_view = create_initialized_view(ubuntu_team, '+index')
76 >>> team_view.has_visible_location81 >>> team_view.has_visible_location
77 False82 False
7883
=== modified file 'lib/lp/registry/stories/location/personlocation.txt'
--- lib/lp/registry/stories/location/personlocation.txt 2010-07-15 10:55:27 +0000
+++ lib/lp/registry/stories/location/personlocation.txt 2010-08-28 23:07:46 +0000
@@ -1,4 +1,5 @@
1= Person Locations =1Person Locations
2================
23
3People can have a location and time zone in Launchpad. In some cases, a4People can have a location and time zone in Launchpad. In some cases, a
4person has a time zone, but no location. We test that their home page renders5person has a time zone, but no location. We test that their home page renders
@@ -16,18 +17,38 @@
16 >>> print extract_text(17 >>> print extract_text(
17 ... find_tag_by_id(anon_browser.contents, 'portlet-map'))18 ... find_tag_by_id(anon_browser.contents, 'portlet-map'))
1819
20If a person has a location, but the gmap2 feature is not enabled, the user
21sees the timezone, but no map.
22
23 >>> login('test@canonical.com')
24 >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',
25 ... latitude=52.2, longitude=0.3)
26 >>> logout()
27
28 >>> anon_browser.open('http://launchpad.dev/~yyy')
29 >>> markup = str(anon_browser.contents)
30 >>> print extract_text(
31 ... find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
32 Location
33 Time zone: Europe/London...
34
35 >>> 'src="http://maps.google.com/maps' in markup
36 False
37
19If a person has a location, there is a little map portlet in their38If a person has a location, there is a little map portlet in their
20profile page. We can't test all the google javascript, but we can make sure39profile page. We can't test all the google javascript, but we can make sure
21there's a map, and the scripts are loaded.40there's a map, and the scripts are loaded when the gmap2 feature is enabled
41for users.
2242
23 >>> login('test@canonical.com')43 >>> from lp.services.features.model import FeatureFlag, getFeatureStore
24 >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',44 >>> ignore = getFeatureStore().add(FeatureFlag(
25 ... latitude=52.2, longitude=0.3)45 ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
26 >>> logout()46 >>> transaction.commit()
2747
28 >>> anon_browser.open('http://launchpad.dev/~yyy')48 >>> anon_browser.open('http://launchpad.dev/~yyy')
29 >>> markup = str(anon_browser.contents)49 >>> markup = str(anon_browser.contents)
30 >>> print extract_text(find_tag_by_id(markup, 'portlet-map'), skip_tags=[])50 >>> print extract_text(
51 ... find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
31 Location52 Location
32 Time zone: Europe/London...53 Time zone: Europe/London...
33 Y.lp.app.mapping.renderPersonMapSmall(...54 Y.lp.app.mapping.renderPersonMapSmall(...
3455
=== modified file 'lib/lp/registry/stories/location/team-map.txt'
--- lib/lp/registry/stories/location/team-map.txt 2010-07-15 10:55:27 +0000
+++ lib/lp/registry/stories/location/team-map.txt 2010-08-28 23:07:46 +0000
@@ -1,4 +1,27 @@
1== The map of a team's members ==1The map of a team's members
2===========================
3
4Maps are disabled
5-----------------
6
7Users cannot see maps when the gmap2 feature is disbaled for them
8
9 >>> user_browser.open('http://launchpad.dev/~guadamen')
10 >>> body = find_main_content(user_browser.contents)
11 >>> mapdiv = find_tag_by_id(str(body), 'team_map_div')
12 >>> 'lp.app.mapping.renderTeamMapSmall(' in str(body)
13 False
14
15
16Maps are enabled
17----------------
18
19Users can see maps when the gmap2 feature is enabled for them.
20
21 >>> from lp.services.features.model import FeatureFlag, getFeatureStore
22 >>> ignore = getFeatureStore().add(FeatureFlag(
23 ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
24 >>> transaction.commit()
225
3If a team has members that have locations, then you should see a portlet26If a team has members that have locations, then you should see a portlet
4with their locations displayed.27with their locations displayed.
@@ -37,7 +60,9 @@
37 <participant60 <participant
38 displayname="Colin Watson"61 displayname="Colin Watson"
39 name="kamion"62 name="kamion"
40 logo_html="&lt;img alt=&quot;&quot; width=&quot;64&quot; height=&quot;64&quot; src=&quot;/@@/person-logo&quot; /&gt;"63 logo_html="&lt;img alt=&quot;&quot;
64 width=&quot;64&quot; height=&quot;64&quot;
65 src=&quot;/@@/person-logo&quot; /&gt;"
41 url="/~kamion"66 url="/~kamion"
42 local_time="..."67 local_time="..."
43 lat="52.2"68 lat="52.2"
@@ -72,7 +97,9 @@
72 <participant97 <participant
73 displayname="Colin Watson"98 displayname="Colin Watson"
74 name="kamion"99 name="kamion"
75 logo_html="&lt;img alt=&quot;&quot; width=&quot;64&quot; height=&quot;64&quot; src=&quot;/@@/person-logo&quot; /&gt;"100 logo_html="&lt;img alt=&quot;&quot;
101 width=&quot;64&quot; height=&quot;64&quot;
102 src=&quot;/@@/person-logo&quot; /&gt;"
76 url="/~kamion"103 url="/~kamion"
77 local_time="..."104 local_time="..."
78 lat="52.2"105 lat="52.2"
@@ -90,7 +117,8 @@
90 http://launchpad.dev/~guadamen/+map117 http://launchpad.dev/~guadamen/+map
91118
92119
93== +mapdata ==120+mapdata
121--------
94122
95The display name of all team participants will be escaped to prevent123The display name of all team participants will be escaped to prevent
96XSS attacks on any callsite of +mapdata.124XSS attacks on any callsite of +mapdata.
@@ -106,5 +134,6 @@
106 >>> anon_browser.open('http://launchpad.dev/~guadamen/+mapdata')134 >>> anon_browser.open('http://launchpad.dev/~guadamen/+mapdata')
107 >>> print anon_browser.contents135 >>> print anon_browser.contents
108 <?xml version="1.0"...136 <?xml version="1.0"...
109 ...displayname="&amp;lt;script&amp;gt;alert('Colin &amp;quot;nasty&amp;quot;');&amp;lt;/script&amp;gt;"137 ...displayname="&amp;lt;script&amp;gt;alert('Colin
138 &amp;quot;nasty&amp;quot;');&amp;lt;/script&amp;gt;"
110 ...139 ...
111140
=== modified file 'lib/lp/registry/stories/person/xx-person-home.txt'
--- lib/lp/registry/stories/person/xx-person-home.txt 2010-06-24 15:30:55 +0000
+++ lib/lp/registry/stories/person/xx-person-home.txt 2010-08-28 23:07:46 +0000
@@ -1,4 +1,5 @@
1= Personal Home Pages =1Personal Home Pages
2===================
23
3Launchpad creates profiles for people that have contributed to free4Launchpad creates profiles for people that have contributed to free
4software (e.g. in a bug import or a translation template upload). It's5software (e.g. in a bug import or a translation template upload). It's
@@ -15,7 +16,8 @@
15 2006-12-13 when importing the Portuguese...16 2006-12-13 when importing the Portuguese...
1617
1718
18== Email address disclosure ==19Email address disclosure
20------------------------
1921
20Mark has a registered email address, and he has chosen to disclose it to22Mark has a registered email address, and he has chosen to disclose it to
21the world. Anonymous users cannot see Mark's address23the world. Anonymous users cannot see Mark's address
@@ -51,9 +53,11 @@
51 testing@canonical.com53 testing@canonical.com
5254
5355
54== Open ID link ==56Open ID link
57------------
5558
56When a person visits his or her own page, they'll see their OpenID login URL.59When a person visits his or her own page, they'll see their OpenID login
60URL.
5761
58 >>> user_browser.open('http://launchpad.dev/~no-priv')62 >>> user_browser.open('http://launchpad.dev/~no-priv')
59 >>> print extract_text(63 >>> print extract_text(
@@ -80,7 +84,8 @@
80 LinkNotFoundError84 LinkNotFoundError
8185
8286
83== Jabber IDs ==87Jabber IDs
88----------
8489
85A person's jabber IDs are only show to authenticated users.90A person's jabber IDs are only show to authenticated users.
8691
@@ -95,11 +100,12 @@
95 Jabber: &lt;email address hidden&gt;100 Jabber: &lt;email address hidden&gt;
96101
97102
98== OpenPGP keys ==103OpenPGP keys
104------------
99105
100In order to avoid email harvesters to find a person's email addresses just by106In order to avoid email harvesters to find a person's email addresses
101following the link to that person's OpenPGP keys, only authenticated users can107just by following the link to that person's OpenPGP keys, only
102see the key ID with a link to the keyserver.108authenticated users can see the key ID with a link to the keyserver.
103109
104 >>> user_browser.open('http://launchpad.dev/~name16')110 >>> user_browser.open('http://launchpad.dev/~name16')
105 >>> print find_tag_by_id(user_browser.contents, 'pgp-keys')111 >>> print find_tag_by_id(user_browser.contents, 'pgp-keys')
@@ -112,18 +118,19 @@
112 <dd> 12345678...118 <dd> 12345678...
113119
114120
115== Languages ==121Languages
122---------
116123
117The contact details portlet shows the languages that the user speaks.124The contact details portlet shows the languages that the user speaks. No
118No Privileges Person can see the languages that mark speaks.125Privileges Person can see the languages that mark speaks.
119126
120 >>> user_browser.open('http://launchpad.dev/~carlos')127 >>> user_browser.open('http://launchpad.dev/~carlos')
121 >>> print extract_text(find_tag_by_id(user_browser.contents, 'languages'))128 >>> print extract_text(find_tag_by_id(user_browser.contents, 'languages'))
122 Languages:129 Languages:
123 Catalan, English, Spanish130 Catalan, English, Spanish
124131
125When viewing his own page, No Privileges Person sees his languages and can132When viewing his own page, No Privileges Person sees his languages and
126edit them.133can edit them.
127134
128 >>> user_browser.open('http://launchpad.dev/~no-priv')135 >>> user_browser.open('http://launchpad.dev/~no-priv')
129 >>> print extract_text(find_tag_by_id(user_browser.contents, 'languages'))136 >>> print extract_text(find_tag_by_id(user_browser.contents, 'languages'))
@@ -131,7 +138,8 @@
131 English138 English
132139
133140
134== Summary Pagelets ==141Summary Pagelets
142----------------
135143
136A person's homepage also lists Karma information:144A person's homepage also lists Karma information:
137145
@@ -154,6 +162,7 @@
154162
155 >>> print extract_text(find_tag_by_id(browser.contents, 'karma-total'))163 >>> print extract_text(find_tag_by_id(browser.contents, 'karma-total'))
156 130164 130
165
157 >>> print extract_text(find_tag_by_id(browser.contents, 'member-since'))166 >>> print extract_text(find_tag_by_id(browser.contents, 'member-since'))
158 2005-06-06167 2005-06-06
159168
@@ -164,7 +173,8 @@
164 2005-06-06173 2005-06-06
165174
166175
167=== Time zones ===176Time zones
177..........
168178
169The user's time zone is displayed next to their location details:179The user's time zone is displayed next to their location details:
170180
@@ -174,26 +184,20 @@
174 Location184 Location
175 Time zone: Europe/London...185 Time zone: Europe/London...
176186
177If the user does not have location data set then the portlet will not187If the user does not have location data set then the portlet will not be
178be shown.188shown.
179189
180 >>> browser.open('http://launchpad.dev/~bac')190 >>> browser.open('http://launchpad.dev/~bac')
181 >>> print extract_text(191 >>> print extract_text(
182 ... find_tag_by_id(browser.contents, 'portlet-map'))192 ... find_tag_by_id(browser.contents, 'portlet-map'))
183193
184Teams don't have a time zone field.194
185195Table of contributions
186 >>> browser.open('http://launchpad.dev/~guadamen')196----------------------
187 >>> 'Time zone' in extract_text(197
188 ... find_tag_by_id(browser.contents, 'portlet-map'))198A person's home page also displays a table with the contributions made
189 False199by that person. This table includes 5 projects in which this person is
190200most active and also the areas in which (s)he worked on each project.
191
192== Table of contributions ==
193
194A person's home page also displays a table with the contributions made by that
195person. This table includes 5 projects in which this person is most active
196and also the areas in which (s)he worked on each project.
197201
198 >>> anon_browser.open('http://launchpad.dev/~name16')202 >>> anon_browser.open('http://launchpad.dev/~name16')
199 >>> table = find_tag_by_id(anon_browser.contents, 'contributions')203 >>> table = find_tag_by_id(anon_browser.contents, 'contributions')
@@ -220,8 +224,8 @@
220 >>> anon_browser.getLink('Recent activities')224 >>> anon_browser.getLink('Recent activities')
221 <Link text='Recent activities' url='http://launchpad.dev/~name16/+karma'>225 <Link text='Recent activities' url='http://launchpad.dev/~name16/+karma'>
222226
223If the person hasn't made any contributions, the table is not present in its227If the person hasn't made any contributions, the table is not present in
224page.228its page.
225229
226 >>> anon_browser.open('http://launchpad.dev/~jdub')230 >>> anon_browser.open('http://launchpad.dev/~jdub')
227 >>> print find_tag_by_id(anon_browser.contents, 'contributions')231 >>> print find_tag_by_id(anon_browser.contents, 'contributions')
@@ -237,9 +241,9 @@
237Unactivated profiles241Unactivated profiles
238--------------------242--------------------
239243
240Many profiles are created for users who contributed to projects that were244Many profiles are created for users who contributed to projects that
241imported into Launchpad. Any user can see an unclaimed profile and a link245were imported into Launchpad. Any user can see an unclaimed profile and
242to request a claim the profile.246a link to request a claim the profile.
243247
244 >>> anon_browser.open('https://launchpad.dev/~jvprat')248 >>> anon_browser.open('https://launchpad.dev/~jvprat')
245 >>> print anon_browser.title249 >>> print anon_browser.title
@@ -252,13 +256,13 @@
252 >>> anon_browser.getLink('Are you Jordi Vilalta')256 >>> anon_browser.getLink('Are you Jordi Vilalta')
253 <Link text='Are you Jordi Vilalta?' url='.../people/+requestmerge...'>257 <Link text='Are you Jordi Vilalta?' url='.../people/+requestmerge...'>
254258
255It is possible for the preferred email address to be set if it is associated259It is possible for the preferred email address to be set if it is
256with an Ubuntu Single Signon account. Anonymous and logged in users cannot260associated with an Ubuntu Single Signon account. Anonymous and logged in
257see this, but admins like Foo Bar can.261users cannot see this, but admins like Foo Bar can.
258262
259 >>> from zope.component import getUtility263 >>> from zope.component import getUtility
260 >>> from canonical.launchpad.interfaces.emailaddress import (264 >>> from canonical.launchpad.interfaces.emailaddress import (
261 ... EmailAddressStatus, IEmailAddressSet)265 ... EmailAddressStatus, IEmailAddressSet)
262266
263 >>> login('admin@canonical.com')267 >>> login('admin@canonical.com')
264 >>> address = getUtility(IEmailAddressSet).getByEmail('jvprat@wanadoo.es')268 >>> address = getUtility(IEmailAddressSet).getByEmail('jvprat@wanadoo.es')
@@ -279,3 +283,5 @@
279 ... find_tag_by_id(admin_browser.contents, 'email-addresses'))283 ... find_tag_by_id(admin_browser.contents, 'email-addresses'))
280 jvprat@wanadoo.es284 jvprat@wanadoo.es
281 Change e-mail settings285 Change e-mail settings
286
287
282288
=== modified file 'lib/lp/registry/templates/person-portlet-map.pt'
--- lib/lp/registry/templates/person-portlet-map.pt 2009-11-16 21:39:26 +0000
+++ lib/lp/registry/templates/person-portlet-map.pt 2010-08-28 23:07:46 +0000
@@ -14,8 +14,11 @@
14 <div tal:condition="context/time_zone">14 <div tal:condition="context/time_zone">
15 <strong>Time zone:</strong>15 <strong>Time zone:</strong>
16 <span tal:replace="context/time_zone">UTC</span>16 <span tal:replace="context/time_zone">UTC</span>
17 <a tal:replace="structure overview_menu/editlocation/fmt:icon" />
17 </div>18 </div>
1819
20
21 <tal:gmap2 condition="view/gmap2_enabled">
19 <div style="width: 400px;" tal:condition="context/latitude">22 <div style="width: 400px;" tal:condition="context/latitude">
20 <div id="person_map_actions"23 <div id="person_map_actions"
21 style="position:relative; z-index: 9999;24 style="position:relative; z-index: 9999;
@@ -28,6 +31,7 @@
28 <a tal:replace="structure overview_menu/editlocation/fmt:link-icon" />31 <a tal:replace="structure overview_menu/editlocation/fmt:link-icon" />
29 </div>32 </div>
30 </div>33 </div>
34 </tal:gmap2>
3135
32 <tal:comment condition="nothing">36 <tal:comment condition="nothing">
33 Only the user can see the editlocation image and link.37 Only the user can see the editlocation image and link.
3438
=== modified file 'lib/lp/registry/templates/team-portlet-map.pt'
--- lib/lp/registry/templates/team-portlet-map.pt 2009-08-25 02:01:55 +0000
+++ lib/lp/registry/templates/team-portlet-map.pt 2010-08-28 23:07:46 +0000
@@ -5,7 +5,8 @@
5 omit-tag="">5 omit-tag="">
66
7<div class="portlet" id="portlet-map" style="margin-bottom: 0px;"7<div class="portlet" id="portlet-map" style="margin-bottom: 0px;"
8 tal:define="link context/menu:overview/map">8 tal:define="link context/menu:overview/map"
9 tal:condition="view/gmap2_enabled">
9<table>10<table>
10<tr><td>11<tr><td>
11 <h2>12 <h2>