Начальное наполнение
3
__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from . import controllers
|
17
__manifest__.py
Normal file
@ -0,0 +1,17 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': 'Google Maps',
|
||||
'category': 'Website/Website',
|
||||
'summary': 'Show your company address on Google Maps',
|
||||
'version': '1.0',
|
||||
'description': """
|
||||
Show your company address/partner address on Google Maps. Configure an API key in the Website settings.
|
||||
""",
|
||||
'depends': ['base_geolocalize', 'website_partner'],
|
||||
'data': [
|
||||
'views/google_map_templates.xml',
|
||||
],
|
||||
'installable': True,
|
||||
'license': 'LGPL-3',
|
||||
}
|
4
controllers/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import main
|
58
controllers/main.py
Normal file
@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo import http
|
||||
from odoo.http import request
|
||||
from odoo.tools.json import scriptsafe
|
||||
|
||||
|
||||
class GoogleMap(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, sitemap=False)
|
||||
def google_map(self, *arg, **post):
|
||||
clean_ids = []
|
||||
for partner_id in post.get('partner_ids', "").split(","):
|
||||
try:
|
||||
clean_ids.append(int(partner_id))
|
||||
except ValueError:
|
||||
pass
|
||||
partners = request.env['res.partner'].sudo().search([("id", "in", clean_ids),
|
||||
('website_published', '=', True), ('is_company', '=', True)])
|
||||
partner_data = {
|
||||
"counter": len(partners),
|
||||
"partners": []
|
||||
}
|
||||
for partner in partners.with_context(show_address=True):
|
||||
partner_data["partners"].append({
|
||||
'id': partner.id,
|
||||
'name': partner.name,
|
||||
'address': '\n'.join(partner.display_name.split('\n')[1:]),
|
||||
'latitude': str(partner.partner_latitude) if partner.partner_latitude else False,
|
||||
'longitude': str(partner.partner_longitude) if partner.partner_longitude else False,
|
||||
})
|
||||
if 'customers' in post.get('partner_url', ''):
|
||||
partner_url = '/customers/'
|
||||
else:
|
||||
partner_url = '/partners/'
|
||||
|
||||
google_maps_api_key = request.website.google_maps_api_key
|
||||
values = {
|
||||
'partner_url': partner_url,
|
||||
'partner_data': scriptsafe.dumps(partner_data),
|
||||
'google_maps_api_key': google_maps_api_key,
|
||||
}
|
||||
return request.render("website_google_map.google_map", values)
|
15
i18n/website_google_map.pot
Normal file
@ -0,0 +1,15 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 17.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-10-26 21:56+0000\n"
|
||||
"PO-Revision-Date: 2023-10-26 21:56+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
BIN
static/description/icon.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
1
static/description/icon.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg width="50" height="50" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg"><path d="M30.439.813A18.546 18.546 0 0 0 25.001 0C19.47 0 14.52 2.423 11.22 6.23l8.504 6.934L30.439.813Z" fill="#1A73E8"/><path d="M11.217 6.23C8.587 9.262 7 13.175 7 17.443c0 3.282.675 5.94 1.783 8.321l10.938-12.6-8.504-6.934Z" fill="#EA4335"/><path d="M25.003 10.774c3.804 0 6.885 2.987 6.885 6.673 0 1.64-.612 3.145-1.626 4.306 0 0 5.437-6.268 10.715-12.347-2.18-4.064-5.96-7.19-10.532-8.593l-10.723 12.35a6.954 6.954 0 0 1 5.281-2.389Z" fill="#4285F4"/><path d="M25.003 24.115c-3.803 0-6.885-2.987-6.885-6.673a6.55 6.55 0 0 1 1.603-4.283L8.783 25.763c1.869 4.019 4.978 7.244 8.18 11.307l13.294-15.318a6.957 6.957 0 0 1-5.254 2.363Z" fill="#FBBC04"/><path d="M29.994 41.252C35.998 32.152 43 28.021 43 17.443c0-2.9-.733-5.633-2.025-8.037L16.965 37.07a62.11 62.11 0 0 1 3.047 4.185C23.663 46.722 22.65 50 25.005 50c2.349 0 1.338-3.281 4.99-8.748Z" fill="#34A853"/></svg>
|
After Width: | Height: | Size: 955 B |
28
static/src/css/website_google_map.css
Normal file
@ -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;
|
||||
}
|
BIN
static/src/img/partners.png
Normal file
After Width: | Height: | Size: 719 B |
89
static/src/js/website_google_map.js
Normal file
@ -0,0 +1,89 @@
|
||||
/* global MarkerClusterer, google */
|
||||
function initialize_map() {
|
||||
'use strict';
|
||||
|
||||
// MAP CONFIG AND LOADING
|
||||
var map = new google.maps.Map(document.getElementById('odoo-google-map'), {
|
||||
zoom: 1,
|
||||
center: {lat: 0.0, lng: 0.0},
|
||||
mapTypeId: google.maps.MapTypeId.ROADMAP
|
||||
});
|
||||
|
||||
// ENABLE ADDRESS 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 = [];
|
||||
var options = {
|
||||
imagePath: '/website_google_map/static/src/lib/images/m'
|
||||
};
|
||||
|
||||
google.maps.event.addListener(map, 'click', function() {
|
||||
infoWindow.close();
|
||||
});
|
||||
|
||||
// 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>' )+
|
||||
(p.type ? ' <b>' + p.type + '</b>' : '')+
|
||||
' <pre>' + p.address + '</pre>'+
|
||||
'</div>'
|
||||
);
|
||||
infoWindow.open(map, marker);
|
||||
};
|
||||
|
||||
// Create a bubble for a partner
|
||||
var set_marker = function(partner) {
|
||||
// If no lat & long, geocode address
|
||||
// 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) {
|
||||
var location = results[0].geometry.location;
|
||||
partner.latitude = location.ob;
|
||||
partner.longitude = location.pb;
|
||||
var marker = new google.maps.Marker({
|
||||
partner: partner,
|
||||
map: map,
|
||||
icon: partners,
|
||||
position: location
|
||||
});
|
||||
google.maps.event.addListener(marker, 'click', onMarkerClick);
|
||||
markers.push(marker);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/* eslint-disable no-undef */
|
||||
// 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]);
|
||||
}
|
||||
new MarkerClusterer(map, markers, options);
|
||||
}
|
||||
/* eslint-enable no-undef */
|
||||
}
|
||||
|
||||
// Initialize map once the DOM has been loaded
|
||||
google.maps.event.addDomListener(window, 'load', initialize_map);
|
BIN
static/src/lib/images/conv30.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
static/src/lib/images/conv40.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
static/src/lib/images/conv50.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
static/src/lib/images/heart30.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/src/lib/images/heart40.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
static/src/lib/images/heart50.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
static/src/lib/images/m1.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
static/src/lib/images/m2.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
static/src/lib/images/m3.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
static/src/lib/images/m4.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
static/src/lib/images/m5.png
Normal file
After Width: | Height: | Size: 6.7 KiB |
BIN
static/src/lib/images/people35.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
static/src/lib/images/people45.png
Normal file
After Width: | Height: | Size: 2.0 KiB |
BIN
static/src/lib/images/people55.png
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
static/src/lib/images/pin.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
1315
static/src/lib/markerclusterer.js
Normal file
28
views/google_map_templates.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<template id="google_map">
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<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/website_google_map.css"/>
|
||||
</head>
|
||||
<body t-att-data-partner-url="partner_url or None">
|
||||
<script>
|
||||
var odoo_partner_data = <t t-out="partner_data"/>;
|
||||
</script>
|
||||
<div id="odoo-google-map"></div>
|
||||
<t t-if="google_maps_api_key">
|
||||
<script t-attf-src="//maps.google.com/maps/api/js?key=#{google_maps_api_key}"></script>
|
||||
</t>
|
||||
<t t-else="1">
|
||||
<script src="//maps.google.com/maps/api/js"></script>
|
||||
</t>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/lib/markerclusterer.js"></script>
|
||||
<script type="text/javascript" src="/website_google_map/static/src/js/website_google_map.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</template>
|
||||
</odoo>
|