Merge lp:~bac/launchpad/bug-436986-team-map into lp:launchpad

Proposed by Brad Crittenden
Status: Merged
Merged at revision: not available
Proposed branch: lp:~bac/launchpad/bug-436986-team-map
Merge into: lp:launchpad
Diff against target: 183 lines
6 files modified
lib/canonical/launchpad/javascript/lp/mapping.js (+1/-1)
lib/lp/registry/browser/configure.zcml (+7/-1)
lib/lp/registry/browser/team.py (+17/-9)
lib/lp/registry/browser/tests/team-views.txt (+6/-6)
lib/lp/registry/model/person.py (+2/-2)
lib/lp/registry/stories/location/team-map.txt (+25/-0)
To merge this branch: bzr merge lp:~bac/launchpad/bug-436986-team-map
Reviewer Review Type Date Requested Status
Abel Deuring (community) Approve
Review via email: mp+13471@code.launchpad.net

Commit message

Fix timeouts on the team index page caused by the bounds method not limiting data.

To post a comment you must log in.
Revision history for this message
Brad Crittenden (bac) wrote :

= Summary =

The bounds method for the map portlet on the team index page times out as it uses all
participants to calculate the bounds. (Bug 436986)

== Proposed fix ==

1) Pass the limit to the model method that calculates the bounds.
2) Create new views for the portlet rather than relying on the ?preview parameter.
The ?preview happens only in the JS call but the view to calculate the bounds was
being used without preview and no limits.

== Pre-implementation notes ==

None

== Implementation details ==

As above.

== Tests ==

bin/test -vv -t team-views.txt -t team-map.txt

== Demo and Q/A ==

Create a huge team (e.g., big-team)and set the location for each member and then
visit https://launchpad.dev/~big-team. Verify that a subset of the members are shown
and the bounds are set appropriately for that subset.

= Launchpad lint =

Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.

Linting changed files:
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/browser/team.py
  lib/canonical/launchpad/javascript/lp/mapping.js
  lib/lp/registry/browser/tests/team-views.txt
  lib/lp/registry/model/person.py
  lib/lp/registry/stories/location/team-map.txt

== JSLint notices ==
jslint: Lint found in
'/home/bac/canonical/lp-branches/bug-436986-team-map/lib/canonical/launchpad/javascript/bugs/bugtask-index.js':
Line 1382 character 33: Missing semicolon.
        assignee_picker.render()

jslint: No problem found in
'/home/bac/canonical/lp-branches/bug-436986-team-map/lib/canonical/launchpad/javascript/lp/mapping.js'.

jslint: 2 files to lint.

I'll fix this problem before landing.

Revision history for this message
Abel Deuring (adeuring) wrote :

thanks for your explanations on IRC for my quite stupid questions...
r=me

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

> thanks for your explanations on IRC for my quite stupid questions...
> r=me

Good questions and good ideas on making the tests clearer and reducing the propagation of magic numbers.

An incremental diff is at http://pastebin.ubuntu.com/294744/

Revision history for this message
Abel Deuring (adeuring) wrote :

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 16.10.2009 16:24, Brad Crittenden wrote:
>> thanks for your explanations on IRC for my quite stupid questions...
>> r=me
>
> Good questions and good ideas on making the tests clearer and reducing the propagation of magic numbers.
>
> An incremental diff is at http://pastebin.ubuntu.com/294744/

looks good

Abel
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iD8DBQFK2KtRekBPhm8NrtARAqVuAJ9pGKQDc8VIzsBrrFRto7W5ukdFcgCfXaMz
ppWQrb3knAx6QJtc9ESFSDk=
=tDYn
-----END PGP SIGNATURE-----

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/javascript/lp/mapping.js'
--- lib/canonical/launchpad/javascript/lp/mapping.js 2009-07-12 15:40:23 +0000
+++ lib/canonical/launchpad/javascript/lp/mapping.js 2009-10-16 14:41:12 +0000
@@ -225,7 +225,7 @@
225 }225 }
226 var team_map = mapping.getSmallMap(226 var team_map = mapping.getSmallMap(
227 'team_map_div', center_lat, center_lng);227 'team_map_div', center_lat, center_lng);
228 gDownloadUrl("+mapdata?preview=true", function(data) {228 gDownloadUrl("+mapdataltd", function(data) {
229 mapping.setMarkersInfoWindowForSmallMap(data, team_map);229 mapping.setMarkersInfoWindowForSmallMap(data, team_map);
230 });230 });
231 };231 };
232232
=== modified file 'lib/lp/registry/browser/configure.zcml'
--- lib/lp/registry/browser/configure.zcml 2009-10-09 17:18:38 +0000
+++ lib/lp/registry/browser/configure.zcml 2009-10-16 14:41:12 +0000
@@ -1079,6 +1079,12 @@
1079 <browser:page1079 <browser:page
1080 for="lp.registry.interfaces.person.ITeam"1080 for="lp.registry.interfaces.person.ITeam"
1081 permission="zope.Public"1081 permission="zope.Public"
1082 class="lp.registry.browser.team.TeamMapLtdData"
1083 template="../templates/team-map-data.pt"
1084 name="+mapdataltd"/>
1085 <browser:page
1086 for="lp.registry.interfaces.person.ITeam"
1087 permission="zope.Public"
1082 class="lp.registry.browser.person.TeamEditLocationView"1088 class="lp.registry.browser.person.TeamEditLocationView"
1083 name="+editlocation"/>1089 name="+editlocation"/>
1084 <browser:page1090 <browser:page
@@ -1094,7 +1100,7 @@
1094 class="lp.registry.browser.person.TeamMugshotView"/>1100 class="lp.registry.browser.person.TeamMugshotView"/>
1095 <browser:page1101 <browser:page
1096 for="lp.registry.interfaces.person.ITeam"1102 for="lp.registry.interfaces.person.ITeam"
1097 class="lp.registry.browser.team.TeamMapView"1103 class="lp.registry.browser.team.TeamMapLtdView"
1098 permission="zope.Public"1104 permission="zope.Public"
1099 name="+portlet-map"1105 name="+portlet-map"
1100 template="../templates/team-portlet-map.pt"/>1106 template="../templates/team-portlet-map.pt"/>
11011107
=== modified file 'lib/lp/registry/browser/team.py'
--- lib/lp/registry/browser/team.py 2009-09-15 22:55:30 +0000
+++ lib/lp/registry/browser/team.py 2009-10-16 14:41:12 +0000
@@ -15,7 +15,9 @@
15 'TeamMailingListModerationView',15 'TeamMailingListModerationView',
16 'TeamMailingListSubscribersView',16 'TeamMailingListSubscribersView',
17 'TeamMapData',17 'TeamMapData',
18 'TeamMapLtdData',
18 'TeamMapView',19 'TeamMapView',
20 'TeamMapLtdView',
19 'TeamMemberAddView',21 'TeamMemberAddView',
20 'TeamPrivacyAdapter',22 'TeamPrivacyAdapter',
21 ]23 ]
@@ -1012,14 +1014,7 @@
1012 """1014 """
10131015
1014 label = "Team member locations"1016 label = "Team member locations"
10151017 limit = None
1016 def __init__(self, context, request):
1017 """Accept the 'preview' parameter to limit mapped participants."""
1018 super(TeamMapView, self).__init__(context, request)
1019 if 'preview' in self.request.form:
1020 self.limit = 24
1021 else:
1022 self.limit = None
10231018
1024 def initialize(self):1019 def initialize(self):
1025 # Tell our main-template to include Google's gmap2 javascript so that1020 # Tell our main-template to include Google's gmap2 javascript so that
@@ -1067,7 +1062,7 @@
1067 def bounds(self):1062 def bounds(self):
1068 """A dictionary with the bounds and center of the map, or None"""1063 """A dictionary with the bounds and center of the map, or None"""
1069 if self.has_mapped_participants:1064 if self.has_mapped_participants:
1070 return self.context.getMappedParticipantsBounds()1065 return self.context.getMappedParticipantsBounds(self.limit)
1071 return None1066 return None
10721067
1073 @property1068 @property
@@ -1110,6 +1105,19 @@
1110 return body.encode('utf-8')1105 return body.encode('utf-8')
11111106
11121107
1108class TeamMapLtdMixin:
1109 """A mixin for team views with limited participants."""
1110 limit = 24
1111
1112
1113class TeamMapLtdView(TeamMapLtdMixin, TeamMapView):
1114 """Team map view with limited participants."""
1115
1116
1117class TeamMapLtdData(TeamMapLtdMixin, TeamMapData):
1118 """An XML dump of the locations of limited number of team members."""
1119
1120
1113class TeamHierarchyView(LaunchpadView):1121class TeamHierarchyView(LaunchpadView):
1114 """View for ~team/+teamhierarchy page."""1122 """View for ~team/+teamhierarchy page."""
11151123
11161124
=== modified file 'lib/lp/registry/browser/tests/team-views.txt'
--- lib/lp/registry/browser/tests/team-views.txt 2009-10-12 18:59:54 +0000
+++ lib/lp/registry/browser/tests/team-views.txt 2009-10-16 14:41:12 +0000
@@ -160,19 +160,19 @@
160 >>> len(view.times)160 >>> len(view.times)
161 2161 2
162162
163The number of persons returned my mapped_participants is governed by the163The number of persons returned by mapped_participants is governed by the
164view's limit attribute. the default value is None, meaning there is no164view's limit attribute. The default value is None, meaning there is no
165limit.165limit. This view is used for displaying the full map.
166166
167 >>> print view.limit167 >>> print view.limit
168 None168 None
169 >>> len(view.mapped_participants)169 >>> len(view.mapped_participants)
170 3170 3
171171
172When the preview parameter is sent to the view, the number of172A portlet for the map also exists which is used for displaying the map
173mapped_participants is limited to 24.173inside the person or team page. It has the number of participants limited.
174174
175 >>> view = create_initialized_view(context, '+map', form={'preview': 'anything'})175 >>> view = create_initialized_view(context, '+portlet-map')
176 >>> view.limit176 >>> view.limit
177 24177 24
178178
179179
=== modified file 'lib/lp/registry/model/person.py'
--- lib/lp/registry/model/person.py 2009-10-12 11:48:21 +0000
+++ lib/lp/registry/model/person.py 2009-10-16 14:41:12 +0000
@@ -1615,13 +1615,13 @@
1615 """See `IPersonViewRestricted`."""1615 """See `IPersonViewRestricted`."""
1616 return self._getMappedParticipantsLocations().count()1616 return self._getMappedParticipantsLocations().count()
16171617
1618 def getMappedParticipantsBounds(self):1618 def getMappedParticipantsBounds(self, limit=None):
1619 """See `IPersonViewRestricted`."""1619 """See `IPersonViewRestricted`."""
1620 max_lat = -90.01620 max_lat = -90.0
1621 min_lat = 90.01621 min_lat = 90.0
1622 max_lng = -180.01622 max_lng = -180.0
1623 min_lng = 180.01623 min_lng = 180.0
1624 locations = self._getMappedParticipantsLocations()1624 locations = self._getMappedParticipantsLocations(limit)
1625 if self.mapped_participants_count == 0:1625 if self.mapped_participants_count == 0:
1626 raise AssertionError, (1626 raise AssertionError, (
1627 'This method cannot be called when '1627 'This method cannot be called when '
16281628
=== modified file 'lib/lp/registry/stories/location/team-map.txt'
--- lib/lp/registry/stories/location/team-map.txt 2009-09-14 21:01:18 +0000
+++ lib/lp/registry/stories/location/team-map.txt 2009-10-16 14:41:12 +0000
@@ -56,6 +56,31 @@
56 </participants>56 </participants>
57 <BLANKLINE>57 <BLANKLINE>
5858
59The team index page has a map with data limited to 24 members and uses
60a slightly different URL. We can see the URL works though there isn't
61enough test data to demonstrate the limit but that is done in the view
62test.
63
64 >>> anon_browser.open('http://launchpad.dev/~guadamen/+mapdataltd')
65 >>> print anon_browser.contents
66 <?xml version="1.0"...
67 <participants>
68 <!--
69 This collection of team location data is (c) Canonical Ltd and
70 contributors, and the format may be changed at any time.
71 -->
72 <participant
73 displayname="Colin Watson"
74 name="kamion"
75 logo_html="&lt;img alt=&quot;&quot; width=&quot;64&quot; height=&quot;64&quot; src=&quot;/@@/person-logo&quot; /&gt;"
76 url="/~kamion"
77 local_time="..."
78 lat="52.2"
79 lng="0.3"/>
80 </participants>
81 <BLANKLINE>
82
83
59It doesn't make sense to edit the location of the team itself, not even84It doesn't make sense to edit the location of the team itself, not even
60if we are an admin, so a team's +editlocation page will simply redirect85if we are an admin, so a team's +editlocation page will simply redirect
61to +map.86to +map.