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

Proposed by Curtis Hovey
Status: Merged
Merged at revision: 11593
Proposed branch: lp:~sinzui/launchpad/remove-gmaps-0
Merge into: lp:launchpad
Diff against target: 1262 lines (+42/-826)
20 files modified
lib/canonical/launchpad/doc/location-widget.txt (+2/-6)
lib/canonical/launchpad/webapp/servers.py (+1/-5)
lib/canonical/widgets/location.py (+7/-3)
lib/canonical/widgets/templates/location.pt (+7/-28)
lib/lp/app/javascript/mapping.js (+0/-365)
lib/lp/app/templates/base-layout-macros.pt (+0/-10)
lib/lp/registry/browser/__init__.py (+0/-18)
lib/lp/registry/browser/configure.zcml (+1/-6)
lib/lp/registry/browser/person.py (+10/-57)
lib/lp/registry/browser/team.py (+2/-12)
lib/lp/registry/browser/tests/person-views.txt (+0/-107)
lib/lp/registry/browser/tests/team-views.txt (+5/-28)
lib/lp/registry/doc/personlocation.txt (+4/-2)
lib/lp/registry/stories/location/personlocation-edit.txt (+2/-33)
lib/lp/registry/stories/location/personlocation.txt (+0/-40)
lib/lp/registry/stories/location/team-map.txt (+0/-53)
lib/lp/registry/templates/person-editlocation.pt (+0/-23)
lib/lp/registry/templates/person-portlet-map.pt (+0/-25)
lib/lp/registry/templates/team-index.pt (+0/-3)
lib/lp/registry/templates/team-portlet-map.pt (+1/-2)
To merge this branch: bzr merge lp:~sinzui/launchpad/remove-gmaps-0
Reviewer Review Type Date Requested Status
Māris Fogels (community) Approve
Review via email: mp+36169@code.launchpad.net

Description of the change

This is my branch to remove Google maps.

    lp:~sinzui/launchpad/remove-gmaps-0
    Diff size: 1263 (-846, +62)
    Launchpad bug:
          https://bugs.launchpad.net/bugs/277276
          https://bugs.launchpad.net/bugs/625556
          https://bugs.launchpad.net/bugs/633178
    Test command: ./bin/test -vv \
          -t personlocation -t location-widget -t person-views -t team-views \
          -t team-map
    Pre-implementation: statik, jml
    Target release: 10.10

Remove Google maps
------------------

This branch removes the Google map dependency from Launchpad. Launchpad still
has a concept of location and map, but they are hidden. We may remove the
map concept in October if there is no progress in getting a map tile server.
This branch address 3 specific issues:

https://bugs.launchpad.net/bugs/633178
    Remove Google maps (deletes)

https://bugs.launchpad.net/bugs/625556
    Remove the gmap2 feature flag because nothing uses gmaps (deletes)

https://bugs.launchpad.net/bugs/277276
    Allow users to set their timezone without using a map
    This last point requires rewrites of code (adds)

Rules
-----

    * Update the location widget to only render the time zone
    * Simplify the edit location form because it is not doing anything
      special anymore
    * Remove the Google map calls from the templates
    * Remove the gmap2 calls from the view code
    * Remove the mapping library that uses Google maps
    * Remove the gmap2 feature flag

QA
--

    * Visit your profile page
    * Verify a map is not displayed
    * Choose to edit your time zone
    * Verify a map is not shown and that there is no javascript error.
    * Set your timezone and save
    * Verify your timezone is set

    * Visit https://edge.launchpad.net/~launchpad
    * Verify a map is not shown.
    * Assuming someone bookmarked the map page,
      visit https://edge.launchpad.net/~launchpad/+map
    * Verify a map is not shown and that there is no JS error.

Lint
----

Linting changed files:
  lib/canonical/launchpad/doc/location-widget.txt
  lib/canonical/launchpad/webapp/servers.py
  lib/canonical/widgets/location.py
  lib/canonical/widgets/templates/location.pt
  lib/lp/app/templates/base-layout-macros.pt
  lib/lp/registry/browser/__init__.py
  lib/lp/registry/browser/configure.zcml
  lib/lp/registry/browser/person.py
  lib/lp/registry/browser/team.py
  lib/lp/registry/browser/tests/person-views.txt
  lib/lp/registry/browser/tests/team-views.txt
  lib/lp/registry/doc/personlocation.txt
  lib/lp/registry/stories/location/personlocation-edit.txt
  lib/lp/registry/stories/location/personlocation.txt
  lib/lp/registry/stories/location/team-map.txt
  lib/lp/registry/templates/person-portlet-map.pt
  lib/lp/registry/templates/team-index.pt
  lib/lp/registry/templates/team-portlet-map.pt

Lint wants me to fix some test format issues. I can do this before I land
the branch.

Test
----

    * lib/canonical/launchpad/doc/location-widget.txt
      * Removed tests for gmap.
    * lib/lp/registry/browser/tests/person-views.txt
      * Removed tests that shows how gmaps were used by the view.
    * lib/lp/registry/browser/tests/team-views.txt
      * Removed tests that showed maps use gmaps.
      * The map tests remain because there is a small chance we can use OSM
        to provide maps.
    * lib/lp/registry/doc/personlocation.txt
      * Remove the gmap portion of the location object tests.
    * lib/lp/registry/stories/location/personlocation-edit.txt
      * Removed the gmap portion of the edit location test.
    * lib/lp/registry/stories/location/personlocation.txt
      * Removed gmap portion of the test.
    * lib/lp/registry/stories/location/team-map.txt
      * Removed gmap portion of the test.
      * The map tests remain because there is a small chance we can use OSM
        to provide maps.

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

    * lib/canonical/launchpad/webapp/servers.py
      * Removed code and tests to support gmap2 flags in the request.
    * lib/canonical/widgets/location.py
      * Removed gmap2.
      * Updated the timezone help text from the template to the field.
    * lib/canonical/widgets/templates/location.pt
      * Removed the map, but kept the hidden lat-long fields so that the
        widget continues to work.
      * Moved the help text to the field.
    * lib/lp/app/templates/base-layout-macros.pt
      * Removed the gmap2 mapping library and rules to include it in the page.
    * lib/lp/registry/browser/__init__.py
      * Removed the MapMixin and the feature flag.
    * lib/lp/registry/browser/configure.zcml
      * Switched +editlocation to use the generic template.
      * Removed the unused team view...teams do not have a link to edit their
        location.
    * lib/lp/registry/browser/person.py
      * Removed the gmap2 setup code.
      * Removed the unused TeamEditLocationView
      * Simplified the user +editlocation since it does not need gmaps and
        we only need to show time zone at this time.
    * lib/lp/registry/browser/team.py
      * Removed the gmap2 setup code.
    * lib/lp/registry/templates/person-portlet-map.pt
      * Removed the gmap. This template also rendered timezone so it must
        remain.
    * lib/lp/registry/templates/team-index.pt
      * Removed the call to render the small map.
    * lib/lp/registry/templates/team-portlet-map.pt
      * Removed the gmap check.

To post a comment you must log in.
Revision history for this message
Māris Fogels (mars) wrote :

Hi Curtis,

This is a great change. You really thought of every angle, right down to updating the location page title. Stunning! r=mars

