[FIX][IMP] Make partner maps work properly
[FIX] website*: unfuck buggy controllers [IMP] website*: display GoogleMap in a human-usable interface [IMP] website_google_map: large module cleaning - There is now only one controller, data is sent once for all! - Map is now fully resizable in its hosting template - HTML/CSS cleaning - JavaScript is now human-readable ;-)
This commit is contained in:
parent
c1ae43c807
commit
f04e6de2e7
|
@ -146,7 +146,7 @@ class WebsiteCrmPartnerAssign(http.Controller):
|
|||
# Do not use semantic controller due to SUPERUSER_ID
|
||||
@http.route(['/partners/<partner_id>'], type='http', auth="public", website=True)
|
||||
def partners_detail(self, partner_id, partner_name='', **post):
|
||||
mo = re.search('-([-0-9]+)$', str(partner_id))
|
||||
mo = re.search('([-0-9]+)$', str(partner_id))
|
||||
current_grade, current_country = None, None
|
||||
grade_id = post.get('grade_id')
|
||||
country_id = post.get('country_id')
|
||||
|
|
|
@ -115,10 +115,24 @@
|
|||
|
||||
<template id="ref_country" inherit_id="website_crm_partner_assign.index" optional="enabled" name="Left World Map">
|
||||
<xpath expr="//ul[@id='reseller_countries']" position="after">
|
||||
<h3>World Map</h3>
|
||||
<!-- modal for large map -->
|
||||
<div class="modal fade partner_map_modal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">World Map</h4>
|
||||
</div>
|
||||
<iframe t-attf-src="/google_map/?width=898&height=485&partner_ids=#{ google_map_partner_ids }&partner_url=/partners/"
|
||||
style="width:898px; height:485px; border:0; padding:0; margin:0;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal end -->
|
||||
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".partner_map_modal"><span class="fa fa-external-link" /></button></h3>
|
||||
<ul class="nav">
|
||||
<iframe t-attf-src="/google_map/?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/partners"
|
||||
style="width:260px; height:260px; border:0; padding:0; margin:0;"></iframe>
|
||||
<iframe t-attf-src="/google_map/?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/partners/"
|
||||
style="width:260px; height:240px; border:0; padding:0; margin:0;"></iframe>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
|
|
@ -84,7 +84,7 @@ class WebsiteCustomer(http.Controller):
|
|||
# Do not use semantic controller due to SUPERUSER_ID
|
||||
@http.route(['/customers/<partner_id>'], type='http', auth="public", website=True)
|
||||
def partners_detail(self, partner_id, **post):
|
||||
mo = re.search('-([-0-9]+)$', str(partner_id))
|
||||
mo = re.search('([-0-9]+)$', str(partner_id))
|
||||
if mo:
|
||||
partner_id = int(mo.group(1))
|
||||
partner = request.registry['res.partner'].browse(request.cr, SUPERUSER_ID, partner_id, context=request.context)
|
||||
|
|
|
@ -66,11 +66,27 @@
|
|||
</template>
|
||||
|
||||
<!-- Option: left column: World Map -->
|
||||
<template id="opt_country" inherit_id="website_customer.index" optional="disabled" name="Show Map">
|
||||
<template id="opt_country" inherit_id="website_customer.index" optional="enabled" name="Show Map">
|
||||
<xpath expr="//div[@id='ref_left_column']" position="inside">
|
||||
|
||||
<iframe t-attf-src="/google_map/?partner_ids=#{ google_map_partner_ids }&partner_url=/customers/&output=embed"
|
||||
style="width:100%; border:0; padding:0; margin:0;"></iframe>
|
||||
<!-- modal for large map -->
|
||||
<div class="modal fade customer_map_modal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">World Map</h4>
|
||||
</div>
|
||||
<iframe t-attf-src="/google_map/?width=898&height=485&partner_ids=#{ google_map_partner_ids }&partner_url=/customers/"
|
||||
style="width:898px; height:485px; border:0; padding:0; margin:0;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal end -->
|
||||
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".customer_map_modal"><span class="fa fa-external-link" /></button></h3>
|
||||
<ul class="nav">
|
||||
<iframe t-attf-src="/google_map/?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/customers/"
|
||||
style="width:260px; height:240px; border:0; padding:0; margin:0;"></iframe>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
import controllers
|
||||
import models
|
|
@ -1,3 +1,2 @@
|
|||
import main
|
||||
|
||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1,48 +1,64 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import openerp
|
||||
import json
|
||||
from openerp import SUPERUSER_ID
|
||||
from openerp.addons.web import http
|
||||
from openerp.addons.web.http import request
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
class google_map(http.Controller):
|
||||
'''
|
||||
This class generates on-the-fly partner maps that can be reused in every
|
||||
website page. To do so, just use an ``<iframe ...>`` whose ``src``
|
||||
attribute points to ``/google_map`` (this controller generates a complete
|
||||
HTML5 page).
|
||||
|
||||
URL query parameters:
|
||||
- ``partner_ids``: a comma-separated list of ids (partners to be shown)
|
||||
- ``partner_url``: the base-url to display the partner
|
||||
(eg: if ``partner_url`` is ``/partners/``, when the user will click on
|
||||
a partner on the map, it will be redirected to <myodoo>.com/partners/<id>)
|
||||
|
||||
In order to resize the map, simply resize the ``iframe`` with CSS
|
||||
directives ``width`` and ``height``.
|
||||
'''
|
||||
|
||||
@http.route(['/google_map'], type='http', auth="public", website=True)
|
||||
def google_map(self, *arg, **post):
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
partner_obj = request.registry['res.partner']
|
||||
|
||||
# filter real ints from query parameters and build a domain
|
||||
clean_ids = []
|
||||
for s in post.get('partner_ids', "").split(","):
|
||||
try:
|
||||
i = int(s)
|
||||
clean_ids.append(i)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# search for partners that can be displayed on a map
|
||||
domain = [("id", "in", clean_ids), ('website_published', '=', True), ('is_company', '=', True)]
|
||||
partners_ids = partner_obj.search(cr, SUPERUSER_ID, domain, context=context)
|
||||
|
||||
# browse and format data
|
||||
partner_data = {
|
||||
"counter": len(partners_ids),
|
||||
"partners": []
|
||||
}
|
||||
request.context.update({'show_address': True})
|
||||
for partner in partner_obj.browse(cr, SUPERUSER_ID, partners_ids, context=context):
|
||||
partner_data["partners"].append({
|
||||
'id': partner.id,
|
||||
'name': partner.name,
|
||||
'address': '\n'.join(partner.name_get()[0][1].split('\n')[1:]),
|
||||
'latitude': partner.partner_latitude,
|
||||
'longitude': partner.partner_longitude,
|
||||
})
|
||||
|
||||
# generate the map
|
||||
values = {
|
||||
'partner_ids': post.get('partner_ids', ""),
|
||||
'width': post.get('width', 900),
|
||||
'height': post.get('height', 460),
|
||||
'partner_url': post.get('partner_url'),
|
||||
'partner_data': json.dumps(partner_data)
|
||||
}
|
||||
return request.website.render("website_google_map.google_map", values)
|
||||
|
||||
@http.route(['/google_map/partners.json'], type='http', auth="public", website=True)
|
||||
def google_map_data(self, *arg, **post):
|
||||
partner_obj = request.registry['res.partner']
|
||||
|
||||
domain = [("id", "in", [int(p) for p in post.get('partner_ids', "").split(",") if p])]
|
||||
domain_public = domain + [('website_published', '=', True)]
|
||||
partner_ids = partner_obj.search(request.cr, openerp.SUPERUSER_ID,
|
||||
domain_public, context=request.context)
|
||||
return partner_obj.google_map_json(request.cr, openerp.SUPERUSER_ID,
|
||||
partner_ids, request.context)
|
||||
|
||||
@http.route(['/google_map/set_partner_position'], type='http', methods=['POST'], auth="public", website=True)
|
||||
def google_map_set_partner_position(self, *arg, **post):
|
||||
partner_obj = request.registry['res.partner']
|
||||
|
||||
partner_id = post.get('partner_id') and int(post['partner_id'])
|
||||
latitude = post.get('latitude') and float(post['latitude'])
|
||||
longitude = post.get('longitude') and float(post['longitude'])
|
||||
|
||||
values = {
|
||||
'partner_latitude': latitude,
|
||||
'partner_longitude': longitude,
|
||||
'date_localization': datetime.now().strftime('%Y-%m-%d'),
|
||||
}
|
||||
partner_obj.write(request.cr, openerp.SUPERUSER_ID, [partner_id], values,
|
||||
request.context)
|
||||
|
||||
|
||||
# vim:expandtab:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
import res_partner
|
|
@ -1,28 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from openerp.osv import osv
|
||||
|
||||
import simplejson
|
||||
import werkzeug.wrappers
|
||||
|
||||
|
||||
class res_partner(osv.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def google_map_json(self, cr, uid, ids, context=None):
|
||||
data = {
|
||||
"counter": len(ids),
|
||||
"partners": []
|
||||
}
|
||||
for partner in self.pool.get('res.partner').browse(cr, uid, ids, context={'show_address': True}):
|
||||
data["partners"].append({
|
||||
'id': partner.id,
|
||||
'name': partner.name,
|
||||
'address': '\n'.join(partner.name_get()[0][1].split('\n')[1:]),
|
||||
'latitude': partner.partner_latitude,
|
||||
'longitude': partner.partner_longitude,
|
||||
})
|
||||
|
||||
mime = 'application/json'
|
||||
body = "var data = " + "}, \n{".join(simplejson.dumps(data).split("}, {"))
|
||||
return werkzeug.wrappers.Response(body, headers=[('Content-Type', mime), ('Content-Length', len(body))])
|
|
@ -0,0 +1,28 @@
|
|||
html {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#odoo-google-map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.marker {
|
||||
font-size: 13px !important;
|
||||
}
|
||||
|
||||
.marker a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.marker pre {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
font-family: sans-serif !important;
|
||||
}
|
|
@ -1,29 +1,33 @@
|
|||
function initialize(pt) {
|
||||
var center = new google.maps.LatLng(10.91, 5.38);
|
||||
var Geocoder = new google.maps.Geocoder();
|
||||
function initialize_map() {
|
||||
'use strict';
|
||||
|
||||
var map = new google.maps.Map(document.getElementById('map'), {
|
||||
// MAP CONFIG AND LOADING
|
||||
var map = new google.maps.Map(document.getElementById('odoo-google-map'), {
|
||||
zoom: 1,
|
||||
center: center,
|
||||
center: {lat: 0.0, lng: 0.0},
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
});
|
||||
|
||||
// ENABLE ADRESS GEOCODING
|
||||
var Geocoder = new google.maps.Geocoder();
|
||||
|
||||
// INFO BUBBLES
|
||||
var infoWindow = new google.maps.InfoWindow();
|
||||
var partners = new google.maps.MarkerImage('/website_google_map/static/src/img/partners.png', new google.maps.Size(25, 25));
|
||||
var partner_url = document.body.getAttribute('data-partner-url') || '';
|
||||
var markers = [];
|
||||
|
||||
google.maps.event.addListener(map, 'click', function() {
|
||||
infoWindow.close();
|
||||
});
|
||||
|
||||
var partners = new google.maps.MarkerImage("/website_google_map/static/src/img/partners.png",new google.maps.Size(25, 25));
|
||||
|
||||
var markers = [];
|
||||
|
||||
// Display the bubble once clicked
|
||||
var onMarkerClick = function() {
|
||||
var marker = this;
|
||||
var p = marker.partner;
|
||||
infoWindow.setContent(
|
||||
'<div class="marker">'+
|
||||
(partner_url.length ? '<a target="_top" href="'+partner_url+p.id+'"><b>'+p.name +'</b></a>' : '<b>'+p.name+'</b>' )+ '<br/>'+
|
||||
(partner_url.length ? '<a target="_top" href="'+partner_url+p.id+'"><b>'+p.name +'</b></a>' : '<b>'+p.name+'</b>' )+
|
||||
(p.type ? ' <b>' + p.type + '</b>' : '')+
|
||||
' <pre>' + p.address + '</pre>'+
|
||||
'</div>'
|
||||
|
@ -31,22 +35,16 @@ function initialize(pt) {
|
|||
infoWindow.open(map, marker);
|
||||
};
|
||||
|
||||
// Create a bubble for a partner
|
||||
var set_marker = function(partner) {
|
||||
// If no lat & long, geocode adress
|
||||
// TODO: a server cronjob that will store these coordinates in database instead of resolving them on-the-fly
|
||||
if (!partner.latitude && !partner.longitude) {
|
||||
|
||||
Geocoder.geocode({'address': partner.address}, function(results, status) {
|
||||
if (status == google.maps.GeocoderStatus.OK) {
|
||||
if (status === google.maps.GeocoderStatus.OK) {
|
||||
var location = results[0].geometry.location;
|
||||
|
||||
$.post("/google_map/set_partner_position", {
|
||||
'partner_id': partner.id,
|
||||
'latitude': location.ob,
|
||||
'longitude': location.pb
|
||||
});
|
||||
partner.latitude = location.ob;
|
||||
partner.longitude = location.pb;
|
||||
|
||||
map.setCenter(results[0].geometry.location);
|
||||
var marker = new google.maps.Marker({
|
||||
partner: partner,
|
||||
map: map,
|
||||
|
@ -59,26 +57,27 @@ function initialize(pt) {
|
|||
console.debug('Geocode was not successful for the following reason: ' + status);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
var latLng = new google.maps.LatLng(partner.latitude, partner.longitude);
|
||||
var marker = new google.maps.Marker({
|
||||
partner: partner,
|
||||
icon: partners,
|
||||
map: map,
|
||||
position: latLng
|
||||
});
|
||||
google.maps.event.addListener(marker, 'click', onMarkerClick);
|
||||
markers.push(marker);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (data)
|
||||
for (var i = 0; i < data.counter; i++) {
|
||||
set_marker(data.partners[i]);
|
||||
// Create the markers and cluster them on the map
|
||||
if (odoo_partner_data){ /* odoo_partner_data special variable should have been defined in google_map.xml */
|
||||
for (var i = 0; i < odoo_partner_data.counter; i++) {
|
||||
set_marker(odoo_partner_data.partners[i]);
|
||||
}
|
||||
var markerCluster = new MarkerClusterer(map, markers);
|
||||
}
|
||||
google.maps.event.addDomListener(window, 'load', initialize);
|
||||
}
|
||||
|
||||
// Initialize map once the DOM has been loaded
|
||||
google.maps.event.addDomListener(window, 'load', initialize_map);
|
||||
|
|
|
@ -2,41 +2,24 @@
|
|||
<openerp>
|
||||
<data>
|
||||
<template id="google_map">
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
<title>World wide map</title>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: Helvetica, Arial, sans-serif !important;
|
||||
}
|
||||
.marker {
|
||||
font-size: 12px !important;
|
||||
}
|
||||
.marker b {
|
||||
font-weight: 500;
|
||||
}
|
||||
.marker pre {
|
||||
font-size: 10px !important;
|
||||
}
|
||||
</style>
|
||||
<script>var partner_url = '<t t-raw="partner_url or ''"/>';</script>
|
||||
<script src="//maps.google.com/maps/api/js?sensor=false"></script>
|
||||
<script type="text/javascript" t-attf-src="/google_map/partners.json?partner_ids=#{ partner_ids }"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/markerclusterer_compiled.js"></script>
|
||||
<script src="//code.jquery.com/jquery-1.6.1.min.js"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/google_map.js"></script>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
|
||||
<title>World Map</title>
|
||||
<link rel="stylesheet" type="text/css" href="/website_google_map/static/src/css/google-map.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="map" t-attf-style="width: #{ width }px; height: #{ height }px"></div>
|
||||
<body t-att-data-partner-url="partner_url or ''">
|
||||
<script>
|
||||
var odoo_partner_data = <t t-raw="partner_data"/>;
|
||||
</script>
|
||||
<div id="odoo-google-map"></div>
|
||||
<script src="//maps.google.com/maps/api/js?sensor=false"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/markerclusterer_compiled.js"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/google_map.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</template>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -105,7 +105,7 @@ class WebsiteMembership(http.Controller):
|
|||
# Do not use semantic controller due to SUPERUSER_ID
|
||||
@http.route(['/members/<partner_id>'], type='http', auth="public", website=True)
|
||||
def partners_detail(self, partner_id, **post):
|
||||
mo = re.search('-([-0-9]+)$', str(partner_id))
|
||||
mo = re.search('([-0-9]+)$', str(partner_id))
|
||||
if mo:
|
||||
partner_id = int(mo.group(1))
|
||||
partner = request.registry['res.partner'].browse(request.cr, SUPERUSER_ID, partner_id, context=request.context)
|
||||
|
@ -113,4 +113,4 @@ class WebsiteMembership(http.Controller):
|
|||
values = {}
|
||||
values['main_object'] = values['partner'] = partner
|
||||
return request.website.render("website_membership.partner", values)
|
||||
return self.customers(**post)
|
||||
return self.members(**post)
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 mb32" id="left_column">
|
||||
<div class="col-md-3 mb32" id="left_column">
|
||||
<ul class="nav nav-pills nav-stacked mt16">
|
||||
<li class="nav-header"><h3>Associations</h3></li>
|
||||
<li t-att-class="'' if membership else 'active'"><a href="/members">All</a></li>
|
||||
|
@ -85,7 +85,7 @@
|
|||
|
||||
<template id="opt_index_country" name="Location"
|
||||
optional="enabled" inherit_id="website_membership.index">
|
||||
<xpath expr="//div[@id='left_column']/ul[last()]" position="after">
|
||||
<xpath expr="//div[@id='left_column']/ul[1]" position="after">
|
||||
<ul class="nav nav-pills nav-stacked mt16">
|
||||
<li class="nav-header"><h3>Location</h3></li>
|
||||
<t t-foreach="countries">
|
||||
|
@ -102,13 +102,25 @@
|
|||
<!-- Option: index: Left Google Map -->
|
||||
<template id="opt_index_google_map" name="Left World Map"
|
||||
optional="enabled" inherit_id="website_membership.index">
|
||||
<xpath expr="//div[@id='left_column']/ul[1]" position="before">
|
||||
<ul class="nav nav-pills nav-stacked mt16">
|
||||
<li class="nav-header"><h3>World Map</h3></li>
|
||||
<xpath expr="//div[@id='left_column']/ul[last()]" position="after">
|
||||
<!-- modal for large map -->
|
||||
<div class="modal fade partner_map_modal" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h4 class="modal-title">World Map</h4>
|
||||
</div>
|
||||
<iframe t-attf-src="/google_map/?width=898&height=485&partner_ids=#{ google_map_partner_ids }&partner_url=/members/"
|
||||
style="width:898px; height:485px; border:0; padding:0; margin:0;"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- modal end -->
|
||||
<h3>World Map<button class="btn btn-link" data-toggle="modal" data-target=".partner_map_modal"><span class="fa fa-external-link" /></button></h3>
|
||||
<ul class="nav">
|
||||
<iframe t-attf-src="/google_map/?width=320&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/members"
|
||||
style="width:320px; height:260px; border:0; padding:0; margin:0;"></iframe>
|
||||
</ul>
|
||||
<iframe t-attf-src="/google_map/?width=260&height=240&partner_ids=#{ google_map_partner_ids }&partner_url=/members/"
|
||||
style="width:260px; height:240px; border:0; padding:0; margin:0;"></iframe>
|
||||
</ul>
|
||||
</xpath>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue