[web/views] extract cube geocoding (closes #353000)
authorJulien Cristau <julien.cristau@logilab.fr>
Mon, 17 Dec 2012 14:03:56 +0100
changeset 8830 7fd6c52ef878
parent 8829 bb14dc9848ec
child 8832 26cdfc6dd6f8
[web/views] extract cube geocoding (closes #353000)
misc/migration/bootstrapmigration_repository.py
web/data/cubicweb.gmap.js
web/data/gmap.utility.labeledmarker.js
web/data/gmap_blue_marker.png
web/views/igeocodable.py
--- a/misc/migration/bootstrapmigration_repository.py	Mon Feb 11 11:47:50 2013 +0100
+++ b/misc/migration/bootstrapmigration_repository.py	Mon Dec 17 14:03:56 2012 +0100
@@ -47,6 +47,12 @@
         if not confirm('In cubicweb 3.17 embedding views have been moved to the embed '
                        'cube, which is not installed.  Continue anyway?'):
             raise
+    try:
+        add_cube('geocoding', update_database=False)
+    except ImportError:
+        if not confirm('In cubicweb 3.17 geocoding views have been moved to the geocoding '
+                       'cube, which is not installed.  Continue anyway?'):
+            raise
 
 if applcubicwebversion <= (3, 13, 0) and cubicwebversion >= (3, 13, 1):
     sql('ALTER TABLE entities ADD asource VARCHAR(64)')
--- a/web/data/cubicweb.gmap.js	Mon Feb 11 11:47:50 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/**
- *  :organization: Logilab
- *  :copyright: 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
- *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
- */
-
-Widgets.GMapWidget = defclass('GMapWidget', null, {
-    __init__: function(wdgnode) {
-        // Assume we have imported google maps JS
-        if (GBrowserIsCompatible()) {
-            var uselabelstr = wdgnode.getAttribute('cubicweb:uselabel');
-            var uselabel = true;
-            if (uselabelstr) {
-                if (uselabelstr == 'True') {
-                    uselabel = true;
-                }
-                else {
-                    uselabel = false;
-                }
-            }
-            var map = new GMap2(wdgnode);
-            map.addControl(new GSmallMapControl());
-            var jsonurl = wdgnode.getAttribute('cubicweb:loadurl');
-            var self = this; // bind this to a local variable
-            jQuery.getJSON(jsonurl, function(geodata) {
-                var zoomLevel;
-                var center;
-                var latlngbounds = new GLatLngBounds( );
-                for (var i = 0; i < geodata.markers.length; i++) {
-                    var marker = geodata.markers[i];
-                    var latlng = new GLatLng(marker.latitude, marker.longitude);
-                    latlngbounds.extend( latlng );
-                }
-                if (geodata.zoomlevel) {
-                    zoomLevel = geodata.zoomlevel;
-                } else {
-                    zoomLevel = map.getBoundsZoomLevel( latlngbounds ) - 1;
-                }
-                if (geodata.center) {
-                    center = new GLatng(geodata.center.latitude, geodata.center.longitude);
-                } else {
-                    center = latlngbounds.getCenter();
-                }
-                map.setCenter(center, zoomLevel);
-                for (var i = 0; i < geodata.markers.length; i++) {
-                    var marker = geodata.markers[i];
-                    self.createMarker(map, marker, i + 1, uselabel);
-                }
-            });
-            jQuery(wdgnode).after(this.legendBox);
-        } else { // incompatible browser
-            jQuery.unload(GUnload);
-        }
-    },
-
-    createMarker: function(map, marker, i, uselabel) {
-        var point = new GLatLng(marker.latitude, marker.longitude);
-        var icon = new GIcon();
-        icon.image = marker.icon[0];
-        icon.iconSize = new GSize(marker.icon[1][0], marker.icon[1][1]);
-        icon.iconAnchor = new GPoint(marker.icon[2][0], marker.icon[2][1]);
-        if (marker.icon[3]) {
-            icon.shadow4 = marker.icon[3];
-        }
-        if (typeof LabeledMarker == "undefined") {
-            var gmarker = new GMarker(point, {
-                icon: icon,
-                title: marker.title
-            });
-        } else {
-            var gmarker = new LabeledMarker(point, {
-                icon: icon,
-                title: marker.title,
-                labelText: uselabel ? '<strong>' + i + '</strong>': '',
-                labelOffset: new GSize(2, - 32)
-            });
-        }
-        map.addOverlay(gmarker);
-        GEvent.addListener(gmarker, 'click', function() {
-            jQuery.post(marker.bubbleUrl, function(data) {
-                map.openInfoWindowHtml(point, data);
-            });
-        });
-    }
-
-});
-
--- a/web/data/gmap.utility.labeledmarker.js	Mon Feb 11 11:47:50 2013 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-/* http://code.google.com/p/gmaps-utility-library/source/browse/trunk/labeledmarker/ */
-function LabeledMarker(latlng,opt_opts){this.latlng_=latlng;this.opts_=opt_opts;this.labelText_=opt_opts.labelText||"";this.labelClass_=opt_opts.labelClass||"LabeledMarker_markerLabel";this.labelOffset_=opt_opts.labelOffset||new GSize(0,0);this.clickable_=opt_opts.clickable||true;this.title_=opt_opts.title||"";this.labelVisibility_=true;if(opt_opts.draggable){opt_opts.draggable=false}GMarker.apply(this,arguments)};LabeledMarker.prototype=new GMarker(new GLatLng(0,0));LabeledMarker.prototype.initialize=function(map){GMarker.prototype.initialize.apply(this,arguments);this.map_=map;this.div_=document.createElement("div");this.div_.className=this.labelClass_;this.div_.innerHTML=this.labelText_;this.div_.style.position="absolute";this.div_.style.cursor="pointer";this.div_.title=this.title_;map.getPane(G_MAP_MARKER_PANE).appendChild(this.div_);if(this.clickable_){function newEventPassthru(obj,event){return function(){GEvent.trigger(obj,event)}}var eventPassthrus=['click','dblclick','mousedown','mouseup','mouseover','mouseout'];for(var i=0;i<eventPassthrus.length;i++){var name=eventPassthrus[i];GEvent.addDomListener(this.div_,name,newEventPassthru(this,name))}}};LabeledMarker.prototype.redraw=function(force){GMarker.prototype.redraw.apply(this,arguments);this.redrawLabel_()};LabeledMarker.prototype.redrawLabel_=function(){var p=this.map_.fromLatLngToDivPixel(this.latlng_);var z=GOverlay.getZIndex(this.latlng_.lat());this.div_.style.left=(p.x+this.labelOffset_.width)+"px";this.div_.style.top=(p.y+this.labelOffset_.height)+"px";this.div_.style.zIndex=z};LabeledMarker.prototype.remove=function(){GEvent.clearInstanceListeners(this.div_);if(this.div_.outerHTML){this.div_.outerHTML=""}if(this.div_.parentNode){this.div_.parentNode.removeChild(this.div_)}this.div_=null;GMarker.prototype.remove.apply(this,arguments)};LabeledMarker.prototype.copy=function(){return new LabeledMarker(this.latlng_,this.opts_)};LabeledMarker.prototype.show=function(){GMarker.prototype.show.apply(this,arguments);if(this.labelVisibility_){this.showLabel()}else{this.hideLabel()}};LabeledMarker.prototype.hide=function(){GMarker.prototype.hide.apply(this,arguments);this.hideLabel()};LabeledMarker.prototype.setLatLng=function(latlng){this.latlng_=latlng;GMarker.prototype.setLatLng.apply(this,arguments);this.redrawLabel_()};LabeledMarker.prototype.setLabelVisibility=function(visibility){this.labelVisibility_=visibility;if(!this.isHidden()){if(this.labelVisibility_){this.showLabel()}else{this.hideLabel()}}};LabeledMarker.prototype.getLabelVisibility=function(){return this.labelVisibility_};LabeledMarker.prototype.hideLabel=function(){this.div_.style.visibility='hidden'};LabeledMarker.prototype.showLabel=function(){this.div_.style.visibility='visible'};
Binary file web/data/gmap_blue_marker.png has changed
--- a/web/views/igeocodable.py	Mon Feb 11 11:47:50 2013 +0100
+++ b/web/views/igeocodable.py	Mon Dec 17 14:03:56 2012 +0100
@@ -17,121 +17,21 @@
 # with CubicWeb.  If not, see <http://www.gnu.org/licenses/>.
 """Specific views for entities implementing IGeocodable"""
 
-__docformat__ = "restructuredtext en"
-
-from cubicweb.interfaces import IGeocodable
-from cubicweb.view import EntityView, EntityAdapter, implements_adapter_compat
-from cubicweb.predicates import implements, adaptable
-from cubicweb.utils import json_dumps
-
-class IGeocodableAdapter(EntityAdapter):
-    """interface required by geocoding views such as gmap-view"""
-    __needs_bw_compat__ = True
-    __regid__ = 'IGeocodable'
-    __select__ = implements(IGeocodable, warn=False) # XXX for bw compat, should be abstract
-
-    @property
-    @implements_adapter_compat('IGeocodable')
-    def latitude(self):
-        """returns the latitude of the entity in degree (-90 < float < +90)"""
-        raise NotImplementedError
+try:
+    from cubes.geocoding.views import (IGeocodableAdapter,
+                                       GeocodingJsonView,
+                                       GoogleMapBubbleView,
+                                       GoogleMapsView,
+                                       GoogeMapsLegend)
 
-    @property
-    @implements_adapter_compat('IGeocodable')
-    def longitude(self):
-        """returns the longitude of the entity in degree (-180 < float < +180)"""
-        raise NotImplementedError
-
-    @implements_adapter_compat('IGeocodable')
-    def marker_icon(self):
-        """returns the icon that should be used as the marker.
-
-        an icon is defined by a 4-uple:
-
-          (icon._url, icon.size,  icon.iconAnchor, icon.shadow)
-        """
-        return (self._cw.uiprops['GMARKER_ICON'], (20, 34), (4, 34), None)
-
-
-class GeocodingJsonView(EntityView):
-    __regid__ = 'geocoding-json'
-    __select__ = adaptable('IGeocodable')
-
-    binary = True
-    templatable = False
-    content_type = 'application/json'
+    from logilab.common.deprecation import class_moved
 
-    def call(self):
-        zoomlevel = self._cw.form.pop('zoomlevel', None)
-        extraparams = self._cw.form.copy()
-        extraparams.pop('vid', None)
-        extraparams.pop('rql', None)
-        markers = []
-        for entity in self.cw_rset.entities():
-            igeocodable = entity.cw_adapt_to('IGeocodable')
-            # remove entities that don't define latitude and longitude
-            if not (igeocodable.latitude and igeocodable.longitude):
-                continue
-            markers.append(self.build_marker_data(entity, igeocodable,
-                                                  extraparams))
-        if not markers:
-            return
-        geodata = {
-            'markers': markers,
-            }
-        if zoomlevel:
-            geodata['zoomlevel'] = int(zoomlevel)
-        self.w(json_dumps(geodata))
-
-    def build_marker_data(self, entity, igeocodable, extraparams):
-        return {'latitude': igeocodable.latitude,
-                'longitude': igeocodable.longitude,
-                'icon': igeocodable.marker_icon(),
-                'title': entity.dc_long_title(),
-                'bubbleUrl': entity.absolute_url(
-                    vid='gmap-bubble', __notemplate=1, **extraparams),
-                }
-
-
-class GoogleMapBubbleView(EntityView):
-    __regid__ = 'gmap-bubble'
-    __select__ = adaptable('IGeocodable')
-
-    def cell_call(self, row, col):
-        entity = self.cw_rset.get_entity(row, col)
-        self.w(u'<div>%s</div>' % entity.view('oneline'))
-        # FIXME: we should call something like address-view if available
-
-
-class GoogleMapsView(EntityView):
-    __regid__ = 'gmap-view'
-    __select__ = adaptable('IGeocodable')
-
-    paginable = False
-
-    def call(self, gmap_key, width=400, height=400, uselabel=True, urlparams=None):
-        self._cw.demote_to_html()
-        self._cw.add_js('http://maps.google.com/maps?sensor=false&file=api&v=2&key=%s'
-                        % gmap_key, localfile=False)
-        self._cw.add_js( ('cubicweb.widgets.js', 'cubicweb.gmap.js', 'gmap.utility.labeledmarker.js') )
-        rql = self.cw_rset.printable_rql()
-        if urlparams is None:
-            loadurl = self._cw.build_url(rql=rql, vid='geocoding-json')
-        else:
-            loadurl = self._cw.build_url(rql=rql, vid='geocoding-json', **urlparams)
-        self.w(u'<div style="width: %spx; height: %spx;" class="widget gmap" '
-               u'cubicweb:wdgtype="GMapWidget" cubicweb:loadtype="auto" '
-               u'cubicweb:loadurl="%s" cubicweb:uselabel="%s"> </div>'
-               % (width, height, loadurl, uselabel))
-
-
-class GoogeMapsLegend(EntityView):
-    __regid__ = 'gmap-legend'
-
-    def call(self):
-        self.w(u'<ol>')
-        for rowidx in xrange(len(self.cw_rset)):
-            self.w(u'<li>')
-            self.wview('listitem', self.cw_rset, row=rowidx, col=0)
-            self.w(u'</li>')
-        self.w(u'</ol>')
+    msg = '[3.17] cubicweb.web.views.igeocodable moved to cubes.geocoding.views'
+    IGeocodableAdapter = class_moved(IGeocodableAdapter, message=msg)
+    GeocodingJsonView = class_moved(GeocodingJsonView, message=msg)
+    GoogleMapBubbleView = class_moved(GoogleMapBubbleView, message=msg)
+    GoogleMapsView = class_moved(GoogleMapsView, message=msg)
+    GoogeMapsLegend = class_moved(GoogeMapsLegend, message=msg)
+except ImportError:
+    from cubicweb.web import LOGGER
+    LOGGER.warning('[3.17] igeocoding extracted to cube geocoding that was not found. try installing it.')