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
1=== modified file 'lib/lp/registry/browser/__init__.py'
2--- lib/lp/registry/browser/__init__.py 2010-08-20 20:31:18 +0000
3+++ lib/lp/registry/browser/__init__.py 2010-08-28 23:07:46 +0000
4@@ -7,6 +7,7 @@
5
6 __all__ = [
7 'get_status_counts',
8+ 'MapMixin',
9 'MilestoneOverlayMixin',
10 'RegistryEditFormView',
11 'RegistryDeleteViewMixin',
12@@ -19,6 +20,7 @@
13 from storm.store import Store
14 from zope.component import getUtility
15
16+from canonical.cachedproperty import cachedproperty
17 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
18 from canonical.launchpad.webapp.launchpadform import (
19 action,
20@@ -256,3 +258,19 @@
21 @action("Change", name='change')
22 def change_action(self, action, data):
23 self.updateContextFromData(data)
24+
25+
26+class MapMixin:
27+
28+ @cachedproperty
29+ def gmap2_enabled(self):
30+ # XXX sinzui 2010-08-27 bug=625556: This is a hack to use
31+ # feature flags, which are not ready for general use in the production
32+ # code, but has just enough to support this use case:
33+ # Do not enable gmap2 if Google's service is not operational.
34+ from lp.services.features.flags import FeatureController
35+
36+ def in_scope(value):
37+ return True
38+
39+ return FeatureController(in_scope).getFlag('gmap2') == 'on'
40
41=== modified file 'lib/lp/registry/browser/person.py'
42--- lib/lp/registry/browser/person.py 2010-08-26 22:44:30 +0000
43+++ lib/lp/registry/browser/person.py 2010-08-28 23:07:46 +0000
44@@ -244,6 +244,7 @@
45 from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
46 from lp.code.errors import InvalidNamespace
47 from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
48+from lp.registry.browser import MapMixin
49 from lp.registry.browser.branding import BrandingChangeView
50 from lp.registry.browser.mailinglists import enabled_with_active_mailing_list
51 from lp.registry.browser.menu import (
52@@ -3324,7 +3325,7 @@
53 return self.state is EmailAddressVisibleState.ALLOWED
54
55
56-class PersonIndexView(XRDSContentNegotiationMixin, PersonView):
57+class PersonIndexView(XRDSContentNegotiationMixin, MapMixin, PersonView):
58 """View class for person +index and +xrds pages."""
59
60 xrds_template = ViewPageTemplateFile(
61@@ -3337,7 +3338,8 @@
62 # the location is set, visible, and the viewing user wants to see it.
63 launchpad_views = get_launchpad_views(self.request.cookies)
64 self._small_map = launchpad_views['small_maps']
65- if (self.has_visible_location and self._small_map):
66+ if (self.gmap2_enabled
67+ and self.has_visible_location and self._small_map):
68 self.request.needs_gmap2 = True
69 if self.request.method == "POST":
70 self.processForm()
71
72=== modified file 'lib/lp/registry/browser/team.py'
73--- lib/lp/registry/browser/team.py 2010-08-22 19:14:23 +0000
74+++ lib/lp/registry/browser/team.py 2010-08-28 23:07:46 +0000
75@@ -69,6 +69,7 @@
76 LaunchpadRadioWidget,
77 )
78 from lp.app.errors import UnexpectedFormData
79+from lp.registry.browser import MapMixin
80 from lp.registry.browser.branding import BrandingChangeView
81 from lp.registry.interfaces.mailinglist import (
82 IMailingList,
83@@ -1031,7 +1032,7 @@
84 self.request.response.addInfoNotification(msg)
85
86
87-class TeamMapView(LaunchpadView):
88+class TeamMapView(MapMixin, LaunchpadView):
89 """Show all people with known locations on a map.
90
91 Also provides links to edit the locations of people in the team without
92@@ -1044,7 +1045,7 @@
93 def initialize(self):
94 # Tell our base-layout to include Google's gmap2 javascript so that
95 # we can render the map.
96- if self.mapped_participants_count > 0:
97+ if self.gmap2_enabled and self.mapped_participants_count > 0:
98 self.request.needs_gmap2 = True
99
100 @cachedproperty
101
102=== modified file 'lib/lp/registry/browser/tests/mailinglist-views.txt'
103--- lib/lp/registry/browser/tests/mailinglist-views.txt 2010-07-27 22:13:36 +0000
104+++ lib/lp/registry/browser/tests/mailinglist-views.txt 2010-08-28 23:07:46 +0000
105@@ -175,57 +175,3 @@
106 >>> view = create_view(an_expert)
107 >>> view.list_can_be_purged
108 False
109-
110-
111-Privacy and mailing lists
112-=========================
113-
114-If a private team has a mailing list the information cannot be seen
115-by non-members. Access to the team index page is forbidden and the
116-stanza for the mailing list is not shown. NB: the view class
117-generates an Unauthorized exception which is turned into a NotFound in
118-publication so as to fool the wily hackers.
119-
120- >>> # Create a private team.
121- >>> owner = person_set.getByEmail('owner@canonical.com')
122- >>> login('foo.bar@canonical.com')
123- >>> from lp.registry.interfaces.person import PersonVisibility
124- >>> private_team, private_team_list = factory.makeTeamAndMailingList(
125- ... owner_name='owner',
126- ... team_name='private-team',
127- ... visibility=PersonVisibility.PRIVATE)
128- >>> login(ANONYMOUS)
129- >>> view = create_initialized_view(private_team, '+index')
130- Traceback (most recent call last):
131- ...
132- Unauthorized: (<Person at ...
133-
134-The owner of a team can see information about the mailing list.
135-
136- >>> login('owner@canonical.com')
137- >>> view = create_initialized_view(private_team, '+index')
138- >>> print view.archive_url
139- http://lists.launchpad.dev/private-team
140-
141-A non-owner member can see information about the mailing list.
142-
143- >>> ignored = private_team.addMember(sample_person, owner)
144- >>> login('test@canonical.com')
145- >>> view = create_initialized_view(private_team, '+index')
146- >>> print view.archive_url
147- http://lists.launchpad.dev/private-team
148-
149-An unprivileged non-member cannot see information about the mailing list.
150-
151- >>> login('no-priv@canonical.com')
152- >>> view = create_initialized_view(private_team, '+index')
153- Traceback (most recent call last):
154- ...
155- Unauthorized: (<Person at ...
156-
157-An administrator may see the mailing list information.
158-
159- >>> login('foo.bar@canonical.com')
160- >>> view = create_initialized_view(private_team, '+index')
161- >>> print view.archive_url
162- http://lists.launchpad.dev/private-team
163
164=== modified file 'lib/lp/registry/browser/tests/person-views.txt'
165--- lib/lp/registry/browser/tests/person-views.txt 2010-08-02 17:48:13 +0000
166+++ lib/lp/registry/browser/tests/person-views.txt 2010-08-28 23:07:46 +0000
167@@ -347,6 +347,11 @@
168 When the user set's his visibility to True, needs_gmap2 will be true and
169 the map_portlet_html can be called.
170
171+ >>> from lp.services.features.model import FeatureFlag, getFeatureStore
172+ >>> ignore = getFeatureStore().add(FeatureFlag(
173+ ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
174+ >>> transaction.commit()
175+
176 >>> login_person(sample_person)
177 >>> sample_person.setLocationVisibility(True)
178
179
180=== modified file 'lib/lp/registry/browser/tests/team-views.txt'
181--- lib/lp/registry/browser/tests/team-views.txt 2010-07-12 16:29:33 +0000
182+++ lib/lp/registry/browser/tests/team-views.txt 2010-08-28 23:07:46 +0000
183@@ -72,6 +72,11 @@
184 state of the request's needs_gmap2 attribute to true if there are
185 members who have set their location.
186
187+ >>> from lp.services.features.model import FeatureFlag, getFeatureStore
188+ >>> ignore = getFeatureStore().add(FeatureFlag(
189+ ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
190+ >>> transaction.commit()
191+
192 >>> team_view = create_initialized_view(ubuntu_team, '+index')
193 >>> team_view.has_visible_location
194 False
195
196=== modified file 'lib/lp/registry/stories/location/personlocation.txt'
197--- lib/lp/registry/stories/location/personlocation.txt 2010-07-15 10:55:27 +0000
198+++ lib/lp/registry/stories/location/personlocation.txt 2010-08-28 23:07:46 +0000
199@@ -1,4 +1,5 @@
200-= Person Locations =
201+Person Locations
202+================
203
204 People can have a location and time zone in Launchpad. In some cases, a
205 person has a time zone, but no location. We test that their home page renders
206@@ -16,18 +17,38 @@
207 >>> print extract_text(
208 ... find_tag_by_id(anon_browser.contents, 'portlet-map'))
209
210+If a person has a location, but the gmap2 feature is not enabled, the user
211+sees the timezone, but no map.
212+
213+ >>> login('test@canonical.com')
214+ >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',
215+ ... latitude=52.2, longitude=0.3)
216+ >>> logout()
217+
218+ >>> anon_browser.open('http://launchpad.dev/~yyy')
219+ >>> markup = str(anon_browser.contents)
220+ >>> print extract_text(
221+ ... find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
222+ Location
223+ Time zone: Europe/London...
224+
225+ >>> 'src="http://maps.google.com/maps' in markup
226+ False
227+
228 If a person has a location, there is a little map portlet in their
229 profile page. We can't test all the google javascript, but we can make sure
230-there's a map, and the scripts are loaded.
231+there's a map, and the scripts are loaded when the gmap2 feature is enabled
232+for users.
233
234- >>> login('test@canonical.com')
235- >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',
236- ... latitude=52.2, longitude=0.3)
237- >>> logout()
238+ >>> from lp.services.features.model import FeatureFlag, getFeatureStore
239+ >>> ignore = getFeatureStore().add(FeatureFlag(
240+ ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
241+ >>> transaction.commit()
242
243 >>> anon_browser.open('http://launchpad.dev/~yyy')
244 >>> markup = str(anon_browser.contents)
245- >>> print extract_text(find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
246+ >>> print extract_text(
247+ ... find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
248 Location
249 Time zone: Europe/London...
250 Y.lp.app.mapping.renderPersonMapSmall(...
251
252=== modified file 'lib/lp/registry/stories/location/team-map.txt'
253--- lib/lp/registry/stories/location/team-map.txt 2010-07-15 10:55:27 +0000
254+++ lib/lp/registry/stories/location/team-map.txt 2010-08-28 23:07:46 +0000
255@@ -1,4 +1,27 @@
256-== The map of a team's members ==
257+The map of a team's members
258+===========================
259+
260+Maps are disabled
261+-----------------
262+
263+Users cannot see maps when the gmap2 feature is disbaled for them
264+
265+ >>> user_browser.open('http://launchpad.dev/~guadamen')
266+ >>> body = find_main_content(user_browser.contents)
267+ >>> mapdiv = find_tag_by_id(str(body), 'team_map_div')
268+ >>> 'lp.app.mapping.renderTeamMapSmall(' in str(body)
269+ False
270+
271+
272+Maps are enabled
273+----------------
274+
275+Users can see maps when the gmap2 feature is enabled for them.
276+
277+ >>> from lp.services.features.model import FeatureFlag, getFeatureStore
278+ >>> ignore = getFeatureStore().add(FeatureFlag(
279+ ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
280+ >>> transaction.commit()
281
282 If a team has members that have locations, then you should see a portlet
283 with their locations displayed.
284@@ -37,7 +60,9 @@
285 <participant
286 displayname="Colin Watson"
287 name="kamion"
288- logo_html="&lt;img alt=&quot;&quot; width=&quot;64&quot; height=&quot;64&quot; src=&quot;/@@/person-logo&quot; /&gt;"
289+ logo_html="&lt;img alt=&quot;&quot;
290+ width=&quot;64&quot; height=&quot;64&quot;
291+ src=&quot;/@@/person-logo&quot; /&gt;"
292 url="/~kamion"
293 local_time="..."
294 lat="52.2"
295@@ -72,7 +97,9 @@
296 <participant
297 displayname="Colin Watson"
298 name="kamion"
299- logo_html="&lt;img alt=&quot;&quot; width=&quot;64&quot; height=&quot;64&quot; src=&quot;/@@/person-logo&quot; /&gt;"
300+ logo_html="&lt;img alt=&quot;&quot;
301+ width=&quot;64&quot; height=&quot;64&quot;
302+ src=&quot;/@@/person-logo&quot; /&gt;"
303 url="/~kamion"
304 local_time="..."
305 lat="52.2"
306@@ -90,7 +117,8 @@
307 http://launchpad.dev/~guadamen/+map
308
309
310-== +mapdata ==
311++mapdata
312+--------
313
314 The display name of all team participants will be escaped to prevent
315 XSS attacks on any callsite of +mapdata.
316@@ -106,5 +134,6 @@
317 >>> anon_browser.open('http://launchpad.dev/~guadamen/+mapdata')
318 >>> print anon_browser.contents
319 <?xml version="1.0"...
320- ...displayname="&amp;lt;script&amp;gt;alert('Colin &amp;quot;nasty&amp;quot;');&amp;lt;/script&amp;gt;"
321+ ...displayname="&amp;lt;script&amp;gt;alert('Colin
322+ &amp;quot;nasty&amp;quot;');&amp;lt;/script&amp;gt;"
323 ...
324
325=== modified file 'lib/lp/registry/stories/person/xx-person-home.txt'
326--- lib/lp/registry/stories/person/xx-person-home.txt 2010-06-24 15:30:55 +0000
327+++ lib/lp/registry/stories/person/xx-person-home.txt 2010-08-28 23:07:46 +0000
328@@ -1,4 +1,5 @@
329-= Personal Home Pages =
330+Personal Home Pages
331+===================
332
333 Launchpad creates profiles for people that have contributed to free
334 software (e.g. in a bug import or a translation template upload). It's
335@@ -15,7 +16,8 @@
336 2006-12-13 when importing the Portuguese...
337
338
339-== Email address disclosure ==
340+Email address disclosure
341+------------------------
342
343 Mark has a registered email address, and he has chosen to disclose it to
344 the world. Anonymous users cannot see Mark's address
345@@ -51,9 +53,11 @@
346 testing@canonical.com
347
348
349-== Open ID link ==
350+Open ID link
351+------------
352
353-When a person visits his or her own page, they'll see their OpenID login URL.
354+When a person visits his or her own page, they'll see their OpenID login
355+URL.
356
357 >>> user_browser.open('http://launchpad.dev/~no-priv')
358 >>> print extract_text(
359@@ -80,7 +84,8 @@
360 LinkNotFoundError
361
362
363-== Jabber IDs ==
364+Jabber IDs
365+----------
366
367 A person's jabber IDs are only show to authenticated users.
368
369@@ -95,11 +100,12 @@
370 Jabber: &lt;email address hidden&gt;
371
372
373-== OpenPGP keys ==
374+OpenPGP keys
375+------------
376
377-In order to avoid email harvesters to find a person's email addresses just by
378-following the link to that person's OpenPGP keys, only authenticated users can
379-see the key ID with a link to the keyserver.
380+In order to avoid email harvesters to find a person's email addresses
381+just by following the link to that person's OpenPGP keys, only
382+authenticated users can see the key ID with a link to the keyserver.
383
384 >>> user_browser.open('http://launchpad.dev/~name16')
385 >>> print find_tag_by_id(user_browser.contents, 'pgp-keys')
386@@ -112,18 +118,19 @@
387 <dd> 12345678...
388
389
390-== Languages ==
391+Languages
392+---------
393
394-The contact details portlet shows the languages that the user speaks.
395-No Privileges Person can see the languages that mark speaks.
396+The contact details portlet shows the languages that the user speaks. No
397+Privileges Person can see the languages that mark speaks.
398
399 >>> user_browser.open('http://launchpad.dev/~carlos')
400 >>> print extract_text(find_tag_by_id(user_browser.contents, 'languages'))
401 Languages:
402 Catalan, English, Spanish
403
404-When viewing his own page, No Privileges Person sees his languages and can
405-edit them.
406+When viewing his own page, No Privileges Person sees his languages and
407+can edit them.
408
409 >>> user_browser.open('http://launchpad.dev/~no-priv')
410 >>> print extract_text(find_tag_by_id(user_browser.contents, 'languages'))
411@@ -131,7 +138,8 @@
412 English
413
414
415-== Summary Pagelets ==
416+Summary Pagelets
417+----------------
418
419 A person's homepage also lists Karma information:
420
421@@ -154,6 +162,7 @@
422
423 >>> print extract_text(find_tag_by_id(browser.contents, 'karma-total'))
424 130
425+
426 >>> print extract_text(find_tag_by_id(browser.contents, 'member-since'))
427 2005-06-06
428
429@@ -164,7 +173,8 @@
430 2005-06-06
431
432
433-=== Time zones ===
434+Time zones
435+..........
436
437 The user's time zone is displayed next to their location details:
438
439@@ -174,26 +184,20 @@
440 Location
441 Time zone: Europe/London...
442
443-If the user does not have location data set then the portlet will not
444-be shown.
445+If the user does not have location data set then the portlet will not be
446+shown.
447
448 >>> browser.open('http://launchpad.dev/~bac')
449 >>> print extract_text(
450 ... find_tag_by_id(browser.contents, 'portlet-map'))
451
452-Teams don't have a time zone field.
453-
454- >>> browser.open('http://launchpad.dev/~guadamen')
455- >>> 'Time zone' in extract_text(
456- ... find_tag_by_id(browser.contents, 'portlet-map'))
457- False
458-
459-
460-== Table of contributions ==
461-
462-A person's home page also displays a table with the contributions made by that
463-person. This table includes 5 projects in which this person is most active
464-and also the areas in which (s)he worked on each project.
465+
466+Table of contributions
467+----------------------
468+
469+A person's home page also displays a table with the contributions made
470+by that person. This table includes 5 projects in which this person is
471+most active and also the areas in which (s)he worked on each project.
472
473 >>> anon_browser.open('http://launchpad.dev/~name16')
474 >>> table = find_tag_by_id(anon_browser.contents, 'contributions')
475@@ -220,8 +224,8 @@
476 >>> anon_browser.getLink('Recent activities')
477 <Link text='Recent activities' url='http://launchpad.dev/~name16/+karma'>
478
479-If the person hasn't made any contributions, the table is not present in its
480-page.
481+If the person hasn't made any contributions, the table is not present in
482+its page.
483
484 >>> anon_browser.open('http://launchpad.dev/~jdub')
485 >>> print find_tag_by_id(anon_browser.contents, 'contributions')
486@@ -237,9 +241,9 @@
487 Unactivated profiles
488 --------------------
489
490-Many profiles are created for users who contributed to projects that were
491-imported into Launchpad. Any user can see an unclaimed profile and a link
492-to request a claim the profile.
493+Many profiles are created for users who contributed to projects that
494+were imported into Launchpad. Any user can see an unclaimed profile and
495+a link to request a claim the profile.
496
497 >>> anon_browser.open('https://launchpad.dev/~jvprat')
498 >>> print anon_browser.title
499@@ -252,13 +256,13 @@
500 >>> anon_browser.getLink('Are you Jordi Vilalta')
501 <Link text='Are you Jordi Vilalta?' url='.../people/+requestmerge...'>
502
503-It is possible for the preferred email address to be set if it is associated
504-with an Ubuntu Single Signon account. Anonymous and logged in users cannot
505-see this, but admins like Foo Bar can.
506+It is possible for the preferred email address to be set if it is
507+associated with an Ubuntu Single Signon account. Anonymous and logged in
508+users cannot see this, but admins like Foo Bar can.
509
510 >>> from zope.component import getUtility
511 >>> from canonical.launchpad.interfaces.emailaddress import (
512- ... EmailAddressStatus, IEmailAddressSet)
513+ ... EmailAddressStatus, IEmailAddressSet)
514
515 >>> login('admin@canonical.com')
516 >>> address = getUtility(IEmailAddressSet).getByEmail('jvprat@wanadoo.es')
517@@ -279,3 +283,5 @@
518 ... find_tag_by_id(admin_browser.contents, 'email-addresses'))
519 jvprat@wanadoo.es
520 Change e-mail settings
521+
522+
523
524=== modified file 'lib/lp/registry/templates/person-portlet-map.pt'
525--- lib/lp/registry/templates/person-portlet-map.pt 2009-11-16 21:39:26 +0000
526+++ lib/lp/registry/templates/person-portlet-map.pt 2010-08-28 23:07:46 +0000
527@@ -14,8 +14,11 @@
528 <div tal:condition="context/time_zone">
529 <strong>Time zone:</strong>
530 <span tal:replace="context/time_zone">UTC</span>
531+ <a tal:replace="structure overview_menu/editlocation/fmt:icon" />
532 </div>
533
534+
535+ <tal:gmap2 condition="view/gmap2_enabled">
536 <div style="width: 400px;" tal:condition="context/latitude">
537 <div id="person_map_actions"
538 style="position:relative; z-index: 9999;
539@@ -28,6 +31,7 @@
540 <a tal:replace="structure overview_menu/editlocation/fmt:link-icon" />
541 </div>
542 </div>
543+ </tal:gmap2>
544
545 <tal:comment condition="nothing">
546 Only the user can see the editlocation image and link.
547
548=== modified file 'lib/lp/registry/templates/team-portlet-map.pt'
549--- lib/lp/registry/templates/team-portlet-map.pt 2009-08-25 02:01:55 +0000
550+++ lib/lp/registry/templates/team-portlet-map.pt 2010-08-28 23:07:46 +0000
551@@ -5,7 +5,8 @@
552 omit-tag="">
553
554 <div class="portlet" id="portlet-map" style="margin-bottom: 0px;"
555- tal:define="link context/menu:overview/map">
556+ tal:define="link context/menu:overview/map"
557+ tal:condition="view/gmap2_enabled">
558 <table>
559 <tr><td>
560 <h2>