Maris

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/canonical/launchpad/doc/location-widget.txt'
2--- lib/canonical/launchpad/doc/location-widget.txt 2010-08-11 15:47:27 +0000
3+++ lib/canonical/launchpad/doc/location-widget.txt 2010-09-21 16:51:00 +0000
4@@ -9,22 +9,18 @@
5 >>> salgado = getUtility(IPersonSet).getByName('salgado')
6 >>> field = LocationField(__name__='location', title=u'Location')
7
8-JavaScript and JSON are used in the Google Maps API. By setting the
9-needs_gmap2 and needs_json attributes of the request, the main template
10+JavaScript and JSON are used by the location widget. By setting the
11+needs_json attributes of the request, the main template
12 will include the necessary code to enable these features.
13
14 >>> bound_field = field.bind(salgado)
15 >>> request = LaunchpadTestRequest(
16 ... # Let's pretend requests are coming from Brazil.
17 ... environ={'REMOTE_ADDR': '201.13.165.145'})
18- >>> request.needs_gmap2
19- False
20 >>> request.needs_json
21 False
22
23 >>> widget = LocationWidget(bound_field, request)
24- >>> request.needs_gmap2
25- True
26 >>> request.needs_json
27 True
28
29
30=== modified file 'lib/canonical/launchpad/webapp/servers.py'
31--- lib/canonical/launchpad/webapp/servers.py 2010-09-16 21:08:51 +0000
32+++ lib/canonical/launchpad/webapp/servers.py 2010-09-21 16:51:00 +0000
33@@ -522,7 +522,6 @@
34 self.needs_datepicker_iframe = False
35 self.needs_datetimepicker_iframe = False
36 self.needs_json = False
37- self.needs_gmap2 = False
38 super(BasicLaunchpadRequest, self).__init__(
39 body_instream, environ, response)
40
41@@ -834,12 +833,10 @@
42 >>> request.needs_datepicker_iframe
43 False
44
45- And for JSON and GMap2:
46+ And for JSON:
47
48 >>> request.needs_json
49 False
50- >>> request.needs_gmap2
51- False
52
53 """
54 implements(INotificationRequest, IBasicLaunchpadRequest, IParticipation,
55@@ -857,7 +854,6 @@
56 self.needs_datepicker_iframe = False
57 self.needs_datetimepicker_iframe = False
58 self.needs_json = False
59- self.needs_gmap2 = False
60 # stub out the FeatureController that would normally be provided by
61 # the publication mechanism
62 self.features = NullFeatureController()
63
64=== modified file 'lib/canonical/widgets/location.py'
65--- lib/canonical/widgets/location.py 2010-09-11 19:25:13 +0000
66+++ lib/canonical/widgets/location.py 2010-09-21 16:51:00 +0000
67@@ -42,6 +42,7 @@
68 This is a single object which contains the latitude, longitude and time
69 zone of the location.
70 """
71+
72 def __init__(self, latitude, longitude, time_zone):
73 self.latitude = latitude
74 self.longitude = longitude
75@@ -59,13 +60,16 @@
76 # json-handling, so we flag that in the request so that our
77 # base-layout includes the necessary javascript files.
78 request.needs_json = True
79- request.needs_gmap2 = True
80 super(LocationWidget, self).__init__(context, request)
81 fields = form.Fields(
82 Float(__name__='latitude', title=_('Latitude'), required=False),
83 Float(__name__='longitude', title=_('Longitude'), required=False),
84- Choice(__name__='time_zone', vocabulary='TimezoneName',
85- title=_('Time zone'), required=True))
86+ Choice(
87+ __name__='time_zone', vocabulary='TimezoneName',
88+ title=_('Time zone'), required=True,
89+ description=_(
90+ 'Once the time zone is correctly set, events '
91+ 'in Launchpad will be displayed in local time.')))
92 # This will be the initial zoom level and center of the map.
93 self.zoom = 2
94 self.center_lat = 15.0
95
96=== modified file 'lib/canonical/widgets/templates/location.pt'
97--- lib/canonical/widgets/templates/location.pt 2009-07-17 17:59:07 +0000
98+++ lib/canonical/widgets/templates/location.pt 2010-09-21 16:51:00 +0000
99@@ -2,32 +2,11 @@
100 xmlns:tal="http://xml.zope.org/namespaces/tal"
101 xmlns:i18n="http://xml.zope.org/namespaces/i18n"
102 omit-tag="">
103-<tal:latitude replace="structure view/latitude_widget/hidden" />
104-<tal:longitude replace="structure view/longitude_widget/hidden" />
105-<p class="formHelp">
106- You can drag the marker to change the location, and zoom into the map to
107- see more details and verify the location's accuracy.
108- If your mouse has a scroll wheel, use it to more quickly zoom the
109- map in and out. Double-clicking will also zoom in and move the
110- marker. Please <strong>do not disclose sensitive information such
111- as a specific home location</strong> without the permission of
112- the person involved - rather just indicate a city so that the time
113- zone is correct.
114-</p>
115-<p id="map_div" style="width: 100%; height: 300px; border: 1px; float: left;"
116- ></p>
117-
118-<tal:render-map replace="structure view/map_javascript" />
119-
120-<p>
121- <label>Time zone:
122- <img id="tz_spinner" src="/@@/nospin" width="14" height="14" />
123- </label>
124- <tal:latitude replace="structure view/time_zone_widget" />
125-</p>
126-
127-<p class="formHelp">
128- Once the time zone is correctly set, events in Launchpad will be
129- displayed in local time.
130-</p>
131+ <tal:latitude replace="structure view/latitude_widget/hidden" />
132+ <tal:longitude replace="structure view/longitude_widget/hidden" />
133+ <div>
134+ <tal:time-zone replace="structure view/time_zone_widget" />
135+ </div>
136+ <div class="formHelp"
137+ tal:content="view/time_zone_widget/hint" />
138 </tal:root>
139
140=== removed file 'lib/lp/app/javascript/mapping.js'
141--- lib/lp/app/javascript/mapping.js 2010-07-15 10:55:27 +0000
142+++ lib/lp/app/javascript/mapping.js 1970-01-01 00:00:00 +0000
143@@ -1,365 +0,0 @@
144-/**
145- * Launchpad mapping tools.
146- *
147- * Map rendering and marker creation depends on the Google GMap2 library.
148- *
149- * @module lp.app.mapping
150- * @namespace lp.app.mapping
151- * @required Google GMap2
152- */
153-YUI.add('lp.app.mapping', function(Y) {
154- var module = Y.namespace('lp.app.mapping');
155-
156- module.RETURN_FALSE = function() {return false;};
157- module.RETURN_NULL = function() {return null;};
158-
159- // Replace the crucial GMap functions so that the supporting functions
160- // will work if the GMap script is not loaded.
161- var gBrowserIsCompatible = module.RETURN_FALSE;
162- var gDownloadUrl = module.RETURN_NULL;
163-
164- module.has_gmaps = (typeof(GBrowserIsCompatible) == 'function');
165-
166- if (module.has_gmaps) {
167- // The GMap2 is is loaded; use the real functions.
168- // jslint does not like functions that look like classes.
169- gBrowserIsCompatible = GBrowserIsCompatible;
170- gDownloadUrl = GDownloadUrl;
171- }
172-
173-
174- /**
175- * Add a marker for each participant.
176- *
177- * @function setMarkersInfoWindow
178- * @param {String} data the participant XML.
179- * @param {GMap2} map the Google map to add the markers to.
180- * @param {GLatLngBounds} required_bounds the boundaries or null.
181- * @param {limit} optional max number of markers to set.
182- */
183- module.setMarkersInfoWindow = function(data, map, required_bounds,
184- limit) {
185- var xml = GXml.parse(data);
186- var markers = xml.documentElement.getElementsByTagName("participant");
187- var participant = null;
188-
189- function attrToProp(attr) {
190- participant[attr.name] = attr.value;
191- }
192-
193- limit = typeof(limit) == 'number' ? limit : markers.length;
194- if (markers.length < limit) {
195- limit = markers.length;
196- }
197-
198- for (var i = 0; i < limit; i++) {
199- participant = {};
200- Y.Array.each(markers[i].attributes, attrToProp);
201- var point = new GLatLng(
202- parseFloat(participant.lat), parseFloat(participant.lng));
203- if (required_bounds) {
204- required_bounds.extend(point);
205- }
206- var marker = new GMarker(point);
207- marker.bindInfoWindowHtml(Y.substitute([
208- '<div style="text-align: center">',
209- '<a href="{url}">{displayname} ({name})</a><br />',
210- '{logo_html}<br />',
211- 'Local time: {local_time}</div>'].join(""),
212- participant));
213- map.addOverlay(marker);
214- }
215- };
216-
217- /**
218- * Add a marker for each participant, and update the zoom level.
219- *
220- * @function setMarkersInfoWindowForSmallMap
221- * @param {String} data the participant XML.
222- * @param {GMap2} map the Google map to add the markers to.
223- * @param {limit} optional max number of markers to set.
224- */
225- module.setMarkersInfoWindowForSmallMap = function(data, map, limit) {
226- var required_bounds = new GLatLngBounds();
227- module.setMarkersInfoWindow(data, map, required_bounds, limit);
228- var zoom_level = map.getBoundsZoomLevel(required_bounds);
229- // Some browsers do not display the map when the zoom_level is at the
230- // end of the range, reduce the zoom_level by 1.
231- zoom_level = Math.min(4, zoom_level - 1);
232- map.setZoom(zoom_level);
233- };
234-
235- /**
236- * Set the timezone field to the lat-log location.
237- *
238- * @function setLocation
239- * @param {Number} lat a GLatLng.lat bounded number.
240- * @param {Number} lng a GLatLng.lng bounded number.
241- * @parma {String} geoname the user-name to make geonames requests.
242- * @param {String} tz_name the id of the timezone field.
243- * @param {String} lat_name the id of the latitude field.
244- * @param {String} lng_name the id of the longitude field.
245- */
246- module.setLocation = function(lat, lng, geoname,
247- tz_name, lat_name, lng_name) {
248- Y.one(Y.DOM.byId(lat_name)).set('value', lat);
249- Y.one(Y.DOM.byId(lng_name)).set('value', lng);
250- var spinner = Y.one('#tz_spinner');
251- spinner.set('src', '/@@/spinner');
252-
253- function succeeded() {
254- if (request.readyState == 4) {
255- if (request.responseText) {
256- var tz = request.responseJSON.timezoneId;
257- Y.one(Y.DOM.byId(tz_name)).set('value', tz);
258- spinner.set('src', '/@@/nospin');
259- }
260- }
261- }
262-
263- var url = 'http://ba-ws.geonames.net/timezoneJSON' +
264- '?username=' + geoname + '&lat=' + lat + '&lng=' + lng;
265- // This is a cross-site script request.
266- var request = new JSONScriptRequest();
267- request.open("GET", url);
268- request.onreadystatechange = succeeded;
269- request.send(null);
270- };
271-
272- /**
273- * Show/hide all small maps in pages.
274- *
275- * The state is stored as ``small_maps`` in the launchpad_views cookie.
276- *
277- * @function toggleShowSmallMaps
278- * @param {Event} e the event for this callback.
279- */
280- module.toggleShowSmallMaps = function (checkbox) {
281- var is_shown = checkbox.get('checked');
282- Y.lp.launchpad_views.set('small_maps', is_shown);
283- var display = is_shown ? 'block' : 'none';
284- var maps = Y.all('.small-map');
285- maps.each(function(map) {map.setStyle('display', display);});
286- if (is_shown && !module.has_gmaps) {
287- // The server must add the Google GMap2 dependencies to the page.
288- window.location.reload();
289- }
290- };
291-
292- /**
293- * Add a checkbox to show/hide all small maps in pages.
294- *
295- * @function setupShowSmallMapsControl
296- * @param {String} div_id the CSS3 id of the div that controls the map.
297- */
298- module.setupShowSmallMapsControl = function (div_id) {
299- var show_small_maps = Y.lp.launchpad_views.get('small_maps');
300- var checkbox = Y.Node.create(
301- '<input type="checkbox" name="show_small_maps" />');
302- checkbox.set(
303- 'checked', show_small_maps);
304- checkbox.on(
305- 'click', function(e) {module.toggleShowSmallMaps(checkbox);});
306- var label_text = Y.Node.create('Display map');
307- var label = Y.Node.create('<label></label>');
308- label.appendChild(checkbox);
309- label.appendChild(label_text);
310- var action_div = Y.one(div_id);
311- action_div.appendChild(label);
312- if (!show_small_maps) {
313- module.toggleShowSmallMaps(checkbox);
314- }
315- };
316-
317- /**
318- * Create a small map with the launchpad default configuration.
319- *
320- * @function getSmallMap
321- * @param {String} div_id the id of the map div.
322- * @param {Number} center_lat a GLatLng.lat bounded number.
323- * @param {Number} center_lng a GLatLng.lng bounded number.
324- * @return {GMap2} the Google map
325- */
326- module.getSmallMap = function(div_id, center_lat, center_lng) {
327- var mapdiv = Y.DOM.byId(div_id);
328- mapdiv.style.width = '400px';
329- var map = new GMap2(mapdiv);
330- var center = new GLatLng(center_lat, center_lng);
331- map.setCenter(center, 1);
332- map.setMapType(G_NORMAL_MAP);
333- return map;
334- };
335-
336- /**
337- * Create a small map of where a person is located.
338- *
339- * @function renderPersonMapSmall
340- * @param {Number} center_lat a GLatLng.lat bounded number.
341- * @param {Number} center_lng a GLatLng.lng bounded number.
342- */
343- module.renderPersonMapSmall = function(center_lat, center_lng) {
344- module.setupShowSmallMapsControl('#person_map_actions');
345- if (!gBrowserIsCompatible()) {
346- return;
347- }
348- var map = module.getSmallMap(
349- 'person_map_div', center_lat, center_lng);
350- map.addControl(new GSmallZoomControl());
351- var center = new GLatLng(center_lat, center_lng);
352- var marker = new GMarker(center);
353- map.addOverlay(marker);
354- };
355-
356- /**
357- * Create a small map of where a team's members are located. The map is
358- * limited to 24 members.
359- *
360- * @function renderTeamMapSmall
361- * @param {Number} center_lat a GLatLng.lat bounded number.
362- * @param {Number} center_lng a GLatLng.lng bounded number.
363- */
364- module.renderTeamMapSmall = function(center_lat, center_lng) {
365- module.setupShowSmallMapsControl('#team_map_actions');
366- if (!gBrowserIsCompatible()) {
367- return;
368- }
369- var team_map = module.getSmallMap(
370- 'team_map_div', center_lat, center_lng);
371- gDownloadUrl("+mapdataltd", function(data) {
372- module.setMarkersInfoWindowForSmallMap(data, team_map);
373- });
374- };
375-
376- /**
377- * Create a large map with the launchpad default configuration.
378- *
379- * @function getLargeMap
380- * @param {String} div_id the id of the map div.
381- * @return {GMap2} The Google map
382- */
383- module.getLargeMap = function(div_id) {
384- var mapdiv = Y.DOM.byId(div_id);
385- var mapheight = (parseInt(mapdiv.offsetWidth, 10) / 16 * 9);
386- mapheight = Math.min(mapheight, Y.DOM.winHeight() - 180);
387- mapheight = Math.max(mapheight, 400);
388- mapdiv.style.height = mapheight + 'px';
389- var map = new GMap2(mapdiv);
390- map.setMapType(G_HYBRID_MAP);
391- map.addControl(new GLargeMapControl());
392- map.addControl(new GMapTypeControl());
393- map.addControl(new GScaleControl());
394- map.enableScrollWheelZoom();
395- var overview_control = new GOverviewMapControl();
396- map.addControl(overview_control);
397- GEvent.addListener(map, 'zoomend', function(old, current) {
398- try {
399- if (current < 3) {
400- overview_control.hide();
401- } else {
402- overview_control.show();
403- }
404- } catch(e) {
405- // Google removed this undocumented method.
406- }
407- });
408- return map;
409- };
410-
411- /**
412- * Create a large map of where a team's members are located.
413- *
414- * @function renderTeamMap
415- * @param {Number} min_lat the minimum GLatLng.lat bounded number.
416- * @param {Number} max_lat the maximum GLatLng.lat bounded number.
417- * @param {Number} min_lng the minimum GLatLng.lng bounded number.
418- * @param {Number} max_lng the maximum GLatLng.lng bounded number.
419- * @param {Number} center_lat a GLatLng.lat bounded number.
420- * @param {Number} center_lng a GLatLng.lng bounded number.
421- */
422- module.renderTeamMap = function(min_lat, max_lat, min_lng, max_lng,
423- center_lat, center_lng) {
424- if (!gBrowserIsCompatible()) {
425- return;
426- }
427- var team_map = module.getLargeMap("team_map_div");
428- var center = new GLatLng(center_lat, center_lng);
429- team_map.setCenter(center, 0);
430- var sw = new GLatLng(min_lat, min_lng);
431- var ne = new GLatLng(max_lat, max_lng);
432- var required_bounds = new GLatLngBounds(sw, ne);
433- var zoom_level = team_map.getBoundsZoomLevel(required_bounds);
434- // Some browsers do not display the map when the zoom_level is at
435- // the end of the range, reduce the zoom_level by 1.
436- zoom_level = Math.min(
437- G_HYBRID_MAP.getMaximumResolution(), zoom_level - 1);
438- team_map.setZoom(zoom_level);
439- gDownloadUrl("+mapdata", function(data) {
440- module.setMarkersInfoWindow(data, team_map);
441- });
442- };
443-
444- /**
445- * Create a large, markable map of where a person is located.
446- *
447- * @function renderPersonMap
448- * @param {Number} center_lat a GLatLng.lat bounded number.
449- * @param {Number} center_lng a GLatLng.lng bounded number.
450- * @param {String} displayname the user's display name.
451- * @param {String} name the user's launchpad id.
452- * @param {String} logo_html the markup to display the user's logo.
453- * @param {String} geoname the identity used to access ba-ws.geonames.net.
454- * @param {String} tz_name the id of the timezone field.
455- * @param {String} lat_name the id of the latitude field.
456- * @param {String} lng_name the id of the longitude field.
457- * @param {number} zoom the initial zoom-level.
458- * @param {Boolean} show_marker Show the marker for the person.
459- */
460- module.renderPersonMap = function(center_lat, center_lng, displayname,
461- name, logo_html, geoname, lat_name,
462- lng_name, tz_name, zoom, show_marker) {
463- if (!gBrowserIsCompatible()) {
464- return;
465- }
466- var map = module.getLargeMap('map_div');
467- var center = new GLatLng(center_lat, center_lng);
468- map.setCenter(center, zoom);
469- var marker = new GMarker(center, {draggable: true});
470- marker.bindInfoWindowHtml(Y.substitute(
471- '<div style="text-align: center">' +
472- '<strong>{displayname}</strong><br />' +
473- '{logo_html}<br />({name})</div>',
474- {displayname: displayname, logo_html: logo_html, name: name}),
475- {maxWidth: 120});
476-
477- GEvent.addListener(marker, "dragend", function() {
478- var point = marker.getLatLng();
479- module.setLocation(
480- point.lat(), point.lng(), geoname,
481- tz_name, lat_name, lng_name);
482- });
483-
484- GEvent.addListener(marker, "dragstart", function() {
485- marker.closeInfoWindow();
486- });
487-
488- map.addOverlay(marker);
489- if (!show_marker) {
490- marker.hide();
491- }
492-
493- GEvent.addListener(map, "zoomend", function() {
494- marker.closeInfoWindow();
495- });
496-
497- GEvent.addListener(map, "click", function(overlay, point) {
498- marker.setPoint(point);
499- if (marker.isHidden()) {
500- marker.show();
501- map.panTo(point);
502- }
503- module.setLocation(
504- point.lat(), point.lng(), geoname,
505- tz_name, lat_name, lng_name);
506- });
507- };
508-}, "0.1", {"requires":["node", "dom", "substitute", "lp"]});
509
510=== modified file 'lib/lp/app/templates/base-layout-macros.pt'
511--- lib/lp/app/templates/base-layout-macros.pt 2010-08-20 13:33:51 +0000
512+++ lib/lp/app/templates/base-layout-macros.pt 2010-09-21 16:51:00 +0000
513@@ -179,8 +179,6 @@
514 <script type="text/javascript"
515 tal:attributes="src string:${lp_js}/app/picker.js"></script>
516 <script type="text/javascript"
517- tal:attributes="src string:${lp_js}/app/mapping.js"></script>
518- <script type="text/javascript"
519 tal:attributes="src string:${lp_js}/bugs/bugtracker_overlay.js"></script>
520 <script type="text/javascript"
521 tal:attributes="src string:${lp_js}/registry/milestoneoverlay.js"></script>
522@@ -287,14 +285,6 @@
523 <script type="text/javascript"
524 tal:attributes="src string:${icingroot_contrib}/JSONScriptRequest.js"></script>
525 </tal:needs_json>
526- <tal:needs-gmap2 condition="request/needs_gmap2">
527- <script type="text/javascript"
528- tal:condition="devmode"
529- tal:attributes="src string:http://maps.google.com/maps?${map_query};"></script>
530- <script type="text/javascript"
531- tal:condition="not: devmode"
532- tal:attributes="src string:https://maps-api-ssl.google.com/maps?oe=utf-8&amp;client=gme-canonical${map_query};"></script>
533- </tal:needs-gmap2>
534
535 <metal:load-lavascript use-macro="context/@@+base-layout-macros/load-javascript" />
536
537
538=== modified file 'lib/lp/registry/browser/__init__.py'
539--- lib/lp/registry/browser/__init__.py 2010-09-03 15:02:39 +0000
540+++ lib/lp/registry/browser/__init__.py 2010-09-21 16:51:00 +0000
541@@ -7,7 +7,6 @@
542
543 __all__ = [
544 'get_status_counts',
545- 'MapMixin',
546 'MilestoneOverlayMixin',
547 'RegistryEditFormView',
548 'RegistryDeleteViewMixin',
549@@ -32,7 +31,6 @@
550 )
551 from lp.registry.interfaces.productseries import IProductSeries
552 from lp.registry.interfaces.series import SeriesStatus
553-from lp.services.propertycache import cachedproperty
554
555
556 class StatusCount:
557@@ -258,19 +256,3 @@
558 @action("Change", name='change')
559 def change_action(self, action, data):
560 self.updateContextFromData(data)
561-
562-
563-class MapMixin:
564-
565- @cachedproperty
566- def gmap2_enabled(self):
567- # XXX sinzui 2010-08-27 bug=625556: This is a hack to use
568- # feature flags, which are not ready for general use in the production
569- # code, but has just enough to support this use case:
570- # Do not enable gmap2 if Google's service is not operational.
571- from lp.services.features.flags import FeatureController
572-
573- def in_scope(value):
574- return True
575-
576- return FeatureController(in_scope).getFlag('gmap2') == 'on'
577
578=== modified file 'lib/lp/registry/browser/configure.zcml'
579--- lib/lp/registry/browser/configure.zcml 2010-08-31 10:00:44 +0000
580+++ lib/lp/registry/browser/configure.zcml 2010-09-21 16:51:00 +0000
581@@ -818,7 +818,7 @@
582 for="lp.registry.interfaces.person.IPerson"
583 class="lp.registry.browser.person.PersonEditLocationView"
584 permission="launchpad.Edit"
585- template="../templates/person-editlocation.pt"/>
586+ template="../../app/templates/generic-edit.pt"/>
587 <browser:page
588 name="+contactuser"
589 for="lp.registry.interfaces.person.IPerson"
590@@ -1069,11 +1069,6 @@
591 <browser:page
592 for="lp.registry.interfaces.person.ITeam"
593 permission="zope.Public"
594- class="lp.registry.browser.person.TeamEditLocationView"
595- name="+editlocation"/>
596- <browser:page
597- for="lp.registry.interfaces.person.ITeam"
598- permission="zope.Public"
599 name="+listing-simple"
600 template="../templates/team-listing-simple.pt"/>
601 <browser:page
602
603=== modified file 'lib/lp/registry/browser/person.py'
604--- lib/lp/registry/browser/person.py 2010-09-19 00:35:22 +0000
605+++ lib/lp/registry/browser/person.py 2010-09-21 16:51:00 +0000
606@@ -65,7 +65,6 @@
607 'SearchSubscribedQuestionsView',
608 'TeamAddMyTeamsView',
609 'TeamBreadcrumb',
610- 'TeamEditLocationView',
611 'TeamEditMenu',
612 'TeamIndexMenu',
613 'TeamJoinView',
614@@ -148,7 +147,6 @@
615 helpers,
616 )
617 from canonical.launchpad.browser.feeds import FeedsMixin
618-from canonical.launchpad.browser.launchpad import get_launchpad_views
619 from canonical.launchpad.interfaces.account import (
620 AccountStatus,
621 IAccount,
622@@ -244,7 +242,6 @@
623 from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin
624 from lp.code.errors import InvalidNamespace
625 from lp.code.interfaces.branchnamespace import IBranchNamespaceSet
626-from lp.registry.browser import MapMixin
627 from lp.registry.browser.branding import BrandingChangeView
628 from lp.registry.browser.mailinglists import enabled_with_active_mailing_list
629 from lp.registry.browser.menu import (
630@@ -3325,7 +3322,7 @@
631 return self.state is EmailAddressVisibleState.ALLOWED
632
633
634-class PersonIndexView(XRDSContentNegotiationMixin, MapMixin, PersonView):
635+class PersonIndexView(XRDSContentNegotiationMixin, PersonView):
636 """View class for person +index and +xrds pages."""
637
638 xrds_template = ViewPageTemplateFile(
639@@ -3333,14 +3330,6 @@
640
641 def initialize(self):
642 super(PersonIndexView, self).initialize()
643- # This view requires the gmap2 Javascript in order to render the map
644- # with the person's usual location. The location is only availble if
645- # the location is set, visible, and the viewing user wants to see it.
646- launchpad_views = get_launchpad_views(self.request.cookies)
647- self._small_map = launchpad_views['small_maps']
648- if (self.gmap2_enabled
649- and self.has_visible_location and self._small_map):
650- self.request.needs_gmap2 = True
651 if self.request.method == "POST":
652 self.processForm()
653
654@@ -3397,9 +3386,6 @@
655 assert self.has_visible_location, (
656 "Can't generate the map for a person who hasn't set a "
657 "visible location.")
658- assert self.request.needs_gmap2 or not self._small_map, (
659- "To use this method a view must flag that it needs gmap2.")
660-
661 replacements = {'center_lat': self.context.latitude,
662 'center_lng': self.context.longitude}
663 return u"""
664@@ -5638,7 +5624,7 @@
665 class PersonLocationForm(Interface):
666
667 location = LocationField(
668- title=_('Use the map to indicate default location'),
669+ title=_('Time zone'),
670 required=True)
671 hide = Bool(
672 title=_("Hide my location details from others."),
673@@ -5649,37 +5635,15 @@
674 """Edit a person's location."""
675
676 schema = PersonLocationForm
677- field_names = ['location', 'hide']
678+ field_names = ['location']
679 custom_widget('location', LocationWidget)
680-
681- @property
682- def page_title(self):
683- return smartquote(
684- "%s's location and timezone" % self.context.displayname)
685-
686- label = page_title
687-
688- @property
689- def initial_values(self):
690- """See `LaunchpadFormView`.
691-
692- Set the initial value for the 'hide' field. The initial value for the
693- 'location' field is set by its widget.
694- """
695- if self.context.location is None:
696- return {}
697- else:
698- return {'hide': not self.context.location.visible}
699-
700- def initialize(self):
701- self.next_url = canonical_url(self.context)
702- self.for_team_name = self.request.form.get('for_team')
703- if self.for_team_name is not None:
704- for_team = getUtility(IPersonSet).getByName(self.for_team_name)
705- if for_team is not None:
706- self.next_url = canonical_url(for_team) + '/+map'
707- super(PersonEditLocationView, self).initialize()
708- self.cancel_url = self.next_url
709+ page_title = label = 'Set timezone'
710+
711+ @property
712+ def next_url(self):
713+ return canonical_url(self.context)
714+
715+ cancel_url = next_url
716
717 @action(_("Update"), name="update")
718 def action_update(self, action, data):
719@@ -5696,17 +5660,6 @@
720 self.context.setLocationVisibility(visible)
721
722
723-class TeamEditLocationView(LaunchpadView):
724- """Redirect to the team's +map page.
725-
726- We do that because it doesn't make sense to specify the location of a
727- team."""
728-
729- def initialize(self):
730- self.request.response.redirect(
731- canonical_url(self.context, view_name="+map"))
732-
733-
734 def archive_to_person(archive):
735 """Adapts an `IArchive` to an `IPerson`."""
736 return IPerson(archive.owner)
737
738=== modified file 'lib/lp/registry/browser/team.py'
739--- lib/lp/registry/browser/team.py 2010-09-19 03:13:01 +0000
740+++ lib/lp/registry/browser/team.py 2010-09-21 16:51:00 +0000
741@@ -25,10 +25,7 @@
742
743 from datetime import datetime
744 import math
745-from urllib import (
746- quote,
747- unquote,
748- )
749+from urllib import unquote
750
751 import pytz
752 from zope.app.form.browser import TextAreaWidget
753@@ -71,7 +68,6 @@
754 LaunchpadRadioWidget,
755 )
756 from lp.app.errors import UnexpectedFormData
757-from lp.registry.browser import MapMixin
758 from lp.registry.browser.branding import BrandingChangeView
759 from lp.registry.interfaces.mailinglist import (
760 IMailingList,
761@@ -1083,7 +1079,7 @@
762 self.request.response.addInfoNotification(msg)
763
764
765-class TeamMapView(MapMixin, LaunchpadView):
766+class TeamMapView(LaunchpadView):
767 """Show all people with known locations on a map.
768
769 Also provides links to edit the locations of people in the team without
770@@ -1093,12 +1089,6 @@
771 label = "Team member locations"
772 limit = None
773
774- def initialize(self):
775- # Tell our base-layout to include Google's gmap2 javascript so that
776- # we can render the map.
777- if self.gmap2_enabled and self.mapped_participants_count > 0:
778- self.request.needs_gmap2 = True
779-
780 @cachedproperty
781 def mapped_participants(self):
782 """Participants with locations."""
783
784=== modified file 'lib/lp/registry/browser/tests/person-views.txt'
785--- lib/lp/registry/browser/tests/person-views.txt 2010-08-28 23:01:18 +0000
786+++ lib/lp/registry/browser/tests/person-views.txt 2010-09-21 16:51:00 +0000
787@@ -301,113 +301,6 @@
788 Portuguese (Brazil)
789
790
791-Location
792---------
793-
794-The Person profile page contains the location portlet that shows a map.
795-The map requires the google GMap JavaScript to display, so the views set
796-the state of the request's needs_gmap2 attribute to True only when the
797-user has set his latitude, it is visible, and the viewing user wishes to
798-see it. The map is not rendered if the user has not set his location.
799-
800- >>> sample_person.latitude is None
801- True
802-
803- >>> person_view = create_initialized_view(sample_person, '+index')
804- >>> person_view.request.needs_gmap2
805- False
806-
807-The map_portlet_html property that creates the map cannot be called.
808-
809- >>> print person_view.map_portlet_html
810- Traceback (most recent call last):
811- ...
812- AssertionError: Can't generate the map for a person who hasn't set
813- a visible location.
814-
815-If the user sets his location, but does not make it visible, needs_gmap2
816-will still be False and the map_portlet_html property cannot be called.
817-
818- >>> login_person(sample_person)
819- >>> sample_person.setLocation(
820- ... 38.81, 77.1, 'America/New_York', sample_person)
821- >>> sample_person.setLocationVisibility(False)
822- >>> login('no-priv@canonical.com')
823-
824- >>> person_view = create_initialized_view(sample_person, '+index')
825- >>> person_view.request.needs_gmap2
826- False
827-
828- >>> print person_view.map_portlet_html
829- Traceback (most recent call last):
830- ...
831- AssertionError: Can't generate the map for a person who hasn't set
832- a visible location.
833-
834-When the user set's his visibility to True, needs_gmap2 will be true and
835-the map_portlet_html can be called.
836-
837- >>> from lp.services.features.model import FeatureFlag, getFeatureStore
838- >>> ignore = getFeatureStore().add(FeatureFlag(
839- ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
840- >>> transaction.commit()
841-
842- >>> login_person(sample_person)
843- >>> sample_person.setLocationVisibility(True)
844-
845- >>> person_view = create_initialized_view(sample_person, '+index')
846- >>> person_view.request.needs_gmap2
847- True
848-
849- >>> print person_view.map_portlet_html
850- <script type="text/javascript">
851- YUI().use('node', 'lp.app.mapping', function(Y) { ...
852-
853-The small_maps key in the launchpad_views cookie can be set of the
854-viewing user to 'false' to indicate that small maps are not wanted.
855-While needs_gmap2 is False, the map_portlet_html property's markup is
856-still needed to render the 'Show maps' checkbox.
857-
858- >>> cookie = 'launchpad_views=small_maps=false'
859- >>> person_view = create_initialized_view(
860- ... sample_person, '+index', cookie=cookie)
861- >>> person_view.request.needs_gmap2
862- False
863-
864- >>> print person_view.map_portlet_html
865- <script type="text/javascript">
866- YUI().use('node', 'lp.app.mapping', function(Y) { ...
867-
868-The map portlet is shown if the user has not set his location and is
869-viewing his own page.
870-
871- >>> user = factory.makePerson()
872- >>> user.latitude is None
873- True
874-
875- >>> login_person(user)
876- >>> person_view = create_initialized_view(
877- ... user, '+index')
878- >>> person_view.should_show_map_portlet
879- True
880-
881-However another user will not be shown the portlet.
882-
883- >>> login('foo.bar@canonical.com')
884- >>> person_view = create_initialized_view(
885- ... user, '+index')
886- >>> person_view.should_show_map_portlet
887- False
888-
889-If a user has a location set and it is visibible then the portlet is
890-shown.
891-
892- >>> person_view = create_initialized_view(
893- ... sample_person, '+index')
894- >>> person_view.should_show_map_portlet
895- True
896-
897-
898 Things a person is working on
899 -----------------------------
900
901
902=== modified file 'lib/lp/registry/browser/tests/team-views.txt'
903--- lib/lp/registry/browser/tests/team-views.txt 2010-08-28 23:01:18 +0000
904+++ lib/lp/registry/browser/tests/team-views.txt 2010-09-21 16:51:00 +0000
905@@ -67,21 +67,11 @@
906
907 == +map-portlet ==
908
909-The team profile page contain the location portlet that shows a map. The
910-map requires the google GMap JavaScript to display, so the views set the
911-state of the request's needs_gmap2 attribute to true if there are
912-members who have set their location.
913-
914- >>> from lp.services.features.model import FeatureFlag, getFeatureStore
915- >>> ignore = getFeatureStore().add(FeatureFlag(
916- ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
917- >>> transaction.commit()
918+The team profile page contain the location portlet that shows a map.
919
920 >>> team_view = create_initialized_view(ubuntu_team, '+index')
921 >>> team_view.has_visible_location
922 False
923- >>> team_view.request.needs_gmap2
924- False
925
926 After a member has set his location, the map will be rendered.
927
928@@ -92,8 +82,6 @@
929 >>> team_view = create_initialized_view(ubuntu_team, '+index')
930 >>> team_view.has_visible_location
931 True
932- >>> team_view.request.needs_gmap2
933- True
934
935 The small_maps key in the launchpad_views cookie can be set by the viewing
936 user to 'false' to indicate that small maps are not wanted.
937@@ -101,9 +89,6 @@
938 >>> cookie = 'launchpad_views=small_maps=false'
939 >>> team_view = create_initialized_view(
940 ... ubuntu_team, '+index', cookie=cookie)
941- >>> team_view.request.needs_gmap2
942- False
943-
944
945 == +map ==
946
947@@ -118,15 +103,10 @@
948 >>> view.times
949 []
950
951-There are no mapped member yet, so needs_gmap2 is False, so the map will
952-not be rendered.
953-
954- >>> view.request.needs_gmap2
955- False
956-
957-Once a member is mapped, needs_gmap2 is True and the map will be rendered.
958-The view provides a cached property to access the mapped participants. The
959-views number of times is incremented for each timezone the members reside in.
960+
961+Once a member is mapped, the map will be rendered. The view provides a cached
962+property to access the mapped participants. The views number of times is
963+incremented for each timezone the members reside in.
964
965 >>> london_member = factory.makePerson(
966 ... latitude=51.49, longitude=-0.13, time_zone='Europe/London')
967@@ -139,9 +119,6 @@
968 >>> len(view.times)
969 1
970
971- >>> view.request.needs_gmap2
972- True
973-
974 >>> brazil_member = factory.makePerson(
975 ... latitude=-23.60, longitude=-46.64, time_zone='America/Sao_Paulo')
976 >>> ignored = context.addMember(brazil_member, mark)
977
978=== modified file 'lib/lp/registry/doc/personlocation.txt'
979--- lib/lp/registry/doc/personlocation.txt 2010-08-20 12:25:28 +0000
980+++ lib/lp/registry/doc/personlocation.txt 2010-09-21 16:51:00 +0000
981@@ -1,4 +1,5 @@
982-= Locations for People and Teams =
983+Locations for People and Teams
984+==============================
985
986 The PersonLocation object stores information about the location and time
987 zone of a person. It also remembers who provided that information, and
988@@ -164,7 +165,8 @@
989 mapped_participants_count == 0.
990
991
992-== Location visibility ==
993+Location visibility
994+-------------------
995
996 Some people may not want their location to be disclosed to others, so
997 we provide a way for them to hide their location from other users. By
998
999=== modified file 'lib/lp/registry/stories/location/personlocation-edit.txt'
1000--- lib/lp/registry/stories/location/personlocation-edit.txt 2009-11-15 01:05:49 +0000
1001+++ lib/lp/registry/stories/location/personlocation-edit.txt 2010-09-21 16:51:00 +0000
1002@@ -1,4 +1,5 @@
1003-== Edit person location information ==
1004+Edit person location information
1005+================================
1006
1007 A person's location is only editable by people who have launchpad.Edit on
1008 the person, which is that person and admins.
1009@@ -49,35 +50,3 @@
1010 >>> admin_browser.open('http://launchpad.dev/~zzz/+editlocation')
1011 >>> admin_browser.getControl(name='field.location.latitude').value
1012 '39.48'
1013-
1014-The +editlocation page also allows a person to change his location
1015-visibility, that is, whether or not others can see it.
1016-
1017- >>> nopriv_browser.open('http://launchpad.dev/~no-priv/+editlocation')
1018- >>> nopriv_browser.getControl(
1019- ... 'Hide my location details from others.').selected = True
1020- >>> nopriv_browser.getControl('Update').click()
1021- >>> nopriv_browser.url
1022- 'http://launchpad.dev/~no-priv'
1023-
1024-Once hidden, other users can't see it.
1025-
1026- >>> name12_browser = setupBrowser(auth="Basic test@canonical.com:test")
1027- >>> name12_browser.open('http://launchpad.dev/~no-priv')
1028- >>> print str(find_tag_by_id(name12_browser.contents, 'person_map_div'))
1029- None
1030-
1031-The person himself can still see and change it, though.
1032-
1033- >>> nopriv_browser.open('http://launchpad.dev/~no-priv')
1034- >>> print str(find_tag_by_id(nopriv_browser.contents, 'portlet-map'))
1035- <div...
1036- <h2>Location</h2>
1037- ...
1038-
1039- >>> nopriv_browser.open('http://launchpad.dev/~no-priv/+editlocation')
1040- >>> nopriv_browser.getControl(
1041- ... 'Hide my location details from others.').selected = False
1042- >>> nopriv_browser.getControl('Update').click()
1043- >>> nopriv_browser.url
1044- 'http://launchpad.dev/~no-priv'
1045
1046=== modified file 'lib/lp/registry/stories/location/personlocation.txt'
1047--- lib/lp/registry/stories/location/personlocation.txt 2010-08-27 22:42:17 +0000
1048+++ lib/lp/registry/stories/location/personlocation.txt 2010-09-21 16:51:00 +0000
1049@@ -16,43 +16,3 @@
1050 >>> anon_browser.open('http://launchpad.dev/~zzz')
1051 >>> print extract_text(
1052 ... find_tag_by_id(anon_browser.contents, 'portlet-map'))
1053-
1054-If a person has a location, but the gmap2 feature is not enabled, the user
1055-sees the timezone, but no map.
1056-
1057- >>> login('test@canonical.com')
1058- >>> yyy = factory.makePerson(name='yyy', time_zone='Europe/London',
1059- ... latitude=52.2, longitude=0.3)
1060- >>> logout()
1061-
1062- >>> anon_browser.open('http://launchpad.dev/~yyy')
1063- >>> markup = str(anon_browser.contents)
1064- >>> print extract_text(
1065- ... find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
1066- Location
1067- Time zone: Europe/London...
1068-
1069- >>> 'src="http://maps.google.com/maps' in markup
1070- False
1071-
1072-If a person has a location, there is a little map portlet in their
1073-profile page. We can't test all the google javascript, but we can make sure
1074-there's a map, and the scripts are loaded when the gmap2 feature is enabled
1075-for users.
1076-
1077- >>> from lp.services.features.model import FeatureFlag, getFeatureStore
1078- >>> ignore = getFeatureStore().add(FeatureFlag(
1079- ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
1080- >>> transaction.commit()
1081-
1082- >>> anon_browser.open('http://launchpad.dev/~yyy')
1083- >>> markup = str(anon_browser.contents)
1084- >>> print extract_text(
1085- ... find_tag_by_id(markup, 'portlet-map'), skip_tags=[])
1086- Location
1087- Time zone: Europe/London...
1088- Y.lp.app.mapping.renderPersonMapSmall(...
1089- >>> 'src="http://maps.google.com/maps' in markup
1090- True
1091- >>> 'build/app/mapping.js' in markup
1092- True
1093
1094=== modified file 'lib/lp/registry/stories/location/team-map.txt'
1095--- lib/lp/registry/stories/location/team-map.txt 2010-08-27 22:33:36 +0000
1096+++ lib/lp/registry/stories/location/team-map.txt 2010-09-21 16:51:00 +0000
1097@@ -1,50 +1,6 @@
1098 The map of a team's members
1099 ===========================
1100
1101-Maps are disabled
1102------------------
1103-
1104-Users cannot see maps when the gmap2 feature is disbaled for them
1105-
1106- >>> user_browser.open('http://launchpad.dev/~guadamen')
1107- >>> body = find_main_content(user_browser.contents)
1108- >>> mapdiv = find_tag_by_id(str(body), 'team_map_div')
1109- >>> 'lp.app.mapping.renderTeamMapSmall(' in str(body)
1110- False
1111-
1112-
1113-Maps are enabled
1114-----------------
1115-
1116-Users can see maps when the gmap2 feature is enabled for them.
1117-
1118- >>> from lp.services.features.model import FeatureFlag, getFeatureStore
1119- >>> ignore = getFeatureStore().add(FeatureFlag(
1120- ... scope=u'default', flag=u'gmap2', value=u'on', priority=1))
1121- >>> transaction.commit()
1122-
1123-If a team has members that have locations, then you should see a portlet
1124-with their locations displayed.
1125-
1126- >>> nopriv_browser = setupBrowser(auth='Basic no-priv@canonical.com:test')
1127- >>> nopriv_browser.open('http://launchpad.dev/~guadamen')
1128- >>> body = find_main_content(nopriv_browser.contents)
1129- >>> mapdiv = find_tag_by_id(str(body), 'team_map_div')
1130- >>> 'lp.app.mapping.renderTeamMapSmall(' in str(body)
1131- True
1132- >>> markup = str(nopriv_browser.contents)
1133- >>> 'src="http://maps.google.com/maps' in markup
1134- True
1135- >>> 'build/app/mapping.js' in markup
1136- True
1137-
1138-You should also be able to see a map of the team.
1139-
1140- >>> maplink = nopriv_browser.getLink('View map and time zones')
1141- >>> maplink.click()
1142- >>> nopriv_browser.url
1143- 'http://launchpad.dev/~guadamen/+map'
1144-
1145 The map depends on a stream of XML-formatted data, giving the locations of
1146 all members of the team. We show that this stream works for teams with, and
1147 without, mapped members.
1148@@ -108,15 +64,6 @@
1149 <BLANKLINE>
1150
1151
1152-It doesn't make sense to edit the location of the team itself, not even
1153-if we are an admin, so a team's +editlocation page will simply redirect
1154-to +map.
1155-
1156- >>> admin_browser.open('http://launchpad.dev/~guadamen/+editlocation')
1157- >>> print admin_browser.url
1158- http://launchpad.dev/~guadamen/+map
1159-
1160-
1161 +mapdata
1162 --------
1163
1164
1165=== removed file 'lib/lp/registry/templates/person-editlocation.pt'
1166--- lib/lp/registry/templates/person-editlocation.pt 2009-09-01 19:34:46 +0000
1167+++ lib/lp/registry/templates/person-editlocation.pt 1970-01-01 00:00:00 +0000
1168@@ -1,23 +0,0 @@
1169-<html
1170- xmlns="http://www.w3.org/1999/xhtml"
1171- xmlns:tal="http://xml.zope.org/namespaces/tal"
1172- xmlns:metal="http://xml.zope.org/namespaces/metal"
1173- xmlns:i18n="http://xml.zope.org/namespaces/i18n"
1174- metal:use-macro="view/macro:page/main_only"
1175- i18n:domain="launchpad">
1176-
1177-<body>
1178-
1179- <div metal:fill-slot="main">
1180-
1181- <div metal:use-macro="context/@@launchpad_form/form">
1182- <div metal:fill-slot="extra_info">
1183- <input type="hidden" name="for_team" value=""
1184- tal:attributes="value view/for_team_name" />
1185- </div>
1186- </div>
1187-
1188- </div>
1189-
1190-</body>
1191-</html>
1192
1193=== modified file 'lib/lp/registry/templates/person-portlet-map.pt'
1194--- lib/lp/registry/templates/person-portlet-map.pt 2010-08-27 22:33:36 +0000
1195+++ lib/lp/registry/templates/person-portlet-map.pt 2010-09-21 16:51:00 +0000
1196@@ -8,7 +8,6 @@
1197 tal:define="overview_menu context/menu:overview">
1198
1199 <tal:show-map condition="view/should_show_map_portlet">
1200-
1201 <h2>Location</h2>
1202
1203 <div tal:condition="context/time_zone">
1204@@ -16,30 +15,6 @@
1205 <span tal:replace="context/time_zone">UTC</span>
1206 <a tal:replace="structure overview_menu/editlocation/fmt:icon" />
1207 </div>
1208-
1209-
1210- <tal:gmap2 condition="view/gmap2_enabled">
1211- <div style="width: 400px;" tal:condition="context/latitude">
1212- <div id="person_map_actions"
1213- style="position:relative; z-index: 9999;
1214- float:right; width: 8.5em; margin: 2px;
1215- background-color: white; padding-bottom:1px;"></div>
1216- <div id="person_map_div" class="small-map"
1217- style="height: 200px; border: 1px; margin-top: 4px;"></div>
1218- <tal:mapscript replace="structure view/map_portlet_html" />
1219- <div style="margin-top: 0px;">
1220- <a tal:replace="structure overview_menu/editlocation/fmt:link-icon" />
1221- </div>
1222- </div>
1223- </tal:gmap2>
1224-
1225- <tal:comment condition="nothing">
1226- Only the user can see the editlocation image and link.
1227- </tal:comment>
1228- <a tal:condition="not: context/latitude"
1229- tal:attributes="href overview_menu/editlocation/target"
1230- ><img src="/+icing/portlet-map-unknown.png" />
1231- </a>
1232 </tal:show-map>
1233
1234 </div>
1235
1236=== modified file 'lib/lp/registry/templates/team-index.pt'
1237--- lib/lp/registry/templates/team-index.pt 2010-06-28 21:56:49 +0000
1238+++ lib/lp/registry/templates/team-index.pt 2010-09-21 16:51:00 +0000
1239@@ -88,9 +88,6 @@
1240 <metal:subteam-of use-macro="context/@@+person-macros/subteam-of" />
1241 </div>
1242 </div>
1243-
1244- <div tal:content="structure context/@@+portlet-map" />
1245-
1246 </div>
1247 </body>
1248 </html>
1249
1250=== modified file 'lib/lp/registry/templates/team-portlet-map.pt'
1251--- lib/lp/registry/templates/team-portlet-map.pt 2010-08-27 22:33:36 +0000
1252+++ lib/lp/registry/templates/team-portlet-map.pt 2010-09-21 16:51:00 +0000
1253@@ -5,8 +5,7 @@
1254 omit-tag="">
1255
1256 <div class="portlet" id="portlet-map" style="margin-bottom: 0px;"
1257- tal:define="link context/menu:overview/map"
1258- tal:condition="view/gmap2_enabled">
1259+ tal:define="link context/menu:overview/map">
1260 <table>
1261 <tr><td>
1262 <h2